Update to ciena cordigmp app to add a cord port map for igmp tests
diff --git a/src/test/apps/ciena-cordigmp-1.0-SNAPSHOT.oar b/src/test/apps/ciena-cordigmp-1.0-SNAPSHOT.oar
index c2bd76c..15f70ed 100644
--- a/src/test/apps/ciena-cordigmp-1.0-SNAPSHOT.oar
+++ b/src/test/apps/ciena-cordigmp-1.0-SNAPSHOT.oar
Binary files differ
diff --git a/src/test/apps/ciena-cordigmp/src/main/java/org/ciena/cordigmp/CordIgmp.java b/src/test/apps/ciena-cordigmp/src/main/java/org/ciena/cordigmp/CordIgmp.java
index d3a515a..f3e51e7 100644
--- a/src/test/apps/ciena-cordigmp/src/main/java/org/ciena/cordigmp/CordIgmp.java
+++ b/src/test/apps/ciena-cordigmp/src/main/java/org/ciena/cordigmp/CordIgmp.java
@@ -81,6 +81,7 @@
import java.util.Dictionary;
import java.util.List;
import java.util.Map;
+import java.util.Collection;
import java.util.Properties;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicBoolean;
@@ -144,6 +145,9 @@
//TODO: move this to a ec map
private Map<IpAddress, Integer> groups = Maps.newConcurrentMap();
+ //Map of IGMP groups to port
+ private Map<IpAddress, IgmpPortPair> cordIgmpTranslateTable = Maps.newConcurrentMap();
+
//TODO: move this to distributed atomic long
private AtomicInteger channels = new AtomicInteger(0);
@@ -187,18 +191,19 @@
private Map<DeviceId, Boolean> deviceAvailability = new ConcurrentHashMap<>();
- private static final Class<AccessDeviceConfig> CONFIG_CLASS =
- AccessDeviceConfig.class;
+ private static final Class<CordIgmpTranslateConfig> CORD_IGMP_TRANSLATE_CONFIG_CLASS =
+ CordIgmpTranslateConfig.class;
- private ConfigFactory<DeviceId, AccessDeviceConfig> configFactory =
- new ConfigFactory<DeviceId, AccessDeviceConfig>(
- SubjectFactories.DEVICE_SUBJECT_FACTORY, CONFIG_CLASS, "accessDevice") {
+ private ConfigFactory<ApplicationId, CordIgmpTranslateConfig> cordIgmpTranslateConfigFactory =
+ new ConfigFactory<ApplicationId, CordIgmpTranslateConfig>(
+ SubjectFactories.APP_SUBJECT_FACTORY, CORD_IGMP_TRANSLATE_CONFIG_CLASS, "cordIgmpTranslate") {
@Override
- public AccessDeviceConfig createConfig() {
- return new AccessDeviceConfig();
+ public CordIgmpTranslateConfig createConfig() {
+ return new CordIgmpTranslateConfig();
}
};
+
@Activate
public void activate(ComponentContext context) {
componentConfigService.registerProperties(getClass());
@@ -208,7 +213,7 @@
clearRemoteRoutes();
- networkConfig.registerConfigFactory(configFactory);
+ networkConfig.registerConfigFactory(cordIgmpTranslateConfigFactory);
networkConfig.addListener(configListener);
networkConfig.getSubjects(DeviceId.class, AccessDeviceConfig.class).forEach(
@@ -221,6 +226,15 @@
}
);
+ CordIgmpTranslateConfig cordIgmpTranslateConfig = networkConfig.getConfig(appId, CordIgmpTranslateConfig.class);
+
+ if(cordIgmpTranslateConfig != null) {
+ Collection<McastPorts> translations = cordIgmpTranslateConfig.getCordIgmpTranslations();
+ for(McastPorts port: translations) {
+ cordIgmpTranslateTable.put(port.group(),
+ port.portPair());
+ }
+ }
mcastService.addListener(listener);
@@ -240,7 +254,7 @@
componentConfigService.unregisterProperties(getClass(), false);
deviceService.removeListener(deviceListener);
mcastService.removeListener(listener);
- networkConfig.unregisterConfigFactory(configFactory);
+ networkConfig.unregisterConfigFactory(cordIgmpTranslateConfigFactory);
networkConfig.removeListener(configListener);
deviceAvailability.clear();
log.info("Stopped");
@@ -401,8 +415,13 @@
return;
}
log.warn("Unknown OLT device for unprovisioning. Assuming OVS {}", loc.deviceId());
- final PortNumber inPort = PortNumber.portNumber(inputPort);
- final PortNumber outPort = PortNumber.portNumber(outputPort);
+ final IgmpPortPair portPair = cordIgmpTranslateTable.get(info.route().group());
+ if(portPair == null) {
+ log.warn("Ignoring unprovisioning for group " + info.route().group() + " with no port map");
+ return;
+ }
+ final PortNumber inPort = PortNumber.portNumber(portPair.inputPort());
+ final PortNumber outPort = PortNumber.portNumber(portPair.outputPort());
TrafficSelector.Builder mcast = DefaultTrafficSelector.builder()
.matchInPort(inPort)
.matchEthType(Ethernet.TYPE_IPV4)
@@ -432,10 +451,14 @@
log.warn("Ignoring provisioning mcast route for OLT device: " + sink.deviceId());
return;
}
-
+ final IgmpPortPair portPair = cordIgmpTranslateTable.get(route.group());
+ if(portPair == null) {
+ log.warn("Ports for Group " + route.group() + " not found in cord igmp map. Skipping provisioning.");
+ return;
+ }
Integer ret = groups.computeIfAbsent(route.group(), (g) -> {
- final PortNumber inPort = PortNumber.portNumber(inputPort);
- final PortNumber outPort = PortNumber.portNumber(outputPort);
+ final PortNumber inPort = PortNumber.portNumber(portPair.inputPort());
+ final PortNumber outPort = PortNumber.portNumber(portPair.outputPort());
TrafficSelector.Builder mcast = DefaultTrafficSelector.builder()
.matchInPort(inPort)
.matchEthType(Ethernet.TYPE_IPV4)
@@ -550,18 +573,20 @@
case CONFIG_ADDED:
case CONFIG_UPDATED:
- AccessDeviceConfig config =
- networkConfig.getConfig((DeviceId) event.subject(), CONFIG_CLASS);
- if (config != null) {
- oltData.put(config.getOlt().deviceId(), config.getOlt());
+ if (event.configClass().equals(CORD_IGMP_TRANSLATE_CONFIG_CLASS)) {
+ CordIgmpTranslateConfig config =
+ networkConfig.getConfig((ApplicationId) event.subject(),
+ CORD_IGMP_TRANSLATE_CONFIG_CLASS);
+ if (config != null) {
+ cordIgmpTranslateTable.clear();
+ config.getCordIgmpTranslations().forEach(
+ mcastPorts -> cordIgmpTranslateTable.put(mcastPorts.group(), mcastPorts.portPair()));
+ }
}
-
break;
case CONFIG_REGISTERED:
case CONFIG_UNREGISTERED:
- break;
case CONFIG_REMOVED:
- oltData.remove(event.subject());
break;
default:
break;
@@ -570,7 +595,7 @@
@Override
public boolean isRelevant(NetworkConfigEvent event) {
- return event.configClass().equals(CONFIG_CLASS);
+ return event.configClass().equals(CORD_IGMP_TRANSLATE_CONFIG_CLASS);
}
diff --git a/src/test/apps/ciena-cordigmp/src/main/java/org/ciena/cordigmp/CordIgmpTranslateConfig.java b/src/test/apps/ciena-cordigmp/src/main/java/org/ciena/cordigmp/CordIgmpTranslateConfig.java
new file mode 100644
index 0000000..e55cf11
--- /dev/null
+++ b/src/test/apps/ciena-cordigmp/src/main/java/org/ciena/cordigmp/CordIgmpTranslateConfig.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2016 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.ciena.cordigmp;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import org.onlab.packet.IpAddress;
+import org.onosproject.core.ApplicationId;
+import org.onosproject.net.config.Config;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * IGMP SSM translate configuration.
+ */
+public class CordIgmpTranslateConfig extends Config<ApplicationId> {
+
+ private static final String GROUP = "group";
+ private static final String INPUT_PORT = "inputPort";
+ private static final String OUTPUT_PORT = "outputPort";
+
+ @Override
+ public boolean isValid() {
+ for (JsonNode node : array) {
+ if (!hasOnlyFields((ObjectNode) node, GROUP, INPUT_PORT, OUTPUT_PORT)) {
+ return false;
+ }
+
+ if (!(isIpAddress((ObjectNode) node, GROUP, FieldPresence.MANDATORY) &&
+ node.get(INPUT_PORT).isInt() && node.get(OUTPUT_PORT).isInt())) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Gets the list of CordIgmp translations.
+ *
+ * @return CordIgmp translations
+ */
+ public List<McastPorts> getCordIgmpTranslations() {
+ List<McastPorts> translations = new ArrayList();
+ for (JsonNode node : array) {
+ translations.add(
+ new McastPorts(
+ IpAddress.valueOf(node.path(GROUP).asText().trim()),
+ Integer.valueOf(node.path(INPUT_PORT).asText().trim()),
+ Integer.valueOf(node.path(OUTPUT_PORT).asText().trim())));
+ }
+ return translations;
+ }
+}
diff --git a/src/test/apps/ciena-cordigmp/src/main/java/org/ciena/cordigmp/IgmpPortPair.java b/src/test/apps/ciena-cordigmp/src/main/java/org/ciena/cordigmp/IgmpPortPair.java
new file mode 100644
index 0000000..176cac9
--- /dev/null
+++ b/src/test/apps/ciena-cordigmp/src/main/java/org/ciena/cordigmp/IgmpPortPair.java
@@ -0,0 +1,20 @@
+package org.ciena.cordigmp;
+
+public class IgmpPortPair {
+ private final Integer inputPort;
+ private final Integer outputPort;
+
+ public IgmpPortPair(Integer inputPort, Integer outputPort) {
+ this.inputPort = inputPort;
+ this.outputPort = outputPort;
+ }
+
+ public Integer inputPort() {
+ return inputPort;
+ }
+
+ public Integer outputPort() {
+ return outputPort;
+ }
+}
+
diff --git a/src/test/apps/ciena-cordigmp/src/main/java/org/ciena/cordigmp/McastPorts.java b/src/test/apps/ciena-cordigmp/src/main/java/org/ciena/cordigmp/McastPorts.java
new file mode 100644
index 0000000..e0cd622
--- /dev/null
+++ b/src/test/apps/ciena-cordigmp/src/main/java/org/ciena/cordigmp/McastPorts.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright 2015 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.ciena.cordigmp;
+
+import com.google.common.annotations.Beta;
+import com.google.common.base.Objects;
+import org.onlab.packet.IpAddress;
+
+import static com.google.common.base.MoreObjects.toStringHelper;
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * An entity representing a multicast group and its input and output ports
+ */
+@Beta
+public class McastPorts {
+
+ private final IpAddress group;
+ private final IgmpPortPair portPair;
+
+ public McastPorts(IpAddress group, Integer inputPort, Integer outputPort) {
+ checkNotNull(group, "Multicast route must specify a group address");
+ checkNotNull(inputPort, "Must indicate input port");
+ checkNotNull(outputPort, "Must indicate output port");
+ this.group = group;
+ this.portPair = new IgmpPortPair(inputPort, outputPort);
+ }
+
+ /**
+ * Fetches the group address of this route.
+ *
+ * @return an ip address
+ */
+ public IpAddress group() {
+ return group;
+ }
+
+ public Integer inputPort() {
+ return portPair.inputPort();
+ }
+
+ public Integer outputPort() {
+ return portPair.outputPort();
+ }
+
+ public IgmpPortPair portPair() {
+ return portPair;
+ }
+
+ @Override
+ public String toString() {
+ return toStringHelper(this)
+ .add("group", group)
+ .add("inputPort", inputPort())
+ .add("outputPort", outputPort())
+ .toString();
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+ McastPorts that = (McastPorts) o;
+ return Objects.equal(group, that.group) &&
+ Objects.equal(inputPort(), that.inputPort()) &&
+ Objects.equal(outputPort(), that.outputPort());
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hashCode(group, inputPort(), outputPort());
+ }
+
+}