Ayaka Koshibe
Committed by Gerrit Code Review

Link config enhancements:

o Links can be injected using configs
o fix for AllowedEntity check on links
o config for link durability
o Link operator methods for creating Link descriptions

Change-Id: I8a1fabc688a2e7eeb579feced451a6c1ba7e3232
...@@ -17,6 +17,7 @@ package org.onosproject.net.config.basics; ...@@ -17,6 +17,7 @@ package org.onosproject.net.config.basics;
17 17
18 import org.onosproject.net.Link; 18 import org.onosproject.net.Link;
19 import org.onosproject.net.LinkKey; 19 import org.onosproject.net.LinkKey;
20 +import com.fasterxml.jackson.databind.JsonNode;
20 21
21 import java.time.Duration; 22 import java.time.Duration;
22 23
...@@ -28,6 +29,7 @@ public class BasicLinkConfig extends AllowedEntityConfig<LinkKey> { ...@@ -28,6 +29,7 @@ public class BasicLinkConfig extends AllowedEntityConfig<LinkKey> {
28 public static final String TYPE = "type"; 29 public static final String TYPE = "type";
29 public static final String LATENCY = "latency"; 30 public static final String LATENCY = "latency";
30 public static final String BANDWIDTH = "bandwidth"; 31 public static final String BANDWIDTH = "bandwidth";
32 + public static final String IS_DURABLE = "durable";
31 33
32 /** 34 /**
33 * Returns the link type. 35 * Returns the link type.
...@@ -87,4 +89,26 @@ public class BasicLinkConfig extends AllowedEntityConfig<LinkKey> { ...@@ -87,4 +89,26 @@ public class BasicLinkConfig extends AllowedEntityConfig<LinkKey> {
87 return (BasicLinkConfig) setOrClear(BANDWIDTH, bandwidth); 89 return (BasicLinkConfig) setOrClear(BANDWIDTH, bandwidth);
88 } 90 }
89 91
92 + /**
93 + * Returns if link is durable in the network model or not.
94 + *
95 + * @return true for durable, false otherwise
96 + */
97 + public Boolean isDurable() {
98 + JsonNode res = object.path(IS_DURABLE);
99 + if (res.isMissingNode()) {
100 + return null;
101 + }
102 + return res.asBoolean();
103 + }
104 +
105 + /**
106 + * Sets durability for this link.
107 + *
108 + * @param isDurable true for durable, false otherwise
109 + * @return this BasicLinkConfig
110 + */
111 + public BasicLinkConfig isDurable(Boolean isDurable) {
112 + return (BasicLinkConfig) setOrClear(IS_DURABLE, isDurable);
113 + }
90 } 114 }
......
...@@ -16,12 +16,14 @@ ...@@ -16,12 +16,14 @@
16 package org.onosproject.net.link.impl; 16 package org.onosproject.net.link.impl;
17 17
18 import static org.slf4j.LoggerFactory.getLogger; 18 import static org.slf4j.LoggerFactory.getLogger;
19 +import static com.google.common.base.Preconditions.checkNotNull;
19 20
20 import java.time.Duration; 21 import java.time.Duration;
21 22
22 import org.onosproject.net.AnnotationKeys; 23 import org.onosproject.net.AnnotationKeys;
23 import org.onosproject.net.config.ConfigOperator; 24 import org.onosproject.net.config.ConfigOperator;
24 import org.onosproject.net.config.basics.BasicLinkConfig; 25 import org.onosproject.net.config.basics.BasicLinkConfig;
26 +import org.onosproject.net.ConnectPoint;
25 import org.onosproject.net.DefaultAnnotations; 27 import org.onosproject.net.DefaultAnnotations;
26 import org.onosproject.net.Link; 28 import org.onosproject.net.Link;
27 import org.onosproject.net.SparseAnnotations; 29 import org.onosproject.net.SparseAnnotations;
...@@ -81,6 +83,46 @@ public final class BasicLinkOperator implements ConfigOperator { ...@@ -81,6 +83,46 @@ public final class BasicLinkOperator implements ConfigOperator {
81 if (cfg.bandwidth() != DEF_BANDWIDTH) { 83 if (cfg.bandwidth() != DEF_BANDWIDTH) {
82 b.set(AnnotationKeys.BANDWIDTH, String.valueOf(cfg.bandwidth())); 84 b.set(AnnotationKeys.BANDWIDTH, String.valueOf(cfg.bandwidth()));
83 } 85 }
86 + if (cfg.isDurable() != null) {
87 + b.set(AnnotationKeys.DURABLE, String.valueOf(cfg.isDurable()));
88 + }
84 return DefaultAnnotations.union(an, b.build()); 89 return DefaultAnnotations.union(an, b.build());
85 } 90 }
91 +
92 + /**
93 + * Generates a link description from a link description entity. The endpoints
94 + * must be specified to indicate directionality.
95 + *
96 + * @param src the source ConnectPoint
97 + * @param dst the destination ConnectPoint
98 + * @param link the link config entity
99 + * @return a linkDescription based on the config
100 + */
101 + public static LinkDescription descriptionOf(
102 + ConnectPoint src, ConnectPoint dst, Link link) {
103 + checkNotNull(src, "Must supply a source endpoint");
104 + checkNotNull(dst, "Must supply a destination endpoint");
105 + checkNotNull(link, "Must supply a link");
106 + return new DefaultLinkDescription(
107 + src, dst, link.type(), (SparseAnnotations) link.annotations());
108 + }
109 +
110 + /**
111 + * Generates a link description from a link config entity. This is for
112 + * links that cannot be discovered and has to be injected. The endpoints
113 + * must be specified to indicate directionality.
114 + *
115 + * @param src the source ConnectPoint
116 + * @param dst the destination ConnectPoint
117 + * @param link the link config entity
118 + * @return a linkDescription based on the config
119 + */
120 + public static LinkDescription descriptionOf(
121 + ConnectPoint src, ConnectPoint dst, BasicLinkConfig link) {
122 + checkNotNull(src, "Must supply a source endpoint");
123 + checkNotNull(dst, "Must supply a destination endpoint");
124 + checkNotNull(link, "Must supply a link config");
125 + return new DefaultLinkDescription(
126 + src, dst, link.type(), combine(link, DefaultAnnotations.EMPTY));
127 + }
86 } 128 }
......
...@@ -18,6 +18,7 @@ package org.onosproject.net.link.impl; ...@@ -18,6 +18,7 @@ package org.onosproject.net.link.impl;
18 import com.google.common.base.Predicate; 18 import com.google.common.base.Predicate;
19 import com.google.common.collect.FluentIterable; 19 import com.google.common.collect.FluentIterable;
20 import com.google.common.collect.Sets; 20 import com.google.common.collect.Sets;
21 +
21 import org.apache.felix.scr.annotations.Activate; 22 import org.apache.felix.scr.annotations.Activate;
22 import org.apache.felix.scr.annotations.Component; 23 import org.apache.felix.scr.annotations.Component;
23 import org.apache.felix.scr.annotations.Deactivate; 24 import org.apache.felix.scr.annotations.Deactivate;
...@@ -25,6 +26,7 @@ import org.apache.felix.scr.annotations.Reference; ...@@ -25,6 +26,7 @@ import org.apache.felix.scr.annotations.Reference;
25 import org.apache.felix.scr.annotations.ReferenceCardinality; 26 import org.apache.felix.scr.annotations.ReferenceCardinality;
26 import org.apache.felix.scr.annotations.Service; 27 import org.apache.felix.scr.annotations.Service;
27 import org.onosproject.net.provider.AbstractListenerProviderRegistry; 28 import org.onosproject.net.provider.AbstractListenerProviderRegistry;
29 +import org.onosproject.net.provider.ProviderId;
28 import org.onosproject.net.config.NetworkConfigEvent; 30 import org.onosproject.net.config.NetworkConfigEvent;
29 import org.onosproject.net.config.NetworkConfigListener; 31 import org.onosproject.net.config.NetworkConfigListener;
30 import org.onosproject.net.config.NetworkConfigService; 32 import org.onosproject.net.config.NetworkConfigService;
...@@ -54,7 +56,6 @@ import org.slf4j.Logger; ...@@ -54,7 +56,6 @@ import org.slf4j.Logger;
54 import java.util.Set; 56 import java.util.Set;
55 57
56 import static com.google.common.base.Preconditions.checkNotNull; 58 import static com.google.common.base.Preconditions.checkNotNull;
57 -import static com.google.common.base.Preconditions.checkState;
58 import static org.onosproject.net.LinkKey.linkKey; 59 import static org.onosproject.net.LinkKey.linkKey;
59 import static org.onosproject.security.AppGuard.checkPermission; 60 import static org.onosproject.security.AppGuard.checkPermission;
60 import static org.slf4j.LoggerFactory.getLogger; 61 import static org.slf4j.LoggerFactory.getLogger;
...@@ -207,6 +208,10 @@ public class LinkManager ...@@ -207,6 +208,10 @@ public class LinkManager
207 post(store.removeLink(src, dst)); 208 post(store.removeLink(src, dst));
208 } 209 }
209 210
211 + private boolean isAllowed(BasicLinkConfig cfg) {
212 + return (cfg == null || cfg.isAllowed());
213 + }
214 +
210 // Auxiliary interceptor for device remove events to prune links that 215 // Auxiliary interceptor for device remove events to prune links that
211 // are associated with the removed device or its port. 216 // are associated with the removed device or its port.
212 private class InternalDeviceListener implements DeviceListener { 217 private class InternalDeviceListener implements DeviceListener {
...@@ -240,11 +245,12 @@ public class LinkManager ...@@ -240,11 +245,12 @@ public class LinkManager
240 checkNotNull(linkDescription, LINK_DESC_NULL); 245 checkNotNull(linkDescription, LINK_DESC_NULL);
241 checkValidity(); 246 checkValidity();
242 linkDescription = validateLink(linkDescription); 247 linkDescription = validateLink(linkDescription);
243 - LinkEvent event = store.createOrUpdateLink(provider().id(), 248 + if (linkDescription != null) {
244 - linkDescription); 249 + LinkEvent event = store.createOrUpdateLink(provider().id(), linkDescription);
245 - if (event != null) { 250 + if (event != null) {
246 - log.info("Link {} detected", linkDescription); 251 + log.info("Link {} detected", linkDescription);
247 - post(event); 252 + post(event);
253 + }
248 } 254 }
249 } 255 }
250 256
...@@ -258,11 +264,12 @@ public class LinkManager ...@@ -258,11 +264,12 @@ public class LinkManager
258 BasicLinkConfig cfgTwo = networkConfigService.getConfig(linkKey(linkDescription.dst(), 264 BasicLinkConfig cfgTwo = networkConfigService.getConfig(linkKey(linkDescription.dst(),
259 linkDescription.src()), 265 linkDescription.src()),
260 BasicLinkConfig.class); 266 BasicLinkConfig.class);
261 - 267 + if (isAllowed(cfg) && isAllowed(cfgTwo)) {
262 - checkState(cfg == null || cfg.isAllowed(), "Link " + linkDescription.toString() + " is not allowed"); 268 + return BasicLinkOperator.combine(cfg, linkDescription);
263 - checkState(cfgTwo == null || cfgTwo.isAllowed(), "Link " + linkDescription.toString() + " is not allowed"); 269 + } else {
264 - 270 + log.trace("Link " + linkDescription.toString() + " is not allowed");
265 - return BasicLinkOperator.combine(cfg, linkDescription); 271 + return null;
272 + }
266 } 273 }
267 274
268 @Override 275 @Override
...@@ -324,20 +331,41 @@ public class LinkManager ...@@ -324,20 +331,41 @@ public class LinkManager
324 // listens for NetworkConfigEvents of type BasicLinkConfig and removes 331 // listens for NetworkConfigEvents of type BasicLinkConfig and removes
325 // links that the config does not allow 332 // links that the config does not allow
326 private class InternalNetworkConfigListener implements NetworkConfigListener { 333 private class InternalNetworkConfigListener implements NetworkConfigListener {
334 +
335 + @Override
336 + public boolean isRelevant(NetworkConfigEvent event) {
337 + return event.configClass().equals(BasicLinkConfig.class)
338 + && (event.type() == NetworkConfigEvent.Type.CONFIG_ADDED
339 + || event.type() == NetworkConfigEvent.Type.CONFIG_UPDATED);
340 + }
341 +
327 @Override 342 @Override
328 public void event(NetworkConfigEvent event) { 343 public void event(NetworkConfigEvent event) {
329 - if ((event.type() == NetworkConfigEvent.Type.CONFIG_ADDED || 344 + LinkKey lk = (LinkKey) event.subject();
330 - event.type() == NetworkConfigEvent.Type.CONFIG_UPDATED) && 345 + BasicLinkConfig cfg = networkConfigService.getConfig(lk, BasicLinkConfig.class);
331 - event.configClass().equals(BasicLinkConfig.class)) { 346 +
332 - log.info("Detected Link network config event {}", event.type()); 347 + if (!isAllowed(cfg)) {
333 - LinkKey lk = (LinkKey) event.subject(); 348 + log.info("Kicking out links between {} and {}", lk.src(), lk.dst());
334 - BasicLinkConfig cfg = networkConfigService.getConfig(lk, BasicLinkConfig.class); 349 + removeLink(lk.src(), lk.dst());
335 - if (cfg != null && !cfg.isAllowed()) { 350 + removeLink(lk.dst(), lk.src());
336 - log.info("Kicking out links between {} and {}", lk.src(), lk.dst()); 351 + return;
337 - removeLink(lk.src(), lk.dst());
338 - removeLink(lk.dst(), lk.src());
339 - }
340 } 352 }
353 + Link link = getLink(lk.src(), lk.dst());
354 + LinkDescription fldesc;
355 + LinkDescription rldesc;
356 + if (link == null) {
357 + fldesc = BasicLinkOperator.descriptionOf(lk.src(), lk.dst(), cfg);
358 + rldesc = BasicLinkOperator.descriptionOf(lk.dst(), lk.src(), cfg);
359 + } else {
360 + fldesc = BasicLinkOperator.combine(cfg,
361 + BasicLinkOperator.descriptionOf(lk.src(), lk.dst(), link));
362 + rldesc = BasicLinkOperator.combine(cfg,
363 + BasicLinkOperator.descriptionOf(lk.dst(), lk.src(), link));
364 + }
365 + // XXX think of sane way to fetch the LinkProvider
366 + store.createOrUpdateLink(ProviderId.NONE, fldesc);
367 + store.createOrUpdateLink(ProviderId.NONE, rldesc);
341 } 368 }
369 +
342 } 370 }
343 } 371 }
......
...@@ -211,7 +211,10 @@ public class ECLinkStore ...@@ -211,7 +211,10 @@ public class ECLinkStore
211 // otherwise signal the actual master. 211 // otherwise signal the actual master.
212 if (clusterService.getLocalNode().id().equals(dstNodeId)) { 212 if (clusterService.getLocalNode().id().equals(dstNodeId)) {
213 LinkKey linkKey = linkKey(linkDescription.src(), linkDescription.dst()); 213 LinkKey linkKey = linkKey(linkDescription.src(), linkDescription.dst());
214 - Provided<LinkKey> internalLinkKey = new Provided<>(linkKey, providerId); 214 + Provided<LinkKey> internalLinkKey = getProvided(linkKey, providerId);
215 + if (internalLinkKey == null) {
216 + return null;
217 + }
215 linkDescriptions.compute(internalLinkKey, (k, v) -> createOrUpdateLinkInternal(v , linkDescription)); 218 linkDescriptions.compute(internalLinkKey, (k, v) -> createOrUpdateLinkInternal(v , linkDescription));
216 return refreshLinkCache(linkKey); 219 return refreshLinkCache(linkKey);
217 } else { 220 } else {
...@@ -226,6 +229,18 @@ public class ECLinkStore ...@@ -226,6 +229,18 @@ public class ECLinkStore
226 } 229 }
227 } 230 }
228 231
232 + private Provided<LinkKey> getProvided(LinkKey linkKey, ProviderId provId) {
233 + ProviderId bpid = getBaseProviderId(linkKey);
234 + if (provId == null) {
235 + // The LinkService didn't know who this LinkKey belongs to.
236 + // A fix is to either modify the getProvider() in LinkService classes
237 + // or expose the contents of linkDescriptions to the LinkService.
238 + return (bpid == null) ? null : new Provided<>(linkKey, bpid);
239 + } else {
240 + return new Provided<>(linkKey, provId);
241 + }
242 + }
243 +
229 private LinkDescription createOrUpdateLinkInternal(LinkDescription current, LinkDescription updated) { 244 private LinkDescription createOrUpdateLinkInternal(LinkDescription current, LinkDescription updated) {
230 if (current != null) { 245 if (current != null) {
231 // we only allow transition from INDIRECT -> DIRECT 246 // we only allow transition from INDIRECT -> DIRECT
......