diff --git a/core/api/src/main/java/org/onosproject/net/flow/criteria/ExtensionSelectorType.java b/core/api/src/main/java/org/onosproject/net/flow/criteria/ExtensionSelectorType.java index f65c1685e0..e9715a6c03 100644 --- a/core/api/src/main/java/org/onosproject/net/flow/criteria/ExtensionSelectorType.java +++ b/core/api/src/main/java/org/onosproject/net/flow/criteria/ExtensionSelectorType.java @@ -39,6 +39,10 @@ public class ExtensionSelectorType { NICIRA_MATCH_NSH_CH3(4), NICIRA_MATCH_NSH_CH4(5), NICIRA_MATCH_ENCAP_ETH_TYPE(6), + NICIRA_MATCH_CONNTRACK_STATE(7), + NICIRA_MATCH_CONNTRACK_ZONE(8), + NICIRA_MATCH_CONNTRACK_MARK(9), + NICIRA_MATCH_CONNTRACK_LABEL(10), OFDPA_MATCH_VLAN_VID(16), OFDPA_MATCH_OVID(17), OFDPA_MATCH_MPLS_L2_PORT(18), 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 1371e42bc4..d11a9a97f6 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 @@ -48,6 +48,9 @@ public final class ExtensionTreatmentType { NICIRA_RESUBMIT_TABLE(14), NICIRA_PUSH_NSH(38), NICIRA_POP_NSH(39), + NICIRA_CT(40), + NICIRA_NAT(41), + NICIRA_CT_CLEAR(42), OFDPA_SET_VLAN_ID(64), OFDPA_SET_MPLS_TYPE(65), OFDPA_SET_OVID(66), diff --git a/drivers/default/src/main/java/org/onosproject/driver/extensions/NiciraCt.java b/drivers/default/src/main/java/org/onosproject/driver/extensions/NiciraCt.java new file mode 100644 index 0000000000..62e750611e --- /dev/null +++ b/drivers/default/src/main/java/org/onosproject/driver/extensions/NiciraCt.java @@ -0,0 +1,187 @@ +/* + * Copyright 2017-present 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 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.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +/** + * Nicira ct extension instruction. + */ +public class NiciraCt extends AbstractExtension implements ExtensionTreatment { + + private int flags; + private long zoneSrc; + private int zone; + private short recircTable; + private int alg; + private List nestedActions; + private final KryoNamespace appKryo = new KryoNamespace.Builder().build(); + + /** + * Creates a new nicicra ct instruction. + */ + public NiciraCt() { + flags = 0; + zoneSrc = 0L; + zone = 0; + alg = 0; + recircTable = 0xFF; + nestedActions = new ArrayList<>(); + } + + /** + * Creates a new nicicra ct instruction. + * @param flags zero or commit(0x01) + * @param zoneSrc If 'zone_src' is nonzero, this specifies that the zone should be + * sourced from a field zone_src[ofs:ofs+nbits]. + * @param zone this is the union of zone_imm and zone_ofs_nbits + * If 'zone_src' is zero, then the value of 'zone_imm' + * will be used as the connection tracking zone + * @param recircTable Recirculate to a specific table or 0xff for no recirculation + * @param alg Well-known port number for the protocol, 0 indicates no ALG is required + * @param actions a sequence of zero or more OpenFlow actions + */ + public NiciraCt(int flags, long zoneSrc, int zone, short recircTable, int alg, List actions) { + this.flags = flags; + this.zoneSrc = zoneSrc; + this.zone = zone; + this.recircTable = recircTable; + this.alg = alg; + this.nestedActions = actions; + } + + @Override + public ExtensionTreatmentType type() { + return ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_CT.type(); + } + + /** + * Get Nicira Conntrack flags. + * @return flags + */ + public int niciraCtFlags() { + return flags; + } + + /** + * Get Nicira Conntrack zone. + * @return zone + */ + public int niciraCtZone() { + return zone; + } + + /** + * Get Nicira Conntrack zone src. + * @return zoneSrc + */ + public long niciraCtZoneSrc() { + return zoneSrc; + } + + /** + * Get Nicira Conntrack alg. + * @return alg + */ + public int niciraCtAlg() { + return alg; + } + + /** + * Get Nicira Conntrack Recirc table. + * @return recirc table + */ + public short niciraCtRecircTable() { + return recircTable; + } + + /** + * Get Nicira Conntrack Recirc table. + * @return list extension treatment + */ + public List niciraCtNestActions() { + return nestedActions; + } + + @Override + public void deserialize(byte[] data) { + Map values = appKryo.deserialize(data); + flags = (int) values.get("flags"); + zoneSrc = (long) values.get("zoneSrc"); + zone = (int) values.get("zone"); + recircTable = (short) values.get("recircTable"); + alg = (int) values.get("alg"); + nestedActions = (List) values.get("nestedActions"); + } + + @Override + public byte[] serialize() { + Map values = Maps.newHashMap(); + values.put("flags", flags); + values.put("zoneSrc", zoneSrc); + values.put("zone", zone); + values.put("recircTable", recircTable); + values.put("alg", alg); + values.put("nestedActions", nestedActions); + return appKryo.serialize(values); + } + + @Override + public int hashCode() { + return Objects.hash(type(), flags, zone, zoneSrc, alg, recircTable, nestedActions); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj instanceof NiciraCt) { + NiciraCt that = (NiciraCt) obj; + return Objects.equals(flags, that.flags) && + Objects.equals(zone, that.zone) && + Objects.equals(zoneSrc, that.zoneSrc) && + Objects.equals(alg, that.alg) && + Objects.equals(recircTable, that.recircTable) && + Objects.equals(nestedActions, that.nestedActions) && + Objects.equals(this.type(), that.type()); + } + return false; + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(getClass()) + .add("flags", flags) + .add("zoneSrc", zoneSrc) + .add("zone", zone) + .add("recircTable", recircTable) + .add("alg", alg) + .add("nestedActions", nestedActions) + .toString(); + } +} \ No newline at end of file diff --git a/drivers/default/src/main/java/org/onosproject/driver/extensions/NiciraCtClear.java b/drivers/default/src/main/java/org/onosproject/driver/extensions/NiciraCtClear.java new file mode 100644 index 0000000000..d7aada7dad --- /dev/null +++ b/drivers/default/src/main/java/org/onosproject/driver/extensions/NiciraCtClear.java @@ -0,0 +1,65 @@ +/* + * Copyright 2017-present 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.onlab.util.KryoNamespace; +import org.onosproject.net.flow.AbstractExtension; +import org.onosproject.net.flow.instructions.ExtensionTreatment; +import org.onosproject.net.flow.instructions.ExtensionTreatmentType; + +/** + * Nicira conntrack clear extension instruction. + */ +public class NiciraCtClear extends AbstractExtension implements ExtensionTreatment { + + private final KryoNamespace appKryo = new KryoNamespace.Builder().build(); + + /** + * Creates a conntrack clear instruction. + */ + public NiciraCtClear() { + } + + @Override + public ExtensionTreatmentType type() { + return ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_CT_CLEAR.type(); + } + + @Override + public void deserialize(byte[] data) { + } + + @Override + public byte[] serialize() { + return appKryo.serialize(0); + } + + @Override + public int hashCode() { + return 1; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj instanceof NiciraCtClear) { + return true; + } + return false; + } +} diff --git a/drivers/default/src/main/java/org/onosproject/driver/extensions/NiciraExtensionSelectorInterpreter.java b/drivers/default/src/main/java/org/onosproject/driver/extensions/NiciraExtensionSelectorInterpreter.java index 4bd1aa53a2..b9367fcd74 100644 --- a/drivers/default/src/main/java/org/onosproject/driver/extensions/NiciraExtensionSelectorInterpreter.java +++ b/drivers/default/src/main/java/org/onosproject/driver/extensions/NiciraExtensionSelectorInterpreter.java @@ -28,6 +28,9 @@ import org.onosproject.openflow.controller.ExtensionSelectorInterpreter; import org.projectfloodlight.openflow.protocol.OFFactory; import org.projectfloodlight.openflow.protocol.match.MatchField; import org.projectfloodlight.openflow.protocol.oxm.OFOxm; +import org.projectfloodlight.openflow.protocol.oxm.OFOxmConntrackMark; +import org.projectfloodlight.openflow.protocol.oxm.OFOxmConntrackStateMasked; +import org.projectfloodlight.openflow.protocol.oxm.OFOxmConntrackZone; import org.projectfloodlight.openflow.protocol.oxm.OFOxmEncapEthType; import org.projectfloodlight.openflow.protocol.oxm.OFOxmNsi; import org.projectfloodlight.openflow.protocol.oxm.OFOxmNsp; @@ -66,6 +69,22 @@ public class NiciraExtensionSelectorInterpreter .type())) { return true; } + if (extensionSelectorType.equals(ExtensionSelectorType.ExtensionSelectorTypes.NICIRA_MATCH_CONNTRACK_STATE + .type())) { + return true; + } + if (extensionSelectorType.equals(ExtensionSelectorType.ExtensionSelectorTypes.NICIRA_MATCH_CONNTRACK_ZONE + .type())) { + return true; + } + if (extensionSelectorType.equals(ExtensionSelectorType.ExtensionSelectorTypes.NICIRA_MATCH_CONNTRACK_MARK + .type())) { + return true; + } + if (extensionSelectorType.equals(ExtensionSelectorType.ExtensionSelectorTypes.NICIRA_MATCH_CONNTRACK_LABEL + .type())) { + return true; + } return false; } @@ -97,6 +116,20 @@ public class NiciraExtensionSelectorInterpreter if (type.equals(ExtensionSelectorType.ExtensionSelectorTypes.NICIRA_MATCH_NSH_CH4.type())) { // TODO } + + if (type.equals(ExtensionSelectorType.ExtensionSelectorTypes.NICIRA_MATCH_CONNTRACK_STATE.type())) { + NiciraMatchCtState niciraMatchCtState = (NiciraMatchCtState) extensionSelector; + return factory.oxms().conntrackStateMasked(U32.of(niciraMatchCtState.ctState()), + U32.of(niciraMatchCtState.ctStateMask())); + } + if (type.equals(ExtensionSelectorType.ExtensionSelectorTypes.NICIRA_MATCH_CONNTRACK_ZONE.type())) { + NiciraMatchCtZone niciraMatchCtZone = (NiciraMatchCtZone) extensionSelector; + return factory.oxms().conntrackZone(U16.of(niciraMatchCtZone.ctZone())); + } + if (type.equals(ExtensionSelectorType.ExtensionSelectorTypes.NICIRA_MATCH_CONNTRACK_MARK.type())) { + NiciraMatchCtMark niciraMatchCtMark = (NiciraMatchCtMark) extensionSelector; + return factory.oxms().conntrackMark(U32.of(niciraMatchCtMark.ctMark())); + } return null; } @@ -115,7 +148,18 @@ public class NiciraExtensionSelectorInterpreter OFOxmEncapEthType oxmField = (OFOxmEncapEthType) oxm; return new NiciraMatchEncapEthType(oxmField.getValue().getRaw()); } - + if (oxm.getMatchField() == MatchField.CONNTRACK_STATE) { + OFOxmConntrackStateMasked oxmField = (OFOxmConntrackStateMasked) oxm; + return new NiciraMatchCtState(oxmField.getValue().getRaw(), oxmField.getMask().getRaw()); + } + if (oxm.getMatchField() == MatchField.CONNTRACK_ZONE) { + OFOxmConntrackZone oxmField = (OFOxmConntrackZone) oxm; + return new NiciraMatchCtZone(oxmField.getValue().getRaw()); + } + if (oxm.getMatchField() == MatchField.CONNTRACK_MARK) { + OFOxmConntrackMark oxmField = (OFOxmConntrackMark) oxm; + return new NiciraMatchCtMark(oxmField.getValue().getRaw()); + } return null; } @@ -136,6 +180,15 @@ public class NiciraExtensionSelectorInterpreter || type.equals(ExtensionSelectorType.ExtensionSelectorTypes.NICIRA_MATCH_NSH_CH4.type())) { return new NiciraMatchNshContextHeader(type); } + if (type.equals(ExtensionSelectorType.ExtensionSelectorTypes.NICIRA_MATCH_CONNTRACK_STATE.type())) { + return new NiciraMatchCtState(); + } + if (type.equals(ExtensionSelectorType.ExtensionSelectorTypes.NICIRA_MATCH_CONNTRACK_ZONE.type())) { + return new NiciraMatchCtZone(); + } + if (type.equals(ExtensionSelectorType.ExtensionSelectorTypes.NICIRA_MATCH_CONNTRACK_MARK.type())) { + return new NiciraMatchCtMark(); + } return null; } 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 3a0778e38c..bcc887215c 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 @@ package org.onosproject.driver.extensions; 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.OFFactory; 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.OFOxmNsp; 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 org.projectfloodlight.openflow.types.U8; 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 @@ public class NiciraExtensionTreatmentInterpreter extends AbstractHandlerBehaviou 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 @@ public class NiciraExtensionTreatmentInterpreter extends AbstractHandlerBehaviou .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 @@ public class NiciraExtensionTreatmentInterpreter extends AbstractHandlerBehaviou 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 ipv4RangeList = Lists.newArrayList(); + List ipv6RangeList = Lists.newArrayList(); + List portRangeList = Lists.newArrayList(); + List 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 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 @@ public class NiciraExtensionTreatmentInterpreter extends AbstractHandlerBehaviou 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 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 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 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 @@ public class NiciraExtensionTreatmentInterpreter extends AbstractHandlerBehaviou 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()); } diff --git a/drivers/default/src/main/java/org/onosproject/driver/extensions/NiciraMatchCtMark.java b/drivers/default/src/main/java/org/onosproject/driver/extensions/NiciraMatchCtMark.java new file mode 100644 index 0000000000..562025a3bd --- /dev/null +++ b/drivers/default/src/main/java/org/onosproject/driver/extensions/NiciraMatchCtMark.java @@ -0,0 +1,133 @@ +/* + * Copyright 2017-present 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 com.google.common.collect.Maps; +import org.onlab.util.KryoNamespace; +import org.onosproject.net.flow.AbstractExtension; +import org.onosproject.net.flow.criteria.ExtensionSelector; +import org.onosproject.net.flow.criteria.ExtensionSelectorType; + +import com.google.common.base.MoreObjects; + +/** + * Nicira conntrack mark extension selector. + */ +public class NiciraMatchCtMark extends AbstractExtension implements ExtensionSelector { + + private long ctMark; + private long ctMarkMask; + + private final KryoNamespace appKryo = new KryoNamespace.Builder().build(); + + /** + * Creates a new conntrack mark selector. + */ + NiciraMatchCtMark() { + ctMark = 0L; + ctMarkMask = ~0L; + } + + /** + * Creates a new conntrack state selector with given mark. + * + * @param ctMark conntrack mark + */ + public NiciraMatchCtMark(long ctMark) { + this.ctMark = ctMark; + this.ctMarkMask = ~0L; + } + + /** + * Creates a new conntrack state selector with given mark. + * + * @param ctMark conntrack mark + * @param mask conntrack mark mask + */ + public NiciraMatchCtMark(long ctMark, long mask) { + this.ctMark = ctMark; + this.ctMarkMask = mask; + } + + /** + * Gets the conntrack mark. + * + * @return ctMark + */ + public long ctMark() { + return ctMark; + } + + /** + * Gets the conntrack mark mask. + * + * @return ctMarkMask + */ + public long ctMarkMask() { + return ctMarkMask; + } + + @Override + public ExtensionSelectorType type() { + return ExtensionSelectorType.ExtensionSelectorTypes.NICIRA_MATCH_CONNTRACK_MARK.type(); + } + + @Override + public void deserialize(byte[] data) { + Map values = appKryo.deserialize(data); + ctMark = (long) values.get("ctMark"); + ctMarkMask = (long) values.get("ctMarkMask"); + } + + @Override + public byte[] serialize() { + Map values = Maps.newHashMap(); + values.put("ctMark", ctMark); + values.put("ctMarkMask", ctMarkMask); + return appKryo.serialize(values); + } + + @Override + public int hashCode() { + return Objects.hash(ctMark, ctMarkMask); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj instanceof NiciraMatchCtMark) { + NiciraMatchCtMark that = (NiciraMatchCtMark) obj; + return Objects.equals(ctMark, that.ctMark) + && Objects.equals(ctMarkMask, that.ctMarkMask); + + } + return false; + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(getClass()) + .add("ctMark", ctMark) + .add("ctMarkMask", ctMarkMask) + .toString(); + } +} diff --git a/drivers/default/src/main/java/org/onosproject/driver/extensions/NiciraMatchCtState.java b/drivers/default/src/main/java/org/onosproject/driver/extensions/NiciraMatchCtState.java new file mode 100644 index 0000000000..098e264d35 --- /dev/null +++ b/drivers/default/src/main/java/org/onosproject/driver/extensions/NiciraMatchCtState.java @@ -0,0 +1,121 @@ +/* + * Copyright 2017-present 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 com.google.common.collect.Maps; +import org.onlab.util.KryoNamespace; +import org.onosproject.net.flow.AbstractExtension; +import org.onosproject.net.flow.criteria.ExtensionSelector; +import org.onosproject.net.flow.criteria.ExtensionSelectorType; + +import com.google.common.base.MoreObjects; +/** + * Nicira conntrack state extension selector. + */ +public class NiciraMatchCtState extends AbstractExtension implements ExtensionSelector { + + private long ctState; + private long ctStateMask; + + private final KryoNamespace appKryo = new KryoNamespace.Builder().build(); + + /** + * Creates a new conntrack state selector. + */ + NiciraMatchCtState() { + ctState = 0L; + ctStateMask = ~0L; + } + + /** + * Creates a new conntrack state selector with given state. + * + * @param ctState conntrack state + * @param mask conntrack state mask + */ + public NiciraMatchCtState(long ctState, long mask) { + this.ctState = ctState; + this.ctStateMask = mask; + } + + /** + * Gets the conntrack state. + * + * @return ctState + */ + public long ctState() { + return ctState; + } + + /** + * Gets the conntrack state mask. + * + * @return ctStateMask + */ + public long ctStateMask() { + return ctStateMask; + } + + @Override + public ExtensionSelectorType type() { + return ExtensionSelectorType.ExtensionSelectorTypes.NICIRA_MATCH_CONNTRACK_STATE.type(); + } + + @Override + public void deserialize(byte[] data) { + Map values = appKryo.deserialize(data); + ctState = (long) values.get("ctState"); + ctStateMask = (long) values.get("ctStateMask"); + } + + @Override + public byte[] serialize() { + Map values = Maps.newHashMap(); + values.put("ctState", ctState); + values.put("ctStateMask", ctStateMask); + return appKryo.serialize(values); + } + + @Override + public int hashCode() { + return Objects.hash(ctState, ctStateMask); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj instanceof NiciraMatchCtState) { + NiciraMatchCtState that = (NiciraMatchCtState) obj; + return Objects.equals(ctState, that.ctState) + && Objects.equals(ctStateMask, that.ctStateMask); + } + return false; + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(getClass()) + .add("ctState", ctState) + .add("mask", ctStateMask) + .toString(); + } +} diff --git a/drivers/default/src/main/java/org/onosproject/driver/extensions/NiciraMatchCtZone.java b/drivers/default/src/main/java/org/onosproject/driver/extensions/NiciraMatchCtZone.java new file mode 100644 index 0000000000..5752ee86c5 --- /dev/null +++ b/drivers/default/src/main/java/org/onosproject/driver/extensions/NiciraMatchCtZone.java @@ -0,0 +1,99 @@ +/* + * Copyright 2016-present 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.Objects; + +import org.onlab.util.KryoNamespace; +import org.onosproject.net.flow.AbstractExtension; +import org.onosproject.net.flow.criteria.ExtensionSelector; +import org.onosproject.net.flow.criteria.ExtensionSelectorType; + +import com.google.common.base.MoreObjects; + +/** + * Nicira conntrack zone extension selector. + */ +public class NiciraMatchCtZone extends AbstractExtension implements ExtensionSelector { + + private int ctZone; + + private final KryoNamespace appKryo = new KryoNamespace.Builder().build(); + + /** + * Creates a new conntrack zone selector. + */ + NiciraMatchCtZone() { + ctZone = 0; + } + + /** + * Creates a new conntrack zone selector with given zone. + * + * @param ctZone conntrack zone + */ + public NiciraMatchCtZone(int ctZone) { + this.ctZone = ctZone; + } + + /** + * Gets the conntrack zone. + * + * @return ctZone + */ + public int ctZone() { + return ctZone; + } + + @Override + public ExtensionSelectorType type() { + return ExtensionSelectorType.ExtensionSelectorTypes.NICIRA_MATCH_CONNTRACK_ZONE.type(); + } + + @Override + public void deserialize(byte[] data) { + ctZone = (int) (appKryo.deserialize(data)); + } + + @Override + public byte[] serialize() { + return appKryo.serialize(ctZone); + } + + @Override + public int hashCode() { + return Objects.hash(ctZone); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj instanceof NiciraMatchCtZone) { + NiciraMatchCtZone that = (NiciraMatchCtZone) obj; + return Objects.equals(ctZone, that.ctZone()); + + } + return false; + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(getClass()).add("ctZone", ctZone).toString(); + } +} diff --git a/drivers/default/src/main/java/org/onosproject/driver/extensions/NiciraNat.java b/drivers/default/src/main/java/org/onosproject/driver/extensions/NiciraNat.java new file mode 100644 index 0000000000..9259d829b7 --- /dev/null +++ b/drivers/default/src/main/java/org/onosproject/driver/extensions/NiciraNat.java @@ -0,0 +1,187 @@ +/* + * Copyright 2017-present 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 com.google.common.collect.Maps; +import org.onlab.packet.IpAddress; +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 org.onosproject.store.serializers.IpAddressSerializer; + +import java.util.Map; +import java.util.Objects; + +/** + * Nicira nat extension instruction. + */ +public class NiciraNat extends AbstractExtension implements ExtensionTreatment { + private int flags; + private int presentFlags; + private int portMin; + private int portMax; + private IpAddress ipAddressMin; + private IpAddress ipAddressMax; + private final KryoNamespace appKryo = new KryoNamespace.Builder() + .register(new IpAddressSerializer(), IpAddress.class) + .register(byte[].class) + .build(); + + /** + * Creates a new nat instruction. + */ + public NiciraNat() { + flags = 0; + presentFlags = 0; + portMin = 0; + portMax = 0; + ipAddressMin = IpAddress.valueOf(0); + ipAddressMax = IpAddress.valueOf(0); + } + + /** + * Creates a new nat instruction. + * @param flags nat flags + * @param presentFlags nat present flags + * @param portMin min port + * @param portMax max port + * @param ipAddressMin min ip address + * @param ipAddressMax max ip address + */ + public NiciraNat(int flags, int presentFlags, int portMin, int portMax, IpAddress ipAddressMin, + IpAddress ipAddressMax) { + this.flags = flags; + this.presentFlags = presentFlags; + this.portMin = portMin; + this.portMax = portMax; + this.ipAddressMin = ipAddressMin; + this.ipAddressMax = ipAddressMax; + } + + @Override + public ExtensionTreatmentType type() { + return ExtensionTreatmentType.ExtensionTreatmentTypes.NICIRA_NAT.type(); + } + + /** + * Get Nicira nat flags. + * @return flags + */ + public int niciraNatFlags() { + return flags; + } + + /** + * Get Nicira present flags. + * @return present flags + */ + public int niciraNatPresentFlags() { + return presentFlags; + } + + /** + * Get Nicira Nat min port. + * @return min port + */ + public int niciraNatPortMin() { + return portMin; + } + + /** + * Get Nicira Nat max port. + * @return max port + */ + public int niciraNatPortMax() { + return portMax; + } + + /** + * Get Nicira Nat min ip address. + * @return min ipaddress + */ + public IpAddress niciraNatIpAddressMin() { + return ipAddressMin; + } + + /** + * Get Nicira Nat max ip address. + * @return max ipaddress + */ + public IpAddress niciraNatIpAddressMax() { + return ipAddressMax; + } + + @Override + public void deserialize(byte[] data) { + Map values = appKryo.deserialize(data); + flags = (int) values.get("flags"); + presentFlags = (int) values.get("presentFlags"); + portMin = (int) values.get("portMin"); + portMax = (int) values.get("portMax"); + ipAddressMin = (IpAddress) values.get("ipAddressMin"); + ipAddressMax = (IpAddress) values.get("ipAddressMax"); + } + + @Override + public byte[] serialize() { + Map values = Maps.newHashMap(); + values.put("flags", flags); + values.put("presentFlags", presentFlags); + values.put("portMin", portMin); + values.put("portMax", portMax); + values.put("ipAddressMin", ipAddressMin); + values.put("ipAddressMax", ipAddressMax); + return appKryo.serialize(values); + } + + @Override + public int hashCode() { + return Objects.hash(type(), flags, presentFlags, portMin, portMax, ipAddressMin, ipAddressMax); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj instanceof NiciraNat) { + NiciraNat that = (NiciraNat) obj; + return Objects.equals(flags, that.flags) && + Objects.equals(presentFlags, that.presentFlags) && + Objects.equals(portMin, that.portMin) && + Objects.equals(portMax, that.portMax) && + Objects.equals(ipAddressMin, that.ipAddressMin) && + Objects.equals(ipAddressMax, that.ipAddressMax) && + Objects.equals(this.type(), that.type()); + } + return false; + } + + @Override + public String toString() { + return MoreObjects.toStringHelper(getClass()) + .add("flags", flags) + .add("present_flags", presentFlags) + .add("portMin", portMin) + .add("portMax", portMax) + .add("ipAddressMin", ipAddressMin) + .add("ipAddressMax", ipAddressMax) + .toString(); + } +} diff --git a/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/util/FlowEntryBuilder.java b/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/util/FlowEntryBuilder.java index 0666cc5939..5c245a893e 100644 --- a/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/util/FlowEntryBuilder.java +++ b/providers/openflow/flow/src/main/java/org/onosproject/provider/of/flow/util/FlowEntryBuilder.java @@ -979,7 +979,7 @@ public class FlowEntryBuilder { match.get(MatchField.EXP_ODU_SIG_ID).getTslen(), match.get(MatchField.EXP_ODU_SIG_ID).getTsmap()); builder.add(matchOduSignalId(oduSignalId)); - break; + break; case EXP_ODU_SIGTYPE: try { U8 oduSigType = match.get(MatchField.EXP_ODU_SIGTYPE); @@ -1043,6 +1043,39 @@ public class FlowEntryBuilder { } } break; + case CONNTRACK_STATE: + if (selectorInterpreter != null && + selectorInterpreter.supported(ExtensionSelectorTypes.NICIRA_MATCH_CONNTRACK_STATE.type())) { + try { + OFOxm oxm = ((OFMatchV3) match).getOxmList().get(MatchField.CONNTRACK_STATE); + builder.extension(selectorInterpreter.mapOxm(oxm), deviceId); + } catch (UnsupportedOperationException e) { + log.debug(e.getMessage()); + } + } + break; + case CONNTRACK_ZONE: + if (selectorInterpreter != null && + selectorInterpreter.supported(ExtensionSelectorTypes.NICIRA_MATCH_CONNTRACK_ZONE.type())) { + try { + OFOxm oxm = ((OFMatchV3) match).getOxmList().get(MatchField.CONNTRACK_ZONE); + builder.extension(selectorInterpreter.mapOxm(oxm), deviceId); + } catch (UnsupportedOperationException e) { + log.debug(e.getMessage()); + } + } + break; + case CONNTRACK_MARK: + if (selectorInterpreter != null && + selectorInterpreter.supported(ExtensionSelectorTypes.NICIRA_MATCH_CONNTRACK_MARK.type())) { + try { + OFOxm oxm = ((OFMatchV3) match).getOxmList().get(MatchField.CONNTRACK_MARK); + builder.extension(selectorInterpreter.mapOxm(oxm), deviceId); + } catch (UnsupportedOperationException e) { + log.debug(e.getMessage()); + } + } + break; case OFDPA_OVID: if (selectorInterpreter != null && selectorInterpreter.supported(ExtensionSelectorTypes.OFDPA_MATCH_OVID.type())) {