[ONOS-6208]Implemention of onos and loxi for OVS NAT and connection tracking support
Change-Id: I782422d41fdacc805b523b57c3bd0b6e67e483a2
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 3a0778e..bcc8872 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
@@ -18,8 +18,10 @@
import static com.google.common.base.Preconditions.checkNotNull;
import static org.onlab.util.Tools.nullIsIllegal;
-
+import com.google.common.collect.Lists;
+import com.google.common.primitives.Bytes;
import org.onlab.packet.Ip4Address;
+import org.onlab.packet.IpAddress;
import org.onosproject.codec.CodecContext;
import org.onosproject.net.NshContextHeader;
import org.onosproject.net.NshServiceIndex;
@@ -35,7 +37,9 @@
import org.projectfloodlight.openflow.protocol.action.OFAction;
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.OFActionNiciraMove;
+import org.projectfloodlight.openflow.protocol.action.OFActionNiciraNat;
import org.projectfloodlight.openflow.protocol.action.OFActionNiciraResubmit;
import org.projectfloodlight.openflow.protocol.action.OFActionNiciraResubmitTable;
import org.projectfloodlight.openflow.protocol.action.OFActionSetField;
@@ -54,6 +58,7 @@
import org.projectfloodlight.openflow.protocol.oxm.OFOxmTunGpeNp;
import org.projectfloodlight.openflow.protocol.oxm.OFOxmTunnelIpv4Dst;
import org.projectfloodlight.openflow.types.IPv4Address;
+import org.projectfloodlight.openflow.types.IPv6Address;
import org.projectfloodlight.openflow.types.MacAddress;
import org.projectfloodlight.openflow.types.U16;
import org.projectfloodlight.openflow.types.U32;
@@ -61,6 +66,9 @@
import com.fasterxml.jackson.databind.node.ObjectNode;
+import java.util.ArrayList;
+import java.util.List;
+
/**
* Interpreter for Nicira OpenFlow treatment extensions.
*/
@@ -80,9 +88,19 @@
private static final int TUN_IPV4_DST = 0x00014004;
private static final int TUN_ID = 0x12008;
+ private static final int NAT_RANGE_IPV4_MIN = 0x01;
+ private static final int NAT_RANGE_IPV4_MAX = 0x02;
+ private static final int NAT_RANGE_IPV6_MIN = 0x04;
+ private static final int NAT_RANGE_IPV6_MAX = 0x08;
+ private static final int NAT_RANGE_PROTO_MIN = 0x10;
+ private static final int NAT_RANGE_PROTO_MAX = 0x20;
+
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_CT = 35;
+ private static final int SUB_TYPE_NAT = 36;
+ private static final int SUB_TYPE_CT_CLEAR = 43;
private static final int SUB_TYPE_PUSH_NSH = 38;
private static final int SUB_TYPE_POP_NSH = 39;
@@ -199,6 +217,15 @@
.type())) {
return true;
}
+ if (extensionTreatmentType.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_CT.type())) {
+ return true;
+ }
+ if (extensionTreatmentType.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_NAT.type())) {
+ return true;
+ }
+ if (extensionTreatmentType.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_CT_CLEAR.type())) {
+ return true;
+ }
return false;
}
@@ -299,6 +326,70 @@
action.setDst(mov.dst());
return action.build();
}
+ if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_CT.type())) {
+ NiciraCt niciraCt = (NiciraCt) extensionTreatment;
+ OFActionNiciraCt.Builder ctAction = factory.actions().buildNiciraCt();
+ ctAction.setFlags(niciraCt.niciraCtFlags());
+ ctAction.setZoneSrc(niciraCt.niciraCtZoneSrc());
+ ctAction.setZone(niciraCt.niciraCtZone());
+ ctAction.setRecircTable(niciraCt.niciraCtRecircTable());
+ ctAction.setAlg(niciraCt.niciraCtAlg());
+
+ for (ExtensionTreatment nestedTreatment : niciraCt.niciraCtNestActions()) {
+ if (nestedTreatment instanceof NiciraNat) {
+ NiciraNat niciraNat = (NiciraNat) nestedTreatment;
+ OFActionNiciraNat.Builder action = factory.actions().buildNiciraNat();
+ action.setFlags(niciraNat.niciraNatFlags());
+
+ int presetFlags = niciraNat.niciraNatPresentFlags();
+ action.setRangePresent(presetFlags);
+
+ List<IPv4Address> ipv4RangeList = Lists.newArrayList();
+ List<IPv6Address> ipv6RangeList = Lists.newArrayList();
+ List<U16> portRangeList = Lists.newArrayList();
+ List<U8> padList = Lists.newArrayList();
+ if ((presetFlags & NAT_RANGE_IPV4_MIN) != 0) {
+ ipv4RangeList.add(IPv4Address.of(niciraNat.niciraNatIpAddressMin().getIp4Address().toString()));
+ }
+ if ((presetFlags & NAT_RANGE_IPV4_MAX) != 0) {
+ ipv4RangeList.add(IPv4Address.of(niciraNat.niciraNatIpAddressMax().getIp4Address().toString()));
+ }
+
+ if ((presetFlags & NAT_RANGE_IPV6_MIN) != 0) {
+ ipv6RangeList.add(IPv6Address.of(niciraNat.niciraNatIpAddressMin().getIp6Address().toString()));
+ }
+ if ((presetFlags & NAT_RANGE_IPV6_MAX) != 0) {
+ ipv6RangeList.add(IPv6Address.of(niciraNat.niciraNatIpAddressMax().getIp6Address().toString()));
+ }
+
+ if ((presetFlags & NAT_RANGE_PROTO_MIN) != 0) {
+ portRangeList.add(U16.of(niciraNat.niciraNatPortMin()));
+ }
+ if ((presetFlags & NAT_RANGE_PROTO_MAX) != 0) {
+ portRangeList.add(U16.of(niciraNat.niciraNatPortMax()));
+ }
+
+ for (; (ipv6RangeList.size() * 16 + ipv4RangeList.size() * 4
+ + portRangeList.size() * 2 + padList.size()) % 8 != 0;) {
+ padList.add(U8.ofRaw((byte) 0));
+ }
+
+ action.setIpv4Range(ipv4RangeList);
+ action.setIpv6Range(ipv6RangeList);
+ action.setPortRange(portRangeList);
+ action.setPad(padList);
+
+ //nat action must be nested in ct action
+ List<OFAction> actions = Lists.newArrayList();
+ actions.add(action.build());
+ ctAction.setActions(actions);
+ }
+ }
+ return ctAction.build();
+ }
+ if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_CT_CLEAR.type())) {
+ return factory.actions().niciraCtClear();
+ }
return null;
}
@@ -404,14 +495,87 @@
case SUB_TYPE_RESUBMIT:
OFActionNiciraResubmit resubmitAction = (OFActionNiciraResubmit) nicira;
return new NiciraResubmit(PortNumber.portNumber(resubmitAction.getInPort()));
- case SUB_TYPE_PUSH_NSH:
- return new NiciraPushNsh();
- case SUB_TYPE_POP_NSH:
- return new NiciraPopNsh();
- case SUB_TYPE_RESUBMIT_TABLE:
- OFActionNiciraResubmitTable resubmitTable = (OFActionNiciraResubmitTable) nicira;
- return new NiciraResubmitTable(PortNumber.portNumber(resubmitTable.getInPort()),
- resubmitTable.getTable());
+ case SUB_TYPE_PUSH_NSH:
+ return new NiciraPushNsh();
+ case SUB_TYPE_POP_NSH:
+ return new NiciraPopNsh();
+ case SUB_TYPE_RESUBMIT_TABLE:
+ OFActionNiciraResubmitTable resubmitTable = (OFActionNiciraResubmitTable) nicira;
+ return new NiciraResubmitTable(PortNumber.portNumber(resubmitTable.getInPort()),
+ resubmitTable.getTable());
+ case SUB_TYPE_CT:
+ OFActionNiciraCt ctAction = (OFActionNiciraCt) nicira;
+ List<OFAction> actions = ctAction.getActions();
+ for (OFAction act : actions) {
+ OFActionExperimenter ctExperimenter = (OFActionExperimenter) act;
+ if (Long.valueOf(ctExperimenter.getExperimenter()).intValue() == TYPE_NICIRA) {
+ OFActionNicira actionNicira = (OFActionNicira) ctExperimenter;
+ switch (actionNicira.getSubtype()) {
+ case SUB_TYPE_NAT:
+ OFActionNiciraNat natAction = (OFActionNiciraNat) actionNicira;
+ int portMin = 0;
+ int portMax = 0;
+ IpAddress ipAddressMin = IpAddress.valueOf(0);
+ IpAddress ipAddressMax = IpAddress.valueOf(0);
+ //FIXME: we need to get ipv6 and port from list<ipv4> temporarily,
+ // becase loxi don't know how to arrange these data to corresonding field.
+ IPv4Address[] arrays = (IPv4Address[]) natAction
+ .getIpv4Range().toArray(new IPv4Address[0]);
+ int index = 0;
+ if ((natAction.getRangePresent() & NAT_RANGE_IPV4_MIN) != 0) {
+ ipAddressMin = IpAddress.valueOf(arrays[index++].toString());
+ }
+ if ((natAction.getRangePresent() & NAT_RANGE_IPV4_MAX) != 0) {
+ ipAddressMax = IpAddress.valueOf(arrays[index++].toString());
+ }
+ if ((natAction.getRangePresent() & NAT_RANGE_IPV6_MIN) != 0) {
+ byte[] bytes = Bytes.concat(arrays[index++].getBytes(),
+ arrays[index++].getBytes(),
+ arrays[index++].getBytes(),
+ arrays[index++].getBytes());
+
+ ipAddressMin = IpAddress.valueOf(IpAddress.Version.INET6, bytes);
+ }
+ if ((natAction.getRangePresent() & NAT_RANGE_IPV6_MAX) != 0) {
+ byte[] bytes = Bytes.concat(arrays[index++].getBytes(),
+ arrays[index++].getBytes(),
+ arrays[index++].getBytes(),
+ arrays[index++].getBytes());
+
+ ipAddressMax = IpAddress.valueOf(IpAddress.Version.INET6, bytes);
+ }
+ if ((natAction.getRangePresent() & NAT_RANGE_PROTO_MIN) != 0) {
+ portMin = arrays[index].getInt() >> 16 & 0x0000ffff;
+ }
+ if ((natAction.getRangePresent() & NAT_RANGE_PROTO_MAX) != 0) {
+ portMax = arrays[index].getInt() & 0x0000ffff;
+ }
+ List<ExtensionTreatment> treatments = new ArrayList<>();
+ NiciraNat natTreatment = new NiciraNat(natAction.getFlags(),
+ natAction.getRangePresent(),
+ portMin, portMax,
+ ipAddressMin, ipAddressMax);
+ treatments.add(natTreatment);
+ return new NiciraCt(ctAction.getFlags(),
+ ctAction.getZoneSrc(),
+ ctAction.getZone(),
+ ctAction.getRecircTable(),
+ ctAction.getAlg(),
+ treatments);
+ default:
+ throw new UnsupportedOperationException("Driver does not support nested" +
+ " in ct action extension subtype " + actionNicira.getSubtype());
+ }
+ }
+ }
+ return new NiciraCt(ctAction.getFlags(),
+ ctAction.getZoneSrc(),
+ ctAction.getZone(),
+ ctAction.getRecircTable(),
+ ctAction.getAlg(),
+ new ArrayList<>());
+ case SUB_TYPE_CT_CLEAR:
+ return new NiciraCtClear();
default:
throw new UnsupportedOperationException("Driver does not support extension subtype "
+ nicira.getSubtype());
@@ -502,6 +666,15 @@
if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_MOV_NSH_C2_TO_TUN_ID.type())) {
return NiciraMoveTreatmentFactory.createNiciraMovNshC2ToTunId();
}
+ if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_CT.type())) {
+ return new NiciraCt();
+ }
+ if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_NAT.type())) {
+ return new NiciraNat();
+ }
+ if (type.equals(ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_CT_CLEAR.type())) {
+ return new NiciraCtClear();
+ }
throw new UnsupportedOperationException("Driver does not support extension type " + type.toString());
}