package org.openflow.protocol;
import java.io.Serializable;
import java.nio.ByteBuffer;
import java.util.Arrays;
import org.openflow.util.HexString;
import org.openflow.util.U16;
import org.openflow.util.U8;
/**
* Represents an ofp_match structure
*
* @author David Erickson (daviderickson@cs.stanford.edu)
* @author Rob Sherwood (rob.sherwood@stanford.edu)
*
*/
public class OFMatch implements Cloneable, Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
public static int MINIMUM_LENGTH = 40;
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, 6
* bits).
*/
/* List of Strings for marshalling and unmarshalling to human readable forms */
final public static String STR_IN_PORT = "in_port";
final public static String STR_DL_DST = "dl_dst";
final public static String STR_DL_SRC = "dl_src";
final public static String STR_DL_TYPE = "dl_type";
final public static String STR_DL_VLAN = "dl_vlan";
final public static String STR_DL_VLAN_PCP = "dl_vpcp";
final public static String STR_NW_DST = "nw_dst";
final public static String STR_NW_SRC = "nw_src";
final public static String STR_NW_PROTO = "nw_proto";
final public static String STR_NW_TOS = "nw_tos";
final public static String STR_TP_DST = "tp_dst";
final public static String STR_TP_SRC = "tp_src";
protected int wildcards;
protected short inputPort;
protected byte[] dataLayerSource;
protected byte[] dataLayerDestination;
protected short dataLayerVirtualLan;
protected byte dataLayerVirtualLanPriorityCodePoint;
protected short dataLayerType;
protected byte networkTypeOfService;
protected byte networkProtocol;
protected int networkSource;
protected int networkDestination;
protected short transportSource;
protected short transportDestination;
/**
* By default, create a OFMatch that matches everything
*
* (mostly because it's the least amount of work to make a valid OFMatch)
*/
public OFMatch() {
this.wildcards = OFPFW_ALL;
this.dataLayerDestination = new byte[6];
this.dataLayerSource = new byte[6];
}
/**
* Get dl_dst
*
* @return an arrays of bytes
*/
public byte[] getDataLayerDestination() {
return this.dataLayerDestination;
}
/**
* Set dl_dst
*
* @param dataLayerDestination
*/
public OFMatch setDataLayerDestination(byte[] dataLayerDestination) {
this.dataLayerDestination = dataLayerDestination;
return this;
}
/**
* Set dl_dst, but first translate to byte[] using HexString
*
* @param mac
* A colon separated string of 6 pairs of octets, e..g.,
* "00:17:42:EF:CD:8D"
*/
public OFMatch setDataLayerDestination(String mac) {
byte bytes[] = HexString.fromHexString(mac);
if (bytes.length != 6)
throw new IllegalArgumentException(
"expected string with 6 octets, got '" + mac + "'");
this.dataLayerDestination = bytes;
return this;
}
/**
* Get dl_src
*
* @return an array of bytes
*/
public byte[] getDataLayerSource() {
return this.dataLayerSource;
}
/**
* Set dl_src
*
* @param dataLayerSource
*/
public OFMatch setDataLayerSource(byte[] dataLayerSource) {
this.dataLayerSource = dataLayerSource;
return this;
}
/**
* Set dl_src, but first translate to byte[] using HexString
*
* @param mac
* A colon separated string of 6 pairs of octets, e..g.,
* "00:17:42:EF:CD:8D"
*/
public OFMatch setDataLayerSource(String mac) {
byte bytes[] = HexString.fromHexString(mac);
if (bytes.length != 6)
throw new IllegalArgumentException(
"expected string with 6 octets, got '" + mac + "'");
this.dataLayerSource = bytes;
return this;
}
/**
* Get dl_type
*
* @return ether_type
*/
public short getDataLayerType() {
return this.dataLayerType;
}
/**
* Set dl_type
*
* @param dataLayerType
*/
public OFMatch setDataLayerType(short dataLayerType) {
this.dataLayerType = dataLayerType;
return this;
}
/**
* Get dl_vlan
*
* @return vlan tag; VLAN_NONE == no tag
*/
public short getDataLayerVirtualLan() {
return this.dataLayerVirtualLan;
}
/**
* Set dl_vlan
*
* @param dataLayerVirtualLan
*/
public OFMatch setDataLayerVirtualLan(short dataLayerVirtualLan) {
this.dataLayerVirtualLan = dataLayerVirtualLan;
return this;
}
/**
* Get dl_vlan_pcp
*
* @return
*/
public byte getDataLayerVirtualLanPriorityCodePoint() {
return this.dataLayerVirtualLanPriorityCodePoint;
}
/**
* Set dl_vlan_pcp
*
* @param pcp
*/
public OFMatch setDataLayerVirtualLanPriorityCodePoint(byte pcp) {
this.dataLayerVirtualLanPriorityCodePoint = pcp;
return this;
}
/**
* Get in_port
*
* @return
*/
public short getInputPort() {
return this.inputPort;
}
/**
* Set in_port
*
* @param inputPort
*/
public OFMatch setInputPort(short inputPort) {
this.inputPort = inputPort;
return this;
}
/**
* Get nw_dst
*
* @return
*/
public int getNetworkDestination() {
return this.networkDestination;
}
/**
* Set nw_dst
*
* @param networkDestination
*/
public OFMatch setNetworkDestination(int networkDestination) {
this.networkDestination = networkDestination;
return this;
}
/**
* 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 63 ( 32>= implies exact
* match)
*/
public int getNetworkDestinationMaskLen() {
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 getNetworkSourceMaskLen() {
return Math
.max(32 - ((wildcards & OFPFW_NW_SRC_MASK) >> OFPFW_NW_SRC_SHIFT),
0);
}
/**
* Get nw_proto
*
* @return
*/
public byte getNetworkProtocol() {
return this.networkProtocol;
}
/**
* Set nw_proto
*
* @param networkProtocol
*/
public OFMatch setNetworkProtocol(byte networkProtocol) {
this.networkProtocol = networkProtocol;
return this;
}
/**
* Get nw_src
*
* @return
*/
public int getNetworkSource() {
return this.networkSource;
}
/**
* Set nw_src
*
* @param networkSource
*/
public OFMatch setNetworkSource(int networkSource) {
this.networkSource = networkSource;
return this;
}
/**
* Get nw_tos
*
* @return
*/
public byte getNetworkTypeOfService() {
return this.networkTypeOfService;
}
/**
* Set nw_tos
*
* @param networkTypeOfService
*/
public OFMatch setNetworkTypeOfService(byte networkTypeOfService) {
this.networkTypeOfService = networkTypeOfService;
return this;
}
/**
* Get tp_dst
*
* @return
*/
public short getTransportDestination() {
return this.transportDestination;
}
/**
* Set tp_dst
*
* @param transportDestination
*/
public OFMatch setTransportDestination(short transportDestination) {
this.transportDestination = transportDestination;
return this;
}
/**
* Get tp_src
*
* @return
*/
public short getTransportSource() {
return this.transportSource;
}
/**
* Set tp_src
*
* @param transportSource
*/
public OFMatch setTransportSource(short transportSource) {
this.transportSource = transportSource;
return this;
}
/**
* Get wildcards
*
* @return
*/
public int getWildcards() {
return this.wildcards;
}
/**
* Set wildcards
*
* @param wildcards
*/
public OFMatch setWildcards(int wildcards) {
this.wildcards = wildcards;
return this;
}
/**
* Initializes this OFMatch structure with the corresponding data from the
* specified packet.
*
* Must specify the input port, to ensure that this.in_port is set
* correctly.
*
* Specify OFPort.NONE or OFPort.ANY if input port not applicable or
* available
*
* @param packetData
* The packet's data
* @param inputPort
* the port the packet arrived on
*/
public OFMatch loadFromPacket(byte[] packetData, short inputPort) {
short scratch;
int transportOffset = 34;
ByteBuffer packetDataBB = ByteBuffer.wrap(packetData);
int limit = packetDataBB.limit();
this.wildcards = 0; // all fields have explicit entries
this.inputPort = inputPort;
if (inputPort == OFPort.OFPP_ALL.getValue())
this.wildcards |= OFPFW_IN_PORT;
assert (limit >= 14);
// dl dst
this.dataLayerDestination = new byte[6];
packetDataBB.get(this.dataLayerDestination);
// dl src
this.dataLayerSource = new byte[6];
packetDataBB.get(this.dataLayerSource);
// dl type
this.dataLayerType = packetDataBB.getShort();
if (getDataLayerType() != (short) 0x8100) { // need cast to avoid signed
// bug
setDataLayerVirtualLan((short) 0xffff);
setDataLayerVirtualLanPriorityCodePoint((byte) 0);
} else {
// has vlan tag
scratch = packetDataBB.getShort();
setDataLayerVirtualLan((short) (0xfff & scratch));
setDataLayerVirtualLanPriorityCodePoint((byte) ((0xe000 & scratch) >> 13));
this.dataLayerType = packetDataBB.getShort();
}
switch (getDataLayerType()) {
case 0x0800:
// ipv4
// check packet length
scratch = packetDataBB.get();
scratch = (short) (0xf & scratch);
transportOffset = (packetDataBB.position() - 1) + (scratch * 4);
// nw tos (dscp)
scratch = packetDataBB.get();
setNetworkTypeOfService((byte) ((0xfc & scratch) >> 2));
// nw protocol
packetDataBB.position(packetDataBB.position() + 7);
this.networkProtocol = packetDataBB.get();
// nw src
packetDataBB.position(packetDataBB.position() + 2);
this.networkSource = packetDataBB.getInt();
// nw dst
this.networkDestination = packetDataBB.getInt();
packetDataBB.position(transportOffset);
break;
case 0x0806:
// arp
int arpPos = packetDataBB.position();
// opcode
scratch = packetDataBB.getShort(arpPos + 6);
setNetworkProtocol((byte) (0xff & scratch));
scratch = packetDataBB.getShort(arpPos + 2);
// if ipv4 and addr len is 4
if (scratch == 0x800 && packetDataBB.get(arpPos + 5) == 4) {
// nw src
this.networkSource = packetDataBB.getInt(arpPos + 14);
// nw dst
this.networkDestination = packetDataBB.getInt(arpPos + 24);
} else {
setNetworkSource(0);
setNetworkDestination(0);
}
break;
default:
setNetworkTypeOfService((byte) 0);
setNetworkProtocol((byte) 0);
setNetworkSource(0);
setNetworkDestination(0);
break;
}
switch (getNetworkProtocol()) {
case 0x01:
// icmp
// type
this.transportSource = U8.f(packetDataBB.get());
// code
this.transportDestination = U8.f(packetDataBB.get());
break;
case 0x06:
// tcp
// tcp src
this.transportSource = packetDataBB.getShort();
// tcp dest
this.transportDestination = packetDataBB.getShort();
break;
case 0x11:
// udp
// udp src
this.transportSource = packetDataBB.getShort();
// udp dest
this.transportDestination = packetDataBB.getShort();
break;
default:
setTransportDestination((short) 0);
setTransportSource((short) 0);
break;
}
return this;
}
/**
* Read this message off the wire from the specified ByteBuffer
*
* @param data
*/
public void readFrom(ByteBuffer data) {
this.wildcards = data.getInt();
this.inputPort = data.getShort();
this.dataLayerSource = new byte[6];
data.get(this.dataLayerSource);
this.dataLayerDestination = new byte[6];
data.get(this.dataLayerDestination);
this.dataLayerVirtualLan = data.getShort();
this.dataLayerVirtualLanPriorityCodePoint = data.get();
data.get(); // pad
this.dataLayerType = data.getShort();
this.networkTypeOfService = data.get();
this.networkProtocol = data.get();
data.get(); // pad
data.get(); // pad
this.networkSource = data.getInt();
this.networkDestination = data.getInt();
this.transportSource = data.getShort();
this.transportDestination = data.getShort();
}
/**
* Write this message's binary format to the specified ByteBuffer
*
* @param data
*/
public void writeTo(ByteBuffer data) {
data.putInt(wildcards);
data.putShort(inputPort);
data.put(this.dataLayerSource);
data.put(this.dataLayerDestination);
data.putShort(dataLayerVirtualLan);
data.put(dataLayerVirtualLanPriorityCodePoint);
data.put((byte) 0x0); // pad
data.putShort(dataLayerType);
data.put(networkTypeOfService);
data.put(networkProtocol);
data.put((byte) 0x0); // pad
data.put((byte) 0x0); // pad
data.putInt(networkSource);
data.putInt(networkDestination);
data.putShort(transportSource);
data.putShort(transportDestination);
}
@Override
public int hashCode() {
final int prime = 131;
int result = 1;
result = prime * result + Arrays.hashCode(dataLayerDestination);
result = prime * result + Arrays.hashCode(dataLayerSource);
result = prime * result + dataLayerType;
result = prime * result + dataLayerVirtualLan;
result = prime * result + dataLayerVirtualLanPriorityCodePoint;
result = prime * result + inputPort;
result = prime * result + networkDestination;
result = prime * result + networkProtocol;
result = prime * result + networkSource;
result = prime * result + networkTypeOfService;
result = prime * result + transportDestination;
result = prime * result + transportSource;
result = prime * result + wildcards;
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (!(obj instanceof OFMatch)) {
return false;
}
OFMatch other = (OFMatch) obj;
if (!Arrays.equals(dataLayerDestination, other.dataLayerDestination)) {
return false;
}
if (!Arrays.equals(dataLayerSource, other.dataLayerSource)) {
return false;
}
if (dataLayerType != other.dataLayerType) {
return false;
}
if (dataLayerVirtualLan != other.dataLayerVirtualLan) {
return false;
}
if (dataLayerVirtualLanPriorityCodePoint != other.dataLayerVirtualLanPriorityCodePoint) {
return false;
}
if (inputPort != other.inputPort) {
return false;
}
if (networkDestination != other.networkDestination) {
return false;
}
if (networkProtocol != other.networkProtocol) {
return false;
}
if (networkSource != other.networkSource) {
return false;
}
if (networkTypeOfService != other.networkTypeOfService) {
return false;
}
if (transportDestination != other.transportDestination) {
return false;
}
if (transportSource != other.transportSource) {
return false;
}
if ((wildcards & OFMatch.OFPFW_ALL) != (other.wildcards & OFPFW_ALL)) { // only
// consider
// allocated
// part
// of
// wildcards
return false;
}
return true;
}
/**
* Implement clonable interface
*/
@Override
public OFMatch clone() {
try {
OFMatch ret = (OFMatch) super.clone();
ret.dataLayerDestination = this.dataLayerDestination.clone();
ret.dataLayerSource = this.dataLayerSource.clone();
return ret;
} catch (CloneNotSupportedException e) {
throw new RuntimeException(e);
}
}
/**
* Output a dpctl-styled string, i.e., only list the elements that are not
* wildcarded
*
* A match-everything OFMatch outputs "OFMatch[]"
*
* @return
* "OFMatch[dl_src:00:20:01:11:22:33,nw_src:192.168.0.0/24,tp_dst:80]"
*/
@Override
public String toString() {
String str = "";
// l1
if ((wildcards & OFPFW_IN_PORT) == 0)
str += "," + STR_IN_PORT + "=" + U16.f(this.inputPort);
// l2
if ((wildcards & OFPFW_DL_DST) == 0)
str += "," + STR_DL_DST + "="
+ HexString.toHexString(this.dataLayerDestination);
if ((wildcards & OFPFW_DL_SRC) == 0)
str += "," + STR_DL_SRC + "="
+ HexString.toHexString(this.dataLayerSource);
if ((wildcards & OFPFW_DL_TYPE) == 0)
str += "," + STR_DL_TYPE + "=0x"
+ Integer.toHexString(U16.f(this.dataLayerType));
if ((wildcards & OFPFW_DL_VLAN) == 0)
str += "," + STR_DL_VLAN + "=0x"
+ Integer.toHexString(U16.f(this.dataLayerVirtualLan));
if ((wildcards & OFPFW_DL_VLAN_PCP) == 0)
str += ","
+ STR_DL_VLAN_PCP
+ "="
+ Integer.toHexString(U8
.f(this.dataLayerVirtualLanPriorityCodePoint));
// l3
if (getNetworkDestinationMaskLen() > 0)
str += ","
+ STR_NW_DST
+ "="
+ cidrToString(networkDestination,
getNetworkDestinationMaskLen());
if (getNetworkSourceMaskLen() > 0)
str += "," + STR_NW_SRC + "="
+ cidrToString(networkSource, getNetworkSourceMaskLen());
if ((wildcards & OFPFW_NW_PROTO) == 0)
str += "," + STR_NW_PROTO + "=" + this.networkProtocol;
if ((wildcards & OFPFW_NW_TOS) == 0)
str += "," + STR_NW_TOS + "=" + this.networkTypeOfService;
// l4
if ((wildcards & OFPFW_TP_DST) == 0)
str += "," + STR_TP_DST + "=" + this.transportDestination;
if ((wildcards & OFPFW_TP_SRC) == 0)
str += "," + STR_TP_SRC + "=" + this.transportSource;
if ((str.length() > 0) && (str.charAt(0) == ','))
str = str.substring(1); // trim the leading ","
// done
return "OFMatch[" + str + "]";
}
private String cidrToString(int ip, int prefix) {
String str;
if (prefix >= 32) {
str = ipToString(ip);
} else {
// use the negation of mask to fake endian magic
int mask = ~((1 << (32 - prefix)) - 1);
str = ipToString(ip & mask) + "/" + prefix;
}
return str;
}
/**
* Set this OFMatch's parameters based on a comma-separated key=value pair
* dpctl-style string, e.g., from the output of OFMatch.toString()
*
* Supported keys/values include
*
*
KEY(s) * | VALUE * |
"in_port","input_port" * | integer * |
"dl_src","eth_src", "dl_dst","eth_dst" * | hex-string * |
"dl_type", "dl_vlan", "dl_vlan_pcp" * | integer * |
"nw_src", "nw_dst", "ip_src", "ip_dst" * | CIDR-style netmask * |
"tp_src","tp_dst" * | integer (max 64k) * |
* The CIDR-style netmasks assume 32 netmask if none given, so: * "128.8.128.118/32" is the same as "128.8.128.118" * * @param match * a key=value comma separated string, e.g. * "in_port=5,ip_dst=192.168.0.0/16,tp_src=80" * @throws IllegalArgumentException * on unexpected key or value */ public void fromString(String match) throws IllegalArgumentException { if (match.equals("") || match.equalsIgnoreCase("any") || match.equalsIgnoreCase("all") || match.equals("[]")) match = "OFMatch[]"; String[] tokens = match.split("[\\[,\\]]"); String[] values; int initArg = 0; if (tokens[0].equals("OFMatch")) initArg = 1; this.wildcards = OFPFW_ALL; int i; for (i = initArg; i < tokens.length; i++) { values = tokens[i].split("="); if (values.length != 2) throw new IllegalArgumentException("Token " + tokens[i] + " does not have form 'key=value' parsing " + match); values[0] = values[0].toLowerCase(); // try to make this case insens if (values[0].equals(STR_IN_PORT) || values[0].equals("input_port")) { this.inputPort = U16.t(Integer.valueOf(values[1])); this.wildcards &= ~OFPFW_IN_PORT; } else if (values[0].equals(STR_DL_DST) || values[0].equals("eth_dst")) { this.dataLayerDestination = HexString.fromHexString(values[1]); this.wildcards &= ~OFPFW_DL_DST; } else if (values[0].equals(STR_DL_SRC) || values[0].equals("eth_src")) { this.dataLayerSource = HexString.fromHexString(values[1]); this.wildcards &= ~OFPFW_DL_SRC; } else if (values[0].equals(STR_DL_TYPE) || values[0].equals("eth_type")) { if (values[1].startsWith("0x")) this.dataLayerType = U16.t(Integer.valueOf( values[1].replaceFirst("0x", ""), 16)); else this.dataLayerType = U16.t(Integer.valueOf(values[1])); this.wildcards &= ~OFPFW_DL_TYPE; } else if (values[0].equals(STR_DL_VLAN)) { this.dataLayerVirtualLan = U16.t(Integer.valueOf(values[1])); this.wildcards &= ~OFPFW_DL_VLAN; } else if (values[0].equals(STR_DL_VLAN_PCP)) { this.dataLayerVirtualLanPriorityCodePoint = U8.t(Short .valueOf(values[1])); this.wildcards &= ~OFPFW_DL_VLAN_PCP; } else if (values[0].equals(STR_NW_DST) || values[0].equals("ip_dst")) setFromCIDR(values[1], STR_NW_DST); else if (values[0].equals(STR_NW_SRC) || values[0].equals("ip_src")) setFromCIDR(values[1], STR_NW_SRC); else if (values[0].equals(STR_NW_PROTO)) { this.networkProtocol = U8.t(Short.valueOf(values[1])); this.wildcards &= ~OFPFW_NW_PROTO; } else if (values[0].equals(STR_NW_TOS)) { this.networkTypeOfService = U8.t(Short.valueOf(values[1])); this.wildcards &= ~OFPFW_NW_TOS; } else if (values[0].equals(STR_TP_DST)) { this.transportDestination = U16.t(Integer.valueOf(values[1])); this.wildcards &= ~OFPFW_TP_DST; } else if (values[0].equals(STR_TP_SRC)) { this.transportSource = U16.t(Integer.valueOf(values[1])); this.wildcards &= ~OFPFW_TP_SRC; } else throw new IllegalArgumentException("unknown token " + tokens[i] + " parsing " + match); } } /** * Set the networkSource or networkDestionation address and their wildcards * from the CIDR string * * @param cidr * "192.168.0.0/16" or "172.16.1.5" * @param which * one of STR_NW_DST or STR_NW_SRC * @throws IllegalArgumentException */ private void setFromCIDR(String cidr, String which) throws IllegalArgumentException { String values[] = cidr.split("/"); String[] ip_str = values[0].split("\\."); int ip = 0; ip += Integer.valueOf(ip_str[0]) << 24; ip += Integer.valueOf(ip_str[1]) << 16; ip += Integer.valueOf(ip_str[2]) << 8; ip += Integer.valueOf(ip_str[3]); int prefix = 32; // all bits are fixed, by default if (values.length >= 2) prefix = Integer.valueOf(values[1]); int mask = 32 - prefix; if (which.equals(STR_NW_DST)) { this.networkDestination = ip; this.wildcards = (wildcards & ~OFPFW_NW_DST_MASK) | (mask << OFPFW_NW_DST_SHIFT); } else if (which.equals(STR_NW_SRC)) { this.networkSource = ip; this.wildcards = (wildcards & ~OFPFW_NW_SRC_MASK) | (mask << OFPFW_NW_SRC_SHIFT); } } protected static String ipToString(int ip) { return Integer.toString(U8.f((byte) ((ip & 0xff000000) >> 24))) + "." + Integer.toString((ip & 0x00ff0000) >> 16) + "." + Integer.toString((ip & 0x0000ff00) >> 8) + "." + Integer.toString(ip & 0x000000ff); } /** * Reverses a match such that source and destination values plus * corresponding masks are swapped. An input port must be explicitly * passed in as the match does not contain an output port. * * @param inputPort new input port to use in match * @param wildcardInputPort should the input port be wildcarded * * @return Reversed copy of match */ public OFMatch reverse(short inputPort, boolean wildcardInputPort) { OFMatch ret = this.clone(); // Set the input port if (wildcardInputPort) { ret.inputPort = 0; ret.wildcards |= OFPFW_IN_PORT; } else { ret.inputPort = inputPort; ret.wildcards &= ~OFPFW_IN_PORT; } // Switch the source/dest fields ret.dataLayerDestination = this.dataLayerSource.clone(); ret.dataLayerSource = this.dataLayerDestination.clone(); ret.networkDestination = this.networkSource; ret.networkSource = this.networkDestination; ret.transportDestination = this.transportSource; ret.transportSource = this.transportDestination; // Switch the wildcards on source/dest fields ret.wildcards &= ~(OFPFW_DL_DST | OFPFW_DL_SRC | OFPFW_NW_DST_MASK | OFPFW_NW_SRC_MASK | OFPFW_TP_DST | OFPFW_TP_SRC); ret.wildcards |= ((this.wildcards & OFPFW_DL_DST) != 0 ) ? OFPFW_DL_SRC : 0; ret.wildcards |= ((this.wildcards & OFPFW_DL_SRC) != 0 ) ? OFPFW_DL_DST : 0; ret.wildcards |= (((this.wildcards & OFPFW_NW_DST_MASK) >> OFPFW_NW_DST_SHIFT) << OFPFW_NW_SRC_SHIFT); ret.wildcards |= (((this.wildcards & OFPFW_NW_SRC_MASK) >> OFPFW_NW_SRC_SHIFT) << OFPFW_NW_DST_SHIFT); ret.wildcards |= ((this.wildcards & OFPFW_TP_DST) != 0 ) ? OFPFW_TP_SRC : 0; ret.wildcards |= ((this.wildcards & OFPFW_TP_SRC) != 0 ) ? OFPFW_TP_DST : 0; return ret; } /** * Check whether this match subsumes another match. * * This match subsumes another match if each field in this * object either: *