Support Nicira load extension, add L4 mod builder for group buckets
Change-Id: Ic16b4d853daed38792aeb199be732aa868c26bad
diff --git a/core/api/src/main/java/org/onosproject/net/flow/instructions/ExtensionTreatmentType.java b/core/api/src/main/java/org/onosproject/net/flow/instructions/ExtensionTreatmentType.java
index 4029bcf..85cc81c 100644
--- a/core/api/src/main/java/org/onosproject/net/flow/instructions/ExtensionTreatmentType.java
+++ b/core/api/src/main/java/org/onosproject/net/flow/instructions/ExtensionTreatmentType.java
@@ -46,6 +46,7 @@
NICIRA_MOV_TUN_ID_TO_TUN_ID(11),
NICIRA_MOV_NSH_C2_TO_TUN_ID(12),
NICIRA_RESUBMIT_TABLE(14),
+ NICIRA_LOAD(20),
NICIRA_PUSH_NSH(38),
NICIRA_POP_NSH(39),
NICIRA_CT(40),
diff --git a/drivers/default/src/main/java/org/onosproject/driver/extensions/NiciraExtensionTreatmentInterpreter.java b/drivers/default/src/main/java/org/onosproject/driver/extensions/NiciraExtensionTreatmentInterpreter.java
index edc8a1e..e80809b 100644
--- a/drivers/default/src/main/java/org/onosproject/driver/extensions/NiciraExtensionTreatmentInterpreter.java
+++ b/drivers/default/src/main/java/org/onosproject/driver/extensions/NiciraExtensionTreatmentInterpreter.java
@@ -16,8 +16,7 @@
package org.onosproject.driver.extensions;
-import static com.google.common.base.Preconditions.checkNotNull;
-import static org.onlab.util.Tools.nullIsIllegal;
+import com.fasterxml.jackson.databind.node.ObjectNode;
import com.google.common.collect.Lists;
import com.google.common.primitives.Bytes;
import org.onlab.packet.Ip4Address;
@@ -38,6 +37,7 @@
import org.projectfloodlight.openflow.protocol.action.OFActionExperimenter;
import org.projectfloodlight.openflow.protocol.action.OFActionNicira;
import org.projectfloodlight.openflow.protocol.action.OFActionNiciraCt;
+import org.projectfloodlight.openflow.protocol.action.OFActionNiciraLoad;
import org.projectfloodlight.openflow.protocol.action.OFActionNiciraMove;
import org.projectfloodlight.openflow.protocol.action.OFActionNiciraNat;
import org.projectfloodlight.openflow.protocol.action.OFActionNiciraResubmit;
@@ -62,13 +62,15 @@
import org.projectfloodlight.openflow.types.MacAddress;
import org.projectfloodlight.openflow.types.U16;
import org.projectfloodlight.openflow.types.U32;
+import org.projectfloodlight.openflow.types.U64;
import org.projectfloodlight.openflow.types.U8;
-import com.fasterxml.jackson.databind.node.ObjectNode;
-
import java.util.ArrayList;
import java.util.List;
+import static com.google.common.base.Preconditions.checkNotNull;
+import static org.onlab.util.Tools.nullIsIllegal;
+
/**
* Interpreter for Nicira OpenFlow treatment extensions.
*/
@@ -98,6 +100,7 @@
private static final int SUB_TYPE_RESUBMIT = 1;
private static final int SUB_TYPE_RESUBMIT_TABLE = 14;
private static final int SUB_TYPE_MOVE = 6;
+ private static final int SUB_TYPE_LOAD = 7;
private static final int SUB_TYPE_CT = 35;
private static final int SUB_TYPE_NAT = 36;
private static final int SUB_TYPE_CT_CLEAR = 43;
@@ -111,6 +114,7 @@
private static final String NICIRA_NSH_SI = "niciraNshSi";
private static final String NICIRA_NSH_CH = "niciraNshCh";
private static final String NICIRA_MOVE = "niciraMove";
+ private static final String NICIRA_LOAD = "niciraLoad";
private static final String TYPE = "type";
@@ -226,6 +230,9 @@
if (extensionTreatmentType.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_CT_CLEAR.type())) {
return true;
}
+ if (extensionTreatmentType.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_LOAD.type())) {
+ return true;
+ }
return false;
}
@@ -326,6 +333,15 @@
action.setDst(mov.dst());
return action.build();
}
+ if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_LOAD.type())) {
+ NiciraLoad load = (NiciraLoad) extensionTreatment;
+ OFActionNiciraLoad.Builder action = factory.actions()
+ .buildNiciraLoad();
+ action.setOfsNbits(load.ofsNbits());
+ action.setDst(load.dst());
+ action.setValue(U64.of(load.value()));
+ return action.build();
+ }
if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_CT.type())) {
NiciraCt niciraCt = (NiciraCt) extensionTreatment;
OFActionNiciraCt.Builder ctAction = factory.actions().buildNiciraCt();
@@ -576,6 +592,10 @@
new ArrayList<>());
case SUB_TYPE_CT_CLEAR:
return new NiciraCtClear();
+ case SUB_TYPE_LOAD:
+ OFActionNiciraLoad loadAction = (OFActionNiciraLoad) nicira;
+ return new NiciraLoad(loadAction.getOfsNbits(),
+ loadAction.getDst(), loadAction.getValue().getValue());
default:
throw new UnsupportedOperationException("Driver does not support extension subtype "
+ nicira.getSubtype());
@@ -675,6 +695,9 @@
if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_CT_CLEAR.type())) {
return new NiciraCtClear();
}
+ if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_LOAD.type())) {
+ return new NiciraLoad();
+ }
throw new UnsupportedOperationException("Driver does not support extension type " + type.toString());
}
diff --git a/drivers/default/src/main/java/org/onosproject/driver/extensions/NiciraLoad.java b/drivers/default/src/main/java/org/onosproject/driver/extensions/NiciraLoad.java
new file mode 100644
index 0000000..c1108cb
--- /dev/null
+++ b/drivers/default/src/main/java/org/onosproject/driver/extensions/NiciraLoad.java
@@ -0,0 +1,138 @@
+/*
+ * Copyright 2019-present Open Networking Foundation
+ *
+ * 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 com.google.common.collect.Maps;
+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.HashMap;
+import java.util.Map;
+import java.util.Objects;
+
+/**
+ * Nicira load extension instruction.
+ */
+public class NiciraLoad extends AbstractExtension implements ExtensionTreatment {
+ private int ofsNbits;
+ private long dst;
+ private long value;
+
+ private final KryoNamespace appKryo = new KryoNamespace.Builder()
+ .register(Map.class)
+ .register(HashMap.class)
+ .build();
+
+ /**
+ * Empty constructor.
+ */
+ public NiciraLoad() {
+ }
+
+ /**
+ * Creates a new load treatment.
+ *
+ * @param ofsNbits off set and nBits
+ * @param dst destination
+ * @param value value
+ */
+ public NiciraLoad(int ofsNbits, long dst, long value) {
+ this.ofsNbits = ofsNbits;
+ this.dst = dst;
+ this.value = value;
+ }
+
+ /**
+ * Gets load nBits.
+ *
+ * @return nBits
+ */
+ public int ofsNbits() {
+ return ofsNbits;
+ }
+
+ /**
+ * Gets load destination.
+ *
+ * @return load destination
+ */
+ public long dst() {
+ return dst;
+ }
+
+ /**
+ * Gets load value.
+ *
+ * @return load value
+ */
+ public long value() {
+ return value;
+ }
+
+ @Override
+ public ExtensionTreatmentType type() {
+ return ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_LOAD.type();
+ }
+
+ @Override
+ public byte[] serialize() {
+ Map<String, Object> values = Maps.newHashMap();
+ values.put("ofsNbits", ofsNbits);
+ values.put("dst", dst);
+ values.put("value", value);
+ return appKryo.serialize(values);
+ }
+
+ @Override
+ public void deserialize(byte[] data) {
+ Map<String, Object> values = appKryo.deserialize(data);
+ ofsNbits = (int) values.get("ofsNbits");
+ dst = (long) values.get("dst");
+ value = (long) values.get("value");
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+ NiciraLoad that = (NiciraLoad) o;
+ return ofsNbits == that.ofsNbits &&
+ dst == that.dst &&
+ value == that.value &&
+ Objects.equals(this.type(), that.type());
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(ofsNbits, dst, value);
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(this)
+ .add("ofsNbits", ofsNbits)
+ .add("dst", dst)
+ .add("value", value)
+ .toString();
+ }
+}
\ No newline at end of file
diff --git a/providers/openflow/group/src/main/java/org/onosproject/provider/of/group/impl/GroupModBuilder.java b/providers/openflow/group/src/main/java/org/onosproject/provider/of/group/impl/GroupModBuilder.java
index acd22ac..f5d02b0 100644
--- a/providers/openflow/group/src/main/java/org/onosproject/provider/of/group/impl/GroupModBuilder.java
+++ b/providers/openflow/group/src/main/java/org/onosproject/provider/of/group/impl/GroupModBuilder.java
@@ -31,6 +31,7 @@
import org.onosproject.net.flow.instructions.L0ModificationInstruction;
import org.onosproject.net.flow.instructions.L2ModificationInstruction;
import org.onosproject.net.flow.instructions.L3ModificationInstruction;
+import org.onosproject.net.flow.instructions.L4ModificationInstruction;
import org.onosproject.net.group.GroupBucket;
import org.onosproject.net.group.GroupBuckets;
import org.onosproject.net.group.GroupDescription;
@@ -54,6 +55,7 @@
import org.projectfloodlight.openflow.types.OFGroup;
import org.projectfloodlight.openflow.types.OFPort;
import org.projectfloodlight.openflow.types.OFVlanVidMatch;
+import org.projectfloodlight.openflow.types.TransportPort;
import org.projectfloodlight.openflow.types.U32;
import org.projectfloodlight.openflow.types.U64;
import org.projectfloodlight.openflow.types.VlanPcp;
@@ -231,6 +233,9 @@
case L3MODIFICATION:
actions.add(buildL3Modification(i));
break;
+ case L4MODIFICATION:
+ actions.add(buildL4Modification(i));
+ break;
case OUTPUT:
Instructions.OutputInstruction out =
(Instructions.OutputInstruction) i;
@@ -392,6 +397,38 @@
return null;
}
+ protected OFAction buildL4Modification(Instruction i) {
+ L4ModificationInstruction l4m = (L4ModificationInstruction) i;
+ L4ModificationInstruction.ModTransportPortInstruction tp;
+ OFOxm<?> oxm = null;
+ switch (l4m.subtype()) {
+ case TCP_SRC:
+ tp = (L4ModificationInstruction.ModTransportPortInstruction) l4m;
+ oxm = factory.oxms().tcpSrc(TransportPort.of(tp.port().toInt()));
+ break;
+ case TCP_DST:
+ tp = (L4ModificationInstruction.ModTransportPortInstruction) l4m;
+ oxm = factory.oxms().tcpDst(TransportPort.of(tp.port().toInt()));
+ break;
+ case UDP_SRC:
+ tp = (L4ModificationInstruction.ModTransportPortInstruction) l4m;
+ oxm = factory.oxms().udpSrc(TransportPort.of(tp.port().toInt()));
+ break;
+ case UDP_DST:
+ tp = (L4ModificationInstruction.ModTransportPortInstruction) l4m;
+ oxm = factory.oxms().udpDst(TransportPort.of(tp.port().toInt()));
+ break;
+ default:
+ log.warn("Unimplemented action type {}.", l4m.subtype());
+ break;
+ }
+
+ if (oxm != null) {
+ return factory.actions().buildSetField().setField(oxm).build();
+ }
+ return null;
+ }
+
private OFGroupType getOFGroupType(GroupDescription.Type groupType) {
switch (groupType) {
case INDIRECT: