Merge into master from pull request #91:
java_gen/DataPathId: make comparable (https://github.com/floodlight/loxigen/pull/91)
diff --git a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/MacAddress.java b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/MacAddress.java
index 87be7c2..009dae5 100644
--- a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/MacAddress.java
+++ b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/MacAddress.java
@@ -19,6 +19,9 @@
private final static long NONE_VAL = 0x0L;
public static final MacAddress NONE = new MacAddress(NONE_VAL);
+ private final static long BROADCAST_VAL = 0x0000FFFFFFFFFFFFL;
+ public static final MacAddress BROADCAST = new MacAddress(BROADCAST_VAL);
+
public static final MacAddress NO_MASK = MacAddress.of(0xFFFFFFFFFFFFFFFFl);
public static final MacAddress FULL_MASK = MacAddress.of(0x0);
@@ -27,6 +30,9 @@
}
public static MacAddress of(final byte[] address) {
+ if (address.length != MacAddrLen)
+ throw new IllegalArgumentException(
+ "Mac address byte array must be exactly 6 bytes long; length = " + address.length);
long raw =
(address[0] & 0xFFL) << 40 | (address[1] & 0xFFL) << 32
| (address[2] & 0xFFL) << 24 | (address[3] & 0xFFL) << 16
@@ -34,30 +40,36 @@
return MacAddress.of(raw);
}
- public static MacAddress of(final long raw) {
+ public static MacAddress of(long raw) {
+ raw &= BROADCAST_VAL;
if(raw == NONE_VAL)
return NONE;
-
+ if (raw == BROADCAST_VAL)
+ return BROADCAST;
return new MacAddress(raw);
}
public static MacAddress of(final String string) {
int index = 0;
int shift = 40;
+ final String FORMAT_ERROR = "Mac address is not well-formed. " +
+ "It must consist of 6 hex digit pairs separated by colons: ";
long raw = 0;
if (string.length() != 6 * 2 + 5)
- throw new IllegalArgumentException("Mac address not well formed: " + string);
+ throw new IllegalArgumentException(FORMAT_ERROR + string);
while (shift >= 0) {
- raw |=
- ((long) (Character.digit(string.charAt(index++), 16) << 4 | Character
- .digit(string.charAt(index++), 16))) << shift;
+ int digit1 = Character.digit(string.charAt(index++), 16);
+ int digit2 = Character.digit(string.charAt(index++), 16);
+ if ((digit1 < 0) || (digit2 < 0))
+ throw new IllegalArgumentException(FORMAT_ERROR + string);
+ raw |= ((long) (digit1 << 4 | digit2)) << shift;
if (shift == 0)
break;
if (string.charAt(index++) != ':')
- throw new IllegalArgumentException("Mac address not well formed: " + string);
+ throw new IllegalArgumentException(FORMAT_ERROR + string);
shift -= 8;
}
return MacAddress.of(raw);
@@ -82,6 +94,25 @@
return bytesCache;
}
+ /**
+ * Returns {@code true} if the MAC address is the broadcast address.
+ * @return {@code true} if the MAC address is the broadcast address.
+ */
+ public boolean isBroadcast() {
+ return this == BROADCAST;
+ }
+
+ /**
+ * Returns {@code true} if the MAC address is a multicast address.
+ * @return {@code true} if the MAC address is a multicast address.
+ */
+ public boolean isMulticast() {
+ if (isBroadcast()) {
+ return false;
+ }
+ return (rawValue & (0x01L << 40)) != 0;
+ }
+
@Override
public int getLength() {
return MacAddrLen;
diff --git a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/OFBufferId.java b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/OFBufferId.java
index f541b61..f3812dd 100644
--- a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/OFBufferId.java
+++ b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/OFBufferId.java
@@ -1,8 +1,6 @@
package org.projectfloodlight.openflow.types;
-import org.jboss.netty.buffer.ChannelBuffer;
import org.projectfloodlight.openflow.annotations.Immutable;
-import org.projectfloodlight.openflow.exceptions.OFParseError;
import com.google.common.primitives.UnsignedInts;
diff --git a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/util/ChannelUtils.java b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/util/ChannelUtils.java
index ea2c4a9..13cfdc7 100644
--- a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/util/ChannelUtils.java
+++ b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/util/ChannelUtils.java
@@ -21,7 +21,12 @@
public static String readFixedLengthString(ChannelBuffer bb, int length) {
byte[] dst = new byte[length];
bb.readBytes(dst, 0, length);
- return new String(dst, Charsets.US_ASCII);
+ int validLength = 0;
+ for (validLength = 0; validLength < length; validLength++) {
+ if (dst[validLength] == 0)
+ break;
+ }
+ return new String(dst, 0, validLength, Charsets.US_ASCII);
}
public static void writeFixedLengthString(ChannelBuffer bb, String string,
diff --git a/java_gen/pre-written/src/test/java/org/projectfloodlight/openflow/types/MacAddressTest.java b/java_gen/pre-written/src/test/java/org/projectfloodlight/openflow/types/MacAddressTest.java
index dc25b12..ed380ee 100644
--- a/java_gen/pre-written/src/test/java/org/projectfloodlight/openflow/types/MacAddressTest.java
+++ b/java_gen/pre-written/src/test/java/org/projectfloodlight/openflow/types/MacAddressTest.java
@@ -2,6 +2,8 @@
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import java.util.Arrays;
@@ -29,9 +31,11 @@
0x00ffffffffffffL
};
- String[] invalidMacs = {
+ String[] invalidMacStrings = {
"",
"1.2.3.4",
+ "0T:00:01:02:03:04",
+ "00:01:02:03:04:05:06",
"00:ff:ef:12:12:ff:",
"00:fff:ef:12:12:ff",
"01:02:03:04:05;06",
@@ -39,6 +43,10 @@
"01:02:03:04"
};
+ byte[][] invalidMacBytes = {
+ new byte[]{0x01, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06},
+ new byte[]{0x01, 0x01, 0x02, 0x03, 0x04}
+ };
@Test
public void testOfString() {
@@ -72,8 +80,8 @@
@Test
- public void testInvalidMacss() throws OFParseError {
- for(String invalid : invalidMacs) {
+ public void testInvalidMacStrings() throws OFParseError {
+ for(String invalid : invalidMacStrings) {
try {
MacAddress.of(invalid);
fail("Invalid IP "+invalid+ " should have raised IllegalArgumentException");
@@ -82,4 +90,54 @@
}
}
}
+
+ @Test
+ public void testInvalidMacBytes() throws OFParseError {
+ for(byte[] invalid : invalidMacBytes) {
+ try {
+ MacAddress.of(invalid);
+ fail("Invalid IP "+invalid+ " should have raised IllegalArgumentException");
+ } catch(IllegalArgumentException e) {
+ // ok
+ }
+ }
+ }
+
+ // Test data is imported from org.projectfloodlight.packet.EthernetTest
+ @Test
+ public void testToLong() {
+ assertEquals(
+ 281474976710655L,
+ MacAddress.of(new byte[]{(byte) 0xff, (byte) 0xff,
+ (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff}).getLong());
+
+ assertEquals(
+ 1103823438081L,
+ MacAddress.of(new byte[] { (byte) 0x01, (byte) 0x01,
+ (byte) 0x01, (byte) 0x01, (byte) 0x01, (byte) 0x01 }).getLong());
+
+ assertEquals(
+ 141289400074368L,
+ MacAddress.of(new byte[] { (byte) 0x80, (byte) 0x80,
+ (byte) 0x80, (byte) 0x80, (byte) 0x80, (byte) 0x80 }).getLong());
+
+ }
+
+ @Test
+ public void testIsBroadcast() {
+ assertTrue(MacAddress.of("FF:FF:FF:FF:FF:FF").isBroadcast());
+ assertTrue(MacAddress.of(-1).isBroadcast());
+ assertTrue(MacAddress.of(0x05FFFFFFFFFFFFL).isBroadcast());
+ assertFalse(MacAddress.of("11:22:33:44:55:66").isBroadcast());
+ }
+
+ @Test
+ public void testIsMulticast() {
+ assertTrue(MacAddress.of("01:80:C2:00:00:00").isMulticast());
+ assertFalse(MacAddress.of("00:80:C2:00:00:00").isMulticast());
+ assertFalse(MacAddress.of("FE:80:C2:00:00:00").isMulticast());
+ assertFalse(MacAddress.of(-1).isMulticast());
+ assertFalse(MacAddress.of(0x05FFFFFFFFFFFFL).isMulticast());
+ assertFalse(MacAddress.of("FF:FF:FF:FF:FF:FF").isMulticast());
+ }
}
diff --git a/java_gen/templates/custom/OFMatchV1Ver10.Builder.java b/java_gen/templates/custom/OFMatchV1Ver10.Builder.java
index 38cc127..239828e 100644
--- a/java_gen/templates/custom/OFMatchV1Ver10.Builder.java
+++ b/java_gen/templates/custom/OFMatchV1Ver10.Builder.java
@@ -25,6 +25,15 @@
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;
@@ -32,13 +41,13 @@
result = ipProto;
break;
case IPV4_SRC:
- result = ipv4Dst;
+ result = ipv4Src;
break;
case IPV4_DST:
result = ipv4Dst;
break;
case TCP_SRC:
- result = ipv4Src;
+ result = tcpSrc;
break;
case TCP_DST:
result = tcpDst;
@@ -77,10 +86,12 @@
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());
@@ -101,6 +112,9 @@
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:
@@ -122,6 +136,8 @@
@Override
public boolean supportsMasked(MatchField<?> field) {
switch (field.id) {
+ case ARP_SPA:
+ case ARP_TPA:
case IPV4_SRC:
case IPV4_DST:
return true;
@@ -145,6 +161,12 @@
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:
@@ -216,6 +238,12 @@
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:
@@ -248,11 +276,13 @@
@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 = getIpv4SrcCidrMaskLen();
+ int dstCidrLen = getIpv4DstCidrMaskLen();
return dstCidrLen > 0 && dstCidrLen < 32;
default:
throw new UnsupportedOperationException("OFMatch does not support masked matching on field " + field.getName());
@@ -300,10 +330,16 @@
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;
@@ -347,6 +383,7 @@
case VLAN_VID:
setVlanVid((VlanVid) value);
wildcards &= ~OFPFW_DL_VLAN;
+ break;
default:
throw new UnsupportedOperationException(
"OFMatch does not support matching on field " + field.getName());
@@ -359,6 +396,8 @@
F value, F mask) {
initWildcards();
switch (field.id) {
+ case ARP_SPA:
+ case ARP_TPA:
case IPV4_DST:
case IPV4_SRC:
Object valObj = value;
@@ -369,10 +408,12 @@
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);
@@ -428,10 +469,12 @@
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;
diff --git a/java_gen/templates/custom/OFMatchV1Ver10.java b/java_gen/templates/custom/OFMatchV1Ver10.java
index eaaacb0..82ff10f 100644
--- a/java_gen/templates/custom/OFMatchV1Ver10.java
+++ b/java_gen/templates/custom/OFMatchV1Ver10.java
@@ -61,6 +61,15 @@
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;
@@ -68,7 +77,7 @@
result = ipProto;
break;
case IPV4_SRC:
- result = ipv4Dst;
+ result = ipv4Src;
break;
case IPV4_DST:
result = ipv4Dst;
@@ -114,10 +123,12 @@
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());
@@ -138,6 +149,9 @@
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:
@@ -159,6 +173,8 @@
@Override
public boolean supportsMasked(MatchField<?> field) {
switch (field.id) {
+ case ARP_SPA:
+ case ARP_TPA:
case IPV4_SRC:
case IPV4_DST:
return true;
@@ -185,6 +201,12 @@
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:
@@ -259,6 +281,12 @@
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:
@@ -294,9 +322,11 @@
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 = getIpv4SrcCidrMaskLen();
return dstCidrLen > 0 && dstCidrLen < 32;
diff --git a/java_gen/templates/of_factories.java b/java_gen/templates/of_factories.java
index 0044335..0a27c59 100644
--- a/java_gen/templates/of_factories.java
+++ b/java_gen/templates/of_factories.java
@@ -36,6 +36,9 @@
//:: include("_imports.java")
public final class OFFactories {
+
+ private final static GenericReader GENERIC_READER = new GenericReader();
+
public static OFFactory getFactory(OFVersion version) {
switch(version) {
//:: for v in versions:
@@ -46,4 +49,25 @@
throw new IllegalArgumentException("Unknown version: "+version);
}
}
+
+ private static class GenericReader implements OFMessageReader<OFMessage> {
+ public OFMessage readFrom(ChannelBuffer bb) throws OFParseError {
+ short wireVersion = U8.f(bb.getByte(0));
+ OFFactory factory;
+ switch (wireVersion) {
+ //:: for v in versions:
+ case ${v.int_version}:
+ factory = org.projectfloodlight.openflow.protocol.ver${v.of_version}.OFFactoryVer${v.of_version}.INSTANCE;
+ break;
+ //:: #endfor
+ default:
+ throw new IllegalArgumentException("Unknown wire version: " + wireVersion);
+ }
+ return factory.getReader().readFrom(bb);
+ }
+ }
+
+ public static OFMessageReader<OFMessage> getGenericReader() {
+ return GENERIC_READER;
+ }
}
diff --git a/openflow_input/standard-1.0 b/openflow_input/standard-1.0
index 3493c6b..79d5bad 100644
--- a/openflow_input/standard-1.0
+++ b/openflow_input/standard-1.0
@@ -94,6 +94,7 @@
OFPPC_NO_FLOOD = 0x10,
OFPPC_NO_FWD = 0x20,
OFPPC_NO_PACKET_IN = 0x40,
+ OFPPC_BSN_MIRROR_DEST = 0x80000000,
};
enum ofp_port_state(wire_type=uint32_t, bitmask=True) {
diff --git a/openflow_input/standard-1.1 b/openflow_input/standard-1.1
index f985b6d..9937c6d 100644
--- a/openflow_input/standard-1.1
+++ b/openflow_input/standard-1.1
@@ -135,6 +135,7 @@
OFPPC_NO_RECV = 0x4,
OFPPC_NO_FWD = 0x20,
OFPPC_NO_PACKET_IN = 0x40,
+ OFPPC_BSN_MIRROR_DEST = 0x80000000,
};
enum ofp_port_state(wire_type=uint32_t, bitmask=True) {
diff --git a/openflow_input/standard-1.2 b/openflow_input/standard-1.2
index 9032458..182794e 100644
--- a/openflow_input/standard-1.2
+++ b/openflow_input/standard-1.2
@@ -138,6 +138,7 @@
OFPPC_NO_RECV = 0x4,
OFPPC_NO_FWD = 0x20,
OFPPC_NO_PACKET_IN = 0x40,
+ OFPPC_BSN_MIRROR_DEST = 0x80000000,
};
enum ofp_port_state(wire_type=uint32_t, bitmask=True) {
diff --git a/openflow_input/standard-1.3 b/openflow_input/standard-1.3
index b567d6d..9d53f11 100644
--- a/openflow_input/standard-1.3
+++ b/openflow_input/standard-1.3
@@ -137,6 +137,7 @@
OFPPC_NO_RECV = 0x4,
OFPPC_NO_FWD = 0x20,
OFPPC_NO_PACKET_IN = 0x40,
+ OFPPC_BSN_MIRROR_DEST = 0x80000000,
};
enum ofp_port_state(wire_type=uint32_t, bitmask=True) {