Add configuration to pick type of VC
Change-Id: Id0fb3dadeffc19de4bf96a79de7044e34240e830
diff --git a/sdx-l2/src/main/java/org/onosproject/sdxl2/SdxL2ArpNdpHandler.java b/sdx-l2/src/main/java/org/onosproject/sdxl2/SdxL2ArpNdpHandler.java
index 48e78b9..6100763 100644
--- a/sdx-l2/src/main/java/org/onosproject/sdxl2/SdxL2ArpNdpHandler.java
+++ b/sdx-l2/src/main/java/org/onosproject/sdxl2/SdxL2ArpNdpHandler.java
@@ -45,7 +45,6 @@
import org.onosproject.net.packet.InboundPacket;
import org.onosproject.net.packet.PacketContext;
import org.onosproject.net.packet.PacketService;
-import org.slf4j.Logger;
import java.nio.ByteBuffer;
import java.util.Iterator;
@@ -55,26 +54,29 @@
import static org.onosproject.net.flow.instructions.L2ModificationInstruction.ModVlanIdInstruction;
import static org.onosproject.security.AppGuard.checkPermission;
import static org.onosproject.security.AppPermission.Type.PACKET_WRITE;
-import static org.slf4j.LoggerFactory.getLogger;
/**
* Implementation of ARP and NDP handler based on ProxyArpManager.
*/
public class SdxL2ArpNdpHandler {
- private final Logger log = getLogger(SdxL2ArpNdpHandler.class);
-
private static final String MSG_NULL = "ARP or NDP message cannot be null.";
- protected IntentService intentService;
+ private IntentService intentService;
- protected ApplicationId applicationId;
+ private ApplicationId applicationId;
- protected PacketService packetService;
+ private PacketService packetService;
- public static String vcType;
+ private static String vcType;
-
+ /**
+ * Creates an ARP/NDP packet handler.
+ *
+ * @param intentService IntentService object
+ * @param packetService PacketService object
+ * @param applicationId ApplicationId object
+ */
public SdxL2ArpNdpHandler(IntentService intentService,
PacketService packetService, ApplicationId applicationId) {
this.intentService = intentService;
@@ -390,7 +392,6 @@
}
/**
- * /**
* Builds TrafficSelector for MAC
* based tunnels.
*
@@ -407,7 +408,23 @@
}
return selectorBuilder.build();
}
-
}
+ /**
+ * Retrieves the SDX-L2 VC type.
+ *
+ * @return VC type
+ */
+ public static String getVcType() {
+ return vcType;
+ }
+
+ /**
+ * Sets up the SDX-L2 VC type.
+ *
+ * @param vcType VC type
+ */
+ public static void setVcType(String vcType) {
+ SdxL2ArpNdpHandler.vcType = vcType;
+ }
}
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 edd7901..69b3510 100644
--- a/sdx-l2/src/main/java/org/onosproject/sdxl2/SdxL2Manager.java
+++ b/sdx-l2/src/main/java/org/onosproject/sdxl2/SdxL2Manager.java
@@ -19,12 +19,15 @@
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.Modified;
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.Property;
import org.onlab.packet.Ethernet;
import org.onlab.packet.ICMP6;
import org.onlab.packet.IPv6;
+import org.onosproject.cfg.ComponentConfigService;
import org.onosproject.core.ApplicationId;
import org.onosproject.core.CoreService;
import org.onosproject.net.ConnectPoint;
@@ -32,7 +35,9 @@
import org.onosproject.net.edge.EdgePortService;
import org.onosproject.net.flow.DefaultTrafficSelector;
import org.onosproject.net.flow.TrafficSelector;
+import org.onosproject.net.intent.Intent;
import org.onosproject.net.intent.IntentService;
+import org.onosproject.net.intent.IntentState;
import org.onosproject.net.intent.Key;
import org.onosproject.net.packet.InboundPacket;
import org.onosproject.net.packet.PacketContext;
@@ -43,12 +48,15 @@
import org.slf4j.LoggerFactory;
import java.util.Collections;
+import java.util.Dictionary;
+import java.util.Iterator;
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;
+import static com.google.common.base.Strings.isNullOrEmpty;
import static org.onlab.packet.Ethernet.TYPE_ARP;
import static org.onlab.packet.Ethernet.TYPE_IPV6;
import static org.onlab.packet.ICMP6.NEIGHBOR_ADVERTISEMENT;
@@ -65,13 +73,17 @@
public class SdxL2Manager implements SdxL2Service {
private static final String SDXL2_APP = "org.onosproject.sdxl2";
+ private static final String ERROR_ADD_VC_CPS = "Unable to find %s and %s in sdxl2=%s";
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";
+ @Property(name = "VirtualCircuitType", value = VC_0, label = "Tunnel mechanism for Virtual Circuits")
+ private String vcType = VC_0;
+ private String previousvcType = vcType;
+
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)
@@ -81,7 +93,10 @@
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected EdgePortService edgePortService;
@Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
+ protected ComponentConfigService cfgService;
+ @Reference(cardinality = ReferenceCardinality.MANDATORY_UNARY)
protected PacketService packetService;
+
protected SdxL2Processor processor = new SdxL2Processor();
protected ApplicationId appId;
protected SdxL2MonitoringService monitoringManager;
@@ -97,8 +112,11 @@
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);
+ SdxL2ArpNdpHandler.setVcType(VC_0);
+ vcManager = buildVCManager();
+ cfgService.registerProperties(getClass());
+ readComponentConfiguration(context);
+ changeVCTunnel();
handleArpNdp();
log.info("Started");
}
@@ -108,11 +126,120 @@
*/
@Deactivate
protected void deactivate() {
- this.cleanSdxL2();
+ this.cleanup();
unhandleArpNdp();
log.info("Stopped");
}
+ @Modified
+ public void modified(ComponentContext context) {
+ readComponentConfiguration(context);
+ changeVCTunnel();
+ }
+
+ /**
+ * Determines if the currently used VC is active or not.
+ *
+ * @return Boolean value indicating whether VC is active (true) or not (false).
+ */
+ private boolean isCircuitActive() {
+ Iterator<Intent> intents = intentService.getIntents().iterator();
+ Intent intent;
+ while (intents.hasNext()) {
+ intent = intents.next();
+ if (intent.appId().equals(this.appId) &&
+ intentService.getIntentState(intent.key()) == IntentState.INSTALLED) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+
+ /**
+ * Checks if property name is defined and set to True.
+ *
+ * @param properties properties to be looked up
+ * @param propertyName the name of the property to look up
+ * @return value when the propertyName is defined or return null
+ */
+ private static String isTunnelEnabled(Dictionary<?, ?> properties,
+ String propertyName) {
+ String value = null;
+ try {
+ String s = (String) properties.get(propertyName);
+ value = isNullOrEmpty(s) ? null : s.trim();
+ if (value != null &&
+ !value.equals("MAC") &&
+ !value.equals("VLAN") &&
+ !value.equals("MPLS")) {
+ value = null;
+ }
+ } catch (ClassCastException e) {
+ // No propertyName defined.
+ }
+ return value;
+ }
+
+ /**
+ * Extracts properties from the component configuration context.
+ *
+ * @param context the component context
+ */
+ private void readComponentConfiguration(ComponentContext context) {
+ Dictionary<?, ?> properties = context.getProperties();
+ String tunnel;
+ tunnel = isTunnelEnabled(properties, "VirtualCircuitType");
+ if (tunnel == null) {
+ log.info("Tunnel mechanism for VC is not configured, " +
+ "using current value {}", vcType);
+ } else {
+ vcType = tunnel;
+ log.info("Configured. Tunnel mechanism is {}", vcType);
+ }
+ }
+
+ /**
+ * Changes the tunnel mechanism for the VCs.
+ */
+ private void changeVCTunnel() {
+ if (previousvcType.equals(vcType)) {
+ log.info("Tunnel mechanism has not been changed");
+ return;
+ }
+ if (isCircuitActive()) {
+ log.info("Change of tunnels not allowed - there are active circuits");
+ vcType = previousvcType;
+ return;
+ }
+ previousvcType = vcType;
+ SdxL2ArpNdpHandler.setVcType(vcType);
+ vcManager = buildVCManager();
+ }
+
+ /**
+ * Builds a VC depending on the internal variable "vcType", previously set-up.
+ * Default circuit is through VLANs
+ *
+ * @return VirtualCircuit object of the selected type
+ */
+ private SdxL2VCService buildVCManager() {
+ SdxL2VCService manager;
+ switch (vcType) {
+ case "MAC":
+ manager = new SdxL2MacVCManager(appId, sdxL2Store, intentService);
+ break;
+ case "MPLS":
+ manager = new SdxL2MplsVCManager(appId, sdxL2Store, intentService);
+ break;
+ default:
+ case "VLAN":
+ manager = new SdxL2VlanVCManager(appId, sdxL2Store, intentService);
+ break;
+ }
+ return manager;
+ }
+
@Override
public void createSdxL2(String sdxl2) {
@@ -290,7 +417,16 @@
*/
@Override
public void cleanSdxL2() {
+ Set<String> sdxl2s = this.getSdxL2s();
+ sdxl2s.forEach(sdxl2 -> this.deleteSdxL2(sdxl2));
+ }
+
+ /**
+ * Stops monitoring and unregister configuration service.
+ */
+ public void cleanup() {
this.monitoringManager.cleanup();
+ this.cfgService.unregisterProperties(getClass(), false);
}
/**
@@ -298,7 +434,7 @@
* and registers the SDX-L2 PacketProcessor.
*/
private void handleArpNdp() {
- SdxL2ArpNdpHandler.vcType = VC_0;
+ SdxL2ArpNdpHandler.setVcType(VC_0);
arpndpHandler = new SdxL2ArpNdpHandler(intentService, packetService, appId);
packetService.addProcessor(processor, PacketProcessor.director(1));