[ONOS-5283] Arbitrary connect points, support multiple vlans
Change-Id: I9bd3536c08dfd8a637293460395de7e2a1dc1dc1
diff --git a/apps/vpls/src/main/java/org/onosproject/vpls/IntentInstaller.java b/apps/vpls/src/main/java/org/onosproject/vpls/IntentInstaller.java
index 79ed713..52a3924 100644
--- a/apps/vpls/src/main/java/org/onosproject/vpls/IntentInstaller.java
+++ b/apps/vpls/src/main/java/org/onosproject/vpls/IntentInstaller.java
@@ -15,18 +15,18 @@
*/
package org.onosproject.vpls;
-import com.google.common.collect.SetMultimap;
-import org.apache.commons.lang3.tuple.Pair;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Lists;
import org.onlab.packet.MacAddress;
-import org.onlab.packet.VlanId;
import org.onosproject.core.ApplicationId;
import org.onosproject.net.ConnectPoint;
+import org.onosproject.net.FilteredConnectPoint;
+import org.onosproject.net.Host;
import org.onosproject.net.flow.DefaultTrafficSelector;
-import org.onosproject.net.flow.DefaultTrafficTreatment;
import org.onosproject.net.flow.TrafficSelector;
-import org.onosproject.net.flow.TrafficTreatment;
import org.onosproject.net.intent.Intent;
import org.onosproject.net.intent.IntentService;
+import org.onosproject.net.intent.IntentState;
import org.onosproject.net.intent.Key;
import org.onosproject.net.intent.MultiPointToSinglePointIntent;
import org.onosproject.net.intent.SinglePointToMultiPointIntent;
@@ -34,24 +34,37 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Set;
-import java.util.stream.Collectors;
/**
* Synchronizes intents between the in-memory intent store and the
* IntentService.
*/
public class IntentInstaller {
+ private static final String SUBMIT =
+ "Submitting intents to the Intent Synchronizer";
+ private static final String WITHDRAW =
+ "Withdrawing intents to the Intent Synchronizer";
+ private static final String SP2MP =
+ "Building sp2mp intent from {}";
+ private static final String MP2SP =
+ "Building mp2sp intent to {}";
+
private static final Logger log = LoggerFactory.getLogger(
IntentInstaller.class);
private static final int PRIORITY_OFFSET = 1000;
- private static final String PREFIX_BROADCAST = "brc";
- private static final String PREFIX_UNICAST = "uni";
+ private static final Set<IntentState> WITHDRAWN_INTENT_STATES =
+ ImmutableSet.of(IntentState.WITHDRAWN,
+ IntentState.WITHDRAW_REQ,
+ IntentState.WITHDRAWING);
+
+ static final String PREFIX_BROADCAST = "brc";
+ static final String PREFIX_UNICAST = "uni";
+ static final String DASH = "-";
private final ApplicationId appId;
private final IntentSynchronizationService intentSynchronizer;
@@ -72,173 +85,150 @@
}
/**
- * Formats the requests for creating and submit intents.
- * Single Points to Multi Point intents are created for all the configured
- * Connect Points. Multi Point to Single Point intents are created for
- * Connect Points configured that have hosts attached.
- *
- * @param confHostPresentCPoint A map of Connect Points with the eventual
- * MAC address of the host attached, by VLAN
- */
- protected void installIntents(SetMultimap<VlanId,
- Pair<ConnectPoint,
- MacAddress>> confHostPresentCPoint) {
- List<Intent> intents = new ArrayList<>();
-
- confHostPresentCPoint.keySet()
- .stream()
- .filter(vlanId -> confHostPresentCPoint.get(vlanId) != null)
- .forEach(vlanId -> {
- Set<Pair<ConnectPoint, MacAddress>> cPoints =
- confHostPresentCPoint.get(vlanId);
- cPoints.forEach(cPoint -> {
- MacAddress mac = cPoint.getValue();
- ConnectPoint src = cPoint.getKey();
- Set<ConnectPoint> dsts = cPoints.stream()
- .map(Pair::getKey)
- .filter(cp -> !cp.equals(src))
- .collect(Collectors.toSet());
- Key brcKey = buildKey(PREFIX_BROADCAST, src, vlanId);
-
- if (dsts.isEmpty()) {
- return;
- }
-
- intents.add(buildBrcIntent(brcKey, src, dsts, vlanId));
-
- if (mac != null && countMacInCPoints(cPoints) > 1) {
- Key uniKey = buildKey(PREFIX_UNICAST, src, vlanId);
- MultiPointToSinglePointIntent uniIntent =
- buildUniIntent(uniKey,
- dsts,
- src,
- vlanId,
- mac);
- intents.add(uniIntent);
- }
- });
- });
- submitIntents(intents);
- }
-
- /**
* Requests to install the intents passed as argument to the Intent Service.
*
* @param intents intents to be submitted
*/
- private void submitIntents(Collection<Intent> intents) {
- log.debug("Submitting intents to the Intent Synchronizer");
- intents.forEach(intent -> {
- intentSynchronizer.submit(intent);
- });
+ protected void submitIntents(Collection<Intent> intents) {
+ log.debug(SUBMIT);
+ intents.forEach(intentSynchronizer::submit);
}
/**
- * Builds a Single Point to Multi Point intent.
+ * Requests to withdraw the intents passed as argument to the Intent Service.
*
- * @param src The source Connect Point
- * @param dsts The destination Connect Points
- * @return Single Point to Multi Point intent generated.
+ * @param intents intents to be withdraw
*/
- private SinglePointToMultiPointIntent buildBrcIntent(Key key,
- ConnectPoint src,
- Set<ConnectPoint> dsts,
- VlanId vlanId) {
- log.debug("Building p2mp intent from {}", src);
+ protected void withdrawIntents(Collection<Intent> intents) {
+ log.debug(WITHDRAW);
+ intents.forEach(intentSynchronizer::withdraw);
+ }
+
+ /**
+ * Returns list of intents belongs to a VPLS.
+ *
+ * @param name required VPLS network name
+ * @return list of intents belongs to a VPLS
+ */
+ protected List<Intent> getIntentsFromVpls(String name) {
+ List<Intent> intents = Lists.newArrayList();
+
+ intentService.getIntents().forEach(intent -> {
+ if (intent.key().toString().startsWith(name)) {
+ intents.add(intent);
+ }
+ });
+
+ return intents;
+ }
+
+ /**
+ * Builds a broadcast intent.
+ *
+ * @param key key to identify the intent
+ * @param src the source connect point
+ * @param dsts the destination connect points
+ * @return the generated single-point to multi-point intent
+ */
+ protected SinglePointToMultiPointIntent buildBrcIntent(Key key,
+ FilteredConnectPoint src,
+ Set<FilteredConnectPoint> dsts) {
+ log.debug(SP2MP, src);
SinglePointToMultiPointIntent intent;
- TrafficTreatment treatment = DefaultTrafficTreatment.emptyTreatment();
-
- TrafficSelector.Builder builder = DefaultTrafficSelector.builder()
+ TrafficSelector selector = DefaultTrafficSelector.builder()
.matchEthDst(MacAddress.BROADCAST)
- .matchVlanId(vlanId);
-
- TrafficSelector selector = builder.build();
+ .build();
intent = SinglePointToMultiPointIntent.builder()
.appId(appId)
.key(key)
.selector(selector)
- .treatment(treatment)
- .ingressPoint(src)
- .egressPoints(dsts)
+ .filteredIngressPoint(src)
+ .filteredEgressPoints(dsts)
.priority(PRIORITY_OFFSET)
.build();
return intent;
}
/**
- * Builds a Multi Point to Single Point intent.
+ * Builds a unicast intent.
*
- * @param srcs The source Connect Points
- * @param dst The destination Connect Point
- * @return Multi Point to Single Point intent generated.
+ * @param key key to identify the intent
+ * @param srcs the source Connect Points
+ * @param dst the destination Connect Point
+ * @param host destination Host
+ * @return the generated multi-point to single-point intent
*/
- private MultiPointToSinglePointIntent buildUniIntent(Key key,
- Set<ConnectPoint> srcs,
- ConnectPoint dst,
- VlanId vlanId,
- MacAddress mac) {
- log.debug("Building mp2p intent to {}", dst);
+ protected MultiPointToSinglePointIntent buildUniIntent(Key key,
+ Set<FilteredConnectPoint> srcs,
+ FilteredConnectPoint dst,
+ Host host) {
+ log.debug(MP2SP, dst);
- MultiPointToSinglePointIntent intent;
+ TrafficSelector selector = DefaultTrafficSelector.builder()
+ .matchEthDst(host.mac())
+ .build();
- TrafficTreatment treatment = DefaultTrafficTreatment.emptyTreatment();
- TrafficSelector.Builder builder = DefaultTrafficSelector.builder()
- .matchEthDst(mac)
- .matchVlanId(vlanId);
-
- TrafficSelector selector = builder.build();
-
- intent = MultiPointToSinglePointIntent.builder()
+ return MultiPointToSinglePointIntent.builder()
.appId(appId)
.key(key)
.selector(selector)
- .treatment(treatment)
- .ingressPoints(srcs)
- .egressPoint(dst)
+ .filteredIngressPoints(srcs)
+ .filteredEgressPoint(dst)
.priority(PRIORITY_OFFSET)
.build();
- return intent;
+
}
/**
- * Builds an intent Key for either for a Single Point to Multi Point or
- * Multi Point to Single Point intent, based on a prefix that defines
+ * Builds an intent Key for either for a single-point to multi-point or
+ * multi-point to single-point intent, based on a prefix that defines
* the type of intent, the single connection point representing the source
- * or the destination and the vlan id representing the network.
+ * or the destination and the VLAN identifier representing the network.
*
- * @param cPoint the source or destination connect point
- * @param vlanId the network vlan id
- * @param prefix prefix string
- * @return
+ * @param prefix key prefix
+ * @param cPoint connect point for single source/destination
+ * @param networkName VPLS network name
+ * @param hostMac source/destination mac address
+ * @return key to identify the intent
*/
- private Key buildKey(String prefix, ConnectPoint cPoint, VlanId vlanId) {
- String keyString = new StringBuilder()
- .append(prefix)
- .append("-")
- .append(cPoint.deviceId())
- .append("-")
- .append(cPoint.port())
- .append("-")
- .append(vlanId)
- .toString();
+ protected Key buildKey(String prefix,
+ ConnectPoint cPoint,
+ String networkName,
+ MacAddress hostMac) {
+ String keyString = networkName +
+ DASH +
+ prefix +
+ DASH +
+ cPoint.deviceId() +
+ DASH +
+ cPoint.port() +
+ DASH +
+ hostMac;
return Key.of(keyString, appId);
}
/**
- * Counts the number of mac addresses associated to a specific list of
- * ConnectPoint.
+ * Returns true if the specified intent exists; false otherwise.
*
- * @param cPoints Set of ConnectPoints, eventually bound to the MAC of the
- * host attached
- * @return number of mac addresses found.
+ * @param intentKey intent key
+ * @return true if the intent exists, false otherwise
*/
- private int countMacInCPoints(Set<Pair<ConnectPoint, MacAddress>> cPoints) {
- return (int) cPoints.stream().filter(p -> p.getValue() != null).count();
- }
+ protected boolean intentExists(Key intentKey) {
+ if (intentService.getIntent(intentKey) == null) {
+ return false;
+ }
+ // Intent does not exist if intent withdrawn
+ IntentState currentIntentState = intentService.getIntentState(intentKey);
+ if (WITHDRAWN_INTENT_STATES.contains(currentIntentState)) {
+ return false;
+ }
+
+ return true;
+ }
}