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
diff --git a/core/api/src/main/java/org/onosproject/net/config/basics/BasicLinkConfig.java b/core/api/src/main/java/org/onosproject/net/config/basics/BasicLinkConfig.java
index b6068ee..e962110 100644
--- a/core/api/src/main/java/org/onosproject/net/config/basics/BasicLinkConfig.java
+++ b/core/api/src/main/java/org/onosproject/net/config/basics/BasicLinkConfig.java
@@ -17,6 +17,7 @@
import org.onosproject.net.Link;
import org.onosproject.net.LinkKey;
+import com.fasterxml.jackson.databind.JsonNode;
import java.time.Duration;
@@ -28,6 +29,7 @@
public static final String TYPE = "type";
public static final String LATENCY = "latency";
public static final String BANDWIDTH = "bandwidth";
+ public static final String IS_DURABLE = "durable";
/**
* Returns the link type.
@@ -87,4 +89,26 @@
return (BasicLinkConfig) setOrClear(BANDWIDTH, bandwidth);
}
+ /**
+ * Returns if link is durable in the network model or not.
+ *
+ * @return true for durable, false otherwise
+ */
+ public Boolean isDurable() {
+ JsonNode res = object.path(IS_DURABLE);
+ if (res.isMissingNode()) {
+ return null;
+ }
+ return res.asBoolean();
+ }
+
+ /**
+ * Sets durability for this link.
+ *
+ * @param isDurable true for durable, false otherwise
+ * @return this BasicLinkConfig
+ */
+ public BasicLinkConfig isDurable(Boolean isDurable) {
+ return (BasicLinkConfig) setOrClear(IS_DURABLE, isDurable);
+ }
}
diff --git a/core/net/src/main/java/org/onosproject/net/link/impl/BasicLinkOperator.java b/core/net/src/main/java/org/onosproject/net/link/impl/BasicLinkOperator.java
index a6b08f6..801092f 100644
--- a/core/net/src/main/java/org/onosproject/net/link/impl/BasicLinkOperator.java
+++ b/core/net/src/main/java/org/onosproject/net/link/impl/BasicLinkOperator.java
@@ -16,12 +16,14 @@
package org.onosproject.net.link.impl;
import static org.slf4j.LoggerFactory.getLogger;
+import static com.google.common.base.Preconditions.checkNotNull;
import java.time.Duration;
import org.onosproject.net.AnnotationKeys;
import org.onosproject.net.config.ConfigOperator;
import org.onosproject.net.config.basics.BasicLinkConfig;
+import org.onosproject.net.ConnectPoint;
import org.onosproject.net.DefaultAnnotations;
import org.onosproject.net.Link;
import org.onosproject.net.SparseAnnotations;
@@ -81,6 +83,46 @@
if (cfg.bandwidth() != DEF_BANDWIDTH) {
b.set(AnnotationKeys.BANDWIDTH, String.valueOf(cfg.bandwidth()));
}
+ if (cfg.isDurable() != null) {
+ b.set(AnnotationKeys.DURABLE, String.valueOf(cfg.isDurable()));
+ }
return DefaultAnnotations.union(an, b.build());
}
+
+ /**
+ * Generates a link description from a link description entity. The endpoints
+ * must be specified to indicate directionality.
+ *
+ * @param src the source ConnectPoint
+ * @param dst the destination ConnectPoint
+ * @param link the link config entity
+ * @return a linkDescription based on the config
+ */
+ public static LinkDescription descriptionOf(
+ ConnectPoint src, ConnectPoint dst, Link link) {
+ checkNotNull(src, "Must supply a source endpoint");
+ checkNotNull(dst, "Must supply a destination endpoint");
+ checkNotNull(link, "Must supply a link");
+ return new DefaultLinkDescription(
+ src, dst, link.type(), (SparseAnnotations) link.annotations());
+ }
+
+ /**
+ * Generates a link description from a link config entity. This is for
+ * links that cannot be discovered and has to be injected. The endpoints
+ * must be specified to indicate directionality.
+ *
+ * @param src the source ConnectPoint
+ * @param dst the destination ConnectPoint
+ * @param link the link config entity
+ * @return a linkDescription based on the config
+ */
+ public static LinkDescription descriptionOf(
+ ConnectPoint src, ConnectPoint dst, BasicLinkConfig link) {
+ checkNotNull(src, "Must supply a source endpoint");
+ checkNotNull(dst, "Must supply a destination endpoint");
+ checkNotNull(link, "Must supply a link config");
+ return new DefaultLinkDescription(
+ src, dst, link.type(), combine(link, DefaultAnnotations.EMPTY));
+ }
}
diff --git a/core/net/src/main/java/org/onosproject/net/link/impl/LinkManager.java b/core/net/src/main/java/org/onosproject/net/link/impl/LinkManager.java
index 157288a..7bdeb4f 100644
--- a/core/net/src/main/java/org/onosproject/net/link/impl/LinkManager.java
+++ b/core/net/src/main/java/org/onosproject/net/link/impl/LinkManager.java
@@ -18,6 +18,7 @@
import com.google.common.base.Predicate;
import com.google.common.collect.FluentIterable;
import com.google.common.collect.Sets;
+
import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
import org.apache.felix.scr.annotations.Deactivate;
@@ -25,6 +26,7 @@
import org.apache.felix.scr.annotations.ReferenceCardinality;
import org.apache.felix.scr.annotations.Service;
import org.onosproject.net.provider.AbstractListenerProviderRegistry;
+import org.onosproject.net.provider.ProviderId;
import org.onosproject.net.config.NetworkConfigEvent;
import org.onosproject.net.config.NetworkConfigListener;
import org.onosproject.net.config.NetworkConfigService;
@@ -54,7 +56,6 @@
import java.util.Set;
import static com.google.common.base.Preconditions.checkNotNull;
-import static com.google.common.base.Preconditions.checkState;
import static org.onosproject.net.LinkKey.linkKey;
import static org.onosproject.security.AppGuard.checkPermission;
import static org.slf4j.LoggerFactory.getLogger;
@@ -207,6 +208,10 @@
post(store.removeLink(src, dst));
}
+ private boolean isAllowed(BasicLinkConfig cfg) {
+ return (cfg == null || cfg.isAllowed());
+ }
+
// Auxiliary interceptor for device remove events to prune links that
// are associated with the removed device or its port.
private class InternalDeviceListener implements DeviceListener {
@@ -240,11 +245,12 @@
checkNotNull(linkDescription, LINK_DESC_NULL);
checkValidity();
linkDescription = validateLink(linkDescription);
- LinkEvent event = store.createOrUpdateLink(provider().id(),
- linkDescription);
- if (event != null) {
- log.info("Link {} detected", linkDescription);
- post(event);
+ if (linkDescription != null) {
+ LinkEvent event = store.createOrUpdateLink(provider().id(), linkDescription);
+ if (event != null) {
+ log.info("Link {} detected", linkDescription);
+ post(event);
+ }
}
}
@@ -258,11 +264,12 @@
BasicLinkConfig cfgTwo = networkConfigService.getConfig(linkKey(linkDescription.dst(),
linkDescription.src()),
BasicLinkConfig.class);
-
- checkState(cfg == null || cfg.isAllowed(), "Link " + linkDescription.toString() + " is not allowed");
- checkState(cfgTwo == null || cfgTwo.isAllowed(), "Link " + linkDescription.toString() + " is not allowed");
-
- return BasicLinkOperator.combine(cfg, linkDescription);
+ if (isAllowed(cfg) && isAllowed(cfgTwo)) {
+ return BasicLinkOperator.combine(cfg, linkDescription);
+ } else {
+ log.trace("Link " + linkDescription.toString() + " is not allowed");
+ return null;
+ }
}
@Override
@@ -324,20 +331,41 @@
// listens for NetworkConfigEvents of type BasicLinkConfig and removes
// links that the config does not allow
private class InternalNetworkConfigListener implements NetworkConfigListener {
+
+ @Override
+ public boolean isRelevant(NetworkConfigEvent event) {
+ return event.configClass().equals(BasicLinkConfig.class)
+ && (event.type() == NetworkConfigEvent.Type.CONFIG_ADDED
+ || event.type() == NetworkConfigEvent.Type.CONFIG_UPDATED);
+ }
+
@Override
public void event(NetworkConfigEvent event) {
- if ((event.type() == NetworkConfigEvent.Type.CONFIG_ADDED ||
- event.type() == NetworkConfigEvent.Type.CONFIG_UPDATED) &&
- event.configClass().equals(BasicLinkConfig.class)) {
- log.info("Detected Link network config event {}", event.type());
- LinkKey lk = (LinkKey) event.subject();
- BasicLinkConfig cfg = networkConfigService.getConfig(lk, BasicLinkConfig.class);
- if (cfg != null && !cfg.isAllowed()) {
- log.info("Kicking out links between {} and {}", lk.src(), lk.dst());
- removeLink(lk.src(), lk.dst());
- removeLink(lk.dst(), lk.src());
- }
+ LinkKey lk = (LinkKey) event.subject();
+ BasicLinkConfig cfg = networkConfigService.getConfig(lk, BasicLinkConfig.class);
+
+ if (!isAllowed(cfg)) {
+ log.info("Kicking out links between {} and {}", lk.src(), lk.dst());
+ removeLink(lk.src(), lk.dst());
+ removeLink(lk.dst(), lk.src());
+ return;
}
+ Link link = getLink(lk.src(), lk.dst());
+ LinkDescription fldesc;
+ LinkDescription rldesc;
+ if (link == null) {
+ fldesc = BasicLinkOperator.descriptionOf(lk.src(), lk.dst(), cfg);
+ rldesc = BasicLinkOperator.descriptionOf(lk.dst(), lk.src(), cfg);
+ } else {
+ fldesc = BasicLinkOperator.combine(cfg,
+ BasicLinkOperator.descriptionOf(lk.src(), lk.dst(), link));
+ rldesc = BasicLinkOperator.combine(cfg,
+ BasicLinkOperator.descriptionOf(lk.dst(), lk.src(), link));
+ }
+ // XXX think of sane way to fetch the LinkProvider
+ store.createOrUpdateLink(ProviderId.NONE, fldesc);
+ store.createOrUpdateLink(ProviderId.NONE, rldesc);
}
+
}
}
diff --git a/core/store/dist/src/main/java/org/onosproject/store/link/impl/ECLinkStore.java b/core/store/dist/src/main/java/org/onosproject/store/link/impl/ECLinkStore.java
index 4577086..243caf8 100644
--- a/core/store/dist/src/main/java/org/onosproject/store/link/impl/ECLinkStore.java
+++ b/core/store/dist/src/main/java/org/onosproject/store/link/impl/ECLinkStore.java
@@ -211,7 +211,10 @@
// otherwise signal the actual master.
if (clusterService.getLocalNode().id().equals(dstNodeId)) {
LinkKey linkKey = linkKey(linkDescription.src(), linkDescription.dst());
- Provided<LinkKey> internalLinkKey = new Provided<>(linkKey, providerId);
+ Provided<LinkKey> internalLinkKey = getProvided(linkKey, providerId);
+ if (internalLinkKey == null) {
+ return null;
+ }
linkDescriptions.compute(internalLinkKey, (k, v) -> createOrUpdateLinkInternal(v , linkDescription));
return refreshLinkCache(linkKey);
} else {
@@ -226,6 +229,18 @@
}
}
+ private Provided<LinkKey> getProvided(LinkKey linkKey, ProviderId provId) {
+ ProviderId bpid = getBaseProviderId(linkKey);
+ if (provId == null) {
+ // The LinkService didn't know who this LinkKey belongs to.
+ // A fix is to either modify the getProvider() in LinkService classes
+ // or expose the contents of linkDescriptions to the LinkService.
+ return (bpid == null) ? null : new Provided<>(linkKey, bpid);
+ } else {
+ return new Provided<>(linkKey, provId);
+ }
+ }
+
private LinkDescription createOrUpdateLinkInternal(LinkDescription current, LinkDescription updated) {
if (current != null) {
// we only allow transition from INDIRECT -> DIRECT