Introduces Virtual Circuit functionality for SDX-L2
Changes:
- Implements commands: sdxl2vc, sdxl2vc-add, sdxl2vc-list, sdxl2vc-remove
- Custom exceptions handled at the VC manager
- Updated README
- Updated unit tests
- Grouped some documentation and code
- Reduced checkstyle warnings
Change-Id: I4cb211dcfd1f3517f4e594c1cc1c816f9c3cdbe3
diff --git a/sdx-l2/src/main/java/org/onosproject/sdxl2/SdxL2ConnectionPoint.java b/sdx-l2/src/main/java/org/onosproject/sdxl2/SdxL2ConnectionPoint.java
index f5f6849..e1075df 100644
--- a/sdx-l2/src/main/java/org/onosproject/sdxl2/SdxL2ConnectionPoint.java
+++ b/sdx-l2/src/main/java/org/onosproject/sdxl2/SdxL2ConnectionPoint.java
@@ -24,22 +24,25 @@
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
import static com.google.common.base.Preconditions.*;
/**
- * SDX-L2 connection point expressed as composition of a:
- * connect point; set of VLAN id; MAC address (optional).
+ * SDX-L2 Connection Point expressed as composition of a:
+ * Connect Point; set of VLAN ids; MAC address (optional).
*/
public class SdxL2ConnectionPoint {
- private String name;
+ private static final String ERROR_INVALID_VLAN = "Provide VLAN with at least value '-1' or '1'";
private final ConnectPoint cPoint;
private final List<VlanId> vlanIds;
private final MacAddress ceMac;
+ private String name;
/**
- * Creates a new SDX-L2 connection point.
+ * Creates a new SDX-L2 Connection Point.
*
* @param name SDX-L2 connection point name
* @param cPoint connect point
@@ -54,18 +57,151 @@
}
/**
- * Returns the name of SDX-L2 connection point.
+ * Parses a device Connection Point from a string, set of VLANs
+ * from a string and MAC from a string.
+ * The connect point should be in the format "deviceUri/portNumber".
+ * The vlans should be in the format "vlan1,vlan2,vlan3"
+ * The mac address should be in hex
*
- * @return a string representing the name of connection point
+ * @param name name of the SDX-L2 Connection Point
+ * @param connectPoint Connection Point to parse
+ * @param vlans VLAN IDs to parse
+ * @param mac MAC address to parse
+ * @return a Connection Point based on the information in the string
+ *
+ */
+ public static SdxL2ConnectionPoint sdxl2ConnectionPoint(
+ String name, String connectPoint, String vlans, String mac) {
+ checkNotNull(connectPoint);
+ enforceNameFormat(name);
+ ConnectPoint connectionPoint = ConnectPoint.deviceConnectPoint(connectPoint);
+ List<VlanId> vlansList = enforceVlans(vlans);
+ MacAddress macAddress = MacAddress.ZERO;
+ if (mac != null) {
+ macAddress = MacAddress.valueOf(mac);
+ }
+ return new SdxL2ConnectionPoint(name, connectionPoint, vlansList, macAddress);
+ }
+
+ /**
+ * Parses a device Connection Point from a string and set of
+ * VLANs from a string.
+ * The Connection Point should be in the format "deviceUri/portNumber".
+ * The VLANs should be in the format "vlan1,vlan2,vlan3"
+ *
+ * @param name name of the SDX-L2 CP
+ * @param connectPoint Connection Point to parse
+ * @param vlans VLAN IDs to parse
+ * @return a Connection Point based on the information in the string
+ *
+ */
+ public static SdxL2ConnectionPoint sdxl2ConnectionPoint(
+ String name, String connectPoint, String vlans) {
+ return sdxl2ConnectionPoint(name, connectPoint, vlans, null);
+ }
+
+ /**
+ * Enforces proper format on the name of the Connection Point.
+ *
+ * @param name name of the SDX-L2 Connection Point
+ */
+ private static void enforceNameFormat(String name) {
+ checkState(!(name.contains(",") ||
+ name.contains("-") ||
+ name.contains("vlanid=") ||
+ name.contains("ConnectPoint{") ||
+ name.contains("elementId=") ||
+ name.contains("portNumber=") ||
+ name.contains("{") ||
+ name.contains("}") ||
+ name.contains("|")), "Names cannot contain some special characters");
+ }
+
+ /**
+ * Enforces proper format on the requested VLANs.
+ *
+ * @param vlans VLANs expressed explicitly, as a range or in combination
+ * @return a list of VLANs to be added
+ */
+ private static List<VlanId> enforceVlans(String vlans) {
+ String[] splitted = parseVlans(vlans);
+ List<VlanId> vlansList = new ArrayList<>();
+ for (String vlan : splitted) {
+ short vlanNumber = Short.parseShort(vlan);
+ if (!vlansList.contains(VlanId.vlanId(vlanNumber)) &&
+ Short.parseShort(vlan) != -1 &&
+ Short.parseShort(vlan) != 1 &&
+ Short.parseShort(vlan) >= 0 &&
+ Short.parseShort(vlan) != 4095) {
+ vlansList.add(VlanId.vlanId(vlanNumber));
+ }
+ }
+ return vlansList;
+ }
+
+ /**
+ * Parses the VLANs requested by the user.
+ *
+ * @param vlans VLANs expressed explicitly, as a range or in combination
+ * @return an array of VLANs to add
+ */
+ private static String[] parseVlans(String vlans) {
+ if (vlans == null) {
+ vlans = "-1";
+ }
+ ArrayList<String> vlanRange = new ArrayList<String>();
+ String[] splittedVlans;
+ String commaSeparator = ",";
+ if (vlans.contains(commaSeparator)) {
+ splittedVlans = vlans.split(commaSeparator);
+ for (String vlan : splittedVlans) {
+ vlanRange.addAll(generateNumberRange(vlan));
+ }
+ } else {
+ vlanRange.addAll(generateNumberRange(vlans));
+ }
+ splittedVlans = new String[vlanRange.size()];
+ splittedVlans = vlanRange.toArray(splittedVlans);
+ return splittedVlans;
+ }
+
+ /**
+ * Generates a range of numbers, given a string of type "X-Y" ("%d-%d").
+ *
+ * @param range range of numbers to compute
+ * @return a list with numbers between "X" and "Y" (inclusive)
+ */
+ private static ArrayList<String> generateNumberRange(String range) {
+ ArrayList<String> parsedNumbers = new ArrayList<String>();
+ Pattern p = Pattern.compile("(\\d+)-(\\d+)");
+ Matcher m = p.matcher(range);
+ if (m.matches()) {
+ int start = Integer.parseInt(m.group(1));
+ int end = Integer.parseInt(m.group(2));
+ int min = Math.min(start, end);
+ int max = Math.max(start, end);
+ for (int v = min; v <= max; v++) {
+ parsedNumbers.add(Integer.toString(v));
+ }
+ } else {
+ parsedNumbers.add(range);
+ }
+ return parsedNumbers;
+ }
+
+ /**
+ * Returns the name of SDX-L2 Connection Point.
+ *
+ * @return a string representing the name of Connection Point
*/
public String name() {
return name;
}
/**
- * Returns the connect point.
+ * Returns the Connection Point.
*
- * @return connect point object
+ * @return Connection Point object
*/
public ConnectPoint connectPoint() {
return cPoint;
@@ -89,87 +225,6 @@
return ceMac;
}
- /**
- * Parse a device connect point from a string, set of VLANs from a string
- * and MAC from a string.
- * The connect point should be in the format "deviceUri/portNumber".
- * The VLANs should be in the format "vlan1,vlan2,vlan3"
- * The MAC address should be in hex
- *
- * @param name name of the SDX-L2 connection point
- * @param connectPoint connect point to parse
- * @param vlans VLAN ids to parse
- * @param mac MAC address to parse
- * @return a SDX-L2 connection point based on the information in the string.
- *
- */
- public static SdxL2ConnectionPoint
- sdxl2ConnectionPoint(String name, String connectPoint, String vlans, String mac) {
- checkNotNull(connectPoint);
- checkNotNull(vlans);
- checkState(!(name.contains(",") ||
- name.contains("-") ||
- name.contains("vlanid=") ||
- name.contains("ConnectPoint{") ||
- name.contains("elementId=") ||
- name.contains("portNumber=") ||
- name.contains("{") ||
- name.contains("}") ||
- name.contains("|")), "Names cannot contain some special characters");
- checkNotNull(mac);
- ConnectPoint connectionPoint = ConnectPoint.deviceConnectPoint(connectPoint);
- String[] splitted = vlans.split(",");
- checkArgument(splitted.length != 0, "At least '-1' or '1' as value");
- List<VlanId> vlanslist = new ArrayList<>();
- for (String vlan : splitted) {
- if (!vlanslist.contains(VlanId.vlanId(Short.parseShort(vlan))) &&
- Short.parseShort(vlan) != -1 &&
- Short.parseShort(vlan) != 1) {
- vlanslist.add(VlanId.vlanId(Short.parseShort(vlan)));
- }
- }
- MacAddress macAddress = MacAddress.valueOf(mac);
- return new SdxL2ConnectionPoint(name, connectionPoint, vlanslist, macAddress);
- }
-
- /**
- * Parse a device connect point from a string and set of VLANs from a string.
- * The connect point should be in the format "deviceUri/portNumber".
- * The VLANs should be in the format "vlan1,vlan2,vlan3"
- *
- * @param name name of the SDX-L2 connection point
- * @param connectPoint connect point to parse
- * @param vlans VLAN ids to parse
- * @return a SDX-L2 connection point based on the information in the string.
- *
- */
- public static SdxL2ConnectionPoint sdxl2ConnectionPoint(String name, String connectPoint, String vlans) {
- checkNotNull(connectPoint);
- checkNotNull(vlans);
- checkState(!(name.contains(",") ||
- name.contains("-") ||
- name.contains("vlanid=") ||
- name.contains("ConnectPoint{") ||
- name.contains("elementId=") ||
- name.contains("portNumber=") ||
- name.contains("{") ||
- name.contains("}") ||
- name.contains("|")), "Names cannot contain some special characters");
- ConnectPoint connectionPoint = ConnectPoint.deviceConnectPoint(connectPoint);
- String[] splitted = vlans.split(",");
- checkArgument(splitted.length != 0, "At least '-1' or '1' as value");
- List<VlanId> vlanslist = new ArrayList<>();
- for (String vlan : splitted) {
- if (!vlanslist.contains(VlanId.vlanId(Short.parseShort(vlan))) &&
- Short.parseShort(vlan) != -1 &&
- Short.parseShort(vlan) != 1) {
- vlanslist.add(VlanId.vlanId(Short.parseShort(vlan)));
- }
- }
- MacAddress macAddress = MacAddress.ZERO;
- return new SdxL2ConnectionPoint(name, connectionPoint, vlanslist, macAddress);
- }
-
@Override
public int hashCode() {
return Objects.hash(name, cPoint, vlanIds, ceMac);
diff --git a/sdx-l2/src/main/java/org/onosproject/sdxl2/SdxL2DistributedStore.java b/sdx-l2/src/main/java/org/onosproject/sdxl2/SdxL2DistributedStore.java
index 02ea103..a3ada37 100644
--- a/sdx-l2/src/main/java/org/onosproject/sdxl2/SdxL2DistributedStore.java
+++ b/sdx-l2/src/main/java/org/onosproject/sdxl2/SdxL2DistributedStore.java
@@ -18,12 +18,12 @@
import com.google.common.collect.ImmutableSet;
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;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.ReferenceCardinality;
import org.apache.felix.scr.annotations.Service;
-import org.apache.felix.scr.annotations.Activate;
-import org.apache.felix.scr.annotations.Deactivate;
import org.onlab.packet.VlanId;
import org.onlab.util.KryoNamespace;
import org.onosproject.store.primitives.DefaultDistributedSet;
@@ -35,14 +35,15 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
-import java.util.Iterator;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;
+import static java.lang.String.format;
/**
* SDX-L2 Store implementation backed by different distributed primitives.
@@ -61,12 +62,18 @@
private Map<SdxL2ConnectionPoint, String> sdxL2CPs;
private ConsistentMap<SdxL2ConnectionPoint, String> sdxL2cps;
+ private Map<String, String> sdxL2VCs;
+ private ConsistentMap<String, String> sdxL2vcs;
+
private static String errorAddSdx = "It is not possible to add %s " +
"because it exists";
private static String errorRemoveSdx = "It is not possible to remove %s " +
"because it does not exist";
+ /*
+ Error definitions for CPs.
+ */
private static String errorAddSdxL2CPName = "It is not possible to add %s " +
"because there is a sdxl2cp with the same name";
private static String errorAddSdxL2CPVlans = "It is not possible to add %s " +
@@ -74,25 +81,31 @@
private static String errorAddSdxL2CPCP = "It is not possible to add %s " +
"because there is a conflict with %s on the connection point";
private static String errorAddSdxL2CPSdx = "It is not possible to add %s " +
- "because the relative sdxl2 does not exist";
+ "because the relative sdxl2 %s does not exist";
+ private static String errorGetSdxL2CP = "It is not possible to retrieve %s " +
+ "because it does not exist";
private static String errorGetSdxL2CPs = "It is not possible to list the sdxl2cps " +
"because sdxl2 %s does not exist";
private static String errorRemoveSdxL2CP = "It is not possible to remove %s " +
"because it does not exist";
- private static String errorGetSdxL2CP = "It is not possible to retrieve %s " +
- "because it does not exist";
+ /*
+ Error definitions for VCs.
+ */
+ private static String errorVCKey = "It is not possible to add vc because " +
+ "there is a problem with key %s (wrong format)";
+ private static String errorAddVCOverlap = "It is not possible to add vc " +
+ "because there is an overlap with %s";
+ private static String errorRemoveVC = "It is not possible to remove the " +
+ "vc because it does not exist";
+ private static String errorRemoveVCAux = "Virtual Circuit between %s and %s " +
+ "does not exist";
- public void initForTest() {
-
- this.sdxL2s = Sets.newHashSet();
-
- this.sdxL2CPs = new ConcurrentHashMap<SdxL2ConnectionPoint, String>();
-
- }
-
+ /**
+ * Activates the implementation of the SDX-L2 store.
+ */
@Activate
public void activate() {
@@ -103,10 +116,10 @@
.build();
sdxL2s = new DefaultDistributedSet<>(this.storageService
- .<String>setBuilder()
- .withSerializer(Serializer.using(custom))
- .withName("sdxl2s")
- .build(), DistributedPrimitive.DEFAULT_OPERTATION_TIMEOUT_MILLIS);
+ .<String>setBuilder()
+ .withSerializer(Serializer.using(custom))
+ .withName("sdxl2s")
+ .build(), DistributedPrimitive.DEFAULT_OPERTATION_TIMEOUT_MILLIS);
sdxL2cps = this.storageService
.<SdxL2ConnectionPoint, String>consistentMapBuilder()
@@ -115,20 +128,32 @@
.build();
sdxL2CPs = sdxL2cps.asJavaMap();
+ sdxL2vcs = this.storageService.<String, String>consistentMapBuilder()
+ .withSerializer(Serializer.using(custom))
+ .withName("vcs")
+ .build();
+ sdxL2VCs = sdxL2vcs.asJavaMap();
+
log.info("Started");
}
+ /**
+ * Helper class called to initialise tests.
+ */
+ public void initForTest() {
+ this.sdxL2s = Sets.newHashSet();
+ this.sdxL2CPs = new ConcurrentHashMap<SdxL2ConnectionPoint, String>();
+ this.sdxL2VCs = new ConcurrentHashMap<String, String>();
+ }
+
+ /**
+ * Deactivates the implementation of the SDX-L2 store.
+ */
@Deactivate
public void deactivate() {
log.info("Stopped");
}
- /**
- * Creates a named SDX-L2.
- *
- * @param sdxl2 SDX-L2 name
- * @throws SdxL2Exception if SDX-L2 exists
- */
@Override
public void putSdxL2(String sdxl2) throws SdxL2Exception {
boolean inserted = sdxL2s.add(sdxl2);
@@ -137,12 +162,6 @@
}
}
- /**
- * Removes a named SDX-L2.
- *
- * @param sdxl2 SDX-L2 name
- * @throws SdxL2Exception if SDX-L2 does not exist
- */
@Override
public void removeSdxL2(String sdxl2) throws SdxL2Exception {
boolean removed = sdxL2s.remove(sdxl2);
@@ -158,35 +177,22 @@
toRemove.forEach(key_value -> sdxL2CPs.remove(key_value.getKey()));
}
- /**
- * Returns a set of SDX-L2 names.
- *
- * @return a set of SDX-L2 names
- */
@Override
public Set<String> getSdxL2s() {
return ImmutableSet.copyOf(sdxL2s);
}
- /**
- * Adds an SDX-L2 connection point to an SDX-L2.
- *
- * @param sdxl2 SDX-L2 name
- * @param connectionPoint the connection point object
- * @throws SdxL2Exception if it is not possible to add the SDX-L2 connection point
- */
@Override
public void addSdxL2ConnectionPoint(String sdxl2, SdxL2ConnectionPoint connectionPoint) throws SdxL2Exception {
-
boolean exist = sdxL2s.contains(sdxl2);
-
+ String errorMissingSdxL2 = String.format(errorAddSdxL2CPSdx, connectionPoint.name(), sdxl2);
if (!exist) {
- throw new SdxL2Exception(String.format(errorAddSdxL2CPSdx, connectionPoint.name()));
+ throw new SdxL2Exception(errorMissingSdxL2);
}
Set<SdxL2ConnectionPoint> sdxl2cpsTemp = ImmutableSet.copyOf(sdxL2CPs.keySet());
Set<SdxL2ConnectionPoint> sdxl2cpsTempByName = sdxl2cpsTemp.parallelStream().filter(
- sdxl2cpTemp-> sdxl2cpTemp.name().equals(connectionPoint.name()
+ sdxl2cpTemp -> sdxl2cpTemp.name().equals(connectionPoint.name()
)
).collect(Collectors.toSet());
@@ -194,9 +200,8 @@
throw new SdxL2Exception(String.format(errorAddSdxL2CPName, connectionPoint.name()));
}
-
Set<SdxL2ConnectionPoint> sdxl2cpsByCP = sdxl2cpsTemp.parallelStream().filter(
- sdxl2cp_temp-> sdxl2cp_temp.connectPoint().equals(connectionPoint.connectPoint()
+ sdxl2cpTemp -> sdxl2cpTemp.connectPoint().equals(connectionPoint.connectPoint()
)
).collect(Collectors.toSet());
@@ -208,7 +213,7 @@
sdxl2cp_by_vlan.vlanIds().contains(vlanId) || sdxl2cp_by_vlan.vlanIds().size() == 0
)).collect(Collectors.toSet());
- tempName = sdxl2cpsByVlan.iterator().hasNext() ? sdxl2cpsByVlan.iterator().next().name() : null;
+ tempName = sdxl2cpsByVlan.iterator().hasNext() ? sdxl2cpsByVlan.iterator().next().name() : null;
if (sdxl2cpsByVlan.size() != 0) {
throw new SdxL2Exception(String.format(errorAddSdxL2CPVlans, connectionPoint.name(), tempName));
@@ -216,24 +221,14 @@
}
- tempName = sdxl2cpsByCP.iterator().hasNext() ? sdxl2cpsByCP.iterator().next().name() : null;
-
+ tempName = sdxl2cpsByCP.iterator().hasNext() ? sdxl2cpsByCP.iterator().next().name() : null;
if (sdxl2cpsByCP.size() != 0 && vlans.size() == 0) {
throw new SdxL2Exception(String.format(errorAddSdxL2CPCP, connectionPoint.name(), tempName));
}
sdxL2CPs.put(connectionPoint, sdxl2);
-
}
- /**
- * Returns all the SDX-L2 connection points names or the SDX-L2 2connection points names
- * that are related to an SDX-L2.
- *
- * @param sdxl2 name (optional) of the SDX-L2
- * @return a set of SDX-L2 connection points names, the result depends on the input parameter;
- * @throws SdxL2Exception if SDX-L2 is present but it does not exist
- */
@Override
public Set<String> getSdxL2ConnectionPoints(Optional<String> sdxl2) throws SdxL2Exception {
@@ -270,12 +265,6 @@
}
- /**
- * Removes a named SDX-L2 connection point in an SDX-L2.
- *
- * @param sdxl2cp the connection point name
- * @throws SdxL2Exception if SDX-L2 connection point does not exist
- */
@Override
public void removeSdxL2ConnectionPoint(String sdxl2cp) throws SdxL2Exception {
@@ -295,13 +284,6 @@
}
- /**
- * Returns an SDX-L2 connection point in a SDX-L2.
- *
- * @param sdxl2cp the connection point name
- * @return the relative SDXL2ConnectionPoint object
- * @throws SdxL2Exception if SDX-L2 connection point does not exist
- */
@Override
public SdxL2ConnectionPoint getSdxL2ConnectionPoint(String sdxl2cp) throws SdxL2Exception {
SdxL2ConnectionPoint sdxl2cpTemp = ImmutableSet.copyOf(sdxL2CPs.keySet()).parallelStream()
@@ -314,4 +296,108 @@
return sdxl2cpTemp;
}
+ @Override
+ public void addVC(String sdxl2, SdxL2ConnectionPoint sdxl2cplhs, SdxL2ConnectionPoint sdxl2cprhs)
+ throws SdxL2Exception {
+ Set<String> vcs = ImmutableSet.copyOf(
+ sdxL2VCs.keySet().parallelStream().filter((vctemp->vctemp.contains(sdxl2cplhs.toString())
+ || vctemp.contains(sdxl2cprhs.toString()))).collect(Collectors.toSet()));
+ for (String vctemp : vcs) {
+ String[] splitted = vctemp.split("~");
+
+ if (splitted.length != 2) {
+ throw new SdxL2Exception(String.format(errorVCKey, "add", vctemp));
+ }
+
+ if (!(!sdxl2cplhs.toString().equals(splitted[0]) &&
+ !sdxl2cplhs.toString().equals(splitted[1]) &&
+ !sdxl2cprhs.toString().equals(splitted[0]) &&
+ !sdxl2cprhs.toString().equals(splitted[1]))) {
+ throw new SdxL2Exception(String.format(errorAddVCOverlap, vctemp));
+ }
+ }
+
+ String cps = sdxl2cplhs.toString().compareTo(sdxl2cprhs.toString()) < 0 ?
+ format(SdxL2VCManager.SDXL2_CPS_FORMAT, sdxl2cplhs, sdxl2cprhs) :
+ format(SdxL2VCManager.SDXL2_CPS_FORMAT, sdxl2cprhs, sdxl2cplhs);
+ String name = sdxl2cplhs.name().compareTo(sdxl2cprhs.name().toString()) < 0 ?
+ format(SdxL2VCManager.NAME_FORMAT, sdxl2, sdxl2cplhs.name(), sdxl2cprhs.name()) :
+ format(SdxL2VCManager.NAME_FORMAT, sdxl2, sdxl2cprhs.name(), sdxl2cplhs.name());
+ sdxL2VCs.put(cps, name);
+ }
+
+ @Override
+ public void removeVC(SdxL2ConnectionPoint sdxl2cplhs, SdxL2ConnectionPoint sdxl2cprhs)
+ throws SdxL2Exception {
+
+ String cps = sdxl2cplhs.toString().compareTo(sdxl2cprhs.toString()) < 0 ?
+ format(SdxL2VCManager.SDXL2_CPS_FORMAT, sdxl2cplhs, sdxl2cprhs) :
+ format(SdxL2VCManager.SDXL2_CPS_FORMAT, sdxl2cprhs, sdxl2cplhs);
+ String name = sdxL2VCs.remove(cps);
+ if (name == null) {
+ throw new SdxL2Exception(String.format(errorRemoveVC));
+ }
+ }
+
+ @Override
+ public void removeVC(SdxL2ConnectionPoint cp) throws SdxL2Exception {
+
+ Set<String> vcs = ImmutableSet.copyOf(sdxL2VCs.keySet()
+ .parallelStream()
+ .filter((vctemp -> vctemp.contains(cp.toString())))
+ .collect(Collectors.toSet()));
+
+ for (String vctemp : vcs) {
+ String[] splitted = vctemp.split("~");
+ if (splitted.length != 2) {
+ throw new SdxL2Exception(String.format(errorVCKey, "delete", vctemp));
+ }
+ if (cp.toString().equals(splitted[0]) || cp.toString().equals(splitted[1])) {
+ sdxL2VCs.remove(vctemp);
+ }
+ }
+ }
+
+ @Override
+ public void removeVCs(String sdxl2) {
+
+ Set<Map.Entry<String, String>> vcsToRemove = sdxL2VCs.entrySet().parallelStream().filter(key_value -> {
+ String[] fields = key_value.getValue().split(":");
+ return fields.length == 2 && fields[0].equals(sdxl2) ? true : false;
+ }).collect(Collectors.toSet());
+
+ vcsToRemove.forEach(key_value -> sdxL2VCs.remove(key_value.getKey()));
+ }
+
+ @Override
+ public String getVC(SdxL2ConnectionPoint sdxl2cplhs, SdxL2ConnectionPoint sdxl2cprhs)
+ throws SdxL2Exception {
+ String cps = sdxl2cplhs.toString().compareTo(sdxl2cprhs.toString()) < 0 ?
+ format(SdxL2VCManager.SDXL2_CPS_FORMAT, sdxl2cplhs, sdxl2cprhs) :
+ format(SdxL2VCManager.SDXL2_CPS_FORMAT, sdxl2cprhs, sdxl2cplhs);
+
+ String encodedvc = ImmutableSet.copyOf(sdxL2VCs.keySet()).parallelStream().filter(
+ encoded_cps -> encoded_cps.equals(cps)).findFirst().orElse(null);
+
+ if (encodedvc == null) {
+ throw new SdxL2Exception(String.format(errorRemoveVCAux,
+ sdxl2cplhs.name(), sdxl2cprhs.name()));
+ }
+ return encodedvc;
+ }
+
+ @Override
+ public Set<String> getVCs(Optional<String> sdxl2) {
+ if (sdxl2.isPresent()) {
+ Set<String> vcs = ImmutableSet.copyOf(sdxL2VCs.values())
+ .parallelStream()
+ .filter(vc -> {
+ String[] parts = vc.split(":");
+ return parts.length == 2 && parts[0].equals(sdxl2.get());
+ }).collect(Collectors.toSet());
+
+ return vcs;
+ }
+ return ImmutableSet.copyOf(sdxL2VCs.values());
+ }
}
diff --git a/sdx-l2/src/main/java/org/onosproject/sdxl2/SdxL2Exception.java b/sdx-l2/src/main/java/org/onosproject/sdxl2/SdxL2Exception.java
index 1692edc..cd7973b 100644
--- a/sdx-l2/src/main/java/org/onosproject/sdxl2/SdxL2Exception.java
+++ b/sdx-l2/src/main/java/org/onosproject/sdxl2/SdxL2Exception.java
@@ -21,6 +21,11 @@
*/
public class SdxL2Exception extends Exception {
+ /**
+ * Returns a custom exception, given a message.
+ *
+ * @param message Exception with custom message
+ */
public SdxL2Exception(String message) {
super(message);
}
diff --git a/sdx-l2/src/main/java/org/onosproject/sdxl2/SdxL2MacVCManager.java b/sdx-l2/src/main/java/org/onosproject/sdxl2/SdxL2MacVCManager.java
new file mode 100644
index 0000000..5a76979
--- /dev/null
+++ b/sdx-l2/src/main/java/org/onosproject/sdxl2/SdxL2MacVCManager.java
@@ -0,0 +1,223 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.sdxl2;
+
+import org.onlab.packet.MacAddress;
+import org.onlab.packet.VlanId;
+import org.onosproject.core.ApplicationId;
+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.Key;
+import org.onosproject.net.intent.PointToPointIntent;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.List;
+
+import static com.google.common.base.Preconditions.checkState;
+
+/**
+ * Manages Virtual Circuits using MAC addresses.
+ */
+public class SdxL2MacVCManager extends SdxL2VCManager {
+
+ private static final int PRIORITY_OFFSET = 2000;
+ private static Logger log = LoggerFactory.getLogger(SdxL2MacVCManager.class);
+
+ private static String errorMacNull = "VC cannot be %s: the mac address of %s is null";
+ private static String errorMacEqual = "VC cannot be %s: same mac addresses on both sides";
+
+ /**
+ * Creates an SDX-L2 MAC VC Manager.
+ *
+ * @param sdxl2id application ID
+ * @param store reference to the SDX-L2 store
+ * @param intentService reference to the Intent service
+ */
+ public SdxL2MacVCManager(ApplicationId sdxl2id,
+ SdxL2Store store,
+ IntentService intentService) {
+ super(sdxl2id, store, intentService);
+ log.info("Started");
+ }
+
+ @Override
+ public Collection<Intent> buildIntents(String sdxl2, SdxL2ConnectionPoint ingress, SdxL2ConnectionPoint egress) {
+ List<Intent> intents = null;
+ TrafficSelector selector;
+ TrafficTreatment treatment;
+ Key key;
+
+ if (ingress.vlanIds().size() == egress.vlanIds().size()) {
+ intents = new ArrayList<Intent>();
+ if (ingress.vlanIds().size() == 0) {
+ selector = buildSelector(ingress.macAddress(),
+ egress.macAddress(),
+ null,
+ null);
+ treatment = DefaultTrafficTreatment.emptyTreatment();
+ key = generateIntentKey(sdxl2, ingress, egress, "1");
+
+ intents.add(PointToPointIntent.builder()
+ .appId(appId)
+ .key(key)
+ .selector(selector)
+ .treatment(treatment)
+
+ .ingressPoint(ingress.connectPoint())
+ .egressPoint(egress.connectPoint())
+ .priority(PRIORITY_OFFSET)
+ .build());
+ } else {
+ Iterator<VlanId> ingressTags = ingress.vlanIds().iterator();
+ Iterator<VlanId> egressTags = egress.vlanIds().iterator();
+ int index = 1;
+ while (ingressTags.hasNext()) {
+ selector = buildSelector(ingress.macAddress(),
+ egress.macAddress(),
+ null,
+ ingressTags.next());
+ treatment = buildTreatment(egressTags.next(),
+ null,
+ false);
+ key = generateIntentKey(sdxl2, ingress, egress, String.valueOf(index));
+
+ intents.add(PointToPointIntent.builder()
+ .appId(appId)
+ .key(key)
+ .selector(selector)
+ .treatment(treatment)
+ .ingressPoint(ingress.connectPoint())
+ .egressPoint(egress.connectPoint())
+ .priority(PRIORITY_OFFSET)
+ .build());
+ index = index + 1;
+ }
+ }
+ return intents;
+ }
+
+ if (ingress.vlanIds().size() == 1 && egress.vlanIds().size() == 0) {
+ Iterator<VlanId> ingressTags = ingress.vlanIds().iterator();
+ intents = new ArrayList<Intent>();
+ selector = buildSelector(ingress.macAddress(),
+ egress.macAddress(),
+ null,
+ ingressTags.next());
+ treatment = buildTreatment(null,
+ null,
+ true);
+ key = generateIntentKey(sdxl2, ingress, egress, "1");
+
+ intents.add(PointToPointIntent.builder()
+ .appId(appId)
+ .key(key)
+ .selector(selector)
+ .treatment(treatment)
+ .ingressPoint(ingress.connectPoint())
+ .egressPoint(egress.connectPoint())
+ .priority(PRIORITY_OFFSET)
+ .build());
+ return intents;
+ }
+
+ if (ingress.vlanIds().size() == 0 && egress.vlanIds().size() == 1) {
+ Iterator<VlanId> egressTags = egress.vlanIds().iterator();
+ intents = new ArrayList<Intent>();
+ selector = buildSelector(ingress.macAddress(),
+ egress.macAddress(),
+ null,
+ null);
+ treatment = buildTreatment(null,
+ egressTags.next(),
+ false);
+ key = generateIntentKey(sdxl2, ingress, egress, "1");
+
+ intents.add(PointToPointIntent.builder()
+ .appId(appId)
+ .key(key)
+ .selector(selector)
+ .treatment(treatment)
+ .ingressPoint(ingress.connectPoint())
+ .egressPoint(egress.connectPoint())
+ .priority(PRIORITY_OFFSET)
+ .build());
+ return intents;
+ }
+
+ log.warn(String.format(errorCreateIntents, ingress.name(), egress.name()));
+
+ return intents;
+ }
+
+ @Override
+ public void addVC(String sdxl2, SdxL2ConnectionPoint sdxl2cplhs, SdxL2ConnectionPoint sdxl2cprhs) {
+ String action = "created";
+ checkState(!(isNullMac(sdxl2cplhs.macAddress()) && isNullMac(sdxl2cprhs.macAddress())),
+ errorMacNull, action, sdxl2cplhs.name() + " and " + sdxl2cprhs.name());
+ checkState(!isNullMac(sdxl2cprhs.macAddress()), errorMacNull, action, sdxl2cplhs.name());
+ checkState(!isNullMac(sdxl2cprhs.macAddress()), errorMacNull, action, sdxl2cprhs.name());
+ checkState(!sdxl2cplhs.macAddress().equals(sdxl2cprhs.macAddress()), errorMacEqual, action);
+ super.addVC(sdxl2, sdxl2cplhs, sdxl2cprhs);
+ }
+
+ @Override
+ public void removeVC(SdxL2ConnectionPoint sdxl2cplhs, SdxL2ConnectionPoint sdxl2cprhs) {
+ String action = "deleted";
+ checkState(!(isNullMac(sdxl2cplhs.macAddress()) && isNullMac(sdxl2cprhs.macAddress())),
+ errorMacNull, action, sdxl2cplhs.name() + " and " + sdxl2cprhs.name());
+ checkState(!sdxl2cplhs.macAddress().equals(MacAddress.ZERO), errorMacNull, action, sdxl2cplhs.name());
+ checkState(!sdxl2cprhs.macAddress().equals(MacAddress.ZERO), errorMacNull, action, sdxl2cprhs.name());
+ checkState(!sdxl2cplhs.macAddress().equals(sdxl2cprhs.macAddress()), errorMacEqual, action);
+ super.removeVC(sdxl2cplhs, sdxl2cprhs);
+ }
+
+ @Override
+ public void removeVC(SdxL2ConnectionPoint cp) {
+ checkState(!cp.macAddress().equals(MacAddress.ZERO), errorMacNull, "deleted", cp.name());
+ super.removeVC(cp);
+ }
+
+ private boolean isNullMac(MacAddress mac) {
+ return mac.equals(MacAddress.ZERO);
+ }
+
+ private TrafficSelector buildSelector(MacAddress ingressMac,
+ MacAddress egressMac,
+ Short ethertype,
+ VlanId ingresstag) {
+
+ TrafficSelector.Builder selectorBuilder = DefaultTrafficSelector.builder();
+ selectorBuilder.matchEthSrc(ingressMac);
+ selectorBuilder.matchEthDst(egressMac);
+ if (ethertype != null) {
+ selectorBuilder.matchEthType(ethertype);
+ }
+ if (ingresstag != null) {
+ selectorBuilder.matchVlanId(ingresstag);
+ }
+ return selectorBuilder.build();
+ }
+
+}
diff --git a/sdx-l2/src/main/java/org/onosproject/sdxl2/SdxL2Manager.java b/sdx-l2/src/main/java/org/onosproject/sdxl2/SdxL2Manager.java
index 21dd06a..edd7901 100644
--- a/sdx-l2/src/main/java/org/onosproject/sdxl2/SdxL2Manager.java
+++ b/sdx-l2/src/main/java/org/onosproject/sdxl2/SdxL2Manager.java
@@ -16,13 +16,12 @@
package org.onosproject.sdxl2;
-
+import org.apache.felix.scr.annotations.Activate;
import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Deactivate;
import org.apache.felix.scr.annotations.Reference;
import org.apache.felix.scr.annotations.ReferenceCardinality;
import org.apache.felix.scr.annotations.Service;
-import org.apache.felix.scr.annotations.Activate;
-import org.apache.felix.scr.annotations.Deactivate;
import org.onlab.packet.Ethernet;
import org.onlab.packet.ICMP6;
import org.onlab.packet.IPv6;
@@ -46,6 +45,7 @@
import java.util.Collections;
import java.util.Optional;
import java.util.Set;
+import java.util.stream.Collectors;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
@@ -56,52 +56,56 @@
import static org.onlab.packet.IPv6.PROTOCOL_ICMP6;
import static org.onosproject.net.packet.PacketPriority.CONTROL;
+
/**
- * Implementation of the SdxL2Service.
+ * Implements SdxL2Service.
*/
@Component(immediate = true)
@Service
public class SdxL2Manager implements SdxL2Service {
private static final String SDXL2_APP = "org.onosproject.sdxl2";
+ private static final String ERROR_ADD_VC_VLANS =
+ "Cannot create VC when CPs have different number of VLANs";
+ private static final String ERROR_ADD_VC_VLANS_CLI =
+ "\u001B[0;31mError executing command: " + ERROR_ADD_VC_VLANS + "\u001B[0;49m";
+ private static final String VC_0 = "MAC";
private static Logger log = LoggerFactory.getLogger(SdxL2Manager.class);
-
+ private static final String ERROR_ADD_VC_CPS = "Unable to find %s and %s in sdxl2=%s";
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected SdxL2Store sdxL2Store;
-
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected CoreService coreService;
-
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected IntentService intentService;
-
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected EdgePortService edgePortService;
-
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected PacketService packetService;
-
protected SdxL2Processor processor = new SdxL2Processor();
-
- protected SdxL2ArpNdpHandler arpndpHandler;
-
protected ApplicationId appId;
-
protected SdxL2MonitoringService monitoringManager;
-
- protected String vcType = "MAC";
+ protected SdxL2ArpNdpHandler arpndpHandler;
+ protected SdxL2VCService vcManager;
+ /**
+ * Activates the implementation of the SDX-L2 service.
+ * @param context ComponentContext object
+ */
@Activate
protected void activate(ComponentContext context) {
appId = coreService.registerApplication(SDXL2_APP);
monitoringManager = new SdxL2MonitoringManager(appId, intentService, edgePortService);
+ SdxL2ArpNdpHandler.vcType = VC_0;
+ vcManager = new SdxL2MacVCManager(appId, sdxL2Store, intentService);
handleArpNdp();
log.info("Started");
}
-
-
+ /**
+ * Deactivates the implementation of the SDX-L2 service.
+ */
@Deactivate
protected void deactivate() {
this.cleanSdxL2();
@@ -109,11 +113,6 @@
log.info("Stopped");
}
- /**
- * Creates a named SDX-L2.
- *
- * @param sdxl2 SDX-L2 name
- */
@Override
public void createSdxL2(String sdxl2) {
@@ -128,14 +127,8 @@
} catch (SdxL2Exception e) {
log.info(e.getMessage());
}
-
}
- /**
- * Deletes a named SDX-L2.
- *
- * @param sdxl2 SDX-L2 name
- */
@Override
public void deleteSdxL2(String sdxl2) {
@@ -149,22 +142,11 @@
}
- /**
- * Returns a set of SDX-L2 names.
- *
- * @return a set of SDX-L2 names
- */
@Override
public Set<String> getSdxL2s() {
return this.sdxL2Store.getSdxL2s();
}
- /**
- * Adds an SDX-L2 connection point to an SDX-L2.
- *
- * @param sdxl2 SDX-L2 name
- * @param sdxl2cp SDX-L2 connection point object
- */
@Override
public void addSdxL2ConnectionPoint(String sdxl2, SdxL2ConnectionPoint sdxl2cp) {
@@ -179,12 +161,6 @@
}
- /**
- * Returns all the SDX-L2 connection points names in a SDX-L2 or all the SDX-L2 connection points names.
- *
- * @param sdxl2 SDX-L2 name
- * @return a set of SDX-L2 connection points names
- */
@Override
public Set<String> getSdxL2ConnectionPoints(Optional<String> sdxl2) {
@@ -195,14 +171,8 @@
}
return Collections.emptySet();
-
}
- /**
- * Removes an SDX-L2 connection point from an SDX-L2.
- *
- * @param sdxl2cp SDX-L2 connection point name
- */
@Override
public void removeSdxL2ConnectionPoint(String sdxl2cp) {
@@ -216,12 +186,55 @@
}
- /**
- * Returns an SDX-L2 connection point in a SDX-L2.
- *
- * @param sdxl2cp SDX-L2 connection point name
- * @return the relative SdxL2ConnectionPoint object
- */
+ @Override
+ public void addVC(String sdxl2, String sdxl2cplhs, String sdxl2cprhs) {
+ SdxL2ConnectionPoint lhs = this.getSdxL2ConnectionPoint(sdxl2cplhs);
+ SdxL2ConnectionPoint rhs = this.getSdxL2ConnectionPoint(sdxl2cprhs);
+
+ Set<String> cps = this.getSdxL2ConnectionPoints(Optional.of(sdxl2))
+ .parallelStream()
+ .filter(cptemp -> (cptemp.equals(sdxl2cplhs) || cptemp.equals(sdxl2cprhs)))
+ .collect(Collectors.toSet());
+
+ checkState(cps.size() == 2, ERROR_ADD_VC_CPS, sdxl2cplhs, sdxl2cprhs, sdxl2);
+
+ if ((lhs.vlanIds().size() != rhs.vlanIds().size()) &&
+ (lhs.vlanIds().size() > 1 || rhs.vlanIds().size() > 1)) {
+ // User can correct this issue in the CLI. Show in console and log
+ System.err.println(ERROR_ADD_VC_VLANS_CLI);
+ log.info(ERROR_ADD_VC_VLANS);
+ return;
+ }
+ this.vcManager.addVC(sdxl2, lhs, rhs);
+ }
+
+ @Override
+ public void removeVC(String vc) {
+ checkNotNull(vc, "VC name cannot be null");
+ String[] splitKeyCPs = vc.split(":");
+ checkState(splitKeyCPs.length == 2, "Bad name format $sdx:$something");
+ String[] cps = splitKeyCPs[1].split("-");
+ checkState(cps.length == 2, "Bad name format $sdx:$lhs-$rhs");
+
+ String lhsName = cps[0];
+ String rhsName = cps[1];
+ SdxL2ConnectionPoint lhs = this.getSdxL2ConnectionPoint(lhsName);
+ SdxL2ConnectionPoint rhs = this.getSdxL2ConnectionPoint(rhsName);
+ if (lhs == null || rhs == null) {
+ return;
+ }
+
+ Set<String> cpsByVC = this.getSdxL2ConnectionPoints(Optional.of(splitKeyCPs[0]))
+ .parallelStream()
+ .filter(tempCP -> (tempCP.equals(lhs.name()) || tempCP.equals(rhs.name())))
+ .collect(Collectors.toSet());
+
+ if (cpsByVC.size() != 2) {
+ return;
+ }
+ this.vcManager.removeVC(lhs, rhs);
+ }
+
@Override
public SdxL2ConnectionPoint getSdxL2ConnectionPoint(String sdxl2cp) {
checkNotNull(sdxl2cp, "SdxL2ConnectionPoint name cannot be null");
@@ -230,28 +243,42 @@
} catch (SdxL2Exception e) {
log.info(e.getMessage());
}
-
return null;
}
- /**
- * Returns the state of the Intent that has been provided as input.
- *
- * @param intentKey key of the intent;
- * @return the last state of the intent;
- */
+ @Override
+ public Set<String> getVirtualCircuits(Optional<String> sdxl2) {
+ return this.vcManager.getVCs(sdxl2);
+ }
+
+ @Override
+ public VirtualCircuit getVirtualCircuit(String sdxl2vc) {
+ checkNotNull(sdxl2vc, "VC name cannot be null");
+ String[] splitKeyCPs = sdxl2vc.split(":");
+ checkState(splitKeyCPs.length == 2, "Bad name format $sdx:$something");
+ String[] cps = splitKeyCPs[1].split("-");
+ checkState(cps.length == 2, "Bad name format $sdx:$lhs-$rhs");
+
+ SdxL2ConnectionPoint lhs = this.getSdxL2ConnectionPoint(cps[0]);
+ SdxL2ConnectionPoint rhs = this.getSdxL2ConnectionPoint(cps[1]);
+ VirtualCircuit vc = null;
+ if (lhs == null || rhs == null) {
+ return vc;
+ }
+
+ String result = this.vcManager.getVC(lhs, rhs);
+ if (result != null) {
+ vc = new VirtualCircuit(lhs, rhs);
+ }
+ return vc;
+ }
+
@Override
public SdxL2State getIntentState(Key intentKey) {
checkNotNull(intentKey, "Intent key cannot be null");
return this.monitoringManager.getIntentState(intentKey);
}
- /**
- * Returns the state of the EdgePort that has been provided as input.
- *
- * @param edgeport the connect point representing the edge port
- * @return the last state of the edgeport;
- */
@Override
public SdxL2State getEdgePortState(ConnectPoint edgeport) {
checkNotNull(edgeport, "Edge port cannot be null");
@@ -267,11 +294,11 @@
}
/**
- * It requests ARP and NDP packets to the PacketService
+ * Requests ARP and NDP packets to the PacketService
* and registers the SDX-L2 PacketProcessor.
*/
private void handleArpNdp() {
- SdxL2ArpNdpHandler.vcType = vcType;
+ SdxL2ArpNdpHandler.vcType = VC_0;
arpndpHandler = new SdxL2ArpNdpHandler(intentService, packetService, appId);
packetService.addProcessor(processor, PacketProcessor.director(1));
@@ -280,7 +307,7 @@
DefaultTrafficSelector.builder();
selectorBuilder.matchEthType(TYPE_ARP);
packetService.requestPackets(selectorBuilder.build(),
- CONTROL, appId, Optional.<DeviceId>empty());
+ CONTROL, appId, Optional.<DeviceId>empty());
// IPv6 Neighbor Solicitation packet.
selectorBuilder = DefaultTrafficSelector.builder();
@@ -288,7 +315,7 @@
selectorBuilder.matchIPProtocol(PROTOCOL_ICMP6);
selectorBuilder.matchIcmpv6Type(NEIGHBOR_SOLICITATION);
packetService.requestPackets(selectorBuilder.build(),
- CONTROL, appId, Optional.<DeviceId>empty());
+ CONTROL, appId, Optional.<DeviceId>empty());
// IPv6 Neighbor Advertisement packet.
selectorBuilder = DefaultTrafficSelector.builder();
@@ -296,7 +323,7 @@
selectorBuilder.matchIPProtocol(PROTOCOL_ICMP6);
selectorBuilder.matchIcmpv6Type(NEIGHBOR_ADVERTISEMENT);
packetService.requestPackets(selectorBuilder.build(),
- CONTROL, appId, Optional.<DeviceId>empty());
+ CONTROL, appId, Optional.<DeviceId>empty());
}
/**
@@ -312,21 +339,21 @@
DefaultTrafficSelector.builder();
selectorBuilder.matchEthType(TYPE_ARP);
packetService.cancelPackets(selectorBuilder.build(),
- CONTROL, appId, Optional.<DeviceId>empty());
+ CONTROL, appId, Optional.<DeviceId>empty());
selectorBuilder = DefaultTrafficSelector.builder();
selectorBuilder.matchEthType(TYPE_IPV6);
selectorBuilder.matchIPProtocol(PROTOCOL_ICMP6);
selectorBuilder.matchIcmpv6Type(NEIGHBOR_SOLICITATION);
packetService.cancelPackets(selectorBuilder.build(),
- CONTROL, appId, Optional.<DeviceId>empty());
+ CONTROL, appId, Optional.<DeviceId>empty());
selectorBuilder = DefaultTrafficSelector.builder();
selectorBuilder.matchEthType(TYPE_IPV6);
selectorBuilder.matchIPProtocol(PROTOCOL_ICMP6);
selectorBuilder.matchIcmpv6Type(NEIGHBOR_ADVERTISEMENT);
packetService.cancelPackets(selectorBuilder.build(),
- CONTROL, appId, Optional.<DeviceId>empty());
+ CONTROL, appId, Optional.<DeviceId>empty());
}
/**
diff --git a/sdx-l2/src/main/java/org/onosproject/sdxl2/SdxL2MplsVCManager.java b/sdx-l2/src/main/java/org/onosproject/sdxl2/SdxL2MplsVCManager.java
new file mode 100644
index 0000000..3a6c33d
--- /dev/null
+++ b/sdx-l2/src/main/java/org/onosproject/sdxl2/SdxL2MplsVCManager.java
@@ -0,0 +1,192 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.sdxl2;
+
+
+import org.onlab.packet.VlanId;
+import org.onosproject.core.ApplicationId;
+import org.onosproject.net.EncapsulationType;
+import org.onosproject.net.flow.DefaultTrafficTreatment;
+import org.onosproject.net.flow.TrafficSelector;
+import org.onosproject.net.flow.TrafficTreatment;
+import org.onosproject.net.intent.Constraint;
+import org.onosproject.net.intent.Intent;
+import org.onosproject.net.intent.IntentService;
+import org.onosproject.net.intent.Key;
+import org.onosproject.net.intent.PointToPointIntent;
+import org.onosproject.net.intent.constraint.EncapsulationConstraint;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * Manages Virtual Circuits using MPLS headers.
+ */
+public class SdxL2MplsVCManager extends SdxL2VCManager {
+
+ private static final int PRIORITY_OFFSET = 2000;
+ private static Logger log = LoggerFactory.getLogger(SdxL2MplsVCManager.class);
+
+ // TODO Remember to create two intents: one for IPv4 and one for IPv6
+
+ /**
+ * Creates an SDX-L2 MPLS VC Manager.
+ *
+ * @param sdxl2id application ID
+ * @param store reference to the SDX-L2 store
+ * @param intentService reference to the Intent service
+ */
+ public SdxL2MplsVCManager(ApplicationId sdxl2id,
+ SdxL2Store store,
+ IntentService intentService) {
+
+ super(sdxl2id, store, intentService);
+ log.info("Started");
+ }
+
+ @Override
+ public Collection<Intent> buildIntents(String sdxl2, SdxL2ConnectionPoint ingress,
+ SdxL2ConnectionPoint egress) {
+ List<Intent> intents = null;
+ TrafficSelector selector;
+ TrafficTreatment treatment;
+ List<Constraint> encapsulation;
+ Key key;
+
+ if (ingress.vlanIds().size() == egress.vlanIds().size()) {
+ intents = new ArrayList<Intent>();
+ if (ingress.vlanIds().size() == 0) {
+
+ selector = buildSelector(null, null);
+ treatment = DefaultTrafficTreatment.emptyTreatment();
+ encapsulation = buildConstraints();
+
+ key = generateIntentKey(sdxl2, ingress, egress, "1");
+
+ intents.add(PointToPointIntent.builder()
+ .appId(appId)
+ .key(key)
+ .selector(selector)
+ .treatment(treatment)
+ .constraints(encapsulation)
+ .ingressPoint(ingress.connectPoint())
+ .egressPoint(egress.connectPoint())
+ .priority(PRIORITY_OFFSET)
+ .build());
+ } else {
+
+ Iterator<VlanId> ingressTags = ingress.vlanIds().iterator();
+ Iterator<VlanId> egressTags = egress.vlanIds().iterator();
+ int index = 1;
+ while (ingressTags.hasNext()) {
+ selector = buildSelector(null, ingressTags.next());
+ treatment = buildTreatment(egressTags.next(),
+ null,
+ false);
+ encapsulation = buildConstraints();
+
+ key = generateIntentKey(sdxl2, ingress, egress, String.valueOf(index));
+
+ intents.add(PointToPointIntent.builder()
+ .appId(appId)
+ .key(key)
+ .selector(selector)
+ .treatment(treatment)
+ .constraints(encapsulation)
+ .ingressPoint(ingress.connectPoint())
+ .egressPoint(egress.connectPoint())
+ .priority(PRIORITY_OFFSET)
+ .build());
+ index = index + 1;
+ }
+
+ }
+ return intents;
+ }
+
+ if (ingress.vlanIds().size() == 1 && egress.vlanIds().size() == 0) {
+
+ Iterator<VlanId> ingressTags = ingress.vlanIds().iterator();
+ intents = new ArrayList<Intent>();
+
+ selector = buildSelector(null, ingressTags.next());
+ treatment = buildTreatment(null,
+ null,
+ true);
+ encapsulation = buildConstraints();
+
+
+ key = generateIntentKey(sdxl2, ingress, egress, "1");
+
+ intents.add(PointToPointIntent.builder()
+ .appId(appId)
+ .key(key)
+ .selector(selector)
+ .treatment(treatment)
+ .constraints(encapsulation)
+ .ingressPoint(ingress.connectPoint())
+ .egressPoint(egress.connectPoint())
+ .priority(PRIORITY_OFFSET)
+ .build());
+ return intents;
+
+ }
+
+ if (ingress.vlanIds().size() == 0 && egress.vlanIds().size() == 1) {
+
+ Iterator<VlanId> egressTags = egress.vlanIds().iterator();
+ intents = new ArrayList<Intent>();
+
+ selector = buildSelector(null, null);
+ treatment = buildTreatment(null,
+ egressTags.next(),
+ false);
+ encapsulation = buildConstraints();
+
+ key = generateIntentKey(sdxl2, ingress, egress, "1");
+
+ intents.add(PointToPointIntent.builder()
+ .appId(appId)
+ .key(key)
+ .selector(selector)
+ .treatment(treatment)
+ .constraints(encapsulation)
+ .ingressPoint(ingress.connectPoint())
+ .egressPoint(egress.connectPoint())
+ .priority(PRIORITY_OFFSET)
+ .build());
+ return intents;
+ }
+
+ log.warn(String.format(errorCreateIntents, ingress.name(), egress.name()));
+
+ return intents;
+ }
+
+ @Override
+ protected List<Constraint> buildConstraints() {
+ final List<Constraint> constraints = new LinkedList<>();
+ constraints.add(new EncapsulationConstraint(EncapsulationType.MPLS));
+ return constraints;
+ }
+
+}
\ No newline at end of file
diff --git a/sdx-l2/src/main/java/org/onosproject/sdxl2/SdxL2Service.java b/sdx-l2/src/main/java/org/onosproject/sdxl2/SdxL2Service.java
index 94629d7..8601abb 100644
--- a/sdx-l2/src/main/java/org/onosproject/sdxl2/SdxL2Service.java
+++ b/sdx-l2/src/main/java/org/onosproject/sdxl2/SdxL2Service.java
@@ -39,61 +39,94 @@
/**
* Deletes a named SDX-L2.
*
- * @param sdxl2 SDX-L2 name
+ * @param sdxl2 name of SDX-L2
*/
void deleteSdxL2(String sdxl2);
/**
* Returns a set of SDX-L2 names.
*
- * @return a set of SDX-L2 names
+ * @return set of SDX-L2 names
*/
Set<String> getSdxL2s();
/**
- * Adds an SDX-L2 connection point to an SDX-L2.
+ * Adds a Connection Point to an SDX-L2.
*
- * @param sdxl2 SDX-L2 name
- * @param sdxl2cp SDX-L2 connection point object
+ * @param sdxl2 name of SDX-L2
+ * @param sdxl2cp SDX-L2 Connection Point object
*/
void addSdxL2ConnectionPoint(String sdxl2, SdxL2ConnectionPoint sdxl2cp);
/**
- * Returns all the SDX-L2 connection points names in a SDX-L2 or all the SDX-L2 connection points names.
+ * Returns all names of Connection Points names in a SDX-L2 or
+ * all the names of SDX-L2 Connection Points.
*
- * @param sdxl2 SDX-L2 name
+ * @param sdxl2 name of SDX-L2
* @return a set of SDX-L2 connection points names
*/
Set<String> getSdxL2ConnectionPoints(Optional<String> sdxl2);
/**
- * Removes an SDX-L2 connection point from an SDX-L2.
+ * Removes a Connection Point from an SDX-L2.
*
- * @param sdxl2cp SDX-L2 connection point name
+ * @param sdxl2cp name of SDX-L2 Connection Point
*/
void removeSdxL2ConnectionPoint(String sdxl2cp);
/**
- * Returns an SDX-L2 connection point in a SDX-L2.
+ * Creates an L2 Virtual Circuit between two SDX-L2 Connection Points.
*
- * @param sdxl2cp SDX-L2 connection point name
+ * @param sdxl2 name of SDX-L2
+ * @param sdxl2cplhs name of SDX-L2 CP, left hand side of the VC
+ * @param sdxl2cprhs name of SDX-L2 CP, right hand side of the VC
+ */
+ void addVC(String sdxl2, String sdxl2cplhs, String sdxl2cprhs);
+
+ /**
+ * Deletes a Virtual Circuit between Connection Points in an SDX-L2.
+ *
+ * @param vc name of SDX-L2 VC
+ */
+ void removeVC(String vc);
+
+ /**
+ * Returns a Connection Point in an SDX-L2.
+ *
+ * @param sdxl2cp name of SDX-L2 Connection Point
* @return the relative SdxL2ConnectionPoint object
*/
SdxL2ConnectionPoint getSdxL2ConnectionPoint(String sdxl2cp);
/**
+ * Returns all the Virtual Circuits in an SDX-L2.
+ *
+ * @param sdxl2 name of SDX-L2
+ * @return set of Virtual Circuits names
+ */
+ Set<String> getVirtualCircuits(Optional<String> sdxl2);
+
+ /**
+ * Returns a Virtual Circuit in an SDX-L2.
+ *
+ * @param sdxl2vc name of the SDX-L2 VC
+ * @return the relative VirtualCircuit object
+ */
+ VirtualCircuit getVirtualCircuit(String sdxl2vc);
+
+ /**
* Returns the state of the Intent that has been provided as input.
*
- * @param intentKey key of the intent;
- * @return the last state of the intent;
+ * @param intentKey key of the intent
+ * @return the last state of the intent
*/
SdxL2State getIntentState(Key intentKey);
/**
* Returns the state of the EdgePort that has been provided as input.
*
- * @param edgeport the connect point representing the edge port
- * @return the last state of the edgeport;
+ * @param edgeport the Connection Point representing the edge port
+ * @return the last state of the edge port
*/
SdxL2State getEdgePortState(ConnectPoint edgeport);
diff --git a/sdx-l2/src/main/java/org/onosproject/sdxl2/SdxL2Store.java b/sdx-l2/src/main/java/org/onosproject/sdxl2/SdxL2Store.java
index c19ee42..0c465ee 100644
--- a/sdx-l2/src/main/java/org/onosproject/sdxl2/SdxL2Store.java
+++ b/sdx-l2/src/main/java/org/onosproject/sdxl2/SdxL2Store.java
@@ -27,32 +27,32 @@
/**
* Creates a named SDX-L2.
*
- * @param sdxl2 SDX-L2 name
- * @throws SdxL2Exception if SDX-L2 exists
+ * @param sdxl2 name of SDX-L2
+ * @throws SdxL2Exception if SDX-L2 is not added
*/
void putSdxL2(String sdxl2) throws SdxL2Exception;
/**
* Removes a named SDX-L2.
*
- * @param sdxl2 SDX-L2 name
- * @throws SdxL2Exception if SDX-L2 does not exist
+ * @param sdxl2 name of SDX-L2
+ * @throws SdxL2Exception if SDX-L2 is not removed
*/
void removeSdxL2(String sdxl2) throws SdxL2Exception;
/**
* Returns a set of SDX-L2 names.
*
- * @return a set of SDX-L2 names
+ * @return set of SDX-L2 names
*/
Set<String> getSdxL2s();
/**
- * Adds an SDX-L2 connection point to an SDX-L2.
+ * Adds a Connection Point to an SDX-L2.
*
- * @param sdxl2 SDX-L2 name
- * @param connectionPoint the SDX-L2 connection point object
- * @throws SdxL2Exception if it is not possible to add the SDX-L2 connection point
+ * @param sdxl2 name of SDX-L2
+ * @param connectionPoint SDX-L2 cCnnection Point object
+ * @throws SdxL2Exception if SDX-L2 is not added
*/
void addSdxL2ConnectionPoint(String sdxl2, SdxL2ConnectionPoint connectionPoint) throws SdxL2Exception;
@@ -60,28 +60,81 @@
* Returns all the SDX-L2 connection points names or the SDX-L2 connection points name
* that are related to an SDX-L2.
*
- * @param sdxl2 name (optional) of the SDX-L2
+ * @param sdxl2 name of the SDX-L2 (optional)
* @return a set of SDX-L2 connection points names, the result depends on the input parameter;
- * @throws SdxL2Exception if SDX-L2 is present but it does not exist
+ * @throws SdxL2Exception if SDX-L2 cannot be found
*/
Set<String> getSdxL2ConnectionPoints(Optional<String> sdxl2) throws SdxL2Exception;
-
/**
- * Removes a named SDX-L2 connection point in an SDX-L2.
+ * Removes a named Connection Point in an SDX-L2.
*
- * @param sdxl2cp the connection point name
- * @throws SdxL2Exception if the connection point does not exist
+ * @param sdxl2cp name of Connection Point
+ * @throws SdxL2Exception if SDX-L2 Connection Point does not exist
*/
void removeSdxL2ConnectionPoint(String sdxl2cp) throws SdxL2Exception;
/**
- * Returns an SDX-L2 connection point in a SDX-L2.
+ * Returns a Connection Point in a SDX-L2.
*
- * @param sdxl2cp the connection point name
- * @return the relative SDXL2ConnectionPoint object
- * @throws SdxL2Exception if SDX-L2 connection point does not exist
+ * @param sdxl2cp name of Connection Point
+ * @return relative SDX-L2 Connection Point
+ * @throws SdxL2Exception if SDX-L2 CP cannot be found
*/
SdxL2ConnectionPoint getSdxL2ConnectionPoint(String sdxl2cp) throws SdxL2Exception;
+ /**
+ * Creates a Virtual Circuit between two SDX-L2 Connection Points.
+ *
+ * @param sdxl2 name of SDX-L2
+ * @param sdxl2cplhs name of SDX-L2 CP, left hand side of the VC
+ * @param sdxl2cprhs name of SDX-L2 CP, right hand side of the VC
+ * @throws SdxL2Exception if SDX-L2 VC cannot be added
+ */
+ void addVC(String sdxl2, SdxL2ConnectionPoint sdxl2cplhs, SdxL2ConnectionPoint sdxl2cprhs)
+ throws SdxL2Exception;;
+
+ /**
+ * Deletes a Virtual Circuit between Connection Points in an SDX-L2.
+ *
+ * @param sdxl2cplhs name of SDX-L2 CP, left hand side of the VC
+ * @param sdxl2cprhs ame of SDX-L2 CP, right hand side of the VC
+ * @throws SdxL2Exception if no name is provided for VC
+ */
+ void removeVC(SdxL2ConnectionPoint sdxl2cplhs, SdxL2ConnectionPoint sdxl2cprhs)
+ throws SdxL2Exception;;
+
+ /**
+ * Deletes a Virtual Circuit where a given SDX-L2 CP acts as endpoint.
+ *
+ * @param cp Connection Point
+ * @throws SdxL2Exception if appropriate VC identifier is not provided
+ */
+ void removeVC(SdxL2ConnectionPoint cp) throws SdxL2Exception;;
+
+ /**
+ * Removes all Virtual Circuits created in a given SDX-L2.
+ *
+ * @param sdxl2 name of SDX-L2
+ */
+ void removeVCs(String sdxl2);
+
+ /**
+ * Returns an encoded Virtual Circuit in a SDX-L2.
+ *
+ * @param sdxl2cplhs name of SDX-L2 CP, left hand side of the VC
+ * @param sdxl2cprhs ame of SDX-L2 CP, right hand side of the VC
+ * @return the encoded Virtual Circuit
+ * @throws SdxL2Exception if no matching VC exists
+ */
+ String getVC(SdxL2ConnectionPoint sdxl2cplhs, SdxL2ConnectionPoint sdxl2cprhs)
+ throws SdxL2Exception;
+
+ /**
+ * Returns a) all Virtual Circuits, or b) Virtual Circuits in a given SDX-L2.
+ *
+ * @param sdxl2 name of SDX-L2
+ * @return set of names for Virtual Circuits
+ */
+ Set<String> getVCs(Optional<String> sdxl2);
}
diff --git a/sdx-l2/src/main/java/org/onosproject/sdxl2/SdxL2VCManager.java b/sdx-l2/src/main/java/org/onosproject/sdxl2/SdxL2VCManager.java
new file mode 100644
index 0000000..1d4d4e1
--- /dev/null
+++ b/sdx-l2/src/main/java/org/onosproject/sdxl2/SdxL2VCManager.java
@@ -0,0 +1,309 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.sdxl2;
+
+import com.google.common.collect.Iterables;
+import org.apache.commons.lang.NotImplementedException;
+import org.onlab.packet.VlanId;
+import org.onosproject.core.ApplicationId;
+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.Constraint;
+import org.onosproject.net.intent.Intent;
+import org.onosproject.net.intent.IntentService;
+import org.onosproject.net.intent.Key;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.Set;
+
+import static java.lang.String.format;
+
+
+/**
+ * Manages Virtual Circuits.
+ * Base class extended by different types of VCs.
+ */
+public class SdxL2VCManager implements SdxL2VCService {
+
+ private static Logger log = LoggerFactory.getLogger(SdxL2VCManager.class);
+
+ protected static final String MATCH_FORMAT = "%s-%s";
+ protected static final String NAME_FORMAT = "%s:%s-%s";
+ protected static final String SDXL2_CPS_FORMAT = "%s~%s";
+ protected static final String KEY_FORMAT = "%s,%s";
+
+ protected ApplicationId appId;
+ protected SdxL2Store sdxL2Store;
+ protected IntentService intentService;
+
+ private static String errorIntentsForward = "Unable to create forward Intents";
+ private static String errorIntentsReverse = "Unable to create reverse Intents";
+ protected static String errorCreateIntents = "Unable to create Intents for %s-%s";
+
+
+ /**
+ * Creates an SDX-L2 VC Manager.
+ *
+ * @param sdxl2id application ID
+ * @param store reference to the SDX-L2 store
+ * @param intentService reference to the Intent service
+ */
+ public SdxL2VCManager(ApplicationId sdxl2id,
+ SdxL2Store store,
+ IntentService intentService) {
+
+ this.appId = sdxl2id;
+ this.sdxL2Store = store;
+ this.intentService = intentService;
+ }
+
+ @Override
+ public void addVC(String sdxl2, SdxL2ConnectionPoint sdxl2cplhs, SdxL2ConnectionPoint sdxl2cprhs) {
+ try {
+ this.sdxL2Store.addVC(sdxl2, sdxl2cplhs, sdxl2cprhs);
+
+ Collection<Intent> intentsFW = buildIntents(sdxl2, sdxl2cplhs, sdxl2cprhs);
+ Collection<Intent> intentsRV = buildIntents(sdxl2, sdxl2cprhs, sdxl2cplhs);
+
+ if (intentsFW == null) {
+ System.err.println("\u001B[0;31mError executing command: "
+ + errorIntentsForward + "\u001B[0;49m");
+ return;
+ }
+ if (intentsRV == null) {
+ System.err.println("\u001B[0;31mError executing command: "
+ + errorIntentsReverse + "\u001B[0;49m");
+ return;
+ }
+
+ List<Intent> intents = new ArrayList<Intent>();
+ intents.addAll(intentsFW);
+ intents.addAll(intentsRV);
+ intents.forEach(intent -> {
+ intentService.submit(intent);
+ });
+ } catch (SdxL2Exception e) {
+ log.error(e.getMessage());
+ }
+ }
+
+ @Override
+ public void removeVC(SdxL2ConnectionPoint sdxl2cplhs, SdxL2ConnectionPoint sdxl2cprhs) {
+ try {
+ this.sdxL2Store.removeVC(sdxl2cplhs, sdxl2cprhs);
+ Iterables.filter(intentService.getIntents(), intent ->
+ (matches(sdxl2cplhs, sdxl2cprhs, intent) ||
+ (matches(sdxl2cprhs, sdxl2cplhs, intent))))
+ .forEach(intentService::withdraw);
+ } catch (SdxL2Exception e) {
+ log.error(e.getMessage());
+ }
+ }
+
+ @Override
+ public void removeVC(SdxL2ConnectionPoint cp) {
+ try {
+ this.sdxL2Store.removeVC(cp);
+ Iterables.filter(intentService.getIntents(), intent -> (matches(cp, intent)))
+ .forEach(intentService::withdraw);
+ } catch (SdxL2Exception e) {
+ log.error(e.getMessage());
+ }
+ }
+
+ /**
+ * Creates a set of Intents for the ingress and egress SDX-L2 Connection Point.
+ *
+ * @param sdxl2 name of SDX-L2
+ * @param ingress the ingress point with the relative traffic attributes
+ * @param egress the egress point with the relative traffic attributes
+ * @return a set of intent or a null set;
+ */
+ public Collection<Intent> buildIntents(String sdxl2, SdxL2ConnectionPoint ingress,
+ SdxL2ConnectionPoint egress) {
+ throw new NotImplementedException("buildIntents not implemented");
+ }
+
+ /**
+ * Matches an intent given two SDX-L2 connection points.
+ *
+ * @param sdxl2cplhs left hand side of the virtual circuit
+ * @param sdxl2cprhs right hand side of the virtual circuit
+ * @param intent intent to match
+ * @return result of the match
+ */
+ protected boolean matches(SdxL2ConnectionPoint sdxl2cplhs, SdxL2ConnectionPoint sdxl2cprhs, Intent intent) {
+ if (!Objects.equals(appId, intent.appId())) {
+ // different app ids
+ return false;
+ }
+
+ String key = intent.key().toString();
+ String[] fields = key.split(":");
+ String cps = format(MATCH_FORMAT, sdxl2cplhs.name(), sdxl2cprhs.name());
+
+ return fields.length == 2 && fields[1].contains(cps);
+ }
+
+ /**
+ * Matches an intent given an SDX-L2 Connection Point.
+ *
+ * @param cp hand side of a Virtual Circuit
+ * @param intent intent to match
+ * @return result of the match
+ */
+ protected boolean matches(SdxL2ConnectionPoint cp, Intent intent) {
+ if (!Objects.equals(appId, intent.appId())) {
+ // different app ids
+ return false;
+ }
+
+ String key = intent.key().toString();
+ String[] fields = key.split(":");
+
+ if (fields.length != 2) {
+ return false;
+ }
+ String[] cps = fields[1].split(",");
+
+ if (cps.length != 2) {
+ return false;
+ }
+ String[] hss = cps[0].split("-");
+
+ return hss.length == 2 && (hss[0].equals(cp.name()) || hss[1].equals(cp.name()));
+ }
+
+ @Override
+ public void removeVCs(String sdxl2) {
+ this.sdxL2Store.removeVCs(sdxl2);
+ Iterables.filter(intentService.getIntents(), intent -> (matches(sdxl2, intent)))
+ .forEach(intentService::withdraw);
+
+ }
+
+ /**
+ * Matches an intent given an SDX-L2 Connection Point.
+ *
+ * @param sdxl2 name of SDX-L2
+ * @param intent intent to match
+ * @return result of the match
+ */
+ protected boolean matches(String sdxl2, Intent intent) {
+ if (!Objects.equals(appId, intent.appId())) {
+ // different app ids
+ return false;
+ }
+
+ String key = intent.key().toString();
+ String[] fields = key.split(":");
+
+ return fields.length == 2 && fields[0].equals(sdxl2);
+ }
+
+ @Override
+ public Set<String> getVCs(Optional<String> sdxl2) {
+ return this.sdxL2Store.getVCs(sdxl2);
+ }
+
+ @Override
+ public String getVC(SdxL2ConnectionPoint sdxl2cplhs, SdxL2ConnectionPoint sdxl2cprhs) {
+ try {
+ return this.sdxL2Store.getVC(sdxl2cplhs, sdxl2cprhs);
+ } catch (SdxL2Exception e) {
+ log.error(e.getMessage());
+ }
+ return null;
+ }
+
+ /**
+ * Returns Intent key from SDX-L2 and two SDX-L2 Connection Points.
+ *
+ * @param sdxl2 name of SDX-L2
+ * @param cpone sdxl2 connection point one
+ * @param cptwo sdxl2 connection point two
+ * @param index digit used to help identify Intent
+ * @return canonical intent string key
+ */
+ protected Key generateIntentKey(String sdxl2, SdxL2ConnectionPoint cpone,
+ SdxL2ConnectionPoint cptwo, String index) {
+ String cps = format(NAME_FORMAT, sdxl2, cpone.name(), cptwo.name());
+ String key = format(KEY_FORMAT, cps, index);
+ return Key.of(key, appId);
+ }
+
+ /**
+ * Returns the traffic treatment, used in the definition of the intents.
+ *
+ * @param setVlan VLAN to set
+ * @param pushVlan VLAN to push
+ * @param popVlan boolean to indicate whether a popVlan action is
+ * performed (true) or not (false)
+ * @return TrafficTreatment object
+ */
+ protected TrafficTreatment buildTreatment(VlanId setVlan,
+ VlanId pushVlan,
+ boolean popVlan) {
+ TrafficTreatment.Builder treatmentBuilder = DefaultTrafficTreatment.builder();
+ if (setVlan != null) {
+ treatmentBuilder.setVlanId(setVlan);
+ }
+ if (pushVlan != null) {
+ treatmentBuilder.pushVlan();
+ treatmentBuilder.setVlanId(pushVlan);
+ }
+ if (popVlan) {
+ treatmentBuilder.popVlan();
+ }
+ return treatmentBuilder.build();
+ }
+
+ /**
+ * Returns the traffic selector, used in the definition of the intents.
+ *
+ * @param ethertype name of the Ethernet type used (e.g. of SDX-L2
+ * @param ingresstag VLAN id used at the ingress
+ * @return TrafficSelector object
+ */
+ protected TrafficSelector buildSelector(Short ethertype, VlanId ingresstag) {
+ TrafficSelector.Builder selectorBuilder = DefaultTrafficSelector.builder();
+ if (ethertype != null) {
+ selectorBuilder.matchEthType(ethertype);
+ }
+ if (ingresstag != null) {
+ selectorBuilder.matchVlanId(ingresstag);
+ }
+ return selectorBuilder.build();
+ }
+
+ /**
+ * Returns constraints depending on the encapsulation used on the VC.
+ *
+ * @return list of constraints to be used in the intents
+ */
+ protected List<Constraint> buildConstraints() {
+ throw new NotImplementedException("buildConstraints not implemented");
+ }
+}
\ No newline at end of file
diff --git a/sdx-l2/src/main/java/org/onosproject/sdxl2/SdxL2VCService.java b/sdx-l2/src/main/java/org/onosproject/sdxl2/SdxL2VCService.java
new file mode 100644
index 0000000..6f65b8b
--- /dev/null
+++ b/sdx-l2/src/main/java/org/onosproject/sdxl2/SdxL2VCService.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.sdxl2;
+
+import java.util.Optional;
+import java.util.Set;
+
+/**
+ * Service that allows the creation of L2 Virtual Circuits
+ * between edge ports of a given SDN network.
+ */
+public interface SdxL2VCService {
+
+ /**
+ * Creates an L2 Virtual Circuit between two SDX-L2 Connection Points.
+ *
+ * @param sdxl2 name of SDX-L2
+ * @param sdxl2cplhs name of SDX-L2 CP, left hand side of the VC
+ * @param sdxl2cprhs name of SDX-L2 CP, right hand side of the VC
+ */
+ void addVC(String sdxl2, SdxL2ConnectionPoint sdxl2cplhs, SdxL2ConnectionPoint sdxl2cprhs);
+
+ /**
+ * Deletes a Virtual Circuit from an SDX-L2.
+ *
+ * @param sdxl2cplhs name of SDX-L2 CP, left hand side of the VC
+ * @param sdxl2cprhs name of SDX-L2 CP, right hand side of the VC
+ */
+ void removeVC(SdxL2ConnectionPoint sdxl2cplhs, SdxL2ConnectionPoint sdxl2cprhs);
+
+ /**
+ * Deletes a Virtual Circuit where a given SDX-L2 CP acts as endpoint.
+ *
+ * @param cp Connection Point
+ */
+ void removeVC(SdxL2ConnectionPoint cp);
+
+ /**
+ * Removes all Virtual Circuits created in a given SDX-L2.
+ *
+ * @param sdxl2 name of SDX-L2
+ */
+ void removeVCs(String sdxl2);
+
+ /**
+ * Returns Virtual Circuits (either all or those created in a given SDX-L2).
+ *
+ * @param sdxl2 name of SDX-L2
+ * @return the set of virtual circuits name
+ */
+ Set<String> getVCs(Optional<String> sdxl2);
+
+ /**
+ * Returns an encoded Virtual Circuit in a given SDX-L2.
+ *
+ * @param lhs left hand side of the VC
+ * @param rhs right hand side of the VC
+ * @return encoded VC
+ */
+ String getVC(SdxL2ConnectionPoint lhs, SdxL2ConnectionPoint rhs);
+}
diff --git a/sdx-l2/src/main/java/org/onosproject/sdxl2/SdxL2VlanVCManager.java b/sdx-l2/src/main/java/org/onosproject/sdxl2/SdxL2VlanVCManager.java
new file mode 100644
index 0000000..ddf6896
--- /dev/null
+++ b/sdx-l2/src/main/java/org/onosproject/sdxl2/SdxL2VlanVCManager.java
@@ -0,0 +1,189 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.sdxl2;
+
+
+import org.onlab.packet.VlanId;
+import org.onosproject.core.ApplicationId;
+import org.onosproject.net.EncapsulationType;
+import org.onosproject.net.flow.DefaultTrafficTreatment;
+import org.onosproject.net.flow.TrafficSelector;
+import org.onosproject.net.flow.TrafficTreatment;
+import org.onosproject.net.intent.Constraint;
+import org.onosproject.net.intent.Intent;
+import org.onosproject.net.intent.IntentService;
+import org.onosproject.net.intent.Key;
+import org.onosproject.net.intent.PointToPointIntent;
+import org.onosproject.net.intent.constraint.EncapsulationConstraint;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+
+/**
+ * Manages Virtual Circuits using VLANs.
+ */
+public class SdxL2VlanVCManager extends SdxL2VCManager {
+
+ private static final int PRIORITY_OFFSET = 2000;
+ private static Logger log = LoggerFactory.getLogger(SdxL2VlanVCManager.class);
+
+ /**
+ * Creates an SDX-L2 VLAN VC Manager.
+ *
+ * @param sdxl2id application ID
+ * @param store reference to the SDX-L2 store
+ * @param intentService reference to the Intent service
+ */
+ public SdxL2VlanVCManager(ApplicationId sdxl2id,
+ SdxL2Store store,
+ IntentService intentService) {
+ super(sdxl2id, store, intentService);
+ log.info("Started");
+ }
+
+ @Override
+ public Collection<Intent> buildIntents(String sdxl2, SdxL2ConnectionPoint ingress, SdxL2ConnectionPoint egress) {
+ List<Intent> intents = null;
+ TrafficSelector selector;
+ TrafficTreatment treatment;
+ List<Constraint> encapsulation;
+ Key key;
+
+ if (ingress.vlanIds().size() == egress.vlanIds().size()) {
+ intents = new ArrayList<Intent>();
+ if (ingress.vlanIds().size() == 0) {
+
+ selector = buildSelector(null, null);
+ treatment = DefaultTrafficTreatment.emptyTreatment();
+ encapsulation = buildConstraints();
+
+ key = generateIntentKey(sdxl2, ingress, egress, "1");
+
+ intents.add(PointToPointIntent.builder()
+ .appId(appId)
+ .key(key)
+ .selector(selector)
+ .treatment(treatment)
+ .constraints(encapsulation)
+ .ingressPoint(ingress.connectPoint())
+ .egressPoint(egress.connectPoint())
+ .priority(PRIORITY_OFFSET)
+ .build());
+ } else {
+
+ Iterator<VlanId> ingressTags = ingress.vlanIds().iterator();
+ Iterator<VlanId> egressTags = egress.vlanIds().iterator();
+ int index = 1;
+ while (ingressTags.hasNext()) {
+
+ selector = buildSelector(null, ingressTags.next());
+ treatment = buildTreatment(egressTags.next(),
+ null,
+ false);
+ encapsulation = buildConstraints();
+
+ key = generateIntentKey(sdxl2, ingress, egress, String.valueOf(index));
+
+ intents.add(PointToPointIntent.builder()
+ .appId(appId)
+ .key(key)
+ .selector(selector)
+ .treatment(treatment)
+ .constraints(encapsulation)
+ .ingressPoint(ingress.connectPoint())
+ .egressPoint(egress.connectPoint())
+ .priority(PRIORITY_OFFSET)
+ .build());
+ index = index + 1;
+ }
+
+ }
+ return intents;
+ }
+
+ if (ingress.vlanIds().size() == 1 && egress.vlanIds().size() == 0) {
+
+ Iterator<VlanId> ingressTags = ingress.vlanIds().iterator();
+ intents = new ArrayList<Intent>();
+
+ selector = buildSelector(null, ingressTags.next());
+ treatment = buildTreatment(null,
+ null,
+ true);
+ encapsulation = buildConstraints();
+
+
+ key = generateIntentKey(sdxl2, ingress, egress, "1");
+
+ intents.add(PointToPointIntent.builder()
+ .appId(appId)
+ .key(key)
+ .selector(selector)
+ .treatment(treatment)
+ .constraints(encapsulation)
+ .ingressPoint(ingress.connectPoint())
+ .egressPoint(egress.connectPoint())
+ .priority(PRIORITY_OFFSET)
+ .build());
+ return intents;
+
+ }
+
+ if (ingress.vlanIds().size() == 0 && egress.vlanIds().size() == 1) {
+
+ Iterator<VlanId> egressTags = egress.vlanIds().iterator();
+ intents = new ArrayList<Intent>();
+
+ selector = buildSelector(null, null);
+ treatment = buildTreatment(null,
+ egressTags.next(),
+ false);
+ encapsulation = buildConstraints();
+
+ key = generateIntentKey(sdxl2, ingress, egress, "1");
+
+ intents.add(PointToPointIntent.builder()
+ .appId(appId)
+ .key(key)
+ .selector(selector)
+ .treatment(treatment)
+ .constraints(encapsulation)
+ .ingressPoint(ingress.connectPoint())
+ .egressPoint(egress.connectPoint())
+ .priority(PRIORITY_OFFSET)
+ .build());
+ return intents;
+ }
+
+ log.warn(String.format(errorCreateIntents, ingress.name(), egress.name()));
+
+ return intents;
+ }
+
+ @Override
+ protected List<Constraint> buildConstraints() {
+ final List<Constraint> constraints = new LinkedList<>();
+ constraints.add(new EncapsulationConstraint(EncapsulationType.VLAN));
+ return constraints;
+ }
+
+}
\ No newline at end of file
diff --git a/sdx-l2/src/main/java/org/onosproject/sdxl2/VirtualCircuit.java b/sdx-l2/src/main/java/org/onosproject/sdxl2/VirtualCircuit.java
new file mode 100644
index 0000000..1561382
--- /dev/null
+++ b/sdx-l2/src/main/java/org/onosproject/sdxl2/VirtualCircuit.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.sdxl2;
+
+import com.google.common.base.MoreObjects;
+
+import java.util.Objects;
+
+/**
+ * Abstraction of a L2 Virtual Circuit.
+ * Note the circuit is expressed as a composition of two SDX-L2 Connection Points.
+ */
+public class VirtualCircuit {
+
+ private final String name;
+ private final SdxL2ConnectionPoint sdxl2cplhs;
+ private final SdxL2ConnectionPoint sdxl2cprhs;
+
+ /**
+ * Creates a new Virtual Circuit.
+ *
+ * @param sdxl2cplhs left hand side of the virtual circuit
+ * @param sdxl2cprhs right hand side of the virtual circuit
+ */
+ public VirtualCircuit(SdxL2ConnectionPoint sdxl2cplhs, SdxL2ConnectionPoint sdxl2cprhs) {
+ this.name = sdxl2cplhs.name() + "-" + sdxl2cprhs.name();
+ this.sdxl2cplhs = sdxl2cplhs;
+ this.sdxl2cprhs = sdxl2cprhs;
+ }
+
+ /**
+ * Returns the left hand side of the Virtual Circuit.
+ *
+ * @return SDX-L2 Connection Point
+ */
+ public SdxL2ConnectionPoint lhs() {
+ return sdxl2cplhs;
+ }
+
+ /**
+ * Returns the right hand side of the Virtual Circuit.
+ *
+ * @return SDX-L2 Connection Point
+ */
+ public SdxL2ConnectionPoint rhs() {
+ return sdxl2cprhs;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(name, sdxl2cplhs, sdxl2cprhs);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof VirtualCircuit) {
+ final VirtualCircuit other = (VirtualCircuit) obj;
+ return (Objects.equals(this.sdxl2cplhs, other.sdxl2cplhs) &&
+ Objects.equals(this.sdxl2cprhs, other.sdxl2cprhs)) ||
+ (Objects.equals(this.sdxl2cplhs, other.sdxl2cprhs) &&
+ Objects.equals(this.sdxl2cprhs, other.sdxl2cplhs));
+ }
+ return false;
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(this)
+ .add("name", name)
+ .add("lhs", sdxl2cplhs)
+ .add("rhs", sdxl2cprhs)
+ .toString();
+ }
+}
diff --git a/sdx-l2/src/main/java/org/onosproject/sdxl2/cli/SdxL2AddCPCommand.java b/sdx-l2/src/main/java/org/onosproject/sdxl2/cli/SdxL2AddCPCommand.java
index eb000b8..ea13441 100644
--- a/sdx-l2/src/main/java/org/onosproject/sdxl2/cli/SdxL2AddCPCommand.java
+++ b/sdx-l2/src/main/java/org/onosproject/sdxl2/cli/SdxL2AddCPCommand.java
@@ -27,38 +27,33 @@
/**
* CLI to create a named SDX-L2 connection point.
*/
-@Command(scope = "sdxl2", name = "sdxl2cp-add", description = "Create a named sdx-l2 connection point")
+@Command(scope = "sdxl2", name = "sdxl2cp-add", description = "Creates a named SDX-L2 Connection Point")
public class SdxL2AddCPCommand extends AbstractShellCommand {
- @Argument(index = 0, name = "sdxl2name", description = "Sdxl2name",
+ @Argument(index = 0, name = "sdxl2name", description = "Name of SDX-L2",
required = true, multiValued = false)
- String sdxl2name = null;
+ private String sdxl2name = null;
- @Argument(index = 1, name = "connectionpoint", description = "Connection point",
+ @Argument(index = 1, name = "connectionpoint", description = "Identifier of SDX-L2 Connection point",
required = true, multiValued = false)
- String cp = null;
+ private String cp = null;
- @Argument(index = 2, name = "vlans", description = "Customer edge vlans separated by comma",
+ @Argument(index = 2, name = "sdxl2cpname", description = "Name of SDX-L2 Connection Point",
required = true, multiValued = false)
- String vlans = null;
+ private String sdxl2cpname = null;
- @Argument(index = 3, name = "sdxl2cpname", description = "Sdxl2 connection point name",
- required = true, multiValued = false)
- String sdxl2cpname = null;
+ @Argument(index = 3, name = "vlans", description = "Customer edge VLANs, separated by dash " +
+ "and comma", required = false, multiValued = false)
+ private String vlans = null;
- @Option(name = "-ce_mac", description = "Customer edge mac address",
+ @Option(name = "-ce_mac", description = "Customer edge MAC address",
required = false, multiValued = false)
- String mac = null;
+ private String mac = null;
@Override
protected void execute() {
SdxL2Service sdxl2Service = get(SdxL2Service.class);
- SdxL2ConnectionPoint sdxl2cp;
- if (mac != null) {
- sdxl2cp = SdxL2ConnectionPoint.sdxl2ConnectionPoint(sdxl2cpname, cp, vlans, mac);
- } else {
- sdxl2cp = SdxL2ConnectionPoint.sdxl2ConnectionPoint(sdxl2cpname, cp, vlans);
- }
+ SdxL2ConnectionPoint sdxl2cp = SdxL2ConnectionPoint.sdxl2ConnectionPoint(sdxl2cpname, cp, vlans, mac);
sdxl2Service.addSdxL2ConnectionPoint(sdxl2name, sdxl2cp);
}
diff --git a/sdx-l2/src/main/java/org/onosproject/sdxl2/cli/SdxL2AddCommand.java b/sdx-l2/src/main/java/org/onosproject/sdxl2/cli/SdxL2AddCommand.java
index c7bb963..4aea7be 100644
--- a/sdx-l2/src/main/java/org/onosproject/sdxl2/cli/SdxL2AddCommand.java
+++ b/sdx-l2/src/main/java/org/onosproject/sdxl2/cli/SdxL2AddCommand.java
@@ -24,11 +24,11 @@
/**
* CLI to create SDX-L2.
*/
-@Command(scope = "sdxl2", name = "sdxl2-add", description = "Create a sdx-l2")
+@Command(scope = "sdxl2", name = "sdxl2-add", description = "Creates a SDX-L2")
public class SdxL2AddCommand extends AbstractShellCommand {
- @Argument(index = 0, name = "sdxl2name", description = "Sdxl2 name", required = true, multiValued = false)
- String sdxl2 = null;
+ @Argument(index = 0, name = "sdxl2name", description = "Name of SDX-L2", required = true, multiValued = false)
+ private String sdxl2 = null;
@Override
protected void execute() {
diff --git a/sdx-l2/src/main/java/org/onosproject/sdxl2/cli/SdxL2AddVCCommand.java b/sdx-l2/src/main/java/org/onosproject/sdxl2/cli/SdxL2AddVCCommand.java
new file mode 100644
index 0000000..2a75e37
--- /dev/null
+++ b/sdx-l2/src/main/java/org/onosproject/sdxl2/cli/SdxL2AddVCCommand.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.sdxl2.cli;
+
+import org.apache.karaf.shell.commands.Argument;
+import org.apache.karaf.shell.commands.Command;
+import org.onosproject.cli.AbstractShellCommand;
+import org.onosproject.sdxl2.SdxL2Service;
+
+/**
+ * CLI to create a VC between two Connection Points in the same SDX-L2.
+ */
+@Command(scope = "sdxl2", name = "sdxl2vc-add",
+ description = "Creates a VC between two Connection Points in the same SDX-L2")
+public class SdxL2AddVCCommand extends AbstractShellCommand {
+
+ @Argument(index = 0, name = "sdxl2name", description = "Name of SDX-L2",
+ required = true, multiValued = false)
+ private String sdxL2name = null;
+
+ @Argument(index = 1, name = "lhs", description = "Left hand side Connection Point",
+ required = true, multiValued = false)
+ private String lhs = null;
+
+ @Argument(index = 2, name = "rhs", description = "Right hand side Connection Point",
+ required = true, multiValued = false)
+ private String rhs = null;
+
+ @Override
+ protected void execute() {
+ SdxL2Service sdxl2Service = get(SdxL2Service.class);
+ sdxl2Service.addVC(sdxL2name, lhs, rhs);
+ }
+}
diff --git a/sdx-l2/src/main/java/org/onosproject/sdxl2/cli/SdxL2GetCPCommand.java b/sdx-l2/src/main/java/org/onosproject/sdxl2/cli/SdxL2GetCPCommand.java
index 8f5b3ea..779da65 100644
--- a/sdx-l2/src/main/java/org/onosproject/sdxl2/cli/SdxL2GetCPCommand.java
+++ b/sdx-l2/src/main/java/org/onosproject/sdxl2/cli/SdxL2GetCPCommand.java
@@ -24,13 +24,13 @@
import org.onosproject.sdxl2.SdxL2State;
/**
- * Cli to print the details of an SdxL2ConnectionPoint.
+ * CLI to print the details of an SdxL2ConnectionPoint.
*/
-@Command(scope = "sdxl2", name = "sdxl2cp", description = "Prints the details of an SDXL2ConnectionPoint")
+@Command(scope = "sdxl2", name = "sdxl2cp", description = "Prints the details of an SDX-L2 Connection Point")
public class SdxL2GetCPCommand extends AbstractShellCommand {
- @Argument(index = 0, name = "sdxl2cpname", description = "Sdxl2cp name", required = true, multiValued = false)
- String sdxl2cpname = null;
+ @Argument(index = 0, name = "sdxl2cpname", description = "Name of SDX-L2", required = true, multiValued = false)
+ private String sdxl2cpname = null;
private static final String HEADER = "\n\u001B[1;37mStatus\t\t" +
"Connection Point\t\tName\t\tVlan IDs\t\tCE Mac Address\u001B[0m";
diff --git a/sdx-l2/src/main/java/org/onosproject/sdxl2/cli/SdxL2GetVCCommand.java b/sdx-l2/src/main/java/org/onosproject/sdxl2/cli/SdxL2GetVCCommand.java
new file mode 100644
index 0000000..66efaf7
--- /dev/null
+++ b/sdx-l2/src/main/java/org/onosproject/sdxl2/cli/SdxL2GetVCCommand.java
@@ -0,0 +1,167 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.sdxl2.cli;
+
+import com.google.common.collect.Iterables;
+import org.apache.karaf.shell.commands.Argument;
+import org.apache.karaf.shell.commands.Command;
+import org.onosproject.cli.AbstractShellCommand;
+import org.onosproject.net.intent.Intent;
+import org.onosproject.net.intent.IntentService;
+import org.onosproject.net.intent.Key;
+import org.onosproject.sdxl2.SdxL2ConnectionPoint;
+import org.onosproject.sdxl2.SdxL2Service;
+import org.onosproject.sdxl2.SdxL2State;
+import org.onosproject.sdxl2.VirtualCircuit;
+
+import java.util.Iterator;
+
+import static java.lang.String.format;
+
+/**
+ * CLI to print the details of a Virtual Circuit in an SDX-L2.
+ */
+@Command(scope = "sdxl2", name = "sdxl2vc", description = "Prints the details of an SDX-L2 Virtual Circuit")
+public class SdxL2GetVCCommand extends AbstractShellCommand {
+
+ @Argument(index = 0, name = "sdxl2vcname", description = "Name of SDX-L2 VC", required = true, multiValued = false)
+ private String sdxl2vcname = null;
+
+ private static final String MATCH_FORMAT = "%s-%s";
+ private static final String HEADER_CP =
+ "\n\u001B[1;37mStatus\t\tConnection Point\t\tName\t\tVlan IDs\t\tCE Mac Address\u001B[0m";
+ private static final String SEPARATOR_CP = "\u001B[1;37m------------" +
+ "-----------------------------------------------------------" +
+ "--------------------------------------\u001B[0m";
+ private static final String FORMAT_SDXL2CP_ONLINE =
+ "\u001B[1;32m%s\u001B[0m\t\t\u001B[1;37m%s/%s\t\t%s\t\t%s\t\t%s\u001B[0m";
+ private static final String FORMAT_SDXL2CP_OFFLINE =
+ "\u001B[1;31m%s\u001B[0m\t\t\u001B[1;37m%s/%s\t\t%s\t\t%s\t\t%s\u001B[0m";
+
+ private static final String HEADER_VC =
+ "\n\u001B[1;37mStatus\t\tIntent\u001B[0m";
+ private static final String SEPARATOR_VC =
+ "\u001B[1;37m--------------------------------------------\u001B[0m";
+ private static final String FORMAT_SDXL2VC_ONLINE =
+ "\u001B[1;32m%s\u001B[0m\t\t\u001B[1;37m%s\u001B[0m";
+ private static final String FORMAT_SDXL2VC_OFFLINE =
+ "\u001B[1;31m%s\u001B[0m\t\t\u001B[1;37m%s\u001B[0m";
+ private static final String FORMAT_SDXL2VC_CHECK =
+ "\u001B[1;33m%s\u001B[0m\t\t\u001B[1;37m%s\u001B[0m";
+
+ @Override
+ protected void execute() {
+ SdxL2Service sdxl2Service = get(SdxL2Service.class);
+ VirtualCircuit virtualCircuit;
+ SdxL2ConnectionPoint sdxl2ConnectionPoint;
+ SdxL2State state;
+ virtualCircuit = sdxl2Service.getVirtualCircuit(sdxl2vcname);
+ if (virtualCircuit == null) {
+ return;
+ }
+
+ print(HEADER_CP);
+ print(SEPARATOR_CP);
+
+ sdxl2ConnectionPoint = virtualCircuit.lhs();
+ state = sdxl2Service.getEdgePortState(sdxl2ConnectionPoint.connectPoint());
+ if (state == SdxL2State.ONLINE) {
+ print(FORMAT_SDXL2CP_ONLINE,
+ "ONLINE",
+ sdxl2ConnectionPoint.connectPoint().elementId(),
+ sdxl2ConnectionPoint.connectPoint().port(),
+ sdxl2ConnectionPoint.name(),
+ sdxl2ConnectionPoint.vlanIds(),
+ sdxl2ConnectionPoint.macAddress());
+ } else if (state == SdxL2State.OFFLINE) {
+ print(FORMAT_SDXL2CP_OFFLINE,
+ "OFFLINE",
+ sdxl2ConnectionPoint.connectPoint().elementId(),
+ sdxl2ConnectionPoint.connectPoint().port(),
+ sdxl2ConnectionPoint.name(),
+ sdxl2ConnectionPoint.vlanIds(),
+ sdxl2ConnectionPoint.macAddress());
+ }
+
+
+ sdxl2ConnectionPoint = virtualCircuit.rhs();
+ state = sdxl2Service.getEdgePortState(sdxl2ConnectionPoint.connectPoint());
+ if (state == SdxL2State.ONLINE) {
+ print(FORMAT_SDXL2CP_ONLINE,
+ "ONLINE",
+ sdxl2ConnectionPoint.connectPoint().elementId(),
+ sdxl2ConnectionPoint.connectPoint().port(),
+ sdxl2ConnectionPoint.name(),
+ sdxl2ConnectionPoint.vlanIds(),
+ sdxl2ConnectionPoint.macAddress());
+ } else if (state == SdxL2State.OFFLINE) {
+ print(FORMAT_SDXL2CP_OFFLINE,
+ "OFFLINE",
+ sdxl2ConnectionPoint.connectPoint().elementId(),
+ sdxl2ConnectionPoint.connectPoint().port(),
+ sdxl2ConnectionPoint.name(),
+ sdxl2ConnectionPoint.vlanIds(),
+ sdxl2ConnectionPoint.macAddress());
+ }
+ print("");
+
+ print(HEADER_VC);
+ print(SEPARATOR_VC);
+ IntentService intentService = get(IntentService.class);
+ Iterator<Intent> intents = Iterables.filter(intentService.getIntents(), intent ->
+ (matches(virtualCircuit.lhs(), virtualCircuit.rhs(), intent) ||
+ (matches(virtualCircuit.rhs(), virtualCircuit.lhs(), intent)))).iterator();
+ Intent intent;
+ Key key;
+ while (intents.hasNext()) {
+ intent = intents.next();
+ key = intent.key();
+ state = sdxl2Service.getIntentState(key);
+ if (state == SdxL2State.ONLINE) {
+ print(FORMAT_SDXL2VC_ONLINE,
+ "ONLINE",
+ key);
+ } else if (state == SdxL2State.OFFLINE) {
+ print(FORMAT_SDXL2VC_OFFLINE,
+ "OFFLINE",
+ key);
+ } else {
+ print(FORMAT_SDXL2VC_CHECK,
+ "CHECK",
+ key);
+ }
+ }
+ print("");
+ }
+
+ /**
+ * Matches an intent given two sdxl2 connection points.
+ *
+ * @param lhs left hand side of the virtual circuit
+ * @param rhs right hand side of the virtual circuit
+ * @param intent intent to match
+ * @return result of the match
+ */
+ private boolean matches(SdxL2ConnectionPoint lhs, SdxL2ConnectionPoint rhs, Intent intent) {
+
+ String key = intent.key().toString();
+ String[] fields = key.split(":");
+ String cps = format(MATCH_FORMAT, lhs.name(), rhs.name());
+
+ return fields.length == 2 && fields[1].contains(cps);
+ }
+}
diff --git a/sdx-l2/src/main/java/org/onosproject/sdxl2/cli/SdxL2ListCPCommand.java b/sdx-l2/src/main/java/org/onosproject/sdxl2/cli/SdxL2ListCPCommand.java
index b25f349..4e702af 100644
--- a/sdx-l2/src/main/java/org/onosproject/sdxl2/cli/SdxL2ListCPCommand.java
+++ b/sdx-l2/src/main/java/org/onosproject/sdxl2/cli/SdxL2ListCPCommand.java
@@ -29,12 +29,12 @@
/**
* CLI to list the SDX-L2 connection points.
*/
-@Command(scope = "sdxl2", name = "sdxl2cps-list", description = "Lists " +
- "all the sdxl2 connection points. Argument not required the name of sdxl2")
+@Command(scope = "sdxl2", name = "sdxl2cp-list", description = "Lists " +
+ "all the SDX-L2 Connection Points. Argument not required the name of SDX-L2")
public class SdxL2ListCPCommand extends AbstractShellCommand {
- @Argument(index = 0, name = "sdxl2name", description = "sdxl2name", required = false, multiValued = false)
- String sdxl2 = null;
+ @Argument(index = 0, name = "sdxl2name", description = "Name of SDX-L2", required = false, multiValued = false)
+ private String sdxl2 = null;
private static final String HEADER = "\n\u001B[1;37mStatus\t\tSDXL2 Connection Point\u001B[0m";
private static final String SEPARATOR = "\u001B[1;37m-----------------------------------------------\u001B[0m";
@@ -48,9 +48,9 @@
Set<String> result = sdxl2Service.getSdxL2ConnectionPoints(sdxl2name);
SdxL2ConnectionPoint sdxl2ConnectionPoint;
SdxL2State sdxl2cpState;
+ print(HEADER);
+ print(SEPARATOR);
if (result.size() > 0) {
- print(HEADER);
- print(SEPARATOR);
for (String sdxl2cp : result) {
sdxl2ConnectionPoint = sdxl2Service.getSdxL2ConnectionPoint(sdxl2cp);
if (sdxl2ConnectionPoint == null) {
diff --git a/sdx-l2/src/main/java/org/onosproject/sdxl2/cli/SdxL2ListCommand.java b/sdx-l2/src/main/java/org/onosproject/sdxl2/cli/SdxL2ListCommand.java
index 42f91d1..f03b656 100644
--- a/sdx-l2/src/main/java/org/onosproject/sdxl2/cli/SdxL2ListCommand.java
+++ b/sdx-l2/src/main/java/org/onosproject/sdxl2/cli/SdxL2ListCommand.java
@@ -25,7 +25,7 @@
/**
* CLI to list the SDX-L2s.
*/
-@Command(scope = "sdxl2", name = "sdxl2-list", description = "Lists the sdx-l2s")
+@Command(scope = "sdxl2", name = "sdxl2-list", description = "Lists the SDX-L2s")
public class SdxL2ListCommand extends AbstractShellCommand {
private static final String HEADER = "\n\u001B[1;37mSDXL2\u001B[0m";
diff --git a/sdx-l2/src/main/java/org/onosproject/sdxl2/cli/SdxL2ListVCCommand.java b/sdx-l2/src/main/java/org/onosproject/sdxl2/cli/SdxL2ListVCCommand.java
new file mode 100644
index 0000000..13eb0f9
--- /dev/null
+++ b/sdx-l2/src/main/java/org/onosproject/sdxl2/cli/SdxL2ListVCCommand.java
@@ -0,0 +1,159 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.sdxl2.cli;
+
+import com.google.common.collect.Iterables;
+import org.apache.karaf.shell.commands.Argument;
+import org.apache.karaf.shell.commands.Command;
+import org.onosproject.cli.AbstractShellCommand;
+import org.onosproject.net.intent.Intent;
+import org.onosproject.net.intent.IntentService;
+import org.onosproject.net.intent.Key;
+import org.onosproject.sdxl2.SdxL2ConnectionPoint;
+import org.onosproject.sdxl2.SdxL2Service;
+import org.onosproject.sdxl2.SdxL2State;
+import org.onosproject.sdxl2.VirtualCircuit;
+
+import java.util.Iterator;
+import java.util.Optional;
+import java.util.Set;
+
+import static java.lang.String.format;
+
+/**
+ * CLI to delete a Connection Point in an SDX-L2.
+ */
+@Command(scope = "sdxl2", name = "sdxl2vc-list",
+ description = "Lists all the SDX-L2 Virtual Circuits. Argument not required the name of SDX-L2")
+public class SdxL2ListVCCommand extends AbstractShellCommand {
+
+ @Argument(index = 0, name = "Name of SDX-L2",
+ description = "Sdxl2 name", required = false, multiValued = false)
+ private String sdxl2 = null;
+
+ private static final String MATCH_FORMAT = "%s-%s";
+
+ private static final String HEADER =
+ "\n\u001B[1;37mStatus\t\tVirtual Circuit\u001B[0m";
+ private static final String SEPARATOR =
+ "\u001B[1;37m-----------------------------------------------\u001B[0m";
+ private static final String FORMAT_SDXL2VC_ONLINE =
+ "\u001B[1;32m%s\u001B[0m\t\t\u001B[1;37m%s\u001B[0m";
+ private static final String FORMAT_SDXL2VC_OFFLINE =
+ "\u001B[1;31m%s\u001B[0m\t\t\u001B[1;37m%s\u001B[0m";
+ private static final String FORMAT_SDXL2VC_CHECK =
+ "\u001B[1;33m%s\u001B[0m\t\t\u001B[1;37m%s\u001B[0m";
+
+
+ @Override
+ protected void execute() {
+ SdxL2Service sdxl2Service = get(SdxL2Service.class);
+ Optional<String> sdxl2name = Optional.ofNullable(sdxl2);
+ Set<String> result = sdxl2Service.getVirtualCircuits(sdxl2name);
+ VirtualCircuit vc;
+ SdxL2State state;
+ print(HEADER);
+ print(SEPARATOR);
+ if (result.size() > 0) {
+ String[] sdxl2VC;
+ for (String sdxl2vc : result) {
+ sdxl2VC = sdxl2vc.split(":");
+ vc = sdxl2Service.getVirtualCircuit(sdxl2vc);
+ if (vc == null) {
+ break;
+ }
+ state = this.getVirtualCircuitState(vc);
+ if (state == SdxL2State.ONLINE) {
+ print(FORMAT_SDXL2VC_ONLINE, "ONLINE", sdxl2VC[1]);
+ } else if (state == SdxL2State.OFFLINE) {
+ print(FORMAT_SDXL2VC_OFFLINE, "OFFLINE", sdxl2VC[1]);
+ } else {
+ print(FORMAT_SDXL2VC_CHECK, "CHECK", sdxl2VC[1]);
+ }
+ }
+ print("");
+ }
+ }
+
+ /**
+ * Retrieves status of a Virtual Circuit from the status of its
+ * Connection Points.
+ *
+ * @param vc VirtualCircuit object
+ * @return state of the Virtual Circuit
+ */
+ private SdxL2State getVirtualCircuitState(VirtualCircuit vc) {
+ IntentService intentService = get(IntentService.class);
+ SdxL2Service sdxl2Service = get(SdxL2Service.class);
+ SdxL2State intentState = SdxL2State.ONLINE;
+ SdxL2State lhsState;
+ SdxL2State rhsstate;
+ Iterator<Intent> intents = Iterables.filter(intentService.getIntents(), intent ->
+ (matches(vc.lhs(), vc.rhs(), intent) ||
+ (matches(vc.rhs(), vc.lhs(), intent)))).iterator();
+ Intent intent;
+ Key key;
+ int numIntents = 0;
+ int numIntentsOffline = 0;
+ while (intents.hasNext()) {
+ intent = intents.next();
+ key = intent.key();
+ intentState = sdxl2Service.getIntentState(key);
+ if (intentState == SdxL2State.OFFLINE || intentState == SdxL2State.CHECK) {
+ numIntentsOffline = numIntentsOffline + 1;
+ }
+ numIntents = numIntents + 1;
+ }
+
+ if (numIntents == numIntentsOffline) {
+ return SdxL2State.OFFLINE;
+ }
+
+ lhsState = sdxl2Service.getEdgePortState(vc.lhs().connectPoint());
+ if (lhsState == SdxL2State.OFFLINE) {
+ return SdxL2State.OFFLINE;
+ }
+
+ rhsstate = sdxl2Service.getEdgePortState(vc.rhs().connectPoint());
+ if (rhsstate == SdxL2State.OFFLINE) {
+ return SdxL2State.OFFLINE;
+ }
+
+ if (intentState == SdxL2State.ONLINE && lhsState == SdxL2State.ONLINE &&
+ rhsstate == SdxL2State.ONLINE) {
+ return SdxL2State.ONLINE;
+ }
+
+ return SdxL2State.CHECK;
+ }
+
+ /**
+ * Matches an intent given two SDX-L2 Connection Points.
+ *
+ * @param lhs left hand side of the virtual circuit
+ * @param rhs right hand side of the virtual circuit
+ * @param intent intent to match
+ * @return result of the match
+ */
+ private boolean matches(SdxL2ConnectionPoint lhs, SdxL2ConnectionPoint rhs, Intent intent) {
+ String key = intent.key().toString();
+ String[] fields = key.split(":");
+ String cps = format(MATCH_FORMAT, lhs.name(), rhs.name());
+
+ return fields.length == 2 && fields[1].contains(cps);
+ }
+}
diff --git a/sdx-l2/src/main/java/org/onosproject/sdxl2/cli/SdxL2RemoveCPCommand.java b/sdx-l2/src/main/java/org/onosproject/sdxl2/cli/SdxL2RemoveCPCommand.java
index 3e1dfee..00da8c5 100644
--- a/sdx-l2/src/main/java/org/onosproject/sdxl2/cli/SdxL2RemoveCPCommand.java
+++ b/sdx-l2/src/main/java/org/onosproject/sdxl2/cli/SdxL2RemoveCPCommand.java
@@ -23,14 +23,14 @@
import org.onosproject.sdxl2.SdxL2Service;
/**
- * CLI to delete a named SDX-L2 connection point.
+ * CLI to delete a named SDX-L2 Connection Point.
*/
-@Command(scope = "sdxl2", name = "sdxl2cp-remove", description = "Remove a named sdxl2 connection point")
+@Command(scope = "sdxl2", name = "sdxl2cp-remove", description = "Removes a named SDX-L2 Connection Point")
public class SdxL2RemoveCPCommand extends AbstractShellCommand {
- @Argument(index = 0, name = "sdxl2cpname", description = "Sdxl2 connection point name",
+ @Argument(index = 0, name = "sdxl2cpname", description = "Name of SDX-L2 Connection Point",
required = true, multiValued = false)
- String sdxl2cpname = null;
+ private String sdxl2cpname = null;
@Override
protected void execute() {
diff --git a/sdx-l2/src/main/java/org/onosproject/sdxl2/cli/SdxL2RemoveCommand.java b/sdx-l2/src/main/java/org/onosproject/sdxl2/cli/SdxL2RemoveCommand.java
index aecb899..ab416e4 100644
--- a/sdx-l2/src/main/java/org/onosproject/sdxl2/cli/SdxL2RemoveCommand.java
+++ b/sdx-l2/src/main/java/org/onosproject/sdxl2/cli/SdxL2RemoveCommand.java
@@ -24,12 +24,12 @@
/**
* CLI to delete a named SDX-L2.
*/
-@Command(scope = "sdxl2", name = "sdxl2-remove", description = "Delete a sdx-l2")
+@Command(scope = "sdxl2", name = "sdxl2-remove", description = "Deletes a SDX-L2")
public class SdxL2RemoveCommand extends AbstractShellCommand {
- @Argument(index = 0, name = "sdxl2name", description = "Sdxl2 name",
+ @Argument(index = 0, name = "sdxl2name", description = "Name of SDX-L2",
required = true, multiValued = false)
- String sdxl2 = null;
+ private String sdxl2 = null;
@Override
protected void execute() {
diff --git a/sdx-l2/src/main/java/org/onosproject/sdxl2/cli/SdxL2RemoveVCCommand.java b/sdx-l2/src/main/java/org/onosproject/sdxl2/cli/SdxL2RemoveVCCommand.java
new file mode 100644
index 0000000..d4b8d25
--- /dev/null
+++ b/sdx-l2/src/main/java/org/onosproject/sdxl2/cli/SdxL2RemoveVCCommand.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.sdxl2.cli;
+
+import org.apache.karaf.shell.commands.Argument;
+import org.apache.karaf.shell.commands.Command;
+import org.onosproject.cli.AbstractShellCommand;
+import org.onosproject.sdxl2.SdxL2Service;
+
+/**
+ * CLI to delete a named Virtual Circuit in an SDX-L2.
+ */
+@Command(scope = "sdxl2", name = "sdxl2vc-remove", description = "Removes a named Virtual Circuit")
+public class SdxL2RemoveVCCommand extends AbstractShellCommand {
+
+ @Argument(index = 0, name = "sdxl2vcname", description = "Name of SDX-L2 Virtual Circuit",
+ required = true, multiValued = false)
+ private String sdxL2VCname = null;
+
+ @Override
+ protected void execute() {
+ SdxL2Service sdxl2Service = get(SdxL2Service.class);
+ sdxl2Service.removeVC(sdxL2VCname);
+ }
+
+}
+
diff --git a/sdx-l2/src/main/java/org/onosproject/sdxl2/cli/completer/SdxL2CPNameCompleter.java b/sdx-l2/src/main/java/org/onosproject/sdxl2/cli/completer/SdxL2CPNameCompleter.java
index 706c1e3..31bebb4 100644
--- a/sdx-l2/src/main/java/org/onosproject/sdxl2/cli/completer/SdxL2CPNameCompleter.java
+++ b/sdx-l2/src/main/java/org/onosproject/sdxl2/cli/completer/SdxL2CPNameCompleter.java
@@ -25,7 +25,7 @@
import java.util.Optional;
/**
- * Completes SDX-L2 connection point names.
+ * Completes name for SDX-L2 Connection Point.
*/
public class SdxL2CPNameCompleter implements Completer {
diff --git a/sdx-l2/src/main/java/org/onosproject/sdxl2/cli/completer/SdxL2NameCompleter.java b/sdx-l2/src/main/java/org/onosproject/sdxl2/cli/completer/SdxL2NameCompleter.java
index 50b4366..df31856 100644
--- a/sdx-l2/src/main/java/org/onosproject/sdxl2/cli/completer/SdxL2NameCompleter.java
+++ b/sdx-l2/src/main/java/org/onosproject/sdxl2/cli/completer/SdxL2NameCompleter.java
@@ -24,7 +24,7 @@
import java.util.List;
/**
- * Completes SDX-L2 names.
+ * Completes name for SDX-L2.
*/
public class SdxL2NameCompleter implements Completer {
diff --git a/sdx-l2/src/main/java/org/onosproject/sdxl2/cli/completer/SdxL2VCNameCompleter.java b/sdx-l2/src/main/java/org/onosproject/sdxl2/cli/completer/SdxL2VCNameCompleter.java
new file mode 100644
index 0000000..e61c33f
--- /dev/null
+++ b/sdx-l2/src/main/java/org/onosproject/sdxl2/cli/completer/SdxL2VCNameCompleter.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2016-present Open Networking Laboratory
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.onosproject.sdxl2.cli.completer;
+
+
+import org.apache.karaf.shell.console.Completer;
+import org.apache.karaf.shell.console.completer.StringsCompleter;
+import org.onosproject.cli.AbstractShellCommand;
+import org.onosproject.sdxl2.SdxL2Service;
+
+import java.util.List;
+import java.util.Optional;
+
+/**
+ * Completes name for SDX-L2 Virtual Circuit.
+ */
+public class SdxL2VCNameCompleter implements Completer {
+
+ @Override
+ public int complete(String buffer, int cursor, List<String> candidates) {
+ StringsCompleter delegate = new StringsCompleter();
+ SdxL2Service service = AbstractShellCommand.get(SdxL2Service.class);
+ delegate.getStrings().addAll(service.getVirtualCircuits(Optional.ofNullable(null)));
+ return delegate.complete(buffer, cursor, candidates);
+ }
+}
diff --git a/sdx-l2/src/main/resources/OSGI-INF/blueprint/shell-config.xml b/sdx-l2/src/main/resources/OSGI-INF/blueprint/shell-config.xml
index 5d576d5..76b3572 100644
--- a/sdx-l2/src/main/resources/OSGI-INF/blueprint/shell-config.xml
+++ b/sdx-l2/src/main/resources/OSGI-INF/blueprint/shell-config.xml
@@ -13,6 +13,7 @@
~ See the License for the specific language governing permissions and
~ limitations under the License.
-->
+
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0">
<command-bundle xmlns="http://karaf.apache.org/xmlns/shell/v1.1.0">
@@ -42,15 +43,39 @@
</completers>
</command>
<command>
+ <action class="org.onosproject.sdxl2.cli.SdxL2GetCPCommand"/>
+ <completers>
+ <ref component-id="sdxl2cpnameCompleter"/>
+ </completers>
+ </command>
+ <command>
<action class="org.onosproject.sdxl2.cli.SdxL2ListCPCommand"/>
<completers>
<ref component-id="sdxl2Completer"/>
</completers>
</command>
<command>
- <action class="org.onosproject.sdxl2.cli.SdxL2GetCPCommand"/>
+ <action class="org.onosproject.sdxl2.cli.SdxL2AddVCCommand"/>
<completers>
- <ref component-id="sdxl2cpnameCompleter"/>
+ <ref component-id="sdxl2vcnameCompleter"/>
+ </completers>
+ </command>
+ <command>
+ <action class="org.onosproject.sdxl2.cli.SdxL2RemoveVCCommand"/>
+ <completers>
+ <ref component-id="sdxl2vcnameCompleter"/>
+ </completers>
+ </command>
+ <command>
+ <action class="org.onosproject.sdxl2.cli.SdxL2GetVCCommand"/>
+ <completers>
+ <ref component-id="sdxl2vcnameCompleter"/>
+ </completers>
+ </command>
+ <command>
+ <action class="org.onosproject.sdxl2.cli.SdxL2ListVCCommand"/>
+ <completers>
+ <ref component-id="sdxl2Completer"/>
</completers>
</command>
</command-bundle>
@@ -58,5 +83,6 @@
<bean id="sdxl2Completer" class="org.onosproject.sdxl2.cli.completer.SdxL2NameCompleter"/>
<bean id="connectPointCompleter" class="org.onosproject.cli.net.ConnectPointCompleter"/>
<bean id="sdxl2cpnameCompleter" class="org.onosproject.sdxl2.cli.completer.SdxL2CPNameCompleter"/>
+ <bean id="sdxl2vcnameCompleter" class="org.onosproject.sdxl2.cli.completer.SdxL2VCNameCompleter"/>
</blueprint>