summaryrefslogtreecommitdiffstats
path: root/framework/src/onos/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'framework/src/onos/drivers')
-rw-r--r--framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/DefaultMoveExtensionTreatment.java146
-rw-r--r--framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/MoveExtensionTreatment.java59
-rw-r--r--framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/NiciraExtensionSelectorInterpreter.java102
-rw-r--r--framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/NiciraExtensionTreatmentInterpreter.java88
-rw-r--r--framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/NiciraMatchNshContextHeader.java95
-rw-r--r--framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/NiciraMatchNshSi.java91
-rw-r--r--framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/NiciraMatchNshSpi.java91
-rw-r--r--framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/NiciraMoveTreatmentFactory.java100
-rw-r--r--framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/NiciraResubmit.java5
-rw-r--r--framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/NiciraResubmitTable.java114
-rw-r--r--framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/NiciraSetNshContextHeader.java108
-rw-r--r--framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/NiciraSetNshSi.java101
-rw-r--r--framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/NiciraSetNshSpi.java17
-rw-r--r--framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/NiciraSetTunnelDst.java6
-rw-r--r--framework/src/onos/drivers/src/main/java/org/onosproject/driver/handshaker/CalientFiberSwitchHandshaker.java42
-rw-r--r--framework/src/onos/drivers/src/main/java/org/onosproject/driver/handshaker/OfOpticalSwitchImplLinc13.java43
-rw-r--r--framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/CpqdOFDPA2Pipeline.java116
-rw-r--r--framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/OFDPA2Pipeline.java769
-rw-r--r--framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/OpenstackPipeline.java286
-rw-r--r--framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/SpringOpenTTP.java53
-rw-r--r--framework/src/onos/drivers/src/main/resources/onos-drivers.xml8
-rw-r--r--framework/src/onos/drivers/src/test/java/org/onosproject/driver/extensions/NiciraSetNshContextHeaderTest.java68
-rw-r--r--framework/src/onos/drivers/src/test/java/org/onosproject/driver/extensions/NiciraSetNshSiTest.java52
-rw-r--r--framework/src/onos/drivers/src/test/java/org/onosproject/driver/extensions/NiciraSetNshSpiTest.java52
24 files changed, 2073 insertions, 539 deletions
diff --git a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/DefaultMoveExtensionTreatment.java b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/DefaultMoveExtensionTreatment.java
new file mode 100644
index 00000000..140a8167
--- /dev/null
+++ b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/DefaultMoveExtensionTreatment.java
@@ -0,0 +1,146 @@
+/*
+ * 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.onosproject.driver.extensions;
+
+import java.util.Map;
+import java.util.Objects;
+
+import org.onlab.util.KryoNamespace;
+import org.onosproject.net.flow.AbstractExtension;
+import org.onosproject.net.flow.instructions.ExtensionTreatmentType;
+
+import com.google.common.base.MoreObjects;
+import com.google.common.collect.Maps;
+
+/**
+ * Default implementation of Move treatment.
+ */
+public class DefaultMoveExtensionTreatment extends AbstractExtension
+ implements MoveExtensionTreatment {
+
+ private int srcOfs;
+ private int dstOfs;
+ private int nBits;
+ private int src;
+ private int dst;
+ private ExtensionTreatmentType type;
+
+ private final KryoNamespace appKryo = new KryoNamespace.Builder()
+ .register(byte[].class).register(Integer.class).register(Map.class)
+ .build();
+
+ /**
+ * Creates a new move Treatment.
+ *
+ * @param srcOfs source offset
+ * @param dstOfs destination offset
+ * @param nBits nbits
+ * @param src source
+ * @param dst destination
+ * @param type extension treatment type
+ */
+ public DefaultMoveExtensionTreatment(int srcOfs, int dstOfs, int nBits,
+ int src, int dst, ExtensionTreatmentType type) {
+ this.srcOfs = srcOfs;
+ this.dstOfs = dstOfs;
+ this.nBits = nBits;
+ this.src = src;
+ this.dst = dst;
+ this.type = type;
+ }
+
+ @Override
+ public ExtensionTreatmentType type() {
+ return type;
+ }
+
+ @Override
+ public byte[] serialize() {
+ Map<String, Integer> values = Maps.newHashMap();
+ values.put("srcOfs", srcOfs);
+ values.put("dstOfs", dstOfs);
+ values.put("nBits", nBits);
+ values.put("src", src);
+ values.put("dst", dst);
+ values.put("type", ExtensionTreatmentType.ExtensionTreatmentTypes.valueOf(type.toString()).ordinal());
+ return appKryo.serialize(values);
+ }
+
+ @Override
+ public void deserialize(byte[] data) {
+ Map<String, Integer> values = appKryo.deserialize(data);
+ srcOfs = values.get("srcOfs");
+ dstOfs = values.get("dstOfs");
+ nBits = values.get("nBits");
+ src = values.get("src");
+ dst = values.get("dst");
+ type = new ExtensionTreatmentType(values.get("type").intValue());
+ }
+
+ @Override
+ public int srcOffset() {
+ return srcOfs;
+ }
+
+ @Override
+ public int dstOffset() {
+ return dstOfs;
+ }
+
+ @Override
+ public int src() {
+ return src;
+ }
+
+ @Override
+ public int dst() {
+ return dst;
+ }
+
+ @Override
+ public int nBits() {
+ return nBits;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(srcOfs, dstOfs, src, dst, nBits);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof DefaultMoveExtensionTreatment) {
+ DefaultMoveExtensionTreatment that = (DefaultMoveExtensionTreatment) obj;
+ return Objects.equals(srcOfs, that.srcOfs)
+ && Objects.equals(dstOfs, that.dstOfs)
+ && Objects.equals(src, that.src)
+ && Objects.equals(dst, that.dst)
+ && Objects.equals(nBits, that.nBits);
+
+ }
+ return false;
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(getClass()).add("srcOfs", srcOfs)
+ .add("dstOfs", dstOfs).add("nBits", nBits).add("src", src)
+ .add("dst", dst).toString();
+ }
+}
diff --git a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/MoveExtensionTreatment.java b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/MoveExtensionTreatment.java
new file mode 100644
index 00000000..b67e1bed
--- /dev/null
+++ b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/MoveExtensionTreatment.java
@@ -0,0 +1,59 @@
+/*
+ * 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.onosproject.driver.extensions;
+
+import org.onosproject.net.flow.instructions.ExtensionTreatment;
+
+/**
+ * The abstraction of Move Treatment.
+ */
+public interface MoveExtensionTreatment extends ExtensionTreatment {
+
+ /**
+ * Returns SRC_OFS field of move extension action.
+ *
+ * @return SRC_OFS
+ */
+ int srcOffset();
+
+ /**
+ * Returns DST_OFS field of move extension action.
+ *
+ * @return DST_OFS
+ */
+ int dstOffset();
+
+ /**
+ * Returns SRC field of move extension action.
+ *
+ * @return SRC
+ */
+ int src();
+
+ /**
+ * Returns DST field of move extension action.
+ *
+ * @return DST
+ */
+ int dst();
+
+ /**
+ * Returns N_BITS field of move extension action.
+ *
+ * @return N_BITS
+ */
+ int nBits();
+}
diff --git a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/NiciraExtensionSelectorInterpreter.java b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/NiciraExtensionSelectorInterpreter.java
new file mode 100644
index 00000000..9f302991
--- /dev/null
+++ b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/NiciraExtensionSelectorInterpreter.java
@@ -0,0 +1,102 @@
+/*
+ * 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.onosproject.driver.extensions;
+
+import org.onosproject.net.behaviour.ExtensionSelectorResolver;
+import org.onosproject.net.driver.AbstractHandlerBehaviour;
+import org.onosproject.net.flow.criteria.ExtensionSelector;
+import org.onosproject.net.flow.criteria.ExtensionSelectorType;
+import org.onosproject.openflow.controller.ExtensionSelectorInterpreter;
+import org.projectfloodlight.openflow.protocol.OFFactory;
+import org.projectfloodlight.openflow.protocol.oxm.OFOxm;
+
+/**
+ * Interpreter for Nicira OpenFlow selector extensions.
+ */
+public class NiciraExtensionSelectorInterpreter
+ extends AbstractHandlerBehaviour
+ implements ExtensionSelectorInterpreter, ExtensionSelectorResolver {
+
+ @Override
+ public boolean supported(ExtensionSelectorType extensionSelectorType) {
+ if (extensionSelectorType.equals(ExtensionSelectorType.ExtensionSelectorTypes.NICIRA_MATCH_NSH_SPI.type())) {
+ return true;
+ }
+ if (extensionSelectorType.equals(ExtensionSelectorType.ExtensionSelectorTypes.NICIRA_MATCH_NSH_SI.type())) {
+ return true;
+ }
+ if (extensionSelectorType.equals(ExtensionSelectorType.ExtensionSelectorTypes.NICIRA_MATCH_NSH_CH1.type())) {
+ return true;
+ }
+ if (extensionSelectorType.equals(ExtensionSelectorType.ExtensionSelectorTypes.NICIRA_MATCH_NSH_CH2.type())) {
+ return true;
+ }
+ if (extensionSelectorType.equals(ExtensionSelectorType.ExtensionSelectorTypes.NICIRA_MATCH_NSH_CH3.type())) {
+ return true;
+ }
+ if (extensionSelectorType.equals(ExtensionSelectorType.ExtensionSelectorTypes.NICIRA_MATCH_NSH_CH4.type())) {
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public OFOxm<?> mapSelector(OFFactory factory, ExtensionSelector extensionSelector) {
+ ExtensionSelectorType type = extensionSelector.type();
+ if (type.equals(ExtensionSelectorType.ExtensionSelectorTypes.NICIRA_MATCH_NSH_SPI.type())) {
+ // TODO
+ }
+ if (type.equals(ExtensionSelectorType.ExtensionSelectorTypes.NICIRA_MATCH_NSH_SI.type())) {
+ // TODO
+ }
+ if (type.equals(ExtensionSelectorType.ExtensionSelectorTypes.NICIRA_MATCH_NSH_CH1.type())) {
+ // TODO
+ }
+ if (type.equals(ExtensionSelectorType.ExtensionSelectorTypes.NICIRA_MATCH_NSH_CH2.type())) {
+ // TODO
+ }
+ if (type.equals(ExtensionSelectorType.ExtensionSelectorTypes.NICIRA_MATCH_NSH_CH3.type())) {
+ // TODO
+ }
+ if (type.equals(ExtensionSelectorType.ExtensionSelectorTypes.NICIRA_MATCH_NSH_CH4.type())) {
+ // TODO
+ }
+ return null;
+ }
+
+ @Override
+ public ExtensionSelector mapOxm(OFOxm<?> oxm) {
+ return null;
+ }
+
+ @Override
+ public ExtensionSelector getExtensionSelector(ExtensionSelectorType type) {
+ if (type.equals(ExtensionSelectorType.ExtensionSelectorTypes.NICIRA_MATCH_NSH_SPI.type())) {
+ return new NiciraMatchNshSpi();
+ }
+ if (type.equals(ExtensionSelectorType.ExtensionSelectorTypes.NICIRA_MATCH_NSH_SI.type())) {
+ return new NiciraMatchNshSi();
+ }
+ if (type.equals(ExtensionSelectorType.ExtensionSelectorTypes.NICIRA_MATCH_NSH_CH1.type())
+ || type.equals(ExtensionSelectorType.ExtensionSelectorTypes.NICIRA_MATCH_NSH_CH2.type())
+ || type.equals(ExtensionSelectorType.ExtensionSelectorTypes.NICIRA_MATCH_NSH_CH3.type())
+ || type.equals(ExtensionSelectorType.ExtensionSelectorTypes.NICIRA_MATCH_NSH_CH4.type())) {
+ return new NiciraMatchNshContextHeader(type);
+ }
+ return null;
+ }
+}
diff --git a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/NiciraExtensionTreatmentInterpreter.java b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/NiciraExtensionTreatmentInterpreter.java
index a7f70f98..5e374d9b 100644
--- a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/NiciraExtensionTreatmentInterpreter.java
+++ b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/NiciraExtensionTreatmentInterpreter.java
@@ -31,7 +31,7 @@ import org.projectfloodlight.openflow.protocol.oxm.OFOxmTunnelIpv4Dst;
import org.projectfloodlight.openflow.types.IPv4Address;
/**
- * Interpreter for Nicira OpenFlow extensions.
+ * Interpreter for Nicira OpenFlow treatment extensions.
*/
public class NiciraExtensionTreatmentInterpreter extends AbstractHandlerBehaviour
implements ExtensionTreatmentInterpreter, ExtensionTreatmentResolver {
@@ -46,8 +46,42 @@ public class NiciraExtensionTreatmentInterpreter extends AbstractHandlerBehaviou
ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_RESUBMIT.type())) {
return true;
}
+ if (extensionTreatmentType.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_SET_NSH_SPI.type())) {
+ return true;
+ }
+ if (extensionTreatmentType.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_SET_NSH_SI.type())) {
+ return true;
+ }
+ if (extensionTreatmentType.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_SET_NSH_CH1.type())) {
+ return true;
+ }
+ if (extensionTreatmentType.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_SET_NSH_CH2.type())) {
+ return true;
+ }
+ if (extensionTreatmentType.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_SET_NSH_CH3.type())) {
+ return true;
+ }
+ if (extensionTreatmentType.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_SET_NSH_CH4.type())) {
+ return true;
+ }
if (extensionTreatmentType.equals(
- ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_SET_NSH_SPI.type())) {
+ ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_RESUBMIT_TABLE.type())) {
+ return true;
+ }
+ if (extensionTreatmentType.equals(
+ ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_MOV_ARP_SHA_TO_THA.type())) {
+ return true;
+ }
+ if (extensionTreatmentType.equals(
+ ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_MOV_ARP_SPA_TO_TPA.type())) {
+ return true;
+ }
+ if (extensionTreatmentType.equals(
+ ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_MOV_ETH_SRC_TO_DST.type())) {
+ return true;
+ }
+ if (extensionTreatmentType.equals(
+ ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_MOV_IP_SRC_TO_DST.type())) {
return true;
}
return false;
@@ -62,11 +96,35 @@ public class NiciraExtensionTreatmentInterpreter extends AbstractHandlerBehaviou
IPv4Address.of(tunnelDst.tunnelDst().toInt())));
}
if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_RESUBMIT.type())) {
- // TODO this will be implemented later
+ // TODO this will be implemented later
}
if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_SET_NSH_SPI.type())) {
// TODO this will be implemented later
}
+ if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_RESUBMIT_TABLE.type())) {
+ // TODO this will be implemented later
+ }
+ if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_SET_NSH_SI.type())) {
+ // TODO this will be implemented later
+ }
+ if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_SET_NSH_CH1.type())) {
+ // TODO this will be implemented later
+ }
+ if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_SET_NSH_CH2.type())) {
+ // TODO this will be implemented later
+ }
+ if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_SET_NSH_CH3.type())) {
+ // TODO this will be implemented later
+ }
+ if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_SET_NSH_CH4.type())) {
+ // TODO this will be implemented later
+ }
+ if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_MOV_ETH_SRC_TO_DST.type())
+ || type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_MOV_ARP_SPA_TO_TPA.type())
+ || type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_MOV_ETH_SRC_TO_DST.type())
+ || type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_MOV_IP_SRC_TO_DST.type())) {
+ // TODO this will be implemented later
+ }
return null;
}
@@ -95,9 +153,33 @@ public class NiciraExtensionTreatmentInterpreter extends AbstractHandlerBehaviou
if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_RESUBMIT.type())) {
return new NiciraResubmit();
}
+ if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_RESUBMIT_TABLE.type())) {
+ return new NiciraResubmitTable();
+ }
if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_SET_NSH_SPI.type())) {
return new NiciraSetNshSpi();
}
+ if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_SET_NSH_SI.type())) {
+ return new NiciraSetNshSi();
+ }
+ if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_SET_NSH_CH1.type())
+ || type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_SET_NSH_CH2.type())
+ || type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_SET_NSH_CH3.type())
+ || type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_SET_NSH_CH4.type())) {
+ return new NiciraSetNshContextHeader(type);
+ }
+ if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_MOV_ARP_SHA_TO_THA.type())) {
+ return NiciraMoveTreatmentFactory.createNiciraMovArpShaToTha();
+ }
+ if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_MOV_ARP_SPA_TO_TPA.type())) {
+ return NiciraMoveTreatmentFactory.createNiciraMovArpSpaToTpa();
+ }
+ if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_MOV_ETH_SRC_TO_DST.type())) {
+ return NiciraMoveTreatmentFactory.createNiciraMovEthSrcToDst();
+ }
+ if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_MOV_IP_SRC_TO_DST.type())) {
+ return NiciraMoveTreatmentFactory.createNiciraMovIpSrcToDst();
+ }
throw new UnsupportedOperationException(
"Driver does not support extension type " + type.toString());
}
diff --git a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/NiciraMatchNshContextHeader.java b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/NiciraMatchNshContextHeader.java
new file mode 100644
index 00000000..5f37247f
--- /dev/null
+++ b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/NiciraMatchNshContextHeader.java
@@ -0,0 +1,95 @@
+/*
+ * 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.onosproject.driver.extensions;
+
+import static com.google.common.base.MoreObjects.toStringHelper;
+
+import java.util.Objects;
+
+import org.onlab.util.KryoNamespace;
+import org.onosproject.net.NshContextHeader;
+import org.onosproject.net.flow.AbstractExtension;
+import org.onosproject.net.flow.criteria.ExtensionSelector;
+import org.onosproject.net.flow.criteria.ExtensionSelectorType;
+/**
+ * Implementation of Nsh context header criterion.
+ */
+public final class NiciraMatchNshContextHeader extends AbstractExtension implements ExtensionSelector {
+ private NshContextHeader nshContextHeader;
+ private ExtensionSelectorType type;
+
+ private final KryoNamespace appKryo = new KryoNamespace.Builder().build();
+
+ /**
+ * Constructor to create Nsh context header.
+ *
+ * @param type extension selector type
+ */
+ public NiciraMatchNshContextHeader(ExtensionSelectorType type) {
+ this.nshContextHeader = null;
+ this.type = type;
+ }
+
+ /**
+ * Gets the nsh context header to match.
+ *
+ * @return the nsh context header to match
+ */
+ public NshContextHeader nshContextHeader() {
+ return nshContextHeader;
+ }
+
+ @Override
+ public byte[] serialize() {
+ return appKryo.serialize(nshContextHeader.nshContextHeader());
+ }
+
+ @Override
+ public void deserialize(byte[] data) {
+ nshContextHeader = nshContextHeader.of(appKryo.deserialize(data));
+
+ }
+
+ @Override
+ public ExtensionSelectorType type() {
+ return type;
+ }
+
+ @Override
+ public String toString() {
+ return toStringHelper(type().toString())
+ .add("nshContextHeader", nshContextHeader.toString())
+ .toString();
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(type(), nshContextHeader);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof NiciraMatchNshContextHeader) {
+ NiciraMatchNshContextHeader that = (NiciraMatchNshContextHeader) obj;
+ return Objects.equals(nshContextHeader, that.nshContextHeader) &&
+ Objects.equals(this.type(), that.type());
+ }
+ return false;
+ }
+}
diff --git a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/NiciraMatchNshSi.java b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/NiciraMatchNshSi.java
new file mode 100644
index 00000000..c98a584a
--- /dev/null
+++ b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/NiciraMatchNshSi.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.onosproject.driver.extensions;
+
+import static com.google.common.base.MoreObjects.toStringHelper;
+
+import java.util.Objects;
+
+import org.onlab.util.KryoNamespace;
+import org.onosproject.net.NshServiceIndex;
+import org.onosproject.net.flow.AbstractExtension;
+import org.onosproject.net.flow.criteria.ExtensionSelector;
+import org.onosproject.net.flow.criteria.ExtensionSelectorType;
+/**
+ * Implementation of NSH Service Index(SI).
+ */
+public final class NiciraMatchNshSi extends AbstractExtension implements ExtensionSelector {
+
+ private NshServiceIndex nshSi;
+
+ private final KryoNamespace appKryo = new KryoNamespace.Builder().build();
+
+ /**
+ * Default constructor.
+ *
+ */
+ public NiciraMatchNshSi() {
+ this.nshSi = null;
+ }
+
+ /**
+ * Gets the nsh service index to match.
+ *
+ * @return the si to match
+ */
+ public NshServiceIndex nshSi() {
+ return nshSi;
+ }
+
+ @Override
+ public byte[] serialize() {
+ return appKryo.serialize(nshSi.serviceIndex());
+ }
+
+ @Override
+ public void deserialize(byte[] data) {
+ nshSi = NshServiceIndex.of(appKryo.deserialize(data));
+ }
+
+ @Override
+ public ExtensionSelectorType type() {
+ return ExtensionSelectorType.ExtensionSelectorTypes.NICIRA_MATCH_NSH_SI.type();
+ }
+
+ @Override
+ public String toString() {
+ return toStringHelper(type().toString())
+ .add("nshSi", nshSi.toString())
+ .toString();
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(type(), nshSi);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof NiciraMatchNshSi) {
+ NiciraMatchNshSi that = (NiciraMatchNshSi) obj;
+ return Objects.equals(nshSi, that.nshSi);
+ }
+ return false;
+ }
+}
diff --git a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/NiciraMatchNshSpi.java b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/NiciraMatchNshSpi.java
new file mode 100644
index 00000000..42bb78d4
--- /dev/null
+++ b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/NiciraMatchNshSpi.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.onosproject.driver.extensions;
+
+import static com.google.common.base.MoreObjects.toStringHelper;
+
+import java.util.Objects;
+
+import org.onlab.util.KryoNamespace;
+import org.onosproject.net.NshServicePathId;
+import org.onosproject.net.flow.AbstractExtension;
+import org.onosproject.net.flow.criteria.ExtensionSelector;
+import org.onosproject.net.flow.criteria.ExtensionSelectorType;
+
+/**
+ * Implementation of NSH Service Path Id selector.
+ */
+public final class NiciraMatchNshSpi extends AbstractExtension implements ExtensionSelector {
+ private NshServicePathId nshSpi;
+
+ private final KryoNamespace appKryo = new KryoNamespace.Builder().build();
+
+ /**
+ * Default constructor.
+ */
+ public NiciraMatchNshSpi() {
+ this.nshSpi = null;
+ }
+
+ /**
+ * Gets the network service path id to match.
+ *
+ * @return the nshSpi to match
+ */
+ public NshServicePathId nshSpi() {
+ return nshSpi;
+ }
+
+ @Override
+ public ExtensionSelectorType type() {
+ return ExtensionSelectorType.ExtensionSelectorTypes.NICIRA_MATCH_NSH_SPI.type();
+ }
+
+ @Override
+ public byte[] serialize() {
+ return appKryo.serialize(nshSpi);
+ }
+
+ @Override
+ public void deserialize(byte[] data) {
+ nshSpi = NshServicePathId.of(appKryo.deserialize(data));
+ }
+
+ @Override
+ public String toString() {
+ return toStringHelper(type().toString())
+ .add("nshSpi", nshSpi.toString())
+ .toString();
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(type(), nshSpi);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof NiciraMatchNshSpi) {
+ NiciraMatchNshSpi that = (NiciraMatchNshSpi) obj;
+ return Objects.equals(nshSpi, that.nshSpi) &&
+ Objects.equals(this.type(), that.type());
+ }
+ return false;
+ }
+}
diff --git a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/NiciraMoveTreatmentFactory.java b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/NiciraMoveTreatmentFactory.java
new file mode 100644
index 00000000..ac42a3b2
--- /dev/null
+++ b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/NiciraMoveTreatmentFactory.java
@@ -0,0 +1,100 @@
+/*
+ * 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.onosproject.driver.extensions;
+
+import org.onosproject.net.flow.instructions.ExtensionTreatment;
+import org.onosproject.net.flow.instructions.ExtensionTreatmentType;
+
+/**
+ * The factory of move treatment.
+ */
+public final class NiciraMoveTreatmentFactory {
+
+ /**
+ * Public constructor is prohibited.
+ */
+ private NiciraMoveTreatmentFactory() {
+
+ }
+
+ /**
+ * Creates a move treatment that move arp sha to tha.
+ *
+ * @return ExtensionTreatment
+ */
+ public static ExtensionTreatment createNiciraMovArpShaToTha() {
+ int srcOfs = 0;
+ int dstOfs = 0;
+ int nBits = 48;
+ int srcSha = 0x00012206;
+ int dstTha = 0x00012406;
+ return new DefaultMoveExtensionTreatment(srcOfs, dstOfs, nBits, srcSha,
+ dstTha,
+ ExtensionTreatmentType.ExtensionTreatmentTypes
+ .NICIRA_MOV_ARP_SHA_TO_THA.type());
+ }
+
+ /**
+ * Creates a move treatment that move arp spa to tpa.
+ *
+ * @return ExtensionTreatment
+ */
+ public static ExtensionTreatment createNiciraMovArpSpaToTpa() {
+ int srcOfs = 0;
+ int dstOfs = 0;
+ int nBits = 32;
+ int srcSpa = 0x00002004;
+ int dstTpa = 0x00002204;
+ return new DefaultMoveExtensionTreatment(srcOfs, dstOfs, nBits, srcSpa,
+ dstTpa,
+ ExtensionTreatmentType.ExtensionTreatmentTypes
+ .NICIRA_MOV_ARP_SPA_TO_TPA.type());
+ }
+
+ /**
+ * Creates a move treatment that move eth src to dst.
+ *
+ * @return ExtensionTreatment
+ */
+ public static ExtensionTreatment createNiciraMovEthSrcToDst() {
+ int srcOfs = 0;
+ int dstOfs = 0;
+ int nBits = 48;
+ int srcEth = 0x00000406;
+ int dstEth = 0x00000206;
+ return new DefaultMoveExtensionTreatment(srcOfs, dstOfs, nBits, srcEth,
+ dstEth,
+ ExtensionTreatmentType.ExtensionTreatmentTypes
+ .NICIRA_MOV_ETH_SRC_TO_DST.type());
+ }
+
+ /**
+ * Creates a move treatment that move ip src to dst.
+ *
+ * @return ExtensionTreatment
+ */
+ public static ExtensionTreatment createNiciraMovIpSrcToDst() {
+ int srcOfs = 0;
+ int dstOfs = 0;
+ int nBits = 32;
+ int srcIp = 0x00000e04;
+ int dstIp = 0x00001006;
+ return new DefaultMoveExtensionTreatment(srcOfs, dstOfs, nBits, srcIp,
+ dstIp,
+ ExtensionTreatmentType.ExtensionTreatmentTypes
+ .NICIRA_MOV_IP_SRC_TO_DST.type());
+ }
+}
diff --git a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/NiciraResubmit.java b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/NiciraResubmit.java
index 481b6f9c..b85af4f2 100644
--- a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/NiciraResubmit.java
+++ b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/NiciraResubmit.java
@@ -19,7 +19,8 @@ package org.onosproject.driver.extensions;
import com.google.common.base.MoreObjects;
import org.onlab.util.KryoNamespace;
import org.onosproject.net.PortNumber;
-import org.onosproject.net.flow.instructions.AbstractExtensionTreatment;
+import org.onosproject.net.flow.AbstractExtension;
+import org.onosproject.net.flow.instructions.ExtensionTreatment;
import org.onosproject.net.flow.instructions.ExtensionTreatmentType;
import org.onosproject.store.serializers.PortNumberSerializer;
@@ -30,7 +31,7 @@ import static com.google.common.base.Preconditions.checkNotNull;
/**
* Nicira resubmit extension instruction.
*/
-public class NiciraResubmit extends AbstractExtensionTreatment {
+public class NiciraResubmit extends AbstractExtension implements ExtensionTreatment {
private PortNumber inPort;
diff --git a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/NiciraResubmitTable.java b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/NiciraResubmitTable.java
new file mode 100644
index 00000000..4743d217
--- /dev/null
+++ b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/NiciraResubmitTable.java
@@ -0,0 +1,114 @@
+/*
+ * 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.onosproject.driver.extensions;
+
+import com.google.common.base.MoreObjects;
+
+import org.onlab.util.KryoNamespace;
+import org.onosproject.net.PortNumber;
+import org.onosproject.net.flow.AbstractExtension;
+import org.onosproject.net.flow.instructions.ExtensionTreatment;
+import org.onosproject.net.flow.instructions.ExtensionTreatmentType;
+import org.onosproject.store.serializers.PortNumberSerializer;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Objects;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+/**
+ * Nicira resubmit-table extension instruction.
+ */
+public class NiciraResubmitTable extends AbstractExtension implements
+ ExtensionTreatment {
+
+ //the list of the in port number(PortNumber) and the table(short)
+ private List<Object> inPortAndTable = new ArrayList<Object>();
+
+ private final KryoNamespace appKryo = new KryoNamespace.Builder()
+ .register(ArrayList.class)
+ .register(new PortNumberSerializer(), PortNumber.class)
+ .register(short.class)
+ .register(byte[].class)
+ .build();
+
+ /**
+ * Creates a new resubmit-table instruction.
+ */
+ NiciraResubmitTable() {
+ inPortAndTable = null;
+ }
+
+ /**
+ * Creates a new resubmit-table instruction with a particular inPort and table.
+ *
+ * @param inPortAndTable the list of in port number and table
+ */
+ public NiciraResubmitTable(List<Object> inPortAndTable) {
+ checkNotNull(inPortAndTable);
+ this.inPortAndTable = inPortAndTable;
+ }
+
+ /**
+ * Gets the inPortAndTable.
+ *
+ * @return inPortAndTable
+ */
+ public List<Object> inPortAndTable() {
+ return inPortAndTable;
+ }
+
+ @Override
+ public ExtensionTreatmentType type() {
+ return ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_RESUBMIT_TABLE.type();
+ }
+
+ @Override
+ public void deserialize(byte[] data) {
+ inPortAndTable = appKryo.deserialize(data);
+ }
+
+ @Override
+ public byte[] serialize() {
+ return appKryo.serialize(inPortAndTable);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(inPortAndTable);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof NiciraResubmitTable) {
+ NiciraResubmitTable that = (NiciraResubmitTable) obj;
+ return Objects.equals(inPortAndTable, that.inPortAndTable);
+
+ }
+ return false;
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(getClass())
+ .add("inPortAndTable", inPortAndTable).toString();
+ }
+}
diff --git a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/NiciraSetNshContextHeader.java b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/NiciraSetNshContextHeader.java
new file mode 100644
index 00000000..c8267984
--- /dev/null
+++ b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/NiciraSetNshContextHeader.java
@@ -0,0 +1,108 @@
+/*
+ * 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.onosproject.driver.extensions;
+
+import com.google.common.base.MoreObjects;
+import org.onlab.util.KryoNamespace;
+import org.onosproject.net.flow.AbstractExtension;
+import org.onosproject.net.flow.instructions.ExtensionTreatment;
+import org.onosproject.net.flow.instructions.ExtensionTreatmentType;
+
+import java.util.Objects;
+
+/**
+ * Nicira set NSH Context header extension instruction.
+ */
+public class NiciraSetNshContextHeader extends AbstractExtension implements
+ ExtensionTreatment {
+
+ private int nshCh;
+ private ExtensionTreatmentType type;
+
+ private final KryoNamespace appKryo = new KryoNamespace.Builder().build();
+
+ /**
+ * Creates a new set nsh context header instruction.
+ *
+ * @param type extension treatment type
+ */
+ NiciraSetNshContextHeader(ExtensionTreatmentType type) {
+ this.nshCh = 0;
+ this.type = type;
+ }
+
+ /**
+ * Creates a new set nsh context header instruction.
+ *
+ * @param nshCh nsh context header
+ * @param type extension treatment type
+ */
+ NiciraSetNshContextHeader(int nshCh, ExtensionTreatmentType type) {
+ this.nshCh = nshCh;
+ this.type = type;
+ }
+
+ /**
+ * Gets the nsh context header.
+ *
+ * @return nsh context header
+ */
+ public int nshCh() {
+ return nshCh;
+ }
+
+ @Override
+ public ExtensionTreatmentType type() {
+ return type;
+ }
+
+ @Override
+ public void deserialize(byte[] data) {
+ nshCh = appKryo.deserialize(data);
+ }
+
+ @Override
+ public byte[] serialize() {
+ return appKryo.serialize(nshCh);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(nshCh, type);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof NiciraSetNshContextHeader) {
+ NiciraSetNshContextHeader that = (NiciraSetNshContextHeader) obj;
+ return Objects.equals(nshCh, that.nshCh) && Objects.equals(type, that.type);
+
+ }
+ return false;
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(getClass())
+ .add("nshCh", nshCh)
+ .add("type", type)
+ .toString();
+ }
+}
diff --git a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/NiciraSetNshSi.java b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/NiciraSetNshSi.java
new file mode 100644
index 00000000..1480508e
--- /dev/null
+++ b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/NiciraSetNshSi.java
@@ -0,0 +1,101 @@
+/*
+ * 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.onosproject.driver.extensions;
+
+import com.google.common.base.MoreObjects;
+import org.onlab.util.KryoNamespace;
+import org.onosproject.net.flow.AbstractExtension;
+import org.onosproject.net.flow.instructions.ExtensionTreatment;
+import org.onosproject.net.flow.instructions.ExtensionTreatmentType;
+
+import java.util.Objects;
+
+/**
+ * Nicira set NSH SI extension instruction.
+ */
+public class NiciraSetNshSi extends AbstractExtension implements
+ ExtensionTreatment {
+
+ private byte nshSi;
+
+ private final KryoNamespace appKryo = new KryoNamespace.Builder().build();
+
+ /**
+ * Creates a new set nsh si instruction.
+ */
+ NiciraSetNshSi() {
+ nshSi = 0;
+ }
+
+ /**
+ * Creates a new set nsh si instruction with given si.
+ *
+ * @param nshSi nsh service index
+ */
+ NiciraSetNshSi(byte nshSi) {
+ this.nshSi = nshSi;
+ }
+
+ /**
+ * Gets the nsh service index.
+ *
+ * @return nsh service index
+ */
+ public byte nshSi() {
+ return nshSi;
+ }
+
+ @Override
+ public ExtensionTreatmentType type() {
+ return ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_SET_NSH_SI.type();
+ }
+
+ @Override
+ public void deserialize(byte[] data) {
+ nshSi = appKryo.deserialize(data);
+ }
+
+ @Override
+ public byte[] serialize() {
+ return appKryo.serialize(nshSi);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(nshSi);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj instanceof NiciraSetNshSi) {
+ NiciraSetNshSi that = (NiciraSetNshSi) obj;
+ return Objects.equals(nshSi, that.nshSi);
+
+ }
+ return false;
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(getClass())
+ .add("nshSi", nshSi)
+ .toString();
+ }
+}
diff --git a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/NiciraSetNshSpi.java b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/NiciraSetNshSpi.java
index 25358702..1a47173e 100644
--- a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/NiciraSetNshSpi.java
+++ b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/NiciraSetNshSpi.java
@@ -16,26 +16,23 @@
package org.onosproject.driver.extensions;
-import java.util.Objects;
-
+import com.google.common.base.MoreObjects;
import org.onlab.util.KryoNamespace;
-import org.onosproject.net.flow.instructions.AbstractExtensionTreatment;
+import org.onosproject.net.flow.AbstractExtension;
+import org.onosproject.net.flow.instructions.ExtensionTreatment;
import org.onosproject.net.flow.instructions.ExtensionTreatmentType;
-import org.onosproject.store.serializers.Ip4AddressSerializer;
-import com.google.common.base.MoreObjects;
+import java.util.Objects;
/**
* Nicira set NSH SPI extension instruction.
*/
-public class NiciraSetNshSpi extends AbstractExtensionTreatment {
+public class NiciraSetNshSpi extends AbstractExtension implements
+ ExtensionTreatment {
private int nshSpi;
- private final KryoNamespace appKryo = new KryoNamespace.Builder()
- .register(new Ip4AddressSerializer(), Integer.class)
- .register(byte[].class)
- .build();
+ private final KryoNamespace appKryo = new KryoNamespace.Builder().build();
/**
* Creates a new set nsh spi instruction.
diff --git a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/NiciraSetTunnelDst.java b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/NiciraSetTunnelDst.java
index ec23a9e0..e28a1e24 100644
--- a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/NiciraSetTunnelDst.java
+++ b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/extensions/NiciraSetTunnelDst.java
@@ -19,7 +19,8 @@ package org.onosproject.driver.extensions;
import com.google.common.base.MoreObjects;
import org.onlab.packet.Ip4Address;
import org.onlab.util.KryoNamespace;
-import org.onosproject.net.flow.instructions.AbstractExtensionTreatment;
+import org.onosproject.net.flow.AbstractExtension;
+import org.onosproject.net.flow.instructions.ExtensionTreatment;
import org.onosproject.net.flow.instructions.ExtensionTreatmentType;
import org.onosproject.store.serializers.Ip4AddressSerializer;
@@ -30,7 +31,8 @@ import static com.google.common.base.Preconditions.checkNotNull;
/**
* Nicira set tunnel destination extension instruction.
*/
-public class NiciraSetTunnelDst extends AbstractExtensionTreatment {
+public class NiciraSetTunnelDst extends AbstractExtension implements
+ ExtensionTreatment {
private Ip4Address tunnelDst;
diff --git a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/handshaker/CalientFiberSwitchHandshaker.java b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/handshaker/CalientFiberSwitchHandshaker.java
index df4dfa53..270008f3 100644
--- a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/handshaker/CalientFiberSwitchHandshaker.java
+++ b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/handshaker/CalientFiberSwitchHandshaker.java
@@ -17,7 +17,14 @@ package org.onosproject.driver.handshaker;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
+import org.onlab.util.Spectrum;
+import org.onosproject.net.ChannelSpacing;
+import org.onosproject.net.DefaultOchSignalComparator;
import org.onosproject.net.Device;
+import org.onosproject.net.GridType;
+import org.onosproject.net.OchSignal;
+import org.onosproject.net.PortNumber;
+import org.onosproject.net.behaviour.LambdaQuery;
import org.onosproject.openflow.controller.OpenFlowOpticalSwitch;
import org.onosproject.openflow.controller.PortDescPropertyType;
import org.onosproject.openflow.controller.driver.AbstractOpenFlowSwitch;
@@ -41,9 +48,24 @@ import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
+import java.util.SortedSet;
+import java.util.TreeSet;
import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.stream.Collectors;
+import java.util.stream.IntStream;
-public class CalientFiberSwitchHandshaker extends AbstractOpenFlowSwitch implements OpenFlowOpticalSwitch {
+/**
+ * Driver for Calient S160 Optical Circuit Switch. Untested on Calient S320 but probably works ok.
+ *
+ * Driver implements custom handshaker, and rewrites flow stats as expected by the device. Port stats are currently
+ * not supported.
+ *
+ * The device consists of OMS ports only, and each port exposes lambda resources covering the whole
+ * usable optical spectrum (U to O band, see {@link Spectrum} for spectrum definitions).
+ */
+public class CalientFiberSwitchHandshaker
+ extends AbstractOpenFlowSwitch
+ implements OpenFlowOpticalSwitch, LambdaQuery {
private final AtomicBoolean driverHandshakeComplete = new AtomicBoolean(false);
private List<OFCalientPortDescStatsEntry> fiberPorts = new ArrayList<>();
@@ -178,4 +200,22 @@ public class CalientFiberSwitchHandshaker extends AbstractOpenFlowSwitch impleme
super.sendMsg(newMsg);
}
+
+ @Override
+ public SortedSet<OchSignal> queryLambdas(PortNumber port) {
+ // S160 data sheet
+ // Wavelength range: 1260 - 1630 nm
+ long startSpacingMultiplier = Spectrum.U_BAND_MIN.subtract(Spectrum.CENTER_FREQUENCY).asHz() /
+ ChannelSpacing.CHL_12P5GHZ.frequency().asHz();
+ long stopSpacingMultiplier = Spectrum.O_BAND_MAX.subtract(Spectrum.CENTER_FREQUENCY).asHz() /
+ ChannelSpacing.CHL_12P5GHZ.frequency().asHz();
+ List<OchSignal> lambdas = IntStream.rangeClosed((int) startSpacingMultiplier, (int) stopSpacingMultiplier)
+ .mapToObj(x -> new OchSignal(GridType.FLEX, ChannelSpacing.CHL_12P5GHZ, x, 1))
+ .collect(Collectors.toList());
+
+ SortedSet<OchSignal> result = new TreeSet<>(new DefaultOchSignalComparator());
+ result.addAll(lambdas);
+
+ return result;
+ }
}
diff --git a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/handshaker/OfOpticalSwitchImplLinc13.java b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/handshaker/OfOpticalSwitchImplLinc13.java
index f91e2a7e..23378e95 100644
--- a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/handshaker/OfOpticalSwitchImplLinc13.java
+++ b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/handshaker/OfOpticalSwitchImplLinc13.java
@@ -16,7 +16,13 @@
package org.onosproject.driver.handshaker;
import com.google.common.collect.ImmutableSet;
+import org.onosproject.net.ChannelSpacing;
+import org.onosproject.net.DefaultOchSignalComparator;
import org.onosproject.net.Device;
+import org.onosproject.net.GridType;
+import org.onosproject.net.OchSignal;
+import org.onosproject.net.PortNumber;
+import org.onosproject.net.behaviour.LambdaQuery;
import org.onosproject.openflow.controller.OpenFlowOpticalSwitch;
import org.onosproject.openflow.controller.PortDescPropertyType;
import org.onosproject.openflow.controller.driver.AbstractOpenFlowSwitch;
@@ -42,7 +48,6 @@ import org.projectfloodlight.openflow.protocol.match.Match;
import org.projectfloodlight.openflow.protocol.match.MatchField;
import org.projectfloodlight.openflow.protocol.oxm.OFOxmExpOchSigId;
import org.projectfloodlight.openflow.types.CircuitSignalID;
-import org.projectfloodlight.openflow.types.OFPort;
import org.projectfloodlight.openflow.types.U8;
import java.io.IOException;
@@ -51,7 +56,11 @@ import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
+import java.util.SortedSet;
+import java.util.TreeSet;
import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.stream.Collectors;
+import java.util.stream.IntStream;
/**
* LINC-OE Optical Emulator switch class.
@@ -65,10 +74,13 @@ import java.util.concurrent.atomic.AtomicBoolean;
* As LINC implements custom OF optical extensions (in contrast to the final standard as specified in
* ONF TS-022 (March 15, 2015), we need to rewrite flow stat requests and flow mods in {@link #sendMsg(OFMessage)}.
*
+ * LINC exposes OchSignal resources: 80 lambdas of 50 GHz around ITU-T G.694.1 center frequency 193.1 GHz.
+ *
*/
public class OfOpticalSwitchImplLinc13
- extends AbstractOpenFlowSwitch implements OpenFlowOpticalSwitch {
+ extends AbstractOpenFlowSwitch implements OpenFlowOpticalSwitch, LambdaQuery {
+ private static final int LAMBDA_COUNT = 80;
private final AtomicBoolean driverHandshakeComplete = new AtomicBoolean(false);
private long barrierXidToWaitFor = -1;
@@ -267,13 +279,13 @@ public class OfOpticalSwitchImplLinc13
/**
* Checks if given port is also part of the regular port desc stats, i.e., is the port a tap port.
*
- * @param port given OF port
+ * @param port given port number
* @return true if the port is a tap (OCh), false otherwise (OMS port)
*/
- private boolean hasPort(OFPort port) {
+ private boolean isOChPort(long port) {
for (OFPortDescStatsReply reply : this.ports) {
for (OFPortDesc p : reply.getEntries()) {
- if (p.getPortNo().equals(port)) {
+ if (p.getPortNo().getPortNumber() == port) {
return true;
}
}
@@ -328,7 +340,7 @@ public class OfOpticalSwitchImplLinc13
short signalType;
// FIXME: use constants once loxi has full optical extensions
- if (hasPort(p.getPortNo())) {
+ if (isOChPort(p.getPortNo().getPortNumber())) {
signalType = 5; // OCH port
} else {
signalType = 2; // OMS port
@@ -351,4 +363,23 @@ public class OfOpticalSwitchImplLinc13
public Set<PortDescPropertyType> getPortTypes() {
return ImmutableSet.of(PortDescPropertyType.OPTICAL_TRANSPORT);
}
+
+ @Override
+ public SortedSet<OchSignal> queryLambdas(PortNumber port) {
+ // OCh ports don't have lambdas
+ if (isOChPort(port.toLong())) {
+ return Collections.emptySortedSet();
+ }
+
+ // OMS ports expose 80 lambdas of 50GHz width, centered around the ITU-T center frequency.
+ // We report these with a spacing of 12.5 GHz.
+ List<OchSignal> lambdas = IntStream.range(0, LAMBDA_COUNT)
+ .mapToObj(x -> new OchSignal(GridType.FLEX, ChannelSpacing.CHL_12P5GHZ, x - (LAMBDA_COUNT / 2), 1))
+ .collect(Collectors.toList());
+
+ SortedSet<OchSignal> result = new TreeSet<>(new DefaultOchSignalComparator());
+ result.addAll(lambdas);
+
+ return result;
+ }
}
diff --git a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/CpqdOFDPA2Pipeline.java b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/CpqdOFDPA2Pipeline.java
index 937c9ac8..02522cf1 100644
--- a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/CpqdOFDPA2Pipeline.java
+++ b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/CpqdOFDPA2Pipeline.java
@@ -39,7 +39,9 @@ import org.onosproject.net.flow.FlowRuleOperations;
import org.onosproject.net.flow.FlowRuleOperationsContext;
import org.onosproject.net.flow.TrafficSelector;
import org.onosproject.net.flow.TrafficTreatment;
+import org.onosproject.net.flow.criteria.Criteria;
import org.onosproject.net.flow.criteria.Criterion;
+import org.onosproject.net.flow.criteria.EthCriterion;
import org.onosproject.net.flow.criteria.EthTypeCriterion;
import org.onosproject.net.flow.criteria.IPCriterion;
import org.onosproject.net.flow.criteria.MplsBosCriterion;
@@ -62,6 +64,14 @@ public class CpqdOFDPA2Pipeline extends OFDPA2Pipeline {
private final Logger log = getLogger(getClass());
+ /*
+ * Cpqd emulation does not require the non-OF standard rules for
+ * matching untagged packets.
+ *
+ * (non-Javadoc)
+ * @see org.onosproject.driver.pipeline.OFDPA2Pipeline#processVlanIdFilter
+ */
+
@Override
protected List<FlowRule> processVlanIdFilter(PortCriterion portCriterion,
VlanIdCriterion vidCriterion,
@@ -122,16 +132,101 @@ public class CpqdOFDPA2Pipeline extends OFDPA2Pipeline {
return rules;
}
+ /*
+ * Cpqd emulation does not handle vlan tags and mpls labels correctly.
+ * Workaround requires popping off the VLAN tags in the TMAC table.
+ *
+ * (non-Javadoc)
+ * @see org.onosproject.driver.pipeline.OFDPA2Pipeline#processEthDstFilter
+ */
@Override
- protected Collection<FlowRule> processSpecific(ForwardingObjective fwd) {
+ protected List<FlowRule> processEthDstFilter(PortCriterion portCriterion,
+ EthCriterion ethCriterion,
+ VlanIdCriterion vidCriterion,
+ VlanId assignedVlan,
+ ApplicationId applicationId) {
+ //handling untagged packets via assigned VLAN
+ if (vidCriterion.vlanId() == VlanId.NONE) {
+ vidCriterion = (VlanIdCriterion) Criteria.matchVlanId(assignedVlan);
+ }
+ // ofdpa cannot match on ALL portnumber, so we need to use separate
+ // rules for each port.
+ List<PortNumber> portnums = new ArrayList<PortNumber>();
+ if (portCriterion.port() == PortNumber.ALL) {
+ for (Port port : deviceService.getPorts(deviceId)) {
+ if (port.number().toLong() > 0 && port.number().toLong() < OFPP_MAX) {
+ portnums.add(port.number());
+ }
+ }
+ } else {
+ portnums.add(portCriterion.port());
+ }
+
+ List<FlowRule> rules = new ArrayList<FlowRule>();
+ for (PortNumber pnum : portnums) {
+ // for unicast IP packets
+ TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
+ TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
+ selector.matchInPort(pnum);
+ selector.matchVlanId(vidCriterion.vlanId());
+ selector.matchEthType(Ethernet.TYPE_IPV4);
+ selector.matchEthDst(ethCriterion.mac());
+ /*
+ * Note: CpqD switches do not handle MPLS-related operation properly
+ * for a packet with VLAN tag. We pop VLAN here as a workaround.
+ * Side effect: HostService learns redundant hosts with same MAC but
+ * different VLAN. No known side effect on the network reachability.
+ */
+ treatment.popVlan();
+ treatment.transition(UNICAST_ROUTING_TABLE);
+ FlowRule rule = DefaultFlowRule.builder()
+ .forDevice(deviceId)
+ .withSelector(selector.build())
+ .withTreatment(treatment.build())
+ .withPriority(DEFAULT_PRIORITY)
+ .fromApp(applicationId)
+ .makePermanent()
+ .forTable(TMAC_TABLE).build();
+ rules.add(rule);
+ //for MPLS packets
+ selector = DefaultTrafficSelector.builder();
+ treatment = DefaultTrafficTreatment.builder();
+ selector.matchInPort(pnum);
+ selector.matchVlanId(vidCriterion.vlanId());
+ selector.matchEthType(Ethernet.MPLS_UNICAST);
+ selector.matchEthDst(ethCriterion.mac());
+ // workaround here again
+ treatment.popVlan();
+ treatment.transition(MPLS_TABLE_0);
+ rule = DefaultFlowRule.builder()
+ .forDevice(deviceId)
+ .withSelector(selector.build())
+ .withTreatment(treatment.build())
+ .withPriority(DEFAULT_PRIORITY)
+ .fromApp(applicationId)
+ .makePermanent()
+ .forTable(TMAC_TABLE).build();
+ rules.add(rule);
+ }
+ return rules;
+ }
+
+ /*
+ * Cpqd emulation allows MPLS ecmp.
+ *
+ * (non-Javadoc)
+ * @see org.onosproject.driver.pipeline.OFDPA2Pipeline#processEthTypeSpecific
+ */
+ @Override
+ protected Collection<FlowRule> processEthTypeSpecific(ForwardingObjective fwd) {
TrafficSelector selector = fwd.selector();
EthTypeCriterion ethType =
(EthTypeCriterion) selector.getCriterion(Criterion.Type.ETH_TYPE);
if ((ethType == null) ||
(ethType.ethType().toShort() != Ethernet.TYPE_IPV4) &&
(ethType.ethType().toShort() != Ethernet.MPLS_UNICAST)) {
- log.warn("processSpecific: Unsupported "
- + "forwarding objective criteraia");
+ log.warn("processSpecific: Unsupported forwarding objective criteria"
+ + "ethType:{} in dev:{}", ethType, deviceId);
fail(fwd, ObjectiveError.UNSUPPORTED);
return Collections.emptySet();
}
@@ -143,8 +238,8 @@ public class CpqdOFDPA2Pipeline extends OFDPA2Pipeline {
.matchIPDst(((IPCriterion)
selector.getCriterion(Criterion.Type.IPV4_DST)).ip());
forTableId = UNICAST_ROUTING_TABLE;
- log.debug("processing IPv4 specific forwarding objective {} hash{} in dev:{}",
- fwd.id(), fwd.hashCode(), deviceId);
+ log.debug("processing IPv4 specific forwarding objective {} -> next:{}"
+ + " in dev:{}", fwd.id(), fwd.nextId(), deviceId);
} else {
filteredSelector
.matchEthType(Ethernet.MPLS_UNICAST)
@@ -156,8 +251,8 @@ public class CpqdOFDPA2Pipeline extends OFDPA2Pipeline {
filteredSelector.matchMplsBos(bos.mplsBos());
}
forTableId = MPLS_TABLE_1;
- log.debug("processing MPLS specific forwarding objective {} hash:{} in dev {}",
- fwd.id(), fwd.hashCode(), deviceId);
+ log.debug("processing MPLS specific forwarding objective {} -> next:{}"
+ + " in dev {}", fwd.id(), fwd.nextId(), deviceId);
}
TrafficTreatment.Builder tb = DefaultTrafficTreatment.builder();
@@ -197,7 +292,6 @@ public class CpqdOFDPA2Pipeline extends OFDPA2Pipeline {
return Collections.singletonList(ruleBuilder.build());
}
-
@Override
protected void initializePipeline() {
processPortTable();
@@ -210,7 +304,6 @@ public class CpqdOFDPA2Pipeline extends OFDPA2Pipeline {
processAclTable();
}
- @Override
protected void processPortTable() {
FlowRuleOperations.Builder ops = FlowRuleOperations.builder();
TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
@@ -239,7 +332,6 @@ public class CpqdOFDPA2Pipeline extends OFDPA2Pipeline {
}));
}
- @Override
protected void processTmacTable() {
//table miss entry
FlowRuleOperations.Builder ops = FlowRuleOperations.builder();
@@ -270,7 +362,6 @@ public class CpqdOFDPA2Pipeline extends OFDPA2Pipeline {
}));
}
- @Override
protected void processIpTable() {
//table miss entry
FlowRuleOperations.Builder ops = FlowRuleOperations.builder();
@@ -278,6 +369,7 @@ public class CpqdOFDPA2Pipeline extends OFDPA2Pipeline {
TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
selector = DefaultTrafficSelector.builder();
treatment = DefaultTrafficTreatment.builder();
+ treatment.deferred().setOutput(PortNumber.CONTROLLER);
treatment.transition(ACL_TABLE);
FlowRule rule = DefaultFlowRule.builder()
.forDevice(deviceId)
@@ -301,7 +393,6 @@ public class CpqdOFDPA2Pipeline extends OFDPA2Pipeline {
}));
}
- @Override
protected void processMplsTable() {
//table miss entry
FlowRuleOperations.Builder ops = FlowRuleOperations.builder();
@@ -374,7 +465,6 @@ public class CpqdOFDPA2Pipeline extends OFDPA2Pipeline {
}));
}
- @Override
protected void processAclTable() {
//table miss entry - catch all to executed action-set
FlowRuleOperations.Builder ops = FlowRuleOperations.builder();
diff --git a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/OFDPA2Pipeline.java b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/OFDPA2Pipeline.java
index 863caebb..5f84b43a 100644
--- a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/OFDPA2Pipeline.java
+++ b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/OFDPA2Pipeline.java
@@ -18,7 +18,6 @@ package org.onosproject.driver.pipeline;
import static org.onlab.util.Tools.groupedThreads;
import static org.slf4j.LoggerFactory.getLogger;
-import java.nio.ByteBuffer;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Collection;
@@ -28,6 +27,7 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
@@ -35,14 +35,9 @@ import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;
import org.onlab.osgi.ServiceDirectory;
-import org.onlab.packet.Data;
import org.onlab.packet.Ethernet;
-import org.onlab.packet.IPv4;
-import org.onlab.packet.IpPrefix;
-import org.onlab.packet.MPLS;
import org.onlab.packet.MacAddress;
import org.onlab.packet.MplsLabel;
-import org.onlab.packet.UDP;
import org.onlab.packet.VlanId;
import org.onlab.util.KryoNamespace;
import org.onosproject.core.ApplicationId;
@@ -99,10 +94,6 @@ import org.onosproject.net.group.GroupEvent;
import org.onosproject.net.group.GroupKey;
import org.onosproject.net.group.GroupListener;
import org.onosproject.net.group.GroupService;
-import org.onosproject.net.packet.DefaultOutboundPacket;
-import org.onosproject.net.packet.OutboundPacket;
-import org.onosproject.net.packet.PacketContext;
-import org.onosproject.net.packet.PacketProcessor;
import org.onosproject.net.packet.PacketService;
import org.onosproject.store.serializers.KryoNamespaces;
import org.slf4j.Logger;
@@ -160,7 +151,6 @@ public class OFDPA2Pipeline extends AbstractHandlerBehaviour implements Pipeline
protected ApplicationId driverId;
protected PacketService packetService;
protected DeviceService deviceService;
- private InternalPacketProcessor processor = new InternalPacketProcessor();
protected KryoNamespace appKryo = new KryoNamespace.Builder()
.register(KryoNamespaces.API)
.register(GroupKey.class)
@@ -170,7 +160,7 @@ public class OFDPA2Pipeline extends AbstractHandlerBehaviour implements Pipeline
.register(ArrayDeque.class)
.build();
- private Cache<GroupKey, OfdpaNextGroup> pendingNextObjectives;
+ private Cache<GroupKey, List<OfdpaNextGroup>> pendingNextObjectives;
private ConcurrentHashMap<GroupKey, Set<GroupChainElem>> pendingGroups;
private ScheduledExecutorService groupChecker =
@@ -196,10 +186,12 @@ public class OFDPA2Pipeline extends AbstractHandlerBehaviour implements Pipeline
pendingNextObjectives = CacheBuilder.newBuilder()
.expireAfterWrite(20, TimeUnit.SECONDS)
.removalListener((
- RemovalNotification<GroupKey, OfdpaNextGroup> notification) -> {
+ RemovalNotification<GroupKey, List<OfdpaNextGroup>> notification) -> {
if (notification.getCause() == RemovalCause.EXPIRED) {
- fail(notification.getValue().nextObjective(),
- ObjectiveError.GROUPINSTALLATIONFAILED);
+ notification.getValue().forEach(ofdpaNextGrp ->
+ fail(ofdpaNextGrp.nextObj,
+ ObjectiveError.GROUPINSTALLATIONFAILED));
+
}
}).build();
@@ -212,7 +204,6 @@ public class OFDPA2Pipeline extends AbstractHandlerBehaviour implements Pipeline
flowObjectiveStore = context.store();
packetService = serviceDirectory.get(PacketService.class);
deviceService = serviceDirectory.get(DeviceService.class);
- packetService.addProcessor(processor, PacketProcessor.director(2));
groupService.addListener(new InnerGroupListener());
driverId = coreService.registerApplication(
@@ -271,7 +262,6 @@ public class OFDPA2Pipeline extends AbstractHandlerBehaviour implements Pipeline
log.warn("Unknown forwarding type {}", fwd.op());
}
-
flowRuleService.apply(flowOpsBuilder.build(new FlowRuleOperationsContext() {
@Override
public void onSuccess(FlowRuleOperations ops) {
@@ -283,7 +273,6 @@ public class OFDPA2Pipeline extends AbstractHandlerBehaviour implements Pipeline
fail(fwd, ObjectiveError.FLOWINSTALLATIONFAILED);
}
}));
-
}
@Override
@@ -697,17 +686,57 @@ public class OFDPA2Pipeline extends AbstractHandlerBehaviour implements Pipeline
* returned if there is an issue in processing the objective.
*/
protected Collection<FlowRule> processSpecific(ForwardingObjective fwd) {
- TrafficSelector selector = fwd.selector();
- EthTypeCriterion ethType =
- (EthTypeCriterion) selector.getCriterion(Criterion.Type.ETH_TYPE);
- if ((ethType == null) ||
- (ethType.ethType().toShort() != Ethernet.TYPE_IPV4) &&
- (ethType.ethType().toShort() != Ethernet.MPLS_UNICAST)) {
- log.warn("processSpecific: Unsupported "
- + "forwarding objective criteraia");
+ log.trace("Processing specific fwd objective:{} in dev:{} with next:{}",
+ fwd.id(), deviceId, fwd.nextId());
+ boolean isEthTypeObj = isSupportedEthTypeObjective(fwd);
+ boolean isEthDstObj = isSupportedEthDstObjective(fwd);
+
+ if (isEthTypeObj) {
+ return processEthTypeSpecific(fwd);
+ } else if (isEthDstObj) {
+ return processEthDstSpecific(fwd);
+ } else {
+ log.warn("processSpecific: Unsupported forwarding objective "
+ + "criteria fwd:{} in dev:{}", fwd.nextId(), deviceId);
fail(fwd, ObjectiveError.UNSUPPORTED);
return Collections.emptySet();
}
+ }
+
+ private boolean isSupportedEthTypeObjective(ForwardingObjective fwd) {
+ TrafficSelector selector = fwd.selector();
+ EthTypeCriterion ethType = (EthTypeCriterion) selector
+ .getCriterion(Criterion.Type.ETH_TYPE);
+ if ((ethType == null) ||
+ ((ethType.ethType().toShort() != Ethernet.TYPE_IPV4) &&
+ (ethType.ethType().toShort() != Ethernet.MPLS_UNICAST))) {
+ return false;
+ }
+ return true;
+ }
+
+ private boolean isSupportedEthDstObjective(ForwardingObjective fwd) {
+ TrafficSelector selector = fwd.selector();
+ EthCriterion ethDst = (EthCriterion) selector
+ .getCriterion(Criterion.Type.ETH_DST);
+ VlanIdCriterion vlanId = (VlanIdCriterion) selector
+ .getCriterion(Criterion.Type.VLAN_VID);
+ if (ethDst == null && vlanId == null) {
+ return false;
+ }
+ return true;
+ }
+
+ /**
+ * Handles forwarding rules to the IP and MPLS tables.
+ *
+ * @param fwd the forwarding objective
+ * @return A collection of flow rules, or an empty set
+ */
+ protected Collection<FlowRule> processEthTypeSpecific(ForwardingObjective fwd) {
+ TrafficSelector selector = fwd.selector();
+ EthTypeCriterion ethType =
+ (EthTypeCriterion) selector.getCriterion(Criterion.Type.ETH_TYPE);
int forTableId = -1;
TrafficSelector.Builder filteredSelector = DefaultTrafficSelector.builder();
@@ -716,8 +745,8 @@ public class OFDPA2Pipeline extends AbstractHandlerBehaviour implements Pipeline
.matchIPDst(((IPCriterion)
selector.getCriterion(Criterion.Type.IPV4_DST)).ip());
forTableId = UNICAST_ROUTING_TABLE;
- log.debug("processing IPv4 specific forwarding objective {} in dev:{}",
- fwd.id(), deviceId);
+ log.debug("processing IPv4 specific forwarding objective {} -> next:{}"
+ + " in dev:{}", fwd.id(), fwd.nextId(), deviceId);
} else {
filteredSelector
.matchEthType(Ethernet.MPLS_UNICAST)
@@ -729,8 +758,8 @@ public class OFDPA2Pipeline extends AbstractHandlerBehaviour implements Pipeline
filteredSelector.matchMplsBos(bos.mplsBos());
}
forTableId = MPLS_TABLE_1;
- log.debug("processing MPLS specific forwarding objective {} in dev {}",
- fwd.id(), deviceId);
+ log.debug("processing MPLS specific forwarding objective {} -> next:{}"
+ + " in dev {}", fwd.id(), fwd.nextId(), deviceId);
}
TrafficTreatment.Builder tb = DefaultTrafficTreatment.builder();
@@ -754,6 +783,7 @@ public class OFDPA2Pipeline extends AbstractHandlerBehaviour implements Pipeline
// MPLS interface, or a MPLS SWAP (with-same) but that would
// have to be handled in the next-objective. Also the pop-mpls
// logic used here won't work in non-BoS case.
+ fail(fwd, ObjectiveError.FLOWINSTALLATIONFAILED);
return Collections.emptySet();
}
@@ -762,7 +792,8 @@ public class OFDPA2Pipeline extends AbstractHandlerBehaviour implements Pipeline
// we only need the top level group's key to point the flow to it
Group group = groupService.getGroup(deviceId, gkeys.get(0).peekFirst());
if (group == null) {
- log.warn("The group left!");
+ log.warn("Group with key:{} for next-id:{} not found in dev:{}",
+ gkeys.get(0).peekFirst(), fwd.nextId(), deviceId);
fail(fwd, ObjectiveError.GROUPMISSING);
return Collections.emptySet();
}
@@ -786,6 +817,88 @@ public class OFDPA2Pipeline extends AbstractHandlerBehaviour implements Pipeline
return Collections.singletonList(ruleBuilder.build());
}
+ /**
+ * Handles forwarding rules to the L2 bridging table. Flow actions are not
+ * allowed in the bridging table - instead we use L2 Interface group or
+ * L2 flood group
+ *
+ * @param fwd the forwarding objective
+ * @return A collection of flow rules, or an empty set
+ */
+ protected Collection<FlowRule> processEthDstSpecific(ForwardingObjective fwd) {
+ List<FlowRule> rules = new ArrayList<>();
+
+ // Build filtered selector
+ TrafficSelector selector = fwd.selector();
+ EthCriterion ethCriterion = (EthCriterion) selector
+ .getCriterion(Criterion.Type.ETH_DST);
+ VlanIdCriterion vlanIdCriterion = (VlanIdCriterion) selector
+ .getCriterion(Criterion.Type.VLAN_VID);
+
+ if (vlanIdCriterion == null) {
+ log.warn("Forwarding objective for bridging requires vlan. Not "
+ + "installing fwd:{} in dev:{}", fwd.id(), deviceId);
+ fail(fwd, ObjectiveError.BADPARAMS);
+ return Collections.emptySet();
+ }
+
+ TrafficSelector.Builder filteredSelectorBuilder =
+ DefaultTrafficSelector.builder();
+ // Do not match MacAddress for subnet broadcast entry
+ if (!ethCriterion.mac().equals(MacAddress.NONE)) {
+ filteredSelectorBuilder.matchEthDst(ethCriterion.mac());
+ log.debug("processing L2 forwarding objective:{} -> next:{} in dev:{}",
+ fwd.id(), fwd.nextId(), deviceId);
+ } else {
+ log.debug("processing L2 Broadcast forwarding objective:{} -> next:{} "
+ + "in dev:{} for vlan:{}",
+ fwd.id(), fwd.nextId(), deviceId, vlanIdCriterion.vlanId());
+ }
+ filteredSelectorBuilder.matchVlanId(vlanIdCriterion.vlanId());
+ TrafficSelector filteredSelector = filteredSelectorBuilder.build();
+
+ if (fwd.treatment() != null) {
+ log.warn("Ignoring traffic treatment in fwd rule {} meant for L2 table"
+ + "for dev:{}. Expecting only nextId", fwd.id(), deviceId);
+ }
+
+ TrafficTreatment.Builder treatmentBuilder = DefaultTrafficTreatment.builder();
+ if (fwd.nextId() != null) {
+ NextGroup next = flowObjectiveStore.getNextGroup(fwd.nextId());
+ if (next != null) {
+ List<Deque<GroupKey>> gkeys = appKryo.deserialize(next.data());
+ // we only need the top level group's key to point the flow to it
+ Group group = groupService.getGroup(deviceId, gkeys.get(0).peekFirst());
+ if (group != null) {
+ treatmentBuilder.deferred().group(group.id());
+ } else {
+ log.warn("Group with key:{} for next-id:{} not found in dev:{}",
+ gkeys.get(0).peekFirst(), fwd.nextId(), deviceId);
+ fail(fwd, ObjectiveError.GROUPMISSING);
+ return Collections.emptySet();
+ }
+ }
+ }
+ treatmentBuilder.immediate().transition(ACL_TABLE);
+ TrafficTreatment filteredTreatment = treatmentBuilder.build();
+
+ // Build bridging table entries
+ FlowRule.Builder flowRuleBuilder = DefaultFlowRule.builder();
+ flowRuleBuilder.fromApp(fwd.appId())
+ .withPriority(fwd.priority())
+ .forDevice(deviceId)
+ .withSelector(filteredSelector)
+ .withTreatment(filteredTreatment)
+ .forTable(BRIDGING_TABLE);
+ if (fwd.permanent()) {
+ flowRuleBuilder.makePermanent();
+ } else {
+ flowRuleBuilder.makeTemporary(fwd.timeout());
+ }
+ rules.add(flowRuleBuilder.build());
+ return rules;
+ }
+
private void pass(Objective obj) {
if (obj.context().isPresent()) {
obj.context().get().onSuccess(obj);
@@ -842,9 +955,26 @@ public class OFDPA2Pipeline extends AbstractHandlerBehaviour implements Pipeline
* @param nextObj the nextObjective of type SIMPLE
*/
private void processSimpleNextObjective(NextObjective nextObj) {
- // break up simple next objective to GroupChain objects
TrafficTreatment treatment = nextObj.next().iterator().next();
+ // determine if plain L2 or L3->L2
+ boolean plainL2 = true;
+ for (Instruction ins : treatment.allInstructions()) {
+ if (ins.type() == Instruction.Type.L2MODIFICATION) {
+ L2ModificationInstruction l2ins = (L2ModificationInstruction) ins;
+ if (l2ins.subtype() == L2SubType.ETH_DST ||
+ l2ins.subtype() == L2SubType.ETH_SRC) {
+ plainL2 = false;
+ break;
+ }
+ }
+ }
+
+ if (plainL2) {
+ createL2InterfaceGroup(nextObj);
+ return;
+ }
+ // break up simple next objective to GroupChain objects
GroupInfo groupInfo = createL2L3Chain(treatment, nextObj.id(),
nextObj.appId(), false,
nextObj.meta());
@@ -860,8 +990,8 @@ public class OFDPA2Pipeline extends AbstractHandlerBehaviour implements Pipeline
Collections.singletonList(gkeyChain),
nextObj);
- // store l3groupkey with the ofdpaGroupChain for the nextObjective that depends on it
- pendingNextObjectives.put(groupInfo.outerGrpDesc.appCookie(), ofdpaGrp);
+ // store l3groupkey with the ofdpaNextGroup for the nextObjective that depends on it
+ updatePendingNextObjective(groupInfo.outerGrpDesc.appCookie(), ofdpaGrp);
// now we are ready to send the l2 groupDescription (inner), as all the stores
// that will get async replies have been updated. By waiting to update
@@ -869,6 +999,98 @@ public class OFDPA2Pipeline extends AbstractHandlerBehaviour implements Pipeline
groupService.addGroup(groupInfo.innerGrpDesc);
}
+ private void updatePendingNextObjective(GroupKey key, OfdpaNextGroup value) {
+ List<OfdpaNextGroup> nextList = new CopyOnWriteArrayList<OfdpaNextGroup>();
+ nextList.add(value);
+ List<OfdpaNextGroup> ret = pendingNextObjectives.asMap()
+ .putIfAbsent(key, nextList);
+ if (ret != null) {
+ ret.add(value);
+ }
+ }
+
+ /**
+ * Creates a simple L2 Interface Group.
+ *
+ * @param nextObj the next Objective
+ */
+ private void createL2InterfaceGroup(NextObjective nextObj) {
+ // only allowed actions are vlan pop and outport
+ TrafficTreatment.Builder ttb = DefaultTrafficTreatment.builder();
+ PortNumber portNum = null;
+ for (Instruction ins : nextObj.next().iterator().next().allInstructions()) {
+ if (ins.type() == Instruction.Type.L2MODIFICATION) {
+ L2ModificationInstruction l2ins = (L2ModificationInstruction) ins;
+ switch (l2ins.subtype()) {
+ case VLAN_POP:
+ ttb.add(l2ins);
+ break;
+ default:
+ break;
+ }
+ } else if (ins.type() == Instruction.Type.OUTPUT) {
+ portNum = ((OutputInstruction) ins).port();
+ ttb.add(ins);
+ } else {
+ log.warn("Driver does not handle this type of TrafficTreatment"
+ + " instruction in simple nextObjectives: {}", ins.type());
+ }
+ }
+ //use the vlanid associated with the port
+ VlanId vlanid = port2Vlan.get(portNum);
+
+ if (vlanid == null && nextObj.meta() != null) {
+ // use metadata vlan info if available
+ Criterion vidCriterion = nextObj.meta().getCriterion(Type.VLAN_VID);
+ if (vidCriterion != null) {
+ vlanid = ((VlanIdCriterion) vidCriterion).vlanId();
+ }
+ }
+
+ if (vlanid == null) {
+ log.error("Driver cannot process an L2/L3 group chain without "
+ + "egress vlan information for dev: {} port:{}",
+ deviceId, portNum);
+ return;
+ }
+
+ // assemble information for ofdpa l2interface group
+ Integer l2groupId = L2INTERFACEMASK | (vlanid.toShort() << 16) | (int) portNum.toLong();
+ // a globally unique groupkey that is different for ports in the same devices
+ // but different for the same portnumber on different devices. Also different
+ // for the various group-types created out of the same next objective.
+ int l2gk = 0x0ffffff & (deviceId.hashCode() << 8 | (int) portNum.toLong());
+ final GroupKey l2groupkey = new DefaultGroupKey(appKryo.serialize(l2gk));
+
+ // create group description for the l2interfacegroup
+ GroupBucket l2interfaceGroupBucket =
+ DefaultGroupBucket.createIndirectGroupBucket(ttb.build());
+ GroupDescription l2groupDescription =
+ new DefaultGroupDescription(
+ deviceId,
+ GroupDescription.Type.INDIRECT,
+ new GroupBuckets(Collections.singletonList(
+ l2interfaceGroupBucket)),
+ l2groupkey,
+ l2groupId,
+ nextObj.appId());
+ log.debug("Trying L2Interface: device:{} gid:{} gkey:{} nextId:{}",
+ deviceId, Integer.toHexString(l2groupId),
+ l2groupkey, nextObj.id());
+
+ // create object for local and distributed storage
+ Deque<GroupKey> singleKey = new ArrayDeque<>();
+ singleKey.addFirst(l2groupkey);
+ OfdpaNextGroup ofdpaGrp = new OfdpaNextGroup(
+ Collections.singletonList(singleKey),
+ nextObj);
+
+ // store l2groupkey for the nextObjective that depends on it
+ updatePendingNextObjective(l2groupkey, ofdpaGrp);
+ // send the group description to the group service
+ groupService.addGroup(l2groupDescription);
+ }
+
/**
* Creates one of two possible group-chains from the treatment
* passed in. Depending on the MPLS boolean, this method either creates
@@ -895,6 +1117,7 @@ public class OFDPA2Pipeline extends AbstractHandlerBehaviour implements Pipeline
TrafficTreatment.Builder innerTtb = DefaultTrafficTreatment.builder();
VlanId vlanid = null;
long portNum = 0;
+ boolean setVlan = false, popVlan = false;
for (Instruction ins : treatment.allInstructions()) {
if (ins.type() == Instruction.Type.L2MODIFICATION) {
L2ModificationInstruction l2ins = (L2ModificationInstruction) ins;
@@ -908,9 +1131,11 @@ public class OFDPA2Pipeline extends AbstractHandlerBehaviour implements Pipeline
case VLAN_ID:
vlanid = ((ModVlanIdInstruction) l2ins).vlanId();
outerTtb.setVlanId(vlanid);
+ setVlan = true;
break;
case VLAN_POP:
innerTtb.popVlan();
+ popVlan = true;
break;
case DEC_MPLS_TTL:
case MPLS_LABEL:
@@ -935,12 +1160,11 @@ public class OFDPA2Pipeline extends AbstractHandlerBehaviour implements Pipeline
vlanid = port2Vlan.get(PortNumber.portNumber(portNum));
}
- if (vlanid == null) {
- // use metadata
- for (Criterion metaCriterion : meta.criteria()) {
- if (metaCriterion.type() == Type.VLAN_VID) {
- vlanid = ((VlanIdCriterion) metaCriterion).vlanId();
- }
+ if (vlanid == null && meta != null) {
+ // use metadata if available
+ Criterion vidCriterion = meta.getCriterion(Type.VLAN_VID);
+ if (vidCriterion != null) {
+ vlanid = ((VlanIdCriterion) vidCriterion).vlanId();
}
}
@@ -951,6 +1175,14 @@ public class OFDPA2Pipeline extends AbstractHandlerBehaviour implements Pipeline
return null;
}
+ if (!setVlan && !popVlan) {
+ // untagged outgoing port
+ TrafficTreatment.Builder temp = DefaultTrafficTreatment.builder();
+ temp.popVlan();
+ innerTtb.build().allInstructions().forEach(i -> temp.add(i));
+ innerTtb = temp;
+ }
+
// assemble information for ofdpa l2interface group
Integer l2groupId = L2INTERFACEMASK | (vlanid.toShort() << 16) | (int) portNum;
// a globally unique groupkey that is different for ports in the same devices
@@ -1077,6 +1309,7 @@ public class OFDPA2Pipeline extends AbstractHandlerBehaviour implements Pipeline
}
// also ensure that all ports are in the same vlan
+ // XXX maybe HA issue here?
VlanId thisvlanid = port2Vlan.get(portNum);
if (vlanid == null) {
vlanid = thisvlanid;
@@ -1151,7 +1384,7 @@ public class OFDPA2Pipeline extends AbstractHandlerBehaviour implements Pipeline
// store l2floodgroupkey with the ofdpaGroupChain for the nextObjective
// that depends on it
- pendingNextObjectives.put(l2floodgroupkey, ofdpaGrp);
+ updatePendingNextObjective(l2floodgroupkey, ofdpaGrp);
for (GroupDescription l2intGrpDesc : l2interfaceGroupDescs) {
// store all l2groupkeys with the groupChainElem for the l2floodgroup
@@ -1336,7 +1569,7 @@ public class OFDPA2Pipeline extends AbstractHandlerBehaviour implements Pipeline
// store l3ecmpGroupKey with the ofdpaGroupChain for the nextObjective
// that depends on it
- pendingNextObjectives.put(l3ecmpGroupKey, ofdpaGrp);
+ updatePendingNextObjective(l3ecmpGroupKey, ofdpaGrp);
log.debug("Trying L3ECMP: device:{} gid:{} gkey:{} nextId:{}",
deviceId, Integer.toHexString(l3ecmpGroupId),
@@ -1422,16 +1655,18 @@ public class OFDPA2Pipeline extends AbstractHandlerBehaviour implements Pipeline
processGroupChain(gce);
}
} else {
- OfdpaNextGroup obj = pendingNextObjectives.getIfPresent(key);
- if (obj != null) {
- log.info("Group service processed group key {} in device:{}. "
- + "Done implementing next objective: {} <<-->> gid:{}",
- key, deviceId, obj.nextObjective().id(),
- Integer.toHexString(groupService.getGroup(deviceId, key)
- .givenGroupId()));
- pass(obj.nextObjective());
+ List<OfdpaNextGroup> objList = pendingNextObjectives.getIfPresent(key);
+ if (objList != null) {
pendingNextObjectives.invalidate(key);
- flowObjectiveStore.putNextGroup(obj.nextObjective().id(), obj);
+ objList.forEach(obj -> {
+ log.info("Group service processed group key {} in device:{}. "
+ + "Done implementing next objective: {} <<-->> gid:{}",
+ key, deviceId, obj.nextObjective().id(),
+ Integer.toHexString(groupService.getGroup(deviceId, key)
+ .givenGroupId()));
+ pass(obj.nextObjective());
+ flowObjectiveStore.putNextGroup(obj.nextObjective().id(), obj);
+ });
}
}
});
@@ -1455,16 +1690,18 @@ public class OFDPA2Pipeline extends AbstractHandlerBehaviour implements Pipeline
processGroupChain(gce);
}
} else {
- OfdpaNextGroup obj = pendingNextObjectives.getIfPresent(key);
- if (obj != null) {
- log.info("group ADDED with key {} in dev {}.. Done implementing next "
- + "objective: {} <<-->> gid:{}",
- key, deviceId, obj.nextObjective().id(),
- Integer.toHexString(groupService.getGroup(deviceId, key)
- .givenGroupId()));
- pass(obj.nextObjective());
+ List<OfdpaNextGroup> objList = pendingNextObjectives.getIfPresent(key);
+ if (objList != null) {
pendingNextObjectives.invalidate(key);
- flowObjectiveStore.putNextGroup(obj.nextObjective().id(), obj);
+ objList.forEach(obj -> {
+ log.info("group ADDED with key {} in dev {}.. Done implementing next "
+ + "objective: {} <<-->> gid:{}",
+ key, deviceId, obj.nextObjective().id(),
+ Integer.toHexString(groupService.getGroup(deviceId, key)
+ .givenGroupId()));
+ pass(obj.nextObjective());
+ flowObjectiveStore.putNextGroup(obj.nextObjective().id(), obj);
+ });
}
}
}
@@ -1550,418 +1787,6 @@ public class OFDPA2Pipeline extends AbstractHandlerBehaviour implements Pipeline
" waiting-on-groups: " + waitOnGroups.get() +
" device: " + deviceId);
}
-
- }
-
- //////////////////////////////////////
- // Test code to be used for future
- // static-flow-pusher app
- //////////////////////////////////////
-
- public void processStaticFlows() {
- //processPortTable();
- processGroupTable();
- processVlanTable();
- processTmacTable();
- processIpTable();
- //processMcastTable();
- //processBridgingTable();
- processAclTable();
- sendPackets();
- processMplsTable();
- }
-
- protected void processGroupTable() {
- TrafficTreatment.Builder act = DefaultTrafficTreatment.builder();
-
- act.popVlan(); // to send out untagged packets
- act.setOutput(PortNumber.portNumber(24));
- GroupBucket bucket =
- DefaultGroupBucket.createIndirectGroupBucket(act.build());
- final GroupKey groupkey = new DefaultGroupKey(appKryo.serialize(500));
- Integer groupId = 0x00c80018; //l2 interface, vlan 200, port 24
- GroupDescription groupDescription = new DefaultGroupDescription(deviceId,
- GroupDescription.Type.INDIRECT,
- new GroupBuckets(Collections.singletonList(bucket)),
- groupkey,
- groupId,
- driverId);
- groupService.addGroup(groupDescription);
-
- TrafficTreatment.Builder act2 = DefaultTrafficTreatment.builder();
- act2.setOutput(PortNumber.portNumber(40));
- GroupBucket bucket2 = DefaultGroupBucket.createIndirectGroupBucket(act2.build());
- final GroupKey groupkey2 = new DefaultGroupKey(appKryo.serialize(502));
- Integer groupId2 = 0x00c50028; //l2 interface, vlan 197, port 40
- GroupDescription groupDescription2 = new DefaultGroupDescription(deviceId,
- GroupDescription.Type.INDIRECT,
- new GroupBuckets(Collections.singletonList(bucket2)),
- groupkey2,
- groupId2,
- driverId);
- groupService.addGroup(groupDescription2);
-
- while (groupService.getGroup(deviceId, groupkey2) == null) {
- try {
- Thread.sleep(500);
- } catch (InterruptedException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- }
-
- //Now for L3 Unicast group
- TrafficTreatment.Builder act3 = DefaultTrafficTreatment.builder();
- act3.setEthDst(MacAddress.valueOf(0x2020));
- act3.setEthSrc(MacAddress.valueOf(0x1010));
- act3.setVlanId(VlanId.vlanId((short) 200));
- act3.group(new DefaultGroupId(0x00c80018)); // point to L2 interface
- // MPLS interface group - does not work for popping single label
- //Integer secGroupId = MPLSINTERFACEMASK | 38; // 0x90000026
- Integer groupId3 = L3UNICASTMASK | 1; // 0x20000001
- GroupBucket bucket3 =
- DefaultGroupBucket.createIndirectGroupBucket(act3.build());
- final GroupKey groupkey3 = new DefaultGroupKey(appKryo.serialize(503));
- GroupDescription groupDescription3 = new DefaultGroupDescription(deviceId,
- GroupDescription.Type.INDIRECT,
- new GroupBuckets(Collections.singletonList(bucket3)),
- groupkey3,
- groupId3,
- driverId);
- groupService.addGroup(groupDescription3);
-
- //Another L3 Unicast group
- TrafficTreatment.Builder act4 = DefaultTrafficTreatment.builder();
- act4.setEthDst(MacAddress.valueOf(0x3030));
- act4.setEthSrc(MacAddress.valueOf(0x1010));
- act4.setVlanId(VlanId.vlanId((short) 197));
- act4.group(new DefaultGroupId(0x00c50028)); // point to L2 interface
- Integer groupId4 = L3UNICASTMASK | 2; // 0x20000002
- GroupBucket bucket4 =
- DefaultGroupBucket.createIndirectGroupBucket(act4.build());
- final GroupKey groupkey4 = new DefaultGroupKey(appKryo.serialize(504));
- GroupDescription groupDescription4 = new DefaultGroupDescription(deviceId,
- GroupDescription.Type.INDIRECT,
- new GroupBuckets(Collections.singletonList(bucket4)),
- groupkey4,
- groupId4,
- driverId);
- groupService.addGroup(groupDescription4);
-
- while (groupService.getGroup(deviceId, groupkey4) == null) {
- try {
- Thread.sleep(500);
- } catch (InterruptedException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- }
-
- // L3 ecmp group
- TrafficTreatment.Builder act5 = DefaultTrafficTreatment.builder();
- act5.group(new DefaultGroupId(0x20000001));
- TrafficTreatment.Builder act6 = DefaultTrafficTreatment.builder();
- act6.group(new DefaultGroupId(0x20000002));
- GroupBucket buckete1 =
- DefaultGroupBucket.createSelectGroupBucket(act5.build());
- GroupBucket buckete2 =
- DefaultGroupBucket.createSelectGroupBucket(act6.build());
- List<GroupBucket> bktlist = new ArrayList<GroupBucket>();
- bktlist.add(buckete1);
- bktlist.add(buckete2);
- final GroupKey groupkey5 = new DefaultGroupKey(appKryo.serialize(505));
- Integer groupId5 = L3ECMPMASK | 5; // 0x70000005
- GroupDescription groupDescription5 = new DefaultGroupDescription(deviceId,
- GroupDescription.Type.SELECT,
- new GroupBuckets(bktlist),
- groupkey5,
- groupId5,
- driverId);
- groupService.addGroup(groupDescription5);
-
-
- }
-
- @SuppressWarnings("deprecation")
- protected void processMplsTable() {
- FlowRuleOperations.Builder ops = FlowRuleOperations.builder();
- TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
- selector.matchEthType(Ethernet.MPLS_UNICAST);
- selector.matchMplsLabel(MplsLabel.mplsLabel(0xff)); //255
- selector.matchMplsBos(true);
- TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
- treatment.decMplsTtl(); // nw_ttl does not work
- treatment.copyTtlIn();
- treatment.popMpls(Ethernet.TYPE_IPV4);
- treatment.deferred().group(new DefaultGroupId(0x20000001)); // point to L3 Unicast
- //treatment.deferred().group(new DefaultGroupId(0x70000005)); // point to L3 ECMP
- treatment.transition(ACL_TABLE);
- FlowRule test = DefaultFlowRule.builder().forDevice(deviceId)
- .withSelector(selector.build()).withTreatment(treatment.build())
- .withPriority(DEFAULT_PRIORITY).fromApp(driverId).makePermanent()
- .forTable(24).build();
- ops = ops.add(test);
-
- flowRuleService.apply(ops.build(new FlowRuleOperationsContext() {
- @Override
- public void onSuccess(FlowRuleOperations ops) {
- log.info("Initialized mpls table");
- }
-
- @Override
- public void onError(FlowRuleOperations ops) {
- log.info("Failed to initialize mpls table");
- }
- }));
-
- }
-
- protected void processPortTable() {
- FlowRuleOperations.Builder ops = FlowRuleOperations.builder();
- TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
- selector.matchInPort(PortNumber.portNumber(0)); // should be maskable?
- TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
- treatment.transition(VLAN_TABLE);
- FlowRule tmisse = DefaultFlowRule.builder()
- .forDevice(deviceId)
- .withSelector(selector.build())
- .withTreatment(treatment.build())
- .withPriority(LOWEST_PRIORITY)
- .fromApp(driverId)
- .makePermanent()
- .forTable(PORT_TABLE).build();
- ops = ops.add(tmisse);
-
- flowRuleService.apply(ops.build(new FlowRuleOperationsContext() {
- @Override
- public void onSuccess(FlowRuleOperations ops) {
- log.info("Initialized port table");
- }
-
- @Override
- public void onError(FlowRuleOperations ops) {
- log.info("Failed to initialize port table");
- }
- }));
-
- }
-
- private void processVlanTable() {
- // Table miss entry is not required as ofdpa default is to drop
- // In OF terms, the absence of a t.m.e. also implies drop
- FlowRuleOperations.Builder ops = FlowRuleOperations.builder();
- TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
- TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
- selector.matchInPort(PortNumber.portNumber(12));
- selector.matchVlanId(VlanId.vlanId((short) 100));
- treatment.transition(TMAC_TABLE);
- FlowRule rule = DefaultFlowRule.builder()
- .forDevice(deviceId)
- .withSelector(selector.build())
- .withTreatment(treatment.build())
- .withPriority(DEFAULT_PRIORITY)
- .fromApp(driverId)
- .makePermanent()
- .forTable(VLAN_TABLE).build();
- ops = ops.add(rule);
- flowRuleService.apply(ops.build(new FlowRuleOperationsContext() {
- @Override
- public void onSuccess(FlowRuleOperations ops) {
- log.info("Initialized vlan table");
- }
-
- @Override
- public void onError(FlowRuleOperations ops) {
- log.info("Failed to initialize vlan table");
- }
- }));
- }
-
- protected void processTmacTable() {
- //table miss entry
- FlowRuleOperations.Builder ops = FlowRuleOperations.builder();
- TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
- TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
- selector.matchInPort(PortNumber.portNumber(12));
- selector.matchVlanId(VlanId.vlanId((short) 100));
- selector.matchEthType(Ethernet.TYPE_IPV4);
- selector.matchEthDst(MacAddress.valueOf("00:00:00:00:00:02"));
- treatment.transition(UNICAST_ROUTING_TABLE);
- FlowRule rule = DefaultFlowRule.builder()
- .forDevice(deviceId)
- .withSelector(selector.build())
- .withTreatment(treatment.build())
- .withPriority(DEFAULT_PRIORITY)
- .fromApp(driverId)
- .makePermanent()
- .forTable(TMAC_TABLE).build();
- ops = ops.add(rule);
-
- selector.matchEthType(Ethernet.MPLS_UNICAST);
- treatment.transition(MPLS_TABLE_0);
- FlowRule rulempls = DefaultFlowRule.builder()
- .forDevice(deviceId)
- .withSelector(selector.build())
- .withTreatment(treatment.build())
- .withPriority(DEFAULT_PRIORITY)
- .fromApp(driverId)
- .makePermanent()
- .forTable(TMAC_TABLE).build();
- ops = ops.add(rulempls);
-
- flowRuleService.apply(ops.build(new FlowRuleOperationsContext() {
- @Override
- public void onSuccess(FlowRuleOperations ops) {
- log.info("Initialized tmac table");
- }
-
- @Override
- public void onError(FlowRuleOperations ops) {
- log.info("Failed to initialize tmac table");
- }
- }));
- }
-
- protected void processIpTable() {
- //table miss entry
- FlowRuleOperations.Builder ops = FlowRuleOperations.builder();
- TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
- TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
- selector.matchEthType(Ethernet.TYPE_IPV4);
- selector.matchIPDst(IpPrefix.valueOf("2.0.0.0/16"));
- treatment.deferred().group(new DefaultGroupId(0x20000001));
- treatment.transition(ACL_TABLE);
- FlowRule rule = DefaultFlowRule.builder()
- .forDevice(deviceId)
- .withSelector(selector.build())
- .withTreatment(treatment.build())
- .withPriority(30000)
- .fromApp(driverId)
- .makePermanent()
- .forTable(UNICAST_ROUTING_TABLE).build();
- ops = ops.add(rule);
- flowRuleService.apply(ops.build(new FlowRuleOperationsContext() {
- @Override
- public void onSuccess(FlowRuleOperations ops) {
- log.info("Initialized IP table");
- }
-
- @Override
- public void onError(FlowRuleOperations ops) {
- log.info("Failed to initialize unicast IP table");
- }
- }));
- }
-
- protected void processAclTable() {
- //table miss entry
- FlowRuleOperations.Builder ops = FlowRuleOperations.builder();
- TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
- TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
- selector.matchEthDst(MacAddress.valueOf("00:00:00:00:00:02"));
- treatment.deferred().group(new DefaultGroupId(0x20000001));
- FlowRule rule = DefaultFlowRule.builder()
- .forDevice(deviceId)
- .withSelector(selector.build())
- .withTreatment(treatment.build())
- .withPriority(60000)
- .fromApp(driverId)
- .makePermanent()
- .forTable(ACL_TABLE).build();
- ops = ops.add(rule);
- flowRuleService.apply(ops.build(new FlowRuleOperationsContext() {
- @Override
- public void onSuccess(FlowRuleOperations ops) {
- log.info("Initialized Acl table");
- }
-
- @Override
- public void onError(FlowRuleOperations ops) {
- log.info("Failed to initialize Acl table");
- }
- }));
- }
-
- private void sendPackets() {
- Ethernet eth = new Ethernet();
- eth.setDestinationMACAddress("00:00:00:00:00:02");
- eth.setSourceMACAddress("00:00:00:11:22:33");
- eth.setVlanID((short) 100);
- eth.setEtherType(Ethernet.MPLS_UNICAST);
- MPLS mplsPkt = new MPLS();
- mplsPkt.setLabel(255);
- mplsPkt.setTtl((byte) 5);
-
- IPv4 ipv4 = new IPv4();
-
- ipv4.setDestinationAddress("4.0.5.6");
- ipv4.setSourceAddress("1.0.2.3");
- ipv4.setTtl((byte) 64);
- ipv4.setChecksum((short) 0);
-
- UDP udp = new UDP();
- udp.setDestinationPort(666);
- udp.setSourcePort(333);
- udp.setPayload(new Data(new byte[]{(byte) 1, (byte) 2}));
- udp.setChecksum((short) 0);
-
- ipv4.setPayload(udp);
- mplsPkt.setPayload(ipv4);
- eth.setPayload(mplsPkt);
-
- TrafficTreatment treatment = DefaultTrafficTreatment.builder()
- .setOutput(PortNumber.portNumber(24))
- .build();
- OutboundPacket packet = new DefaultOutboundPacket(deviceId,
- treatment,
- ByteBuffer.wrap(eth.serialize()));
-
-
- Ethernet eth2 = new Ethernet();
- eth2.setDestinationMACAddress("00:00:00:00:00:02");
- eth2.setSourceMACAddress("00:00:00:11:22:33");
- eth2.setVlanID((short) 100);
- eth2.setEtherType(Ethernet.TYPE_IPV4);
-
- IPv4 ipv42 = new IPv4();
- ipv42.setDestinationAddress("2.0.0.2");
- ipv42.setSourceAddress("1.0.9.9");
- ipv42.setTtl((byte) 64);
- ipv42.setChecksum((short) 0);
-
- UDP udp2 = new UDP();
- udp2.setDestinationPort(999);
- udp2.setSourcePort(333);
- udp2.setPayload(new Data(new byte[]{(byte) 1, (byte) 2}));
- udp2.setChecksum((short) 0);
-
- ipv42.setPayload(udp2);
- eth2.setPayload(ipv42);
-
- TrafficTreatment treatment2 = DefaultTrafficTreatment.builder()
- .setOutput(PortNumber.portNumber(26))
- .build();
- OutboundPacket packet2 = new DefaultOutboundPacket(deviceId,
- treatment2,
- ByteBuffer.wrap(eth2.serialize()));
-
-
- log.info("Emitting packets now");
- packetService.emit(packet);
- packetService.emit(packet);
- packetService.emit(packet2);
- packetService.emit(packet);
- packetService.emit(packet);
- log.info("Done emitting packets");
- }
-
- private class InternalPacketProcessor implements PacketProcessor {
-
- @Override
- public void process(PacketContext context) {
-
-
- }
}
}
diff --git a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/OpenstackPipeline.java b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/OpenstackPipeline.java
new file mode 100644
index 00000000..7a92b4fa
--- /dev/null
+++ b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/OpenstackPipeline.java
@@ -0,0 +1,286 @@
+/*
+ * 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.onosproject.driver.pipeline;
+
+import org.onlab.osgi.ServiceDirectory;
+import org.onlab.packet.Ethernet;
+import org.onosproject.core.ApplicationId;
+import org.onosproject.core.CoreService;
+import org.onosproject.net.DeviceId;
+import org.onosproject.net.behaviour.Pipeliner;
+import org.onosproject.net.behaviour.PipelinerContext;
+import org.onosproject.net.flow.DefaultFlowRule;
+import org.onosproject.net.flow.DefaultTrafficSelector;
+import org.onosproject.net.flow.DefaultTrafficTreatment;
+import org.onosproject.net.flow.FlowRule;
+import org.onosproject.net.flow.FlowRuleOperations;
+import org.onosproject.net.flow.FlowRuleOperationsContext;
+import org.onosproject.net.flow.FlowRuleService;
+import org.onosproject.net.flow.TrafficSelector;
+import org.onosproject.net.flow.TrafficTreatment;
+import org.onosproject.net.flow.criteria.Criterion;
+import org.onosproject.net.flow.criteria.EthTypeCriterion;
+import org.onosproject.net.flow.criteria.UdpPortCriterion;
+import org.onosproject.net.flowobjective.FilteringObjective;
+import org.onosproject.net.flowobjective.FlowObjectiveStore;
+import org.onosproject.net.flowobjective.ForwardingObjective;
+import org.onosproject.net.flowobjective.NextObjective;
+import org.onosproject.net.flowobjective.Objective;
+import org.onosproject.net.flowobjective.ObjectiveError;
+import org.slf4j.Logger;
+
+import java.util.Collection;
+import java.util.Collections;
+
+import static org.slf4j.LoggerFactory.getLogger;
+
+/**
+ * Driver for OpenstackSwitching.
+ */
+public class OpenstackPipeline extends DefaultSingleTablePipeline
+ implements Pipeliner {
+
+ private final Logger log = getLogger(getClass());
+ private CoreService coreService;
+ private ServiceDirectory serviceDirectory;
+ protected FlowObjectiveStore flowObjectiveStore;
+ protected DeviceId deviceId;
+ protected ApplicationId appId;
+ protected FlowRuleService flowRuleService;
+
+ protected static final int VNI_TABLE = 0;
+ protected static final int FORWARDING_TABLE = 1;
+
+ private static final int DROP_PRIORITY = 0;
+ private static final int TIME_OUT = 0;
+ private static final int DHCP_SERVER_PORT = 67;
+ private static final int DHCP_CLIENT_PORT = 68;
+
+
+ @Override
+ public void init(DeviceId deviceId, PipelinerContext context) {
+ super.init(deviceId, context);
+ this.serviceDirectory = context.directory();
+ this.deviceId = deviceId;
+
+ coreService = serviceDirectory.get(CoreService.class);
+ flowRuleService = serviceDirectory.get(FlowRuleService.class);
+ flowObjectiveStore = context.store();
+
+ appId = coreService.registerApplication(
+ "org.onosproject.driver.OpenstackPipeline");
+
+ initializePipeline();
+ }
+
+ @Override
+ public void filter(FilteringObjective filteringObjective) {
+ super.filter(filteringObjective);
+ }
+
+ @Override
+ public void next(NextObjective nextObjective) {
+ super.next(nextObjective);
+ }
+
+ @Override
+ public void forward(ForwardingObjective forwardingObjective) {
+ Collection<FlowRule> rules;
+ FlowRuleOperations.Builder flowOpsBuilder = FlowRuleOperations.builder();
+
+ rules = processForward(forwardingObjective);
+
+ switch (forwardingObjective.op()) {
+ case ADD:
+ rules.stream()
+ .filter(rule -> rule != null)
+ .forEach(flowOpsBuilder::add);
+ break;
+ case REMOVE:
+ rules.stream()
+ .filter(rule -> rule != null)
+ .forEach(flowOpsBuilder::remove);
+ break;
+ default:
+ fail(forwardingObjective, ObjectiveError.UNKNOWN);
+ log.warn("Unknown forwarding type {}");
+ }
+
+ flowRuleService.apply(flowOpsBuilder.build(new FlowRuleOperationsContext() {
+ @Override
+ public void onSuccess(FlowRuleOperations ops) {
+ pass(forwardingObjective);
+ }
+
+ @Override
+ public void onError(FlowRuleOperations ops) {
+ fail(forwardingObjective, ObjectiveError.FLOWINSTALLATIONFAILED);
+ }
+ }));
+ }
+
+ private void initializePipeline() {
+ processVNITable(true);
+ processForwardingTable(true);
+ }
+
+ private void processVNITable(boolean install) {
+ TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
+ TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
+
+ treatment.transition(FORWARDING_TABLE);
+
+ FlowRule flowRule = DefaultFlowRule.builder()
+ .forDevice(deviceId)
+ .withSelector(selector.build())
+ .withTreatment(treatment.build())
+ .withPriority(DROP_PRIORITY)
+ .fromApp(appId)
+ .makePermanent()
+ .forTable(VNI_TABLE)
+ .build();
+
+ applyRules(install, flowRule);
+ }
+
+ private void processForwardingTable(boolean install) {
+ TrafficSelector.Builder selector = DefaultTrafficSelector.builder();
+ TrafficTreatment.Builder treatment = DefaultTrafficTreatment.builder();
+
+ treatment.drop();
+
+ FlowRule flowRule = DefaultFlowRule.builder()
+ .forDevice(deviceId)
+ .withSelector(selector.build())
+ .withTreatment(treatment.build())
+ .withPriority(DROP_PRIORITY)
+ .fromApp(appId)
+ .makePermanent()
+ .forTable(FORWARDING_TABLE)
+ .build();
+
+ applyRules(install, flowRule);
+ }
+
+ private void applyRules(boolean install, FlowRule flowRule) {
+ FlowRuleOperations.Builder flowOpsBuilder = FlowRuleOperations.builder();
+
+ flowOpsBuilder = install ? flowOpsBuilder.add(flowRule) : flowOpsBuilder.remove(flowRule);
+
+ flowRuleService.apply(flowOpsBuilder.build(new FlowRuleOperationsContext() {
+ @Override
+ public void onSuccess(FlowRuleOperations ops) {
+ log.debug("Provisioned vni or forwarding table");
+ }
+
+ @Override
+ public void onError(FlowRuleOperations ops) {
+ log.debug("Failed to privision vni or forwarding table");
+ }
+ }));
+ }
+
+ private Collection<FlowRule> processForward(ForwardingObjective forwardingObjective) {
+ switch (forwardingObjective.flag()) {
+ case SPECIFIC:
+ return processSpecific(forwardingObjective);
+ case VERSATILE:
+ return processVersatile(forwardingObjective);
+ default:
+ fail(forwardingObjective, ObjectiveError.UNKNOWN);
+ log.warn("Unknown forwarding flag {}", forwardingObjective.flag());
+ }
+ return Collections.emptySet();
+ }
+
+ private Collection<FlowRule> processVersatile(ForwardingObjective forwardingObjective) {
+ log.debug("Processing versatile forwarding objective");
+
+ FlowRule.Builder ruleBuilder = DefaultFlowRule.builder()
+ .forDevice(deviceId)
+ .withSelector(forwardingObjective.selector())
+ .withTreatment(forwardingObjective.treatment())
+ .withPriority(forwardingObjective.priority())
+ .fromApp(forwardingObjective.appId());
+
+ if (forwardingObjective.permanent()) {
+ ruleBuilder.makePermanent();
+ } else {
+ ruleBuilder.makeTemporary(TIME_OUT);
+ }
+
+ //ARP & DHCP Rule
+ EthTypeCriterion ethCriterion =
+ (EthTypeCriterion) forwardingObjective.selector().getCriterion(Criterion.Type.ETH_TYPE);
+ UdpPortCriterion udpPortCriterion = (UdpPortCriterion) forwardingObjective
+ .selector().getCriterion(Criterion.Type.UDP_DST);
+ if (ethCriterion != null) {
+ if (ethCriterion.ethType().toShort() == Ethernet.TYPE_ARP ||
+ ethCriterion.ethType().toShort() == Ethernet.TYPE_LLDP) {
+ ruleBuilder.forTable(VNI_TABLE);
+ return Collections.singletonList(ruleBuilder.build());
+ } else if (udpPortCriterion != null && udpPortCriterion.udpPort().toInt() == DHCP_SERVER_PORT) {
+ ruleBuilder.forTable(VNI_TABLE);
+ return Collections.singletonList(ruleBuilder.build());
+ }
+ }
+ return Collections.emptySet();
+ }
+
+ private Collection<FlowRule> processSpecific(ForwardingObjective forwardingObjective) {
+ log.debug("Processing specific forwarding objective");
+
+ FlowRule.Builder ruleBuilder = DefaultFlowRule.builder()
+ .forDevice(deviceId)
+ .withSelector(forwardingObjective.selector())
+ .withTreatment(forwardingObjective.treatment())
+ .withPriority(forwardingObjective.priority())
+ .fromApp(forwardingObjective.appId());
+
+ if (forwardingObjective.permanent()) {
+ ruleBuilder.makePermanent();
+ } else {
+ ruleBuilder.makeTemporary(TIME_OUT);
+ }
+
+ //VNI Table Rule
+ if (forwardingObjective.selector().getCriterion(Criterion.Type.IN_PORT) != null) {
+ TrafficTreatment.Builder tBuilder = DefaultTrafficTreatment.builder();
+ forwardingObjective.treatment().allInstructions().forEach(tBuilder::add);
+ tBuilder.transition(FORWARDING_TABLE);
+ ruleBuilder.withTreatment(tBuilder.build());
+ ruleBuilder.forTable(VNI_TABLE);
+ } else {
+ ruleBuilder.forTable(FORWARDING_TABLE);
+ }
+
+ return Collections.singletonList(ruleBuilder.build());
+ }
+
+
+ private void pass(Objective obj) {
+ if (obj.context().isPresent()) {
+ obj.context().get().onSuccess(obj);
+ }
+ }
+
+ private void fail(Objective obj, ObjectiveError error) {
+ if (obj.context().isPresent()) {
+ obj.context().get().onError(obj, error);
+ }
+ }
+}
+
diff --git a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/SpringOpenTTP.java b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/SpringOpenTTP.java
index 8ac5eec8..dba4557a 100644
--- a/framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/SpringOpenTTP.java
+++ b/framework/src/onos/drivers/src/main/java/org/onosproject/driver/pipeline/SpringOpenTTP.java
@@ -287,24 +287,14 @@ public class SpringOpenTTP extends AbstractHandlerBehaviour
case SIMPLE:
Collection<TrafficTreatment> treatments = nextObjective.next();
if (treatments.size() == 1) {
- TrafficTreatment treatment = treatments.iterator().next();
- GroupBucket bucket = DefaultGroupBucket
- .createIndirectGroupBucket(treatment);
- final GroupKey key = new DefaultGroupKey(
- appKryo.serialize(nextObjective
- .id()));
- GroupDescription groupDescription = new DefaultGroupDescription(
- deviceId,
- GroupDescription.Type.INDIRECT,
- new GroupBuckets(
- Collections.singletonList(bucket)),
- key,
- null,
- nextObjective.appId());
- log.debug("Creating SIMPLE group for next objective id {} "
- + "in dev:{}", nextObjective.id(), deviceId);
- pendingGroups.put(key, nextObjective);
- groupService.addGroup(groupDescription);
+ // Spring Open TTP converts simple nextObjective to flow-actions
+ // in a dummy group
+ TrafficTreatment treatment = nextObjective.next().iterator().next();
+ log.debug("Converting SIMPLE group for next objective id {} " +
+ "to {} flow-actions in device:{}", nextObjective.id(),
+ treatment.allInstructions().size(), deviceId);
+ flowObjectiveStore.putNextGroup(nextObjective.id(),
+ new SpringOpenGroup(null, treatment));
}
break;
case HASHED:
@@ -624,8 +614,9 @@ public class SpringOpenTTP extends AbstractHandlerBehaviour
if (next != null) {
SpringOpenGroup soGroup = appKryo.deserialize(next.data());
if (soGroup.dummy) {
- log.debug("Adding flow-actions for fwd. obj. {} "
- + "in dev: {}", fwd.id(), deviceId);
+ log.debug("Adding {} flow-actions for fwd. obj. {} -> next:{} "
+ + "in dev: {}", soGroup.treatment.allInstructions().size(),
+ fwd.id(), fwd.nextId(), deviceId);
for (Instruction ins : soGroup.treatment.allInstructions()) {
treatmentBuilder.add(ins);
}
@@ -639,7 +630,8 @@ public class SpringOpenTTP extends AbstractHandlerBehaviour
}
treatmentBuilder.deferred().group(group.id());
log.debug("Adding OUTGROUP action to group:{} for fwd. obj. {} "
- + "in dev: {}", group.id(), fwd.id(), deviceId);
+ + "for next:{} in dev: {}", group.id(), fwd.id(),
+ fwd.nextId(), deviceId);
}
} else {
log.warn("processSpecific: No associated next objective object");
@@ -705,10 +697,11 @@ public class SpringOpenTTP extends AbstractHandlerBehaviour
if (next != null) {
SpringOpenGroup soGrp = appKryo.deserialize(next.data());
if (soGrp.dummy) {
- log.debug("Adding flow-actions for fwd. obj. {} "
- + "in dev: {}", fwd.id(), deviceId);
+ log.debug("Adding {} flow-actions for fwd. obj. {} "
+ + "in dev: {}", soGrp.treatment.allInstructions().size(),
+ fwd.id(), deviceId);
for (Instruction ins : soGrp.treatment.allInstructions()) {
- treatmentBuilder.add(ins);
+ treatmentBuilder.deferred().add(ins);
}
} else {
GroupKey key = soGrp.key;
@@ -773,6 +766,12 @@ public class SpringOpenTTP extends AbstractHandlerBehaviour
return rules;
}
+ /*
+ * Note: CpqD switches do not handle MPLS-related operation properly
+ * for a packet with VLAN tag. We pop VLAN here as a workaround.
+ * Side effect: HostService learns redundant hosts with same MAC but
+ * different VLAN. No known side effect on the network reachability.
+ */
protected List<FlowRule> processEthDstFilter(EthCriterion ethCriterion,
VlanIdCriterion vlanIdCriterion,
FilteringObjective filt,
@@ -783,12 +782,6 @@ public class SpringOpenTTP extends AbstractHandlerBehaviour
vlanIdCriterion = (VlanIdCriterion) Criteria.matchVlanId(assignedVlan);
}
- /*
- * Note: CpqD switches do not handle MPLS-related operation properly
- * for a packet with VLAN tag. We pop VLAN here as a workaround.
- * Side effect: HostService learns redundant hosts with same MAC but
- * different VLAN. No known side effect on the network reachability.
- */
List<FlowRule> rules = new ArrayList<>();
TrafficSelector.Builder selectorIp = DefaultTrafficSelector
.builder();
diff --git a/framework/src/onos/drivers/src/main/resources/onos-drivers.xml b/framework/src/onos/drivers/src/main/resources/onos-drivers.xml
index a172c18b..2494e123 100644
--- a/framework/src/onos/drivers/src/main/resources/onos-drivers.xml
+++ b/framework/src/onos/drivers/src/main/resources/onos-drivers.xml
@@ -36,6 +36,10 @@
impl="org.onosproject.driver.extensions.NiciraExtensionTreatmentInterpreter" />
<behaviour api="org.onosproject.net.behaviour.ExtensionTreatmentResolver"
impl="org.onosproject.driver.extensions.NiciraExtensionTreatmentInterpreter" />
+ <behaviour api="org.onosproject.openflow.controller.ExtensionSelectorInterpreter"
+ impl="org.onosproject.driver.extensions.NiciraExtensionSelectorInterpreter" />
+ <behaviour api="org.onosproject.net.behaviour.ExtensionSelectorResolver"
+ impl="org.onosproject.driver.extensions.NiciraExtensionSelectorInterpreter" />
</driver>
<!--This driver is for simulated NETCONF devices through of-config tool on top og OVSDB-->
<driver name="ovs-netconf" extends="default"
@@ -70,6 +74,8 @@
swVersion="LINC-OE OpenFlow Software Switch 1.1">
<behaviour api="org.onosproject.openflow.controller.driver.OpenFlowSwitchDriver"
impl="org.onosproject.driver.handshaker.OfOpticalSwitchImplLinc13"/>
+ <behaviour api="org.onosproject.net.behaviour.LambdaQuery"
+ impl="org.onosproject.driver.handshaker.OfOpticalSwitchImplLinc13"/>
</driver>
<driver name="corsa"
manufacturer="Corsa" hwVersion="Corsa Element" swVersion="2.3.1">
@@ -131,6 +137,8 @@
swVersion="ocs switch">
<behaviour api="org.onosproject.openflow.controller.driver.OpenFlowSwitchDriver"
impl="org.onosproject.driver.handshaker.CalientFiberSwitchHandshaker"/>
+ <behaviour api="org.onosproject.net.behaviour.LambdaQuery"
+ impl="org.onosproject.driver.handshaker.CalientFiberSwitchHandshaker"/>
</driver>
<driver name="onosfw" extends="ovs"
manufacturer="" hwVersion="" swVersion="">
diff --git a/framework/src/onos/drivers/src/test/java/org/onosproject/driver/extensions/NiciraSetNshContextHeaderTest.java b/framework/src/onos/drivers/src/test/java/org/onosproject/driver/extensions/NiciraSetNshContextHeaderTest.java
new file mode 100644
index 00000000..45d6d941
--- /dev/null
+++ b/framework/src/onos/drivers/src/test/java/org/onosproject/driver/extensions/NiciraSetNshContextHeaderTest.java
@@ -0,0 +1,68 @@
+/*
+ * 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.onosproject.driver.extensions;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.notNullValue;
+
+import org.junit.Test;
+import org.onosproject.net.flow.instructions.ExtensionTreatmentType;
+
+import com.google.common.testing.EqualsTester;
+
+/**
+ * Unit tests for NiciraSetNshContextHeader class.
+ */
+public class NiciraSetNshContextHeaderTest {
+
+ final NiciraSetNshContextHeader nshCh1 = new NiciraSetNshContextHeader(10,
+ ExtensionTreatmentType.
+ ExtensionTreatmentTypes.
+ NICIRA_SET_NSH_CH1.type());
+ final NiciraSetNshContextHeader sameAsNshCh1 = new NiciraSetNshContextHeader(10,
+ ExtensionTreatmentType.
+ ExtensionTreatmentTypes.
+ NICIRA_SET_NSH_CH1.type());
+ final NiciraSetNshContextHeader nshCh2 = new NiciraSetNshContextHeader(20,
+ ExtensionTreatmentType.
+ ExtensionTreatmentTypes.
+ NICIRA_SET_NSH_CH1.type());
+
+ /**
+ * Checks the operation of equals() methods.
+ */
+ @Test
+ public void testEquals() {
+ new EqualsTester().addEqualityGroup(nshCh1, sameAsNshCh1).addEqualityGroup(nshCh2).testEquals();
+ }
+
+ /**
+ * Checks the construction of a NiciraSetNshSi object.
+ */
+ @Test
+ public void testConstruction() {
+ final NiciraSetNshContextHeader niciraSetNshCh = new NiciraSetNshContextHeader(10,
+ ExtensionTreatmentType.
+ ExtensionTreatmentTypes.
+ NICIRA_SET_NSH_CH1.type());
+ assertThat(niciraSetNshCh, is(notNullValue()));
+ assertThat(niciraSetNshCh.nshCh(), is(10));
+ assertThat(niciraSetNshCh.type(), is(ExtensionTreatmentType.
+ ExtensionTreatmentTypes.
+ NICIRA_SET_NSH_CH1.type()));
+ }
+}
diff --git a/framework/src/onos/drivers/src/test/java/org/onosproject/driver/extensions/NiciraSetNshSiTest.java b/framework/src/onos/drivers/src/test/java/org/onosproject/driver/extensions/NiciraSetNshSiTest.java
new file mode 100644
index 00000000..8541e9f0
--- /dev/null
+++ b/framework/src/onos/drivers/src/test/java/org/onosproject/driver/extensions/NiciraSetNshSiTest.java
@@ -0,0 +1,52 @@
+/*
+ * 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.onosproject.driver.extensions;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.notNullValue;
+
+import org.junit.Test;
+
+import com.google.common.testing.EqualsTester;
+
+/**
+ * Unit tests for NiciraSetNshSi class.
+ */
+public class NiciraSetNshSiTest {
+
+ final NiciraSetNshSi nshSi1 = new NiciraSetNshSi((byte) 10);
+ final NiciraSetNshSi sameAsNshSi1 = new NiciraSetNshSi((byte) 10);
+ final NiciraSetNshSi nshSi2 = new NiciraSetNshSi((byte) 20);
+
+ /**
+ * Checks the operation of equals() methods.
+ */
+ @Test
+ public void testEquals() {
+ new EqualsTester().addEqualityGroup(nshSi1, sameAsNshSi1).addEqualityGroup(nshSi2).testEquals();
+ }
+
+ /**
+ * Checks the construction of a NiciraSetNshSi object.
+ */
+ @Test
+ public void testConstruction() {
+ final NiciraSetNshSi niciraSetNshSi = new NiciraSetNshSi((byte) 15);
+ assertThat(niciraSetNshSi, is(notNullValue()));
+ assertThat(niciraSetNshSi.nshSi(), is((byte) 15));
+ }
+}
diff --git a/framework/src/onos/drivers/src/test/java/org/onosproject/driver/extensions/NiciraSetNshSpiTest.java b/framework/src/onos/drivers/src/test/java/org/onosproject/driver/extensions/NiciraSetNshSpiTest.java
new file mode 100644
index 00000000..197e3bf9
--- /dev/null
+++ b/framework/src/onos/drivers/src/test/java/org/onosproject/driver/extensions/NiciraSetNshSpiTest.java
@@ -0,0 +1,52 @@
+/*
+ * 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.onosproject.driver.extensions;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.notNullValue;
+
+import org.junit.Test;
+
+import com.google.common.testing.EqualsTester;
+
+/**
+ * Unit tests for NiciraSetNshSpi class.
+ */
+public class NiciraSetNshSpiTest {
+
+ final NiciraSetNshSpi nshSpi1 = new NiciraSetNshSpi(10);
+ final NiciraSetNshSpi sameAsNshSpi1 = new NiciraSetNshSpi(10);
+ final NiciraSetNshSpi nshSpi2 = new NiciraSetNshSpi(20);
+
+ /**
+ * Checks the operation of equals() methods.
+ */
+ @Test
+ public void testEquals() {
+ new EqualsTester().addEqualityGroup(nshSpi1, sameAsNshSpi1).addEqualityGroup(nshSpi2).testEquals();
+ }
+
+ /**
+ * Checks the construction of a NiciraSetNshSpi object.
+ */
+ @Test
+ public void testConstruction() {
+ final NiciraSetNshSpi niciraSetNshSpi = new NiciraSetNshSpi(10);
+ assertThat(niciraSetNshSpi, is(notNullValue()));
+ assertThat(niciraSetNshSpi.nshSpi(), is(10));
+ }
+}