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/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());
}
/**