Added cubby-holes for new projects.
diff --git a/of-save/lib/gen-src/main/java/org/projectfloodlight/openflow/protocol/ver10/OFMatchV1Ver10.java b/of-save/lib/gen-src/main/java/org/projectfloodlight/openflow/protocol/ver10/OFMatchV1Ver10.java
new file mode 100644
index 0000000..14e829c
--- /dev/null
+++ b/of-save/lib/gen-src/main/java/org/projectfloodlight/openflow/protocol/ver10/OFMatchV1Ver10.java
@@ -0,0 +1,2434 @@
+// Copyright (c) 2008 The Board of Trustees of The Leland Stanford Junior University
+// Copyright (c) 2011, 2012 Open Networking Foundation
+// Copyright (c) 2012, 2013 Big Switch Networks, Inc.
+// This library was generated by the LoxiGen Compiler.
+// See the file LICENSE.txt which should have been included in the source distribution
+
+// Automatically generated by LOXI from template of_class.java
+// Do not modify
+
+package org.projectfloodlight.openflow.protocol.ver10;
+
+import org.projectfloodlight.openflow.protocol.*;
+import org.projectfloodlight.openflow.protocol.action.*;
+import org.projectfloodlight.openflow.protocol.actionid.*;
+import org.projectfloodlight.openflow.protocol.bsntlv.*;
+import org.projectfloodlight.openflow.protocol.errormsg.*;
+import org.projectfloodlight.openflow.protocol.meterband.*;
+import org.projectfloodlight.openflow.protocol.instruction.*;
+import org.projectfloodlight.openflow.protocol.instructionid.*;
+import org.projectfloodlight.openflow.protocol.match.*;
+import org.projectfloodlight.openflow.protocol.oxm.*;
+import org.projectfloodlight.openflow.protocol.queueprop.*;
+import org.projectfloodlight.openflow.types.*;
+import org.projectfloodlight.openflow.util.*;
+import org.projectfloodlight.openflow.exceptions.*;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import java.util.List;
+import com.google.common.collect.ImmutableList;
+import java.util.Set;
+import org.jboss.netty.buffer.ChannelBuffer;
+import com.google.common.hash.PrimitiveSink;
+import com.google.common.hash.Funnel;
+
+class OFMatchV1Ver10 implements OFMatchV1 {
+ private static final Logger logger = LoggerFactory.getLogger(OFMatchV1Ver10.class);
+ // version: 1.0
+ final static byte WIRE_VERSION = 1;
+ final static int LENGTH = 40;
+
+ private final static int DEFAULT_WILDCARDS = OFFlowWildcardsSerializerVer10.ALL_VAL;
+ private final static OFPort DEFAULT_IN_PORT = OFPort.ZERO;
+ private final static MacAddress DEFAULT_ETH_SRC = MacAddress.NONE;
+ private final static MacAddress DEFAULT_ETH_DST = MacAddress.NONE;
+ private final static OFVlanVidMatch DEFAULT_VLAN_VID = OFVlanVidMatch.NONE;
+ private final static VlanPcp DEFAULT_VLAN_PCP = VlanPcp.NONE;
+ private final static EthType DEFAULT_ETH_TYPE = EthType.NONE;
+ private final static IpDscp DEFAULT_IP_DSCP = IpDscp.NONE;
+ private final static IpProtocol DEFAULT_IP_PROTO = IpProtocol.NONE;
+ private final static IPv4Address DEFAULT_IPV4_SRC = IPv4Address.NONE;
+ private final static IPv4Address DEFAULT_IPV4_DST = IPv4Address.NONE;
+ private final static TransportPort DEFAULT_TCP_SRC = TransportPort.NONE;
+ private final static TransportPort DEFAULT_TCP_DST = TransportPort.NONE;
+
+ // OF message fields
+ private final int wildcards;
+ private final OFPort inPort;
+ private final MacAddress ethSrc;
+ private final MacAddress ethDst;
+ private final OFVlanVidMatch vlanVid;
+ private final VlanPcp vlanPcp;
+ private final EthType ethType;
+ private final IpDscp ipDscp;
+ private final IpProtocol ipProto;
+ private final IPv4Address ipv4Src;
+ private final IPv4Address ipv4Dst;
+ private final TransportPort tcpSrc;
+ private final TransportPort tcpDst;
+//
+ // Immutable default instance
+ final static OFMatchV1Ver10 DEFAULT = new OFMatchV1Ver10(
+ DEFAULT_WILDCARDS, DEFAULT_IN_PORT, DEFAULT_ETH_SRC, DEFAULT_ETH_DST, DEFAULT_VLAN_VID, DEFAULT_VLAN_PCP, DEFAULT_ETH_TYPE, DEFAULT_IP_DSCP, DEFAULT_IP_PROTO, DEFAULT_IPV4_SRC, DEFAULT_IPV4_DST, DEFAULT_TCP_SRC, DEFAULT_TCP_DST
+ );
+
+ // package private constructor - used by readers, builders, and factory
+ OFMatchV1Ver10(int wildcards, OFPort inPort, MacAddress ethSrc, MacAddress ethDst, OFVlanVidMatch vlanVid, VlanPcp vlanPcp, EthType ethType, IpDscp ipDscp, IpProtocol ipProto, IPv4Address ipv4Src, IPv4Address ipv4Dst, TransportPort tcpSrc, TransportPort tcpDst) {
+ this.wildcards = wildcards;
+ this.inPort = inPort;
+ this.ethSrc = ethSrc;
+ this.ethDst = ethDst;
+ this.vlanVid = vlanVid;
+ this.vlanPcp = vlanPcp;
+ this.ethType = ethType;
+ this.ipDscp = ipDscp;
+ this.ipProto = ipProto;
+ this.ipv4Src = ipv4Src;
+ this.ipv4Dst = ipv4Dst;
+ this.tcpSrc = tcpSrc;
+ this.tcpDst = tcpDst;
+ }
+
+ // Accessors for OF message fields
+ @Override
+ public int getWildcards() {
+ return wildcards;
+ }
+
+ @Override
+ public OFPort getInPort() {
+ return inPort;
+ }
+
+ @Override
+ public MacAddress getEthSrc() {
+ return ethSrc;
+ }
+
+ @Override
+ public MacAddress getEthDst() {
+ return ethDst;
+ }
+
+ @Override
+ public OFVlanVidMatch getVlanVid() {
+ return vlanVid;
+ }
+
+ @Override
+ public VlanPcp getVlanPcp() {
+ return vlanPcp;
+ }
+
+ @Override
+ public EthType getEthType() {
+ return ethType;
+ }
+
+ @Override
+ public IpDscp getIpDscp() {
+ return ipDscp;
+ }
+
+ @Override
+ public IpProtocol getIpProto() {
+ return ipProto;
+ }
+
+ @Override
+ public IPv4Address getIpv4Src() {
+ return ipv4Src;
+ }
+
+ @Override
+ public IPv4Address getIpv4Dst() {
+ return ipv4Dst;
+ }
+
+ @Override
+ public TransportPort getTcpSrc() {
+ return tcpSrc;
+ }
+
+ @Override
+ public TransportPort getTcpDst() {
+ return tcpDst;
+ }
+
+ @Override
+ public OFVersion getVersion() {
+ return OFVersion.OF_10;
+ }
+
+
+ final public static int OFPFW_ALL = ((1 << 22) - 1);
+
+ final public static int OFPFW_IN_PORT = 1 << 0; /* Switch input port. */
+ final public static int OFPFW_DL_VLAN = 1 << 1; /* VLAN id. */
+ final public static int OFPFW_DL_SRC = 1 << 2; /* Ethernet source address. */
+ final public static int OFPFW_DL_DST = 1 << 3; /*
+ * Ethernet destination
+ * address.
+ */
+ final public static int OFPFW_DL_TYPE = 1 << 4; /* Ethernet frame type. */
+ final public static int OFPFW_NW_PROTO = 1 << 5; /* IP protocol. */
+ final public static int OFPFW_TP_SRC = 1 << 6; /* TCP/UDP source port. */
+ final public static int OFPFW_TP_DST = 1 << 7; /* TCP/UDP destination port. */
+
+ /*
+ * IP source address wildcard bit count. 0 is exact match, 1 ignores the
+ * LSB, 2 ignores the 2 least-significant bits, ..., 32 and higher wildcard
+ * the entire field. This is the *opposite* of the usual convention where
+ * e.g. /24 indicates that 8 bits (not 24 bits) are wildcarded.
+ */
+ final public static int OFPFW_NW_SRC_SHIFT = 8;
+ final public static int OFPFW_NW_SRC_BITS = 6;
+ final public static int OFPFW_NW_SRC_MASK = ((1 << OFPFW_NW_SRC_BITS) - 1) << OFPFW_NW_SRC_SHIFT;
+ final public static int OFPFW_NW_SRC_ALL = 32 << OFPFW_NW_SRC_SHIFT;
+
+ /* IP destination address wildcard bit count. Same format as source. */
+ final public static int OFPFW_NW_DST_SHIFT = 14;
+ final public static int OFPFW_NW_DST_BITS = 6;
+ final public static int OFPFW_NW_DST_MASK = ((1 << OFPFW_NW_DST_BITS) - 1) << OFPFW_NW_DST_SHIFT;
+ final public static int OFPFW_NW_DST_ALL = 32 << OFPFW_NW_DST_SHIFT;
+
+ final public static int OFPFW_DL_VLAN_PCP = 1 << 20; /* VLAN priority. */
+ final public static int OFPFW_NW_TOS = 1 << 21; /* IP ToS (DSCP field, 6bits) */
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public <F extends OFValueType<F>> F get(MatchField<F> field)
+ throws UnsupportedOperationException {
+ if (isFullyWildcarded(field))
+ return null;
+ if (!field.arePrerequisitesOK(this))
+ return null;
+
+ Object result;
+ switch (field.id) {
+ case IN_PORT:
+ result = inPort;
+ break;
+ case ETH_DST:
+ result = ethDst;
+ break;
+ case ETH_SRC:
+ result = ethSrc;
+ break;
+ case ETH_TYPE:
+ result = ethType;
+ break;
+ case VLAN_VID:
+ result = vlanVid;
+ break;
+ case VLAN_PCP:
+ result = vlanPcp;
+ break;
+ case ARP_OP:
+ result = ArpOpcode.of(ipProto.getIpProtocolNumber());
+ break;
+ case ARP_SPA:
+ result = ipv4Src;
+ break;
+ case ARP_TPA:
+ result = ipv4Dst;
+ break;
+ case IP_DSCP:
+ result = ipDscp;
+ break;
+ case IP_PROTO:
+ result = ipProto;
+ break;
+ case IPV4_SRC:
+ result = ipv4Src;
+ break;
+ case IPV4_DST:
+ result = ipv4Dst;
+ break;
+ case TCP_SRC:
+ result = tcpSrc;
+ break;
+ case TCP_DST:
+ result = tcpDst;
+ break;
+ case UDP_SRC:
+ result = tcpSrc;
+ break;
+ case UDP_DST:
+ result = tcpDst;
+ break;
+ case SCTP_SRC:
+ result = tcpSrc;
+ break;
+ case SCTP_DST:
+ result = tcpDst;
+ break;
+ case ICMPV4_TYPE:
+ result = tcpSrc;
+ break;
+ case ICMPV4_CODE:
+ result = tcpDst;
+ break;
+ // NOT SUPPORTED:
+ default:
+ throw new UnsupportedOperationException("OFMatch does not support matching on field " + field.getName());
+ }
+ return (F)result;
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public <F extends OFValueType<F>> Masked<F> getMasked(MatchField<F> field)
+ throws UnsupportedOperationException {
+ if (!isPartiallyMasked(field))
+ return null;
+ if (!field.arePrerequisitesOK(this))
+ return null;
+ Object result;
+ switch (field.id) {
+ case ARP_SPA:
+ case IPV4_SRC:
+ int srcBitMask = (-1) << (32 - getIpv4SrcCidrMaskLen());
+ result = IPv4AddressWithMask.of(ipv4Src, IPv4Address.of(srcBitMask));
+ break;
+ case ARP_TPA:
+ case IPV4_DST:
+ int dstBitMask = (-1) << (32 - getIpv4DstCidrMaskLen());
+
+ result = IPv4AddressWithMask.of(ipv4Dst, IPv4Address.of(dstBitMask));
+ break;
+ default:
+ throw new UnsupportedOperationException("OFMatch does not support masked matching on field " + field.getName());
+ }
+ return (Masked<F>)result;
+ }
+
+ @Override
+ public boolean supports(MatchField<?> field) {
+ switch (field.id) {
+ case IN_PORT:
+ case ETH_DST:
+ case ETH_SRC:
+ case ETH_TYPE:
+ case VLAN_VID:
+ case VLAN_PCP:
+ case ARP_OP:
+ case ARP_SPA:
+ case ARP_TPA:
+ case IP_DSCP:
+ case IP_PROTO:
+ case IPV4_SRC:
+ case IPV4_DST:
+ case TCP_SRC:
+ case TCP_DST:
+ case UDP_SRC:
+ case UDP_DST:
+ case SCTP_SRC:
+ case SCTP_DST:
+ case ICMPV4_TYPE:
+ case ICMPV4_CODE:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ @Override
+ public boolean supportsMasked(MatchField<?> field) {
+ switch (field.id) {
+ case ARP_SPA:
+ case ARP_TPA:
+ case IPV4_SRC:
+ case IPV4_DST:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ @Override
+ public boolean isExact(MatchField<?> field) {
+ if (!field.arePrerequisitesOK(this))
+ return false;
+
+ switch (field.id) {
+ case IN_PORT:
+ return (this.wildcards & OFPFW_IN_PORT) == 0;
+ case ETH_DST:
+ return (this.wildcards & OFPFW_DL_DST) == 0;
+ case ETH_SRC:
+ return (this.wildcards & OFPFW_DL_SRC) == 0;
+ case ETH_TYPE:
+ return (this.wildcards & OFPFW_DL_TYPE) == 0;
+ case VLAN_VID:
+ return (this.wildcards & OFPFW_DL_VLAN) == 0;
+ case VLAN_PCP:
+ return (this.wildcards & OFPFW_DL_VLAN_PCP) == 0;
+ case ARP_OP:
+ return (this.wildcards & OFPFW_NW_PROTO) == 0;
+ case ARP_SPA:
+ return this.getIpv4SrcCidrMaskLen() >= 32;
+ case ARP_TPA:
+ return this.getIpv4DstCidrMaskLen() >= 32;
+ case IP_DSCP:
+ return (this.wildcards & OFPFW_NW_TOS) == 0;
+ case IP_PROTO:
+ return (this.wildcards & OFPFW_NW_PROTO) == 0;
+ case IPV4_SRC:
+ return this.getIpv4SrcCidrMaskLen() >= 32;
+ case IPV4_DST:
+ return this.getIpv4DstCidrMaskLen() >= 32;
+ case TCP_SRC:
+ return (this.wildcards & OFPFW_TP_SRC) == 0;
+ case TCP_DST:
+ return (this.wildcards & OFPFW_TP_DST) == 0;
+ case UDP_SRC:
+ return (this.wildcards & OFPFW_TP_SRC) == 0;
+ case UDP_DST:
+ return (this.wildcards & OFPFW_TP_DST) == 0;
+ case SCTP_SRC:
+ return (this.wildcards & OFPFW_TP_SRC) == 0;
+ case SCTP_DST:
+ return (this.wildcards & OFPFW_TP_DST) == 0;
+ case ICMPV4_TYPE:
+ return (this.wildcards & OFPFW_TP_SRC) == 0;
+ case ICMPV4_CODE:
+ return (this.wildcards & OFPFW_TP_DST) == 0;
+ default:
+ throw new UnsupportedOperationException("OFMatch does not support matching on field " + field.getName());
+ }
+ }
+
+ /**
+ * Parse this match's wildcard fields and return the number of significant
+ * bits in the IP destination field. NOTE: this returns the number of bits
+ * that are fixed, i.e., like CIDR, not the number of bits that are free
+ * like OpenFlow encodes.
+ *
+ * @return A number between 0 (matches all IPs) and 32 (exact match)
+ */
+ public int getIpv4DstCidrMaskLen() {
+ return Math.max(32 - ((wildcards & OFPFW_NW_DST_MASK) >> OFPFW_NW_DST_SHIFT),
+ 0);
+ }
+
+ /**
+ * Parse this match's wildcard fields and return the number of significant
+ * bits in the IP destination field. NOTE: this returns the number of bits
+ * that are fixed, i.e., like CIDR, not the number of bits that are free
+ * like OpenFlow encodes.
+ *
+ * @return A number between 0 (matches all IPs) and 32 (exact match)
+ */
+ public int getIpv4SrcCidrMaskLen() {
+ return Math.max(32 - ((wildcards & OFPFW_NW_SRC_MASK) >> OFPFW_NW_SRC_SHIFT),
+ 0);
+ }
+
+
+ @Override
+ public boolean isFullyWildcarded(MatchField<?> field) {
+ if (!field.arePrerequisitesOK(this))
+ return true;
+
+ switch (field.id) {
+ case IN_PORT:
+ return (this.wildcards & OFPFW_IN_PORT) != 0;
+ case ETH_DST:
+ return (this.wildcards & OFPFW_DL_DST) != 0;
+ case ETH_SRC:
+ return (this.wildcards & OFPFW_DL_SRC) != 0;
+ case ETH_TYPE:
+ return (this.wildcards & OFPFW_DL_TYPE) != 0;
+ case VLAN_VID:
+ return (this.wildcards & OFPFW_DL_VLAN) != 0;
+ case VLAN_PCP:
+ return (this.wildcards & OFPFW_DL_VLAN_PCP) != 0;
+ case ARP_OP:
+ return (this.wildcards & OFPFW_NW_PROTO) != 0;
+ case ARP_SPA:
+ return this.getIpv4SrcCidrMaskLen() <= 0;
+ case ARP_TPA:
+ return this.getIpv4DstCidrMaskLen() <= 0;
+ case IP_DSCP:
+ return (this.wildcards & OFPFW_NW_TOS) != 0;
+ case IP_PROTO:
+ return (this.wildcards & OFPFW_NW_PROTO) != 0;
+ case TCP_SRC:
+ return (this.wildcards & OFPFW_TP_SRC) != 0;
+ case TCP_DST:
+ return (this.wildcards & OFPFW_TP_DST) != 0;
+ case UDP_SRC:
+ return (this.wildcards & OFPFW_TP_SRC) != 0;
+ case UDP_DST:
+ return (this.wildcards & OFPFW_TP_DST) != 0;
+ case SCTP_SRC:
+ return (this.wildcards & OFPFW_TP_SRC) != 0;
+ case SCTP_DST:
+ return (this.wildcards & OFPFW_TP_DST) != 0;
+ case ICMPV4_TYPE:
+ return (this.wildcards & OFPFW_TP_SRC) != 0;
+ case ICMPV4_CODE:
+ return (this.wildcards & OFPFW_TP_DST) != 0;
+ case IPV4_SRC:
+ return this.getIpv4SrcCidrMaskLen() <= 0;
+ case IPV4_DST:
+ return this.getIpv4DstCidrMaskLen() <= 0;
+ default:
+ throw new UnsupportedOperationException("OFMatch does not support matching on field " + field.getName());
+ }
+ }
+
+ @Override
+ public boolean isPartiallyMasked(MatchField<?> field) {
+ if (!field.arePrerequisitesOK(this))
+ return false;
+
+ switch (field.id) {
+ case ARP_SPA:
+ case IPV4_SRC:
+ int srcCidrLen = getIpv4SrcCidrMaskLen();
+ return srcCidrLen > 0 && srcCidrLen < 32;
+ case ARP_TPA:
+ case IPV4_DST:
+ int dstCidrLen = getIpv4DstCidrMaskLen();
+ return dstCidrLen > 0 && dstCidrLen < 32;
+ default:
+ return false;
+ }
+ }
+
+ @Override
+ public Iterable<MatchField<?>> getMatchFields() {
+ ImmutableList.Builder<MatchField<?>> builder = ImmutableList.builder();
+ if ((wildcards & OFPFW_IN_PORT) == 0)
+ builder.add(MatchField.IN_PORT);
+ if ((wildcards & OFPFW_DL_VLAN) == 0)
+ builder.add(MatchField.VLAN_VID);
+ if ((wildcards & OFPFW_DL_SRC) == 0)
+ builder.add(MatchField.ETH_SRC);
+ if ((wildcards & OFPFW_DL_DST) == 0)
+ builder.add(MatchField.ETH_DST);
+ if ((wildcards & OFPFW_DL_TYPE) == 0)
+ builder.add(MatchField.ETH_TYPE);
+ if ((wildcards & OFPFW_NW_PROTO) == 0) {
+ if (ethType == EthType.ARP) {
+ builder.add(MatchField.ARP_OP);
+ } else if (ethType == EthType.IPv4) {
+ builder.add(MatchField.IP_PROTO);
+ } else {
+ throw new UnsupportedOperationException(
+ "Unsupported Ethertype for matching on network protocol " + ethType);
+ }
+ }
+ if ((wildcards & OFPFW_TP_SRC) == 0) {
+ if (ipProto == IpProtocol.UDP) {
+ builder.add(MatchField.UDP_SRC);
+ } else if (ipProto == IpProtocol.TCP) {
+ builder.add(MatchField.TCP_SRC);
+ } else if (ipProto == IpProtocol.SCTP) {
+ builder.add(MatchField.SCTP_SRC);
+ } else {
+ throw new UnsupportedOperationException(
+ "Unsupported IP protocol for matching on source port " + ipProto);
+ }
+ }
+ if ((wildcards & OFPFW_TP_DST) == 0) {
+ if (ipProto == IpProtocol.UDP) {
+ builder.add(MatchField.UDP_DST);
+ } else if (ipProto == IpProtocol.TCP) {
+ builder.add(MatchField.TCP_DST);
+ } else if (ipProto == IpProtocol.SCTP) {
+ builder.add(MatchField.SCTP_DST);
+ } else {
+ throw new UnsupportedOperationException(
+ "Unsupported IP protocol for matching on destination port " + ipProto);
+ }
+ }
+ if (((wildcards & OFPFW_NW_SRC_MASK) >> OFPFW_NW_SRC_SHIFT) < 32) {
+ if (ethType == EthType.ARP) {
+ builder.add(MatchField.ARP_SPA);
+ } else if (ethType == EthType.IPv4) {
+ builder.add(MatchField.IPV4_SRC);
+ } else {
+ throw new UnsupportedOperationException(
+ "Unsupported Ethertype for matching on source IP " + ethType);
+ }
+ }
+ if (((wildcards & OFPFW_NW_DST_MASK) >> OFPFW_NW_DST_SHIFT) < 32) {
+ if (ethType == EthType.ARP) {
+ builder.add(MatchField.ARP_TPA);
+ } else if (ethType == EthType.IPv4) {
+ builder.add(MatchField.IPV4_DST);
+ } else {
+ throw new UnsupportedOperationException(
+ "Unsupported Ethertype for matching on destination IP " + ethType);
+ }
+ }
+ if ((wildcards & OFPFW_DL_VLAN_PCP) == 0)
+ builder.add(MatchField.VLAN_PCP);
+ if ((wildcards & OFPFW_NW_TOS) == 0)
+ builder.add(MatchField.IP_DSCP);
+ return builder.build();
+ }
+
+ public OFMatchV1.Builder createBuilder() {
+ return new BuilderWithParent(this);
+ }
+
+ static class BuilderWithParent implements OFMatchV1.Builder {
+ final OFMatchV1Ver10 parentMessage;
+
+ // OF message fields
+ private boolean wildcardsSet;
+ private int wildcards;
+ private boolean inPortSet;
+ private OFPort inPort;
+ private boolean ethSrcSet;
+ private MacAddress ethSrc;
+ private boolean ethDstSet;
+ private MacAddress ethDst;
+ private boolean vlanVidSet;
+ private OFVlanVidMatch vlanVid;
+ private boolean vlanPcpSet;
+ private VlanPcp vlanPcp;
+ private boolean ethTypeSet;
+ private EthType ethType;
+ private boolean ipDscpSet;
+ private IpDscp ipDscp;
+ private boolean ipProtoSet;
+ private IpProtocol ipProto;
+ private boolean ipv4SrcSet;
+ private IPv4Address ipv4Src;
+ private boolean ipv4DstSet;
+ private IPv4Address ipv4Dst;
+ private boolean tcpSrcSet;
+ private TransportPort tcpSrc;
+ private boolean tcpDstSet;
+ private TransportPort tcpDst;
+
+ BuilderWithParent(OFMatchV1Ver10 parentMessage) {
+ this.parentMessage = parentMessage;
+ }
+
+ @Override
+ public int getWildcards() {
+ return wildcards;
+ }
+
+ @Override
+ public OFMatchV1.Builder setWildcards(int wildcards) {
+ this.wildcards = wildcards;
+ this.wildcardsSet = true;
+ return this;
+ }
+ @Override
+ public OFPort getInPort() {
+ return inPort;
+ }
+
+ @Override
+ public OFMatchV1.Builder setInPort(OFPort inPort) {
+ this.inPort = inPort;
+ this.inPortSet = true;
+ return this;
+ }
+ @Override
+ public MacAddress getEthSrc() {
+ return ethSrc;
+ }
+
+ @Override
+ public OFMatchV1.Builder setEthSrc(MacAddress ethSrc) {
+ this.ethSrc = ethSrc;
+ this.ethSrcSet = true;
+ return this;
+ }
+ @Override
+ public MacAddress getEthDst() {
+ return ethDst;
+ }
+
+ @Override
+ public OFMatchV1.Builder setEthDst(MacAddress ethDst) {
+ this.ethDst = ethDst;
+ this.ethDstSet = true;
+ return this;
+ }
+ @Override
+ public OFVlanVidMatch getVlanVid() {
+ return vlanVid;
+ }
+
+ @Override
+ public OFMatchV1.Builder setVlanVid(OFVlanVidMatch vlanVid) {
+ this.vlanVid = vlanVid;
+ this.vlanVidSet = true;
+ return this;
+ }
+ @Override
+ public VlanPcp getVlanPcp() {
+ return vlanPcp;
+ }
+
+ @Override
+ public OFMatchV1.Builder setVlanPcp(VlanPcp vlanPcp) {
+ this.vlanPcp = vlanPcp;
+ this.vlanPcpSet = true;
+ return this;
+ }
+ @Override
+ public EthType getEthType() {
+ return ethType;
+ }
+
+ @Override
+ public OFMatchV1.Builder setEthType(EthType ethType) {
+ this.ethType = ethType;
+ this.ethTypeSet = true;
+ return this;
+ }
+ @Override
+ public IpDscp getIpDscp() {
+ return ipDscp;
+ }
+
+ @Override
+ public OFMatchV1.Builder setIpDscp(IpDscp ipDscp) {
+ this.ipDscp = ipDscp;
+ this.ipDscpSet = true;
+ return this;
+ }
+ @Override
+ public IpProtocol getIpProto() {
+ return ipProto;
+ }
+
+ @Override
+ public OFMatchV1.Builder setIpProto(IpProtocol ipProto) {
+ this.ipProto = ipProto;
+ this.ipProtoSet = true;
+ return this;
+ }
+ @Override
+ public IPv4Address getIpv4Src() {
+ return ipv4Src;
+ }
+
+ @Override
+ public OFMatchV1.Builder setIpv4Src(IPv4Address ipv4Src) {
+ this.ipv4Src = ipv4Src;
+ this.ipv4SrcSet = true;
+ return this;
+ }
+ @Override
+ public IPv4Address getIpv4Dst() {
+ return ipv4Dst;
+ }
+
+ @Override
+ public OFMatchV1.Builder setIpv4Dst(IPv4Address ipv4Dst) {
+ this.ipv4Dst = ipv4Dst;
+ this.ipv4DstSet = true;
+ return this;
+ }
+ @Override
+ public TransportPort getTcpSrc() {
+ return tcpSrc;
+ }
+
+ @Override
+ public OFMatchV1.Builder setTcpSrc(TransportPort tcpSrc) {
+ this.tcpSrc = tcpSrc;
+ this.tcpSrcSet = true;
+ return this;
+ }
+ @Override
+ public TransportPort getTcpDst() {
+ return tcpDst;
+ }
+
+ @Override
+ public OFMatchV1.Builder setTcpDst(TransportPort tcpDst) {
+ this.tcpDst = tcpDst;
+ this.tcpDstSet = true;
+ return this;
+ }
+ @Override
+ public OFVersion getVersion() {
+ return OFVersion.OF_10;
+ }
+
+
+
+ @Override
+ public OFMatchV1 build() {
+ int wildcards = this.wildcardsSet ? this.wildcards : parentMessage.wildcards;
+ OFPort inPort = this.inPortSet ? this.inPort : parentMessage.inPort;
+ if(inPort == null)
+ throw new NullPointerException("Property inPort must not be null");
+ MacAddress ethSrc = this.ethSrcSet ? this.ethSrc : parentMessage.ethSrc;
+ if(ethSrc == null)
+ throw new NullPointerException("Property ethSrc must not be null");
+ MacAddress ethDst = this.ethDstSet ? this.ethDst : parentMessage.ethDst;
+ if(ethDst == null)
+ throw new NullPointerException("Property ethDst must not be null");
+ OFVlanVidMatch vlanVid = this.vlanVidSet ? this.vlanVid : parentMessage.vlanVid;
+ if(vlanVid == null)
+ throw new NullPointerException("Property vlanVid must not be null");
+ VlanPcp vlanPcp = this.vlanPcpSet ? this.vlanPcp : parentMessage.vlanPcp;
+ if(vlanPcp == null)
+ throw new NullPointerException("Property vlanPcp must not be null");
+ EthType ethType = this.ethTypeSet ? this.ethType : parentMessage.ethType;
+ if(ethType == null)
+ throw new NullPointerException("Property ethType must not be null");
+ IpDscp ipDscp = this.ipDscpSet ? this.ipDscp : parentMessage.ipDscp;
+ if(ipDscp == null)
+ throw new NullPointerException("Property ipDscp must not be null");
+ IpProtocol ipProto = this.ipProtoSet ? this.ipProto : parentMessage.ipProto;
+ if(ipProto == null)
+ throw new NullPointerException("Property ipProto must not be null");
+ IPv4Address ipv4Src = this.ipv4SrcSet ? this.ipv4Src : parentMessage.ipv4Src;
+ if(ipv4Src == null)
+ throw new NullPointerException("Property ipv4Src must not be null");
+ IPv4Address ipv4Dst = this.ipv4DstSet ? this.ipv4Dst : parentMessage.ipv4Dst;
+ if(ipv4Dst == null)
+ throw new NullPointerException("Property ipv4Dst must not be null");
+ TransportPort tcpSrc = this.tcpSrcSet ? this.tcpSrc : parentMessage.tcpSrc;
+ if(tcpSrc == null)
+ throw new NullPointerException("Property tcpSrc must not be null");
+ TransportPort tcpDst = this.tcpDstSet ? this.tcpDst : parentMessage.tcpDst;
+ if(tcpDst == null)
+ throw new NullPointerException("Property tcpDst must not be null");
+
+ //
+ // normalize match fields according to current OpenVSwitch behavior. When prerequisites for a field are not met
+ // e.g., eth_type is not set to 0x800, OVS sets the value of corresponding ignored fields (e.g.,
+ // ip_src, tcp_dst) to 0, and sets the wildcard bit to 1.
+ if(ethType.equals(EthType.IPv4)) {
+ // IP
+ if(ipProto.equals(IpProtocol.TCP) || ipProto.equals(IpProtocol.UDP) || ipProto.equals(IpProtocol.ICMP)) {
+ // fully speced, wildcards and all values are fine
+ // normalize 32-63 ipv4 src 'mask' to a full bitmask
+ if((wildcards & OFPFW_NW_SRC_ALL) != 0)
+ wildcards |= OFPFW_NW_SRC_MASK;
+
+ // normalize 32-63 ipv4 dst 'mask' to a full bitmask
+ if((wildcards & OFPFW_NW_DST_ALL) != 0)
+ wildcards |= OFPFW_NW_DST_MASK;
+
+ } else {
+ // normalize 32-63 ipv4 src 'mask' to a full bitmask
+ if((wildcards & OFPFW_NW_SRC_ALL) != 0)
+ wildcards |= OFPFW_NW_SRC_MASK;
+
+ // normalize 32-63 ipv4 dst 'mask' to a full bitmask
+ if((wildcards & OFPFW_NW_DST_ALL) != 0)
+ wildcards |= OFPFW_NW_DST_MASK;
+
+ // not TCP/UDP/ICMP -> Clear TP wildcards for the wire
+ wildcards |= (OFPFW_TP_SRC | OFPFW_TP_DST);
+ tcpSrc = TransportPort.NONE;
+ tcpDst = TransportPort.NONE;
+ }
+ } else if (ethType.equals(EthType.ARP)) {
+ // normalize 32-63 ipv4 src 'mask' to a full bitmask
+ if((wildcards & OFPFW_NW_SRC_ALL) != 0)
+ wildcards |= OFPFW_NW_SRC_MASK;
+
+ // normalize 32-63 ipv4 dst 'mask' to a full bitmask
+ if((wildcards & OFPFW_NW_DST_ALL) != 0)
+ wildcards |= OFPFW_NW_DST_MASK;
+
+ // ARP: clear NW_TOS / TP wildcards for the wire
+ wildcards |= ( OFPFW_NW_TOS | OFPFW_TP_SRC | OFPFW_TP_DST);
+ ipDscp = IpDscp.NONE;
+ tcpSrc = TransportPort.NONE;
+ tcpDst = TransportPort.NONE;
+ } else {
+ // not even IP. Clear NW/TP wildcards for the wire
+ wildcards |= ( OFPFW_NW_TOS | OFPFW_NW_PROTO | OFPFW_NW_SRC_MASK | OFPFW_NW_DST_MASK | OFPFW_TP_SRC | OFPFW_TP_DST);
+ ipDscp = IpDscp.NONE;
+ ipProto = IpProtocol.NONE;
+ ipv4Src = IPv4Address.NONE;
+ ipv4Dst = IPv4Address.NONE;
+ tcpSrc = TransportPort.NONE;
+ tcpDst = TransportPort.NONE;
+ }
+ return new OFMatchV1Ver10(
+ wildcards,
+ inPort,
+ ethSrc,
+ ethDst,
+ vlanVid,
+ vlanPcp,
+ ethType,
+ ipDscp,
+ ipProto,
+ ipv4Src,
+ ipv4Dst,
+ tcpSrc,
+ tcpDst
+ );
+ }
+ @SuppressWarnings("unchecked")
+ @Override
+ public <F extends OFValueType<F>> F get(MatchField<F> field)
+ throws UnsupportedOperationException {
+ if (isFullyWildcarded(field))
+ return null;
+
+ Object result;
+ switch (field.id) {
+ case IN_PORT:
+ result = inPort;
+ break;
+ case ETH_DST:
+ result = ethDst;
+ break;
+ case ETH_SRC:
+ result = ethSrc;
+ break;
+ case ETH_TYPE:
+ result = ethType;
+ break;
+ case VLAN_VID:
+ result = vlanVid;
+ break;
+ case VLAN_PCP:
+ result = vlanPcp;
+ break;
+ case ARP_OP:
+ result = ArpOpcode.of(ipProto.getIpProtocolNumber());
+ break;
+ case ARP_SPA:
+ result = ipv4Src;
+ break;
+ case ARP_TPA:
+ result = ipv4Dst;
+ break;
+ case IP_DSCP:
+ result = ipDscp;
+ break;
+ case IP_PROTO:
+ result = ipProto;
+ break;
+ case IPV4_SRC:
+ result = ipv4Src;
+ break;
+ case IPV4_DST:
+ result = ipv4Dst;
+ break;
+ case TCP_SRC:
+ result = tcpSrc;
+ break;
+ case TCP_DST:
+ result = tcpDst;
+ break;
+ case UDP_SRC:
+ result = tcpSrc;
+ break;
+ case UDP_DST:
+ result = tcpDst;
+ break;
+ case SCTP_SRC:
+ result = tcpSrc;
+ break;
+ case SCTP_DST:
+ result = tcpDst;
+ break;
+ case ICMPV4_TYPE:
+ result = tcpSrc;
+ break;
+ case ICMPV4_CODE:
+ result = tcpDst;
+ break;
+ // NOT SUPPORTED:
+ default:
+ throw new UnsupportedOperationException("OFMatch does not support matching on field " + field.getName());
+ }
+ return (F)result;
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public <F extends OFValueType<F>> Masked<F> getMasked(MatchField<F> field)
+ throws UnsupportedOperationException {
+ if (!isPartiallyMasked(field))
+ return null;
+ Object result;
+ switch (field.id) {
+ case IPV4_SRC:
+ case ARP_SPA:
+ int srcBitMask = (-1) << (32 - getIpv4SrcCidrMaskLen());
+ result = IPv4AddressWithMask.of(ipv4Src, IPv4Address.of(srcBitMask));
+ break;
+ case IPV4_DST:
+ case ARP_TPA:
+ int dstMaskedBits = Math.min(32, (wildcards & OFPFW_NW_DST_MASK) >> OFPFW_NW_DST_SHIFT);
+ int dstBitMask = (-1) << (32 - getIpv4DstCidrMaskLen());
+
+ result = IPv4AddressWithMask.of(ipv4Dst, IPv4Address.of(dstBitMask));
+ break;
+ default:
+ throw new UnsupportedOperationException("OFMatch does not support masked matching on field " + field.getName());
+ }
+ return (Masked<F>)result;
+ }
+
+ @Override
+ public boolean supports(MatchField<?> field) {
+ switch (field.id) {
+ case IN_PORT:
+ case ETH_DST:
+ case ETH_SRC:
+ case ETH_TYPE:
+ case VLAN_VID:
+ case VLAN_PCP:
+ case ARP_OP:
+ case ARP_SPA:
+ case ARP_TPA:
+ case IP_DSCP:
+ case IP_PROTO:
+ case IPV4_SRC:
+ case IPV4_DST:
+ case TCP_SRC:
+ case TCP_DST:
+ case UDP_SRC:
+ case UDP_DST:
+ case SCTP_SRC:
+ case SCTP_DST:
+ case ICMPV4_TYPE:
+ case ICMPV4_CODE:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ @Override
+ public boolean supportsMasked(MatchField<?> field) {
+ switch (field.id) {
+ case ARP_SPA:
+ case ARP_TPA:
+ case IPV4_SRC:
+ case IPV4_DST:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ @Override
+ public boolean isExact(MatchField<?> field) {
+ switch (field.id) {
+ case IN_PORT:
+ return (this.wildcards & OFPFW_IN_PORT) == 0;
+ case ETH_DST:
+ return (this.wildcards & OFPFW_DL_DST) == 0;
+ case ETH_SRC:
+ return (this.wildcards & OFPFW_DL_SRC) == 0;
+ case ETH_TYPE:
+ return (this.wildcards & OFPFW_DL_TYPE) == 0;
+ case VLAN_VID:
+ return (this.wildcards & OFPFW_DL_VLAN) == 0;
+ case VLAN_PCP:
+ return (this.wildcards & OFPFW_DL_VLAN_PCP) == 0;
+ case ARP_OP:
+ return (this.wildcards & OFPFW_NW_PROTO) == 0;
+ case ARP_SPA:
+ return this.getIpv4SrcCidrMaskLen() >= 32;
+ case ARP_TPA:
+ return this.getIpv4DstCidrMaskLen() >= 32;
+ case IP_DSCP:
+ return (this.wildcards & OFPFW_NW_TOS) == 0;
+ case IP_PROTO:
+ return (this.wildcards & OFPFW_NW_PROTO) == 0;
+ case IPV4_SRC:
+ return this.getIpv4SrcCidrMaskLen() >= 32;
+ case IPV4_DST:
+ return this.getIpv4DstCidrMaskLen() >= 32;
+ case TCP_SRC:
+ return (this.wildcards & OFPFW_TP_SRC) == 0;
+ case TCP_DST:
+ return (this.wildcards & OFPFW_TP_DST) == 0;
+ case UDP_SRC:
+ return (this.wildcards & OFPFW_TP_SRC) == 0;
+ case UDP_DST:
+ return (this.wildcards & OFPFW_TP_DST) == 0;
+ case SCTP_SRC:
+ return (this.wildcards & OFPFW_TP_SRC) == 0;
+ case SCTP_DST:
+ return (this.wildcards & OFPFW_TP_DST) == 0;
+ case ICMPV4_TYPE:
+ return (this.wildcards & OFPFW_TP_SRC) == 0;
+ case ICMPV4_CODE:
+ return (this.wildcards & OFPFW_TP_DST) == 0;
+ default:
+ throw new UnsupportedOperationException("OFMatch does not support matching on field " + field.getName());
+ }
+ }
+
+ /**
+ * Parse this match's wildcard fields and return the number of significant
+ * bits in the IP destination field. NOTE: this returns the number of bits
+ * that are fixed, i.e., like CIDR, not the number of bits that are free
+ * like OpenFlow encodes.
+ *
+ * @return A number between 0 (matches all IPs) and 32 (exact match)
+ */
+ public int getIpv4DstCidrMaskLen() {
+ return Math.max(32 - ((wildcards & OFPFW_NW_DST_MASK) >> OFPFW_NW_DST_SHIFT),
+ 0);
+ }
+
+ /**
+ * Parse this match's wildcard fields and return the number of significant
+ * bits in the IP destination field. NOTE: this returns the number of bits
+ * that are fixed, i.e., like CIDR, not the number of bits that are free
+ * like OpenFlow encodes.
+ *
+ * @return A number between 0 (matches all IPs) and 32 (exact match)
+ */
+ public int getIpv4SrcCidrMaskLen() {
+ return Math.max(32 - ((wildcards & OFPFW_NW_SRC_MASK) >> OFPFW_NW_SRC_SHIFT),
+ 0);
+ }
+
+
+ @Override
+ public boolean isFullyWildcarded(MatchField<?> field) {
+ switch (field.id) {
+ case IN_PORT:
+ return (this.wildcards & OFPFW_IN_PORT) != 0;
+ case ETH_DST:
+ return (this.wildcards & OFPFW_DL_DST) != 0;
+ case ETH_SRC:
+ return (this.wildcards & OFPFW_DL_SRC) != 0;
+ case ETH_TYPE:
+ return (this.wildcards & OFPFW_DL_TYPE) != 0;
+ case VLAN_VID:
+ return (this.wildcards & OFPFW_DL_VLAN) != 0;
+ case VLAN_PCP:
+ return (this.wildcards & OFPFW_DL_VLAN_PCP) != 0;
+ case ARP_OP:
+ return (this.wildcards & OFPFW_NW_PROTO) != 0;
+ case ARP_SPA:
+ return this.getIpv4SrcCidrMaskLen() <= 0;
+ case ARP_TPA:
+ return this.getIpv4DstCidrMaskLen() <= 0;
+ case IP_DSCP:
+ return (this.wildcards & OFPFW_NW_TOS) != 0;
+ case IP_PROTO:
+ return (this.wildcards & OFPFW_NW_PROTO) != 0;
+ case TCP_SRC:
+ return (this.wildcards & OFPFW_TP_SRC) != 0;
+ case TCP_DST:
+ return (this.wildcards & OFPFW_TP_DST) != 0;
+ case UDP_SRC:
+ return (this.wildcards & OFPFW_TP_SRC) != 0;
+ case UDP_DST:
+ return (this.wildcards & OFPFW_TP_DST) != 0;
+ case SCTP_SRC:
+ return (this.wildcards & OFPFW_TP_SRC) != 0;
+ case SCTP_DST:
+ return (this.wildcards & OFPFW_TP_DST) != 0;
+ case ICMPV4_TYPE:
+ return (this.wildcards & OFPFW_TP_SRC) != 0;
+ case ICMPV4_CODE:
+ return (this.wildcards & OFPFW_TP_DST) != 0;
+ case IPV4_SRC:
+ return this.getIpv4SrcCidrMaskLen() <= 0;
+ case IPV4_DST:
+ return this.getIpv4DstCidrMaskLen() <= 0;
+ default:
+ throw new UnsupportedOperationException("OFMatch does not support matching on field " + field.getName());
+ }
+ }
+
+ @Override
+ public boolean isPartiallyMasked(MatchField<?> field) {
+ switch (field.id) {
+ case ARP_SPA:
+ case IPV4_SRC:
+ int srcCidrLen = getIpv4SrcCidrMaskLen();
+ return srcCidrLen > 0 && srcCidrLen < 32;
+ case ARP_TPA:
+ case IPV4_DST:
+ int dstCidrLen = getIpv4DstCidrMaskLen();
+ return dstCidrLen > 0 && dstCidrLen < 32;
+ default:
+ throw new UnsupportedOperationException("OFMatch does not support masked matching on field " + field.getName());
+ }
+ }
+
+ private final void initWildcards() {
+ if(!wildcardsSet) {
+ wildcards = parentMessage.wildcards;
+ wildcardsSet = true;
+ }
+ }
+
+ @Override
+ public <F extends OFValueType<F>> Match.Builder setExact(MatchField<F> field,
+ F value) {
+ initWildcards();
+ Object val = value;
+ switch (field.id) {
+ case ETH_DST:
+ setEthDst((MacAddress) value);
+ wildcards &= ~OFPFW_DL_DST;
+ break;
+ case ETH_SRC:
+ setEthSrc((MacAddress) value);
+ wildcards &= ~OFPFW_DL_SRC;
+ break;
+ case ETH_TYPE:
+ setEthType((EthType) value);
+ wildcards &= ~OFPFW_DL_TYPE;
+ break;
+ case ICMPV4_CODE:
+ setTcpDst(TransportPort.of(((ICMPv4Code)value).getCode()));
+ wildcards &= ~OFPFW_TP_DST;
+ break;
+ case ICMPV4_TYPE:
+ setTcpSrc(TransportPort.of(((ICMPv4Type)value).getType()));
+ wildcards &= ~OFPFW_TP_SRC;
+ break;
+ case IN_PORT:
+ setInPort((OFPort) value);
+ wildcards &= ~OFPFW_IN_PORT;
+ break;
+ case ARP_OP:
+ setIpProto(IpProtocol.of((short)((ArpOpcode)value).getOpcode()));
+ wildcards &= ~OFPFW_NW_PROTO;
+ break;
+ case ARP_TPA:
+ case IPV4_DST:
+ setIpv4Dst((IPv4Address) value);
+ wildcards &= ~OFPFW_NW_DST_MASK;
+ break;
+ case ARP_SPA:
+ case IPV4_SRC:
+ setIpv4Src((IPv4Address) value);
+ wildcards &= ~OFPFW_NW_SRC_MASK;
+ break;
+ case IP_DSCP:
+ setIpDscp((IpDscp) value);
+ wildcards &= ~OFPFW_NW_TOS;
+ break;
+ case IP_PROTO:
+ setIpProto((IpProtocol) value);
+ wildcards &= ~OFPFW_NW_PROTO;
+ break;
+ case SCTP_DST:
+ setTcpDst((TransportPort) value);
+ wildcards &= ~OFPFW_TP_DST;
+ break;
+ case SCTP_SRC:
+ setTcpSrc((TransportPort) value);
+ wildcards &= ~OFPFW_TP_SRC;
+ break;
+ case TCP_DST:
+ setTcpDst((TransportPort) value);
+ wildcards &= ~OFPFW_TP_DST;
+ break;
+ case TCP_SRC:
+ setTcpSrc((TransportPort) value);
+ wildcards &= ~OFPFW_TP_SRC;
+ break;
+ case UDP_DST:
+ setTcpDst((TransportPort) value);
+ wildcards &= ~OFPFW_TP_DST;
+ break;
+ case UDP_SRC:
+ setTcpSrc((TransportPort) value);
+ wildcards &= ~OFPFW_TP_SRC;
+ break;
+ case VLAN_PCP:
+ setVlanPcp((VlanPcp) value);
+ wildcards &= ~OFPFW_DL_VLAN_PCP;
+ break;
+ case VLAN_VID:
+ setVlanVid((OFVlanVidMatch) value);
+ wildcards &= ~OFPFW_DL_VLAN;
+ break;
+ default:
+ throw new UnsupportedOperationException(
+ "OFMatch does not support matching on field " + field.getName());
+ }
+ return this;
+ }
+
+ @Override
+ public <F extends OFValueType<F>> Match.Builder setMasked(MatchField<F> field,
+ F value, F mask) {
+ initWildcards();
+ switch (field.id) {
+ case ARP_SPA:
+ case ARP_TPA:
+ case IPV4_DST:
+ case IPV4_SRC:
+ Object valObj = value;
+ Object masObj = mask;
+ IPv4Address ip = ((IPv4Address)valObj);
+ int maskval = ((IPv4Address)masObj).getInt();
+ if (Integer.bitCount(~maskval + 1) != 1)
+ throw new UnsupportedOperationException("OFMatch only supports CIDR masks for IPv4");
+ int maskLen = 32 - Integer.bitCount(maskval);
+ switch(field.id) {
+ case ARP_TPA:
+ case IPV4_DST:
+ setIpv4Dst(ip);
+ wildcards = (wildcards &~OFPFW_NW_DST_MASK) | (maskLen << OFPFW_NW_DST_SHIFT);
+ break;
+ case ARP_SPA:
+ case IPV4_SRC:
+ setIpv4Src(ip);
+ wildcards = (wildcards &~OFPFW_NW_SRC_MASK) | (maskLen << OFPFW_NW_SRC_SHIFT);
+ break;
+ default:
+ // Cannot really get here
+ break;
+ }
+ break;
+ default:
+ throw new UnsupportedOperationException("OFMatch does not support masked matching on field " + field.getName());
+ }
+ return this;
+ }
+
+ @Override
+ public <F extends OFValueType<F>> Match.Builder setMasked(MatchField<F> field, Masked<F> valueWithMask)
+ throws UnsupportedOperationException {
+ return this.setMasked(field, valueWithMask.getValue(), valueWithMask.getMask());
+ }
+
+ @Override
+ public <F extends OFValueType<F>> Match.Builder wildcard(MatchField<F> field) {
+ initWildcards();
+ switch (field.id) {
+ case ETH_DST:
+ setEthDst(MacAddress.NONE);
+ wildcards |= OFPFW_DL_DST;
+ break;
+ case ETH_SRC:
+ setEthSrc(MacAddress.NONE);
+ wildcards |= OFPFW_DL_SRC;
+ break;
+ case ETH_TYPE:
+ setEthType(EthType.NONE);
+ wildcards |= OFPFW_DL_TYPE;
+ break;
+ case ICMPV4_CODE:
+ case TCP_DST:
+ case UDP_DST:
+ case SCTP_DST:
+ setTcpDst(TransportPort.NONE);
+ wildcards |= OFPFW_TP_DST;
+ break;
+ case ICMPV4_TYPE:
+ case TCP_SRC:
+ case UDP_SRC:
+ case SCTP_SRC:
+ setTcpSrc(TransportPort.NONE);
+ wildcards |= OFPFW_TP_SRC;
+ break;
+ case IN_PORT:
+ setInPort(OFPort.of(0)); // NOTE: not 'NONE' -- that is 0xFF for ports
+ wildcards |= OFPFW_IN_PORT;
+ break;
+ case ARP_TPA:
+ case IPV4_DST:
+ setIpv4Dst(IPv4Address.NONE);
+ wildcards |= OFPFW_NW_DST_MASK;
+ break;
+ case ARP_SPA:
+ case IPV4_SRC:
+ setIpv4Src(IPv4Address.NONE);
+ wildcards |= OFPFW_NW_SRC_MASK;
+ break;
+ case IP_DSCP:
+ setIpDscp(IpDscp.NONE);
+ wildcards |= OFPFW_NW_TOS;
+ break;
+ case IP_PROTO:
+ setIpProto(IpProtocol.NONE);
+ wildcards |= OFPFW_NW_PROTO;
+ break;
+ case VLAN_PCP:
+ setVlanPcp(VlanPcp.NONE);
+ wildcards |= OFPFW_DL_VLAN_PCP;
+ break;
+ case VLAN_VID:
+ setVlanVid(OFVlanVidMatch.NONE);
+ wildcards |= OFPFW_DL_VLAN;
+ break;
+ default:
+ throw new UnsupportedOperationException("OFMatch does not support matching on field " + field.getName());
+ }
+ return this;
+ }
+
+ }
+
+ static class Builder implements OFMatchV1.Builder {
+ // OF message fields
+ private boolean wildcardsSet;
+ private int wildcards;
+ private boolean inPortSet;
+ private OFPort inPort;
+ private boolean ethSrcSet;
+ private MacAddress ethSrc;
+ private boolean ethDstSet;
+ private MacAddress ethDst;
+ private boolean vlanVidSet;
+ private OFVlanVidMatch vlanVid;
+ private boolean vlanPcpSet;
+ private VlanPcp vlanPcp;
+ private boolean ethTypeSet;
+ private EthType ethType;
+ private boolean ipDscpSet;
+ private IpDscp ipDscp;
+ private boolean ipProtoSet;
+ private IpProtocol ipProto;
+ private boolean ipv4SrcSet;
+ private IPv4Address ipv4Src;
+ private boolean ipv4DstSet;
+ private IPv4Address ipv4Dst;
+ private boolean tcpSrcSet;
+ private TransportPort tcpSrc;
+ private boolean tcpDstSet;
+ private TransportPort tcpDst;
+
+ @Override
+ public int getWildcards() {
+ return wildcards;
+ }
+
+ @Override
+ public OFMatchV1.Builder setWildcards(int wildcards) {
+ this.wildcards = wildcards;
+ this.wildcardsSet = true;
+ return this;
+ }
+ @Override
+ public OFPort getInPort() {
+ return inPort;
+ }
+
+ @Override
+ public OFMatchV1.Builder setInPort(OFPort inPort) {
+ this.inPort = inPort;
+ this.inPortSet = true;
+ return this;
+ }
+ @Override
+ public MacAddress getEthSrc() {
+ return ethSrc;
+ }
+
+ @Override
+ public OFMatchV1.Builder setEthSrc(MacAddress ethSrc) {
+ this.ethSrc = ethSrc;
+ this.ethSrcSet = true;
+ return this;
+ }
+ @Override
+ public MacAddress getEthDst() {
+ return ethDst;
+ }
+
+ @Override
+ public OFMatchV1.Builder setEthDst(MacAddress ethDst) {
+ this.ethDst = ethDst;
+ this.ethDstSet = true;
+ return this;
+ }
+ @Override
+ public OFVlanVidMatch getVlanVid() {
+ return vlanVid;
+ }
+
+ @Override
+ public OFMatchV1.Builder setVlanVid(OFVlanVidMatch vlanVid) {
+ this.vlanVid = vlanVid;
+ this.vlanVidSet = true;
+ return this;
+ }
+ @Override
+ public VlanPcp getVlanPcp() {
+ return vlanPcp;
+ }
+
+ @Override
+ public OFMatchV1.Builder setVlanPcp(VlanPcp vlanPcp) {
+ this.vlanPcp = vlanPcp;
+ this.vlanPcpSet = true;
+ return this;
+ }
+ @Override
+ public EthType getEthType() {
+ return ethType;
+ }
+
+ @Override
+ public OFMatchV1.Builder setEthType(EthType ethType) {
+ this.ethType = ethType;
+ this.ethTypeSet = true;
+ return this;
+ }
+ @Override
+ public IpDscp getIpDscp() {
+ return ipDscp;
+ }
+
+ @Override
+ public OFMatchV1.Builder setIpDscp(IpDscp ipDscp) {
+ this.ipDscp = ipDscp;
+ this.ipDscpSet = true;
+ return this;
+ }
+ @Override
+ public IpProtocol getIpProto() {
+ return ipProto;
+ }
+
+ @Override
+ public OFMatchV1.Builder setIpProto(IpProtocol ipProto) {
+ this.ipProto = ipProto;
+ this.ipProtoSet = true;
+ return this;
+ }
+ @Override
+ public IPv4Address getIpv4Src() {
+ return ipv4Src;
+ }
+
+ @Override
+ public OFMatchV1.Builder setIpv4Src(IPv4Address ipv4Src) {
+ this.ipv4Src = ipv4Src;
+ this.ipv4SrcSet = true;
+ return this;
+ }
+ @Override
+ public IPv4Address getIpv4Dst() {
+ return ipv4Dst;
+ }
+
+ @Override
+ public OFMatchV1.Builder setIpv4Dst(IPv4Address ipv4Dst) {
+ this.ipv4Dst = ipv4Dst;
+ this.ipv4DstSet = true;
+ return this;
+ }
+ @Override
+ public TransportPort getTcpSrc() {
+ return tcpSrc;
+ }
+
+ @Override
+ public OFMatchV1.Builder setTcpSrc(TransportPort tcpSrc) {
+ this.tcpSrc = tcpSrc;
+ this.tcpSrcSet = true;
+ return this;
+ }
+ @Override
+ public TransportPort getTcpDst() {
+ return tcpDst;
+ }
+
+ @Override
+ public OFMatchV1.Builder setTcpDst(TransportPort tcpDst) {
+ this.tcpDst = tcpDst;
+ this.tcpDstSet = true;
+ return this;
+ }
+ @Override
+ public OFVersion getVersion() {
+ return OFVersion.OF_10;
+ }
+
+//
+ @Override
+ public OFMatchV1 build() {
+ int wildcards = this.wildcardsSet ? this.wildcards : DEFAULT_WILDCARDS;
+ OFPort inPort = this.inPortSet ? this.inPort : DEFAULT_IN_PORT;
+ if(inPort == null)
+ throw new NullPointerException("Property inPort must not be null");
+ MacAddress ethSrc = this.ethSrcSet ? this.ethSrc : DEFAULT_ETH_SRC;
+ if(ethSrc == null)
+ throw new NullPointerException("Property ethSrc must not be null");
+ MacAddress ethDst = this.ethDstSet ? this.ethDst : DEFAULT_ETH_DST;
+ if(ethDst == null)
+ throw new NullPointerException("Property ethDst must not be null");
+ OFVlanVidMatch vlanVid = this.vlanVidSet ? this.vlanVid : DEFAULT_VLAN_VID;
+ if(vlanVid == null)
+ throw new NullPointerException("Property vlanVid must not be null");
+ VlanPcp vlanPcp = this.vlanPcpSet ? this.vlanPcp : DEFAULT_VLAN_PCP;
+ if(vlanPcp == null)
+ throw new NullPointerException("Property vlanPcp must not be null");
+ EthType ethType = this.ethTypeSet ? this.ethType : DEFAULT_ETH_TYPE;
+ if(ethType == null)
+ throw new NullPointerException("Property ethType must not be null");
+ IpDscp ipDscp = this.ipDscpSet ? this.ipDscp : DEFAULT_IP_DSCP;
+ if(ipDscp == null)
+ throw new NullPointerException("Property ipDscp must not be null");
+ IpProtocol ipProto = this.ipProtoSet ? this.ipProto : DEFAULT_IP_PROTO;
+ if(ipProto == null)
+ throw new NullPointerException("Property ipProto must not be null");
+ IPv4Address ipv4Src = this.ipv4SrcSet ? this.ipv4Src : DEFAULT_IPV4_SRC;
+ if(ipv4Src == null)
+ throw new NullPointerException("Property ipv4Src must not be null");
+ IPv4Address ipv4Dst = this.ipv4DstSet ? this.ipv4Dst : DEFAULT_IPV4_DST;
+ if(ipv4Dst == null)
+ throw new NullPointerException("Property ipv4Dst must not be null");
+ TransportPort tcpSrc = this.tcpSrcSet ? this.tcpSrc : DEFAULT_TCP_SRC;
+ if(tcpSrc == null)
+ throw new NullPointerException("Property tcpSrc must not be null");
+ TransportPort tcpDst = this.tcpDstSet ? this.tcpDst : DEFAULT_TCP_DST;
+ if(tcpDst == null)
+ throw new NullPointerException("Property tcpDst must not be null");
+
+ // normalize match fields according to current OpenVSwitch behavior. When prerequisites for a field are not met
+ // e.g., eth_type is not set to 0x800, OVS sets the value of corresponding ignored fields (e.g.,
+ // ip_src, tcp_dst) to 0, and sets the wildcard bit to 1.
+ if(ethType.equals(EthType.IPv4)) {
+ // IP
+ if(ipProto.equals(IpProtocol.TCP) || ipProto.equals(IpProtocol.UDP) || ipProto.equals(IpProtocol.ICMP)) {
+ // fully speced, wildcards and all values are fine
+ // normalize 32-63 ipv4 src 'mask' to a full bitmask
+ if((wildcards & OFPFW_NW_SRC_ALL) != 0)
+ wildcards |= OFPFW_NW_SRC_MASK;
+
+ // normalize 32-63 ipv4 dst 'mask' to a full bitmask
+ if((wildcards & OFPFW_NW_DST_ALL) != 0)
+ wildcards |= OFPFW_NW_DST_MASK;
+
+ } else {
+ // normalize 32-63 ipv4 src 'mask' to a full bitmask
+ if((wildcards & OFPFW_NW_SRC_ALL) != 0)
+ wildcards |= OFPFW_NW_SRC_MASK;
+
+ // normalize 32-63 ipv4 dst 'mask' to a full bitmask
+ if((wildcards & OFPFW_NW_DST_ALL) != 0)
+ wildcards |= OFPFW_NW_DST_MASK;
+
+ // not TCP/UDP/ICMP -> Clear TP wildcards for the wire
+ wildcards |= (OFPFW_TP_SRC | OFPFW_TP_DST);
+ tcpSrc = TransportPort.NONE;
+ tcpDst = TransportPort.NONE;
+ }
+ } else if (ethType.equals(EthType.ARP)) {
+ // normalize 32-63 ipv4 src 'mask' to a full bitmask
+ if((wildcards & OFPFW_NW_SRC_ALL) != 0)
+ wildcards |= OFPFW_NW_SRC_MASK;
+
+ // normalize 32-63 ipv4 dst 'mask' to a full bitmask
+ if((wildcards & OFPFW_NW_DST_ALL) != 0)
+ wildcards |= OFPFW_NW_DST_MASK;
+
+ // ARP: clear NW_TOS / TP wildcards for the wire
+ wildcards |= ( OFPFW_NW_TOS | OFPFW_TP_SRC | OFPFW_TP_DST);
+ ipDscp = IpDscp.NONE;
+ tcpSrc = TransportPort.NONE;
+ tcpDst = TransportPort.NONE;
+ } else {
+ // not even IP. Clear NW/TP wildcards for the wire
+ wildcards |= ( OFPFW_NW_TOS | OFPFW_NW_PROTO | OFPFW_NW_SRC_MASK | OFPFW_NW_DST_MASK | OFPFW_TP_SRC | OFPFW_TP_DST);
+ ipDscp = IpDscp.NONE;
+ ipProto = IpProtocol.NONE;
+ ipv4Src = IPv4Address.NONE;
+ ipv4Dst = IPv4Address.NONE;
+ tcpSrc = TransportPort.NONE;
+ tcpDst = TransportPort.NONE;
+ }
+
+ return new OFMatchV1Ver10(
+ wildcards,
+ inPort,
+ ethSrc,
+ ethDst,
+ vlanVid,
+ vlanPcp,
+ ethType,
+ ipDscp,
+ ipProto,
+ ipv4Src,
+ ipv4Dst,
+ tcpSrc,
+ tcpDst
+ );
+ }
+ @SuppressWarnings("unchecked")
+ @Override
+ public <F extends OFValueType<F>> F get(MatchField<F> field)
+ throws UnsupportedOperationException {
+ if (isFullyWildcarded(field))
+ return null;
+
+ Object result;
+ switch (field.id) {
+ case IN_PORT:
+ result = inPort;
+ break;
+ case ETH_DST:
+ result = ethDst;
+ break;
+ case ETH_SRC:
+ result = ethSrc;
+ break;
+ case ETH_TYPE:
+ result = ethType;
+ break;
+ case VLAN_VID:
+ result = vlanVid;
+ break;
+ case VLAN_PCP:
+ result = vlanPcp;
+ break;
+ case ARP_OP:
+ result = ArpOpcode.of(ipProto.getIpProtocolNumber());
+ break;
+ case ARP_SPA:
+ result = ipv4Src;
+ break;
+ case ARP_TPA:
+ result = ipv4Dst;
+ break;
+ case IP_DSCP:
+ result = ipDscp;
+ break;
+ case IP_PROTO:
+ result = ipProto;
+ break;
+ case IPV4_SRC:
+ result = ipv4Src;
+ break;
+ case IPV4_DST:
+ result = ipv4Dst;
+ break;
+ case TCP_SRC:
+ result = tcpSrc;
+ break;
+ case TCP_DST:
+ result = tcpDst;
+ break;
+ case UDP_SRC:
+ result = tcpSrc;
+ break;
+ case UDP_DST:
+ result = tcpDst;
+ break;
+ case SCTP_SRC:
+ result = tcpSrc;
+ break;
+ case SCTP_DST:
+ result = tcpDst;
+ break;
+ case ICMPV4_TYPE:
+ result = tcpSrc;
+ break;
+ case ICMPV4_CODE:
+ result = tcpDst;
+ break;
+ // NOT SUPPORTED:
+ default:
+ throw new UnsupportedOperationException("OFMatch does not support matching on field " + field.getName());
+ }
+ return (F)result;
+ }
+
+ @SuppressWarnings("unchecked")
+ @Override
+ public <F extends OFValueType<F>> Masked<F> getMasked(MatchField<F> field)
+ throws UnsupportedOperationException {
+ if (!isPartiallyMasked(field))
+ return null;
+ Object result;
+ switch (field.id) {
+ case IPV4_SRC:
+ case ARP_SPA:
+ int srcBitMask = (-1) << (32 - getIpv4SrcCidrMaskLen());
+ result = IPv4AddressWithMask.of(ipv4Src, IPv4Address.of(srcBitMask));
+ break;
+ case IPV4_DST:
+ case ARP_TPA:
+ int dstMaskedBits = Math.min(32, (wildcards & OFPFW_NW_DST_MASK) >> OFPFW_NW_DST_SHIFT);
+ int dstBitMask = (-1) << (32 - getIpv4DstCidrMaskLen());
+
+ result = IPv4AddressWithMask.of(ipv4Dst, IPv4Address.of(dstBitMask));
+ break;
+ default:
+ throw new UnsupportedOperationException("OFMatch does not support masked matching on field " + field.getName());
+ }
+ return (Masked<F>)result;
+ }
+
+ @Override
+ public boolean supports(MatchField<?> field) {
+ switch (field.id) {
+ case IN_PORT:
+ case ETH_DST:
+ case ETH_SRC:
+ case ETH_TYPE:
+ case VLAN_VID:
+ case VLAN_PCP:
+ case ARP_OP:
+ case ARP_SPA:
+ case ARP_TPA:
+ case IP_DSCP:
+ case IP_PROTO:
+ case IPV4_SRC:
+ case IPV4_DST:
+ case TCP_SRC:
+ case TCP_DST:
+ case UDP_SRC:
+ case UDP_DST:
+ case SCTP_SRC:
+ case SCTP_DST:
+ case ICMPV4_TYPE:
+ case ICMPV4_CODE:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ @Override
+ public boolean supportsMasked(MatchField<?> field) {
+ switch (field.id) {
+ case ARP_SPA:
+ case ARP_TPA:
+ case IPV4_SRC:
+ case IPV4_DST:
+ return true;
+ default:
+ return false;
+ }
+ }
+
+ @Override
+ public boolean isExact(MatchField<?> field) {
+ switch (field.id) {
+ case IN_PORT:
+ return (this.wildcards & OFPFW_IN_PORT) == 0;
+ case ETH_DST:
+ return (this.wildcards & OFPFW_DL_DST) == 0;
+ case ETH_SRC:
+ return (this.wildcards & OFPFW_DL_SRC) == 0;
+ case ETH_TYPE:
+ return (this.wildcards & OFPFW_DL_TYPE) == 0;
+ case VLAN_VID:
+ return (this.wildcards & OFPFW_DL_VLAN) == 0;
+ case VLAN_PCP:
+ return (this.wildcards & OFPFW_DL_VLAN_PCP) == 0;
+ case ARP_OP:
+ return (this.wildcards & OFPFW_NW_PROTO) == 0;
+ case ARP_SPA:
+ return this.getIpv4SrcCidrMaskLen() >= 32;
+ case ARP_TPA:
+ return this.getIpv4DstCidrMaskLen() >= 32;
+ case IP_DSCP:
+ return (this.wildcards & OFPFW_NW_TOS) == 0;
+ case IP_PROTO:
+ return (this.wildcards & OFPFW_NW_PROTO) == 0;
+ case IPV4_SRC:
+ return this.getIpv4SrcCidrMaskLen() >= 32;
+ case IPV4_DST:
+ return this.getIpv4DstCidrMaskLen() >= 32;
+ case TCP_SRC:
+ return (this.wildcards & OFPFW_TP_SRC) == 0;
+ case TCP_DST:
+ return (this.wildcards & OFPFW_TP_DST) == 0;
+ case UDP_SRC:
+ return (this.wildcards & OFPFW_TP_SRC) == 0;
+ case UDP_DST:
+ return (this.wildcards & OFPFW_TP_DST) == 0;
+ case SCTP_SRC:
+ return (this.wildcards & OFPFW_TP_SRC) == 0;
+ case SCTP_DST:
+ return (this.wildcards & OFPFW_TP_DST) == 0;
+ case ICMPV4_TYPE:
+ return (this.wildcards & OFPFW_TP_SRC) == 0;
+ case ICMPV4_CODE:
+ return (this.wildcards & OFPFW_TP_DST) == 0;
+ default:
+ throw new UnsupportedOperationException("OFMatch does not support matching on field " + field.getName());
+ }
+ }
+
+ /**
+ * Parse this match's wildcard fields and return the number of significant
+ * bits in the IP destination field. NOTE: this returns the number of bits
+ * that are fixed, i.e., like CIDR, not the number of bits that are free
+ * like OpenFlow encodes.
+ *
+ * @return A number between 0 (matches all IPs) and 32 (exact match)
+ */
+ public int getIpv4DstCidrMaskLen() {
+ return Math.max(32 - ((wildcards & OFPFW_NW_DST_MASK) >> OFPFW_NW_DST_SHIFT),
+ 0);
+ }
+
+ /**
+ * Parse this match's wildcard fields and return the number of significant
+ * bits in the IP destination field. NOTE: this returns the number of bits
+ * that are fixed, i.e., like CIDR, not the number of bits that are free
+ * like OpenFlow encodes.
+ *
+ * @return A number between 0 (matches all IPs) and 32 (exact match)
+ */
+ public int getIpv4SrcCidrMaskLen() {
+ return Math.max(32 - ((wildcards & OFPFW_NW_SRC_MASK) >> OFPFW_NW_SRC_SHIFT),
+ 0);
+ }
+
+
+ @Override
+ public boolean isFullyWildcarded(MatchField<?> field) {
+ switch (field.id) {
+ case IN_PORT:
+ return (this.wildcards & OFPFW_IN_PORT) != 0;
+ case ETH_DST:
+ return (this.wildcards & OFPFW_DL_DST) != 0;
+ case ETH_SRC:
+ return (this.wildcards & OFPFW_DL_SRC) != 0;
+ case ETH_TYPE:
+ return (this.wildcards & OFPFW_DL_TYPE) != 0;
+ case VLAN_VID:
+ return (this.wildcards & OFPFW_DL_VLAN) != 0;
+ case VLAN_PCP:
+ return (this.wildcards & OFPFW_DL_VLAN_PCP) != 0;
+ case ARP_OP:
+ return (this.wildcards & OFPFW_NW_PROTO) != 0;
+ case ARP_SPA:
+ return this.getIpv4SrcCidrMaskLen() <= 0;
+ case ARP_TPA:
+ return this.getIpv4DstCidrMaskLen() <= 0;
+ case IP_DSCP:
+ return (this.wildcards & OFPFW_NW_TOS) != 0;
+ case IP_PROTO:
+ return (this.wildcards & OFPFW_NW_PROTO) != 0;
+ case TCP_SRC:
+ return (this.wildcards & OFPFW_TP_SRC) != 0;
+ case TCP_DST:
+ return (this.wildcards & OFPFW_TP_DST) != 0;
+ case UDP_SRC:
+ return (this.wildcards & OFPFW_TP_SRC) != 0;
+ case UDP_DST:
+ return (this.wildcards & OFPFW_TP_DST) != 0;
+ case SCTP_SRC:
+ return (this.wildcards & OFPFW_TP_SRC) != 0;
+ case SCTP_DST:
+ return (this.wildcards & OFPFW_TP_DST) != 0;
+ case ICMPV4_TYPE:
+ return (this.wildcards & OFPFW_TP_SRC) != 0;
+ case ICMPV4_CODE:
+ return (this.wildcards & OFPFW_TP_DST) != 0;
+ case IPV4_SRC:
+ return this.getIpv4SrcCidrMaskLen() <= 0;
+ case IPV4_DST:
+ return this.getIpv4DstCidrMaskLen() <= 0;
+ default:
+ throw new UnsupportedOperationException("OFMatch does not support matching on field " + field.getName());
+ }
+ }
+
+ @Override
+ public boolean isPartiallyMasked(MatchField<?> field) {
+ switch (field.id) {
+ case ARP_SPA:
+ case IPV4_SRC:
+ int srcCidrLen = getIpv4SrcCidrMaskLen();
+ return srcCidrLen > 0 && srcCidrLen < 32;
+ case ARP_TPA:
+ case IPV4_DST:
+ int dstCidrLen = getIpv4DstCidrMaskLen();
+ return dstCidrLen > 0 && dstCidrLen < 32;
+ default:
+ throw new UnsupportedOperationException("OFMatch does not support masked matching on field " + field.getName());
+ }
+ }
+
+ private final void initWildcards() {
+ if(!wildcardsSet) {
+ wildcards = OFPFW_ALL;
+ wildcardsSet = true;
+ }
+ }
+
+ @Override
+ public <F extends OFValueType<F>> Match.Builder setExact(MatchField<F> field,
+ F value) {
+ initWildcards();
+ Object val = value;
+ switch (field.id) {
+ case ETH_DST:
+ setEthDst((MacAddress) value);
+ wildcards &= ~OFPFW_DL_DST;
+ break;
+ case ETH_SRC:
+ setEthSrc((MacAddress) value);
+ wildcards &= ~OFPFW_DL_SRC;
+ break;
+ case ETH_TYPE:
+ setEthType((EthType) value);
+ wildcards &= ~OFPFW_DL_TYPE;
+ break;
+ case ICMPV4_CODE:
+ setTcpDst(TransportPort.of(((ICMPv4Code)value).getCode()));
+ wildcards &= ~OFPFW_TP_DST;
+ break;
+ case ICMPV4_TYPE:
+ setTcpSrc(TransportPort.of(((ICMPv4Type)value).getType()));
+ wildcards &= ~OFPFW_TP_SRC;
+ break;
+ case IN_PORT:
+ setInPort((OFPort) value);
+ wildcards &= ~OFPFW_IN_PORT;
+ break;
+ case ARP_OP:
+ setIpProto(IpProtocol.of((short)((ArpOpcode)value).getOpcode()));
+ wildcards &= ~OFPFW_NW_PROTO;
+ break;
+ case ARP_TPA:
+ case IPV4_DST:
+ setIpv4Dst((IPv4Address) value);
+ wildcards &= ~OFPFW_NW_DST_MASK;
+ break;
+ case ARP_SPA:
+ case IPV4_SRC:
+ setIpv4Src((IPv4Address) value);
+ wildcards &= ~OFPFW_NW_SRC_MASK;
+ break;
+ case IP_DSCP:
+ setIpDscp((IpDscp) value);
+ wildcards &= ~OFPFW_NW_TOS;
+ break;
+ case IP_PROTO:
+ setIpProto((IpProtocol) value);
+ wildcards &= ~OFPFW_NW_PROTO;
+ break;
+ case SCTP_DST:
+ setTcpDst((TransportPort) value);
+ wildcards &= ~OFPFW_TP_DST;
+ break;
+ case SCTP_SRC:
+ setTcpSrc((TransportPort) value);
+ wildcards &= ~OFPFW_TP_SRC;
+ break;
+ case TCP_DST:
+ setTcpDst((TransportPort) value);
+ wildcards &= ~OFPFW_TP_DST;
+ break;
+ case TCP_SRC:
+ setTcpSrc((TransportPort) value);
+ wildcards &= ~OFPFW_TP_SRC;
+ break;
+ case UDP_DST:
+ setTcpDst((TransportPort) value);
+ wildcards &= ~OFPFW_TP_DST;
+ break;
+ case UDP_SRC:
+ setTcpSrc((TransportPort) value);
+ wildcards &= ~OFPFW_TP_SRC;
+ break;
+ case VLAN_PCP:
+ setVlanPcp((VlanPcp) value);
+ wildcards &= ~OFPFW_DL_VLAN_PCP;
+ break;
+ case VLAN_VID:
+ setVlanVid((OFVlanVidMatch) value);
+ wildcards &= ~OFPFW_DL_VLAN;
+ break;
+ default:
+ throw new UnsupportedOperationException(
+ "OFMatch does not support matching on field " + field.getName());
+ }
+ return this;
+ }
+
+ @Override
+ public <F extends OFValueType<F>> Match.Builder setMasked(MatchField<F> field,
+ F value, F mask) {
+ initWildcards();
+ switch (field.id) {
+ case ARP_SPA:
+ case ARP_TPA:
+ case IPV4_DST:
+ case IPV4_SRC:
+ Object valObj = value;
+ Object masObj = mask;
+ IPv4Address ip = ((IPv4Address)valObj);
+ int maskval = ((IPv4Address)masObj).getInt();
+ if (Integer.bitCount(~maskval + 1) != 1)
+ throw new UnsupportedOperationException("OFMatch only supports CIDR masks for IPv4");
+ int maskLen = 32 - Integer.bitCount(maskval);
+ switch(field.id) {
+ case ARP_TPA:
+ case IPV4_DST:
+ setIpv4Dst(ip);
+ wildcards = (wildcards &~OFPFW_NW_DST_MASK) | (maskLen << OFPFW_NW_DST_SHIFT);
+ break;
+ case ARP_SPA:
+ case IPV4_SRC:
+ setIpv4Src(ip);
+ wildcards = (wildcards &~OFPFW_NW_SRC_MASK) | (maskLen << OFPFW_NW_SRC_SHIFT);
+ break;
+ default:
+ // Cannot really get here
+ break;
+ }
+ break;
+ default:
+ throw new UnsupportedOperationException("OFMatch does not support masked matching on field " + field.getName());
+ }
+ return this;
+ }
+
+ @Override
+ public <F extends OFValueType<F>> Match.Builder setMasked(MatchField<F> field, Masked<F> valueWithMask)
+ throws UnsupportedOperationException {
+ return this.setMasked(field, valueWithMask.getValue(), valueWithMask.getMask());
+ }
+
+ @Override
+ public <F extends OFValueType<F>> Match.Builder wildcard(MatchField<F> field) {
+ initWildcards();
+ switch (field.id) {
+ case ETH_DST:
+ setEthDst(MacAddress.NONE);
+ wildcards |= OFPFW_DL_DST;
+ break;
+ case ETH_SRC:
+ setEthSrc(MacAddress.NONE);
+ wildcards |= OFPFW_DL_SRC;
+ break;
+ case ETH_TYPE:
+ setEthType(EthType.NONE);
+ wildcards |= OFPFW_DL_TYPE;
+ break;
+ case ICMPV4_CODE:
+ case TCP_DST:
+ case UDP_DST:
+ case SCTP_DST:
+ setTcpDst(TransportPort.NONE);
+ wildcards |= OFPFW_TP_DST;
+ break;
+ case ICMPV4_TYPE:
+ case TCP_SRC:
+ case UDP_SRC:
+ case SCTP_SRC:
+ setTcpSrc(TransportPort.NONE);
+ wildcards |= OFPFW_TP_SRC;
+ break;
+ case IN_PORT:
+ setInPort(OFPort.of(0)); // NOTE: not 'NONE' -- that is 0xFF for ports
+ wildcards |= OFPFW_IN_PORT;
+ break;
+ case ARP_TPA:
+ case IPV4_DST:
+ setIpv4Dst(IPv4Address.NONE);
+ wildcards |= OFPFW_NW_DST_MASK;
+ break;
+ case ARP_SPA:
+ case IPV4_SRC:
+ setIpv4Src(IPv4Address.NONE);
+ wildcards |= OFPFW_NW_SRC_MASK;
+ break;
+ case IP_DSCP:
+ setIpDscp(IpDscp.NONE);
+ wildcards |= OFPFW_NW_TOS;
+ break;
+ case IP_PROTO:
+ setIpProto(IpProtocol.NONE);
+ wildcards |= OFPFW_NW_PROTO;
+ break;
+ case VLAN_PCP:
+ setVlanPcp(VlanPcp.NONE);
+ wildcards |= OFPFW_DL_VLAN_PCP;
+ break;
+ case VLAN_VID:
+ setVlanVid(OFVlanVidMatch.NONE);
+ wildcards |= OFPFW_DL_VLAN;
+ break;
+ default:
+ throw new UnsupportedOperationException("OFMatch does not support matching on field " + field.getName());
+ }
+ return this;
+ }
+
+ }
+
+
+ final static Reader READER = new Reader();
+ static class Reader implements OFMessageReader<OFMatchV1> {
+ @Override
+ public OFMatchV1 readFrom(ChannelBuffer bb) throws OFParseError {
+ int wildcards = bb.readInt();
+ OFPort inPort = OFPort.read2Bytes(bb);
+ MacAddress ethSrc = MacAddress.read6Bytes(bb);
+ MacAddress ethDst = MacAddress.read6Bytes(bb);
+ OFVlanVidMatch vlanVid = OFVlanVidMatch.read2BytesOF10(bb);
+ VlanPcp vlanPcp = VlanPcp.readByte(bb);
+ // pad: 1 bytes
+ bb.skipBytes(1);
+ EthType ethType = EthType.read2Bytes(bb);
+ IpDscp ipDscp = IpDscp.readByte(bb);
+ IpProtocol ipProto = IpProtocol.readByte(bb);
+ // pad: 2 bytes
+ bb.skipBytes(2);
+ IPv4Address ipv4Src = IPv4Address.read4Bytes(bb);
+ IPv4Address ipv4Dst = IPv4Address.read4Bytes(bb);
+ TransportPort tcpSrc = TransportPort.read2Bytes(bb);
+ TransportPort tcpDst = TransportPort.read2Bytes(bb);
+
+ // normalize match fields according to current OpenVSwitch behavior. When prerequisites for a field are not met
+ // e.g., eth_type is not set to 0x800, OVS sets the value of corresponding ignored fields (e.g.,
+ // ip_src, tcp_dst) to 0, and sets the wildcard bit to 1.
+ if(ethType.equals(EthType.IPv4)) {
+ // IP
+ if(ipProto.equals(IpProtocol.TCP) || ipProto.equals(IpProtocol.UDP) || ipProto.equals(IpProtocol.ICMP)) {
+ // fully speced, wildcards and all values are fine
+ // normalize 32-63 ipv4 src 'mask' to a full bitmask
+ if((wildcards & OFPFW_NW_SRC_ALL) != 0)
+ wildcards |= OFPFW_NW_SRC_MASK;
+
+ // normalize 32-63 ipv4 dst 'mask' to a full bitmask
+ if((wildcards & OFPFW_NW_DST_ALL) != 0)
+ wildcards |= OFPFW_NW_DST_MASK;
+
+ } else {
+ // normalize 32-63 ipv4 src 'mask' to a full bitmask
+ if((wildcards & OFPFW_NW_SRC_ALL) != 0)
+ wildcards |= OFPFW_NW_SRC_MASK;
+
+ // normalize 32-63 ipv4 dst 'mask' to a full bitmask
+ if((wildcards & OFPFW_NW_DST_ALL) != 0)
+ wildcards |= OFPFW_NW_DST_MASK;
+
+ // not TCP/UDP/ICMP -> Clear TP wildcards for the wire
+ wildcards |= (OFPFW_TP_SRC | OFPFW_TP_DST);
+ tcpSrc = TransportPort.NONE;
+ tcpDst = TransportPort.NONE;
+ }
+ } else if (ethType.equals(EthType.ARP)) {
+ // normalize 32-63 ipv4 src 'mask' to a full bitmask
+ if((wildcards & OFPFW_NW_SRC_ALL) != 0)
+ wildcards |= OFPFW_NW_SRC_MASK;
+
+ // normalize 32-63 ipv4 dst 'mask' to a full bitmask
+ if((wildcards & OFPFW_NW_DST_ALL) != 0)
+ wildcards |= OFPFW_NW_DST_MASK;
+
+ // ARP: clear NW_TOS / TP wildcards for the wire
+ wildcards |= ( OFPFW_NW_TOS | OFPFW_TP_SRC | OFPFW_TP_DST);
+ ipDscp = IpDscp.NONE;
+ tcpSrc = TransportPort.NONE;
+ tcpDst = TransportPort.NONE;
+ } else {
+ // not even IP. Clear NW/TP wildcards for the wire
+ wildcards |= ( OFPFW_NW_TOS | OFPFW_NW_PROTO | OFPFW_NW_SRC_MASK | OFPFW_NW_DST_MASK | OFPFW_TP_SRC | OFPFW_TP_DST);
+ ipDscp = IpDscp.NONE;
+ ipProto = IpProtocol.NONE;
+ ipv4Src = IPv4Address.NONE;
+ ipv4Dst = IPv4Address.NONE;
+ tcpSrc = TransportPort.NONE;
+ tcpDst = TransportPort.NONE;
+ }
+ OFMatchV1Ver10 matchV1Ver10 = new OFMatchV1Ver10(
+ wildcards,
+ inPort,
+ ethSrc,
+ ethDst,
+ vlanVid,
+ vlanPcp,
+ ethType,
+ ipDscp,
+ ipProto,
+ ipv4Src,
+ ipv4Dst,
+ tcpSrc,
+ tcpDst
+ );
+ if(logger.isTraceEnabled())
+ logger.trace("readFrom - read={}", matchV1Ver10);
+ return matchV1Ver10;
+ }
+ }
+
+ public void putTo(PrimitiveSink sink) {
+ FUNNEL.funnel(this, sink);
+ }
+
+ final static OFMatchV1Ver10Funnel FUNNEL = new OFMatchV1Ver10Funnel();
+ static class OFMatchV1Ver10Funnel implements Funnel<OFMatchV1Ver10> {
+ private static final long serialVersionUID = 1L;
+ @Override
+ public void funnel(OFMatchV1Ver10 message, PrimitiveSink sink) {
+ sink.putInt(message.wildcards);
+ message.inPort.putTo(sink);
+ message.ethSrc.putTo(sink);
+ message.ethDst.putTo(sink);
+ message.vlanVid.putTo(sink);
+ message.vlanPcp.putTo(sink);
+ // skip pad (1 bytes)
+ message.ethType.putTo(sink);
+ message.ipDscp.putTo(sink);
+ message.ipProto.putTo(sink);
+ // skip pad (2 bytes)
+ message.ipv4Src.putTo(sink);
+ message.ipv4Dst.putTo(sink);
+ message.tcpSrc.putTo(sink);
+ message.tcpDst.putTo(sink);
+ }
+ }
+
+
+ public void writeTo(ChannelBuffer bb) {
+ WRITER.write(bb, this);
+ }
+
+ final static Writer WRITER = new Writer();
+ static class Writer implements OFMessageWriter<OFMatchV1Ver10> {
+ @Override
+ public void write(ChannelBuffer bb, OFMatchV1Ver10 message) {
+ bb.writeInt(message.wildcards);
+ message.inPort.write2Bytes(bb);
+ message.ethSrc.write6Bytes(bb);
+ message.ethDst.write6Bytes(bb);
+ message.vlanVid.write2BytesOF10(bb);
+ message.vlanPcp.writeByte(bb);
+ // pad: 1 bytes
+ bb.writeZero(1);
+ message.ethType.write2Bytes(bb);
+ message.ipDscp.writeByte(bb);
+ message.ipProto.writeByte(bb);
+ // pad: 2 bytes
+ bb.writeZero(2);
+ message.ipv4Src.write4Bytes(bb);
+ message.ipv4Dst.write4Bytes(bb);
+ message.tcpSrc.write2Bytes(bb);
+ message.tcpDst.write2Bytes(bb);
+
+
+ }
+ }
+
+ @Override
+ public String toString() {
+ StringBuilder b = new StringBuilder("OFMatchV1Ver10(");
+ boolean first = true;
+ for(MatchField<?> field : getMatchFields()) {
+ if(first)
+ first = false;
+ else
+ b.append(", ");
+ String name = field.getName();
+ b.append(name).append('=').append(this.get(field));
+ if(isPartiallyMasked(field)) {
+ b.append('/').append(this.getMasked(field).getMask());
+ }
+ }
+ b.append(")");
+ return b.toString();
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ OFMatchV1Ver10 other = (OFMatchV1Ver10) obj;
+
+ if( wildcards != other.wildcards)
+ return false;
+ if (inPort == null) {
+ if (other.inPort != null)
+ return false;
+ } else if (!inPort.equals(other.inPort))
+ return false;
+ if (ethSrc == null) {
+ if (other.ethSrc != null)
+ return false;
+ } else if (!ethSrc.equals(other.ethSrc))
+ return false;
+ if (ethDst == null) {
+ if (other.ethDst != null)
+ return false;
+ } else if (!ethDst.equals(other.ethDst))
+ return false;
+ if (vlanVid == null) {
+ if (other.vlanVid != null)
+ return false;
+ } else if (!vlanVid.equals(other.vlanVid))
+ return false;
+ if (vlanPcp == null) {
+ if (other.vlanPcp != null)
+ return false;
+ } else if (!vlanPcp.equals(other.vlanPcp))
+ return false;
+ if (ethType == null) {
+ if (other.ethType != null)
+ return false;
+ } else if (!ethType.equals(other.ethType))
+ return false;
+ if (ipDscp == null) {
+ if (other.ipDscp != null)
+ return false;
+ } else if (!ipDscp.equals(other.ipDscp))
+ return false;
+ if (ipProto == null) {
+ if (other.ipProto != null)
+ return false;
+ } else if (!ipProto.equals(other.ipProto))
+ return false;
+ if (ipv4Src == null) {
+ if (other.ipv4Src != null)
+ return false;
+ } else if (!ipv4Src.equals(other.ipv4Src))
+ return false;
+ if (ipv4Dst == null) {
+ if (other.ipv4Dst != null)
+ return false;
+ } else if (!ipv4Dst.equals(other.ipv4Dst))
+ return false;
+ if (tcpSrc == null) {
+ if (other.tcpSrc != null)
+ return false;
+ } else if (!tcpSrc.equals(other.tcpSrc))
+ return false;
+ if (tcpDst == null) {
+ if (other.tcpDst != null)
+ return false;
+ } else if (!tcpDst.equals(other.tcpDst))
+ return false;
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+
+ result = prime * result + wildcards;
+ result = prime * result + ((inPort == null) ? 0 : inPort.hashCode());
+ result = prime * result + ((ethSrc == null) ? 0 : ethSrc.hashCode());
+ result = prime * result + ((ethDst == null) ? 0 : ethDst.hashCode());
+ result = prime * result + ((vlanVid == null) ? 0 : vlanVid.hashCode());
+ result = prime * result + ((vlanPcp == null) ? 0 : vlanPcp.hashCode());
+ result = prime * result + ((ethType == null) ? 0 : ethType.hashCode());
+ result = prime * result + ((ipDscp == null) ? 0 : ipDscp.hashCode());
+ result = prime * result + ((ipProto == null) ? 0 : ipProto.hashCode());
+ result = prime * result + ((ipv4Src == null) ? 0 : ipv4Src.hashCode());
+ result = prime * result + ((ipv4Dst == null) ? 0 : ipv4Dst.hashCode());
+ result = prime * result + ((tcpSrc == null) ? 0 : tcpSrc.hashCode());
+ result = prime * result + ((tcpDst == null) ? 0 : tcpDst.hashCode());
+ return result;
+ }
+
+}