Merge branch 'master' of github.com:floodlight/loxigen
diff --git a/Makefile b/Makefile
index dbaf08b..fe5f19e 100644
--- a/Makefile
+++ b/Makefile
@@ -92,7 +92,7 @@
clean:
rm -rf loxi_output # only delete generated files in the default directory
- rm -f loxigen.log loxigen-test.log .loxi_ts.c .loxi_ts.python .loxi_ts.java
+ rm -f loxigen.log loxigen-test.log .loxi_ts.*
debug:
@echo "LOXI_OUTPUT_DIR=\"${LOXI_OUTPUT_DIR}\""
diff --git a/java_gen/codegen.py b/java_gen/codegen.py
index 4369b30..6c589c9 100644
--- a/java_gen/codegen.py
+++ b/java_gen/codegen.py
@@ -37,6 +37,7 @@
from loxi_ir import *
import lang_java
import test_data
+from collections import namedtuple
from import_cleaner import ImportCleaner
import loxi_utils.loxi_utils as loxi_utils
@@ -52,20 +53,21 @@
shutil.rmtree(basedir)
os.makedirs(basedir)
copy_prewrite_tree(basedir)
- gen = JavaGenerator(basedir)
+ gen = JavaGenerator(basedir, JavaGeneratorOptions(instrument=True))
gen.create_of_interfaces()
gen.create_of_classes()
gen.create_of_const_enums()
gen.create_of_factories()
-
+JavaGeneratorOptions = namedtuple("JavaGeneratorOptions", ("instrument",))
class JavaGenerator(object):
templates_dir = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'templates')
- def __init__(self, basedir):
+ def __init__(self, basedir, gen_opts):
self.basedir = basedir
self.java_model = java_model.model
+ self.gen_opts = gen_opts
def render_class(self, clazz, template, src_dir=None, **context):
if not src_dir:
@@ -74,6 +76,7 @@
context['class_name'] = clazz.name
context['package'] = clazz.package
context['template_dir'] = self.templates_dir
+ context['genopts']= self.gen_opts
filename = os.path.join(self.basedir, src_dir, "%s/%s.java" % (clazz.package.replace(".", "/"), clazz.name))
dirname = os.path.dirname(filename)
@@ -83,14 +86,13 @@
print "filename: %s" % filename
with open(filename, "w") as f:
loxi_utils.render_template(f, template, [self.templates_dir], context, prefix=prefix)
-
+
try:
cleaner = ImportCleaner(filename)
cleaner.find_used_imports()
cleaner.rewrite_file(filename)
except:
print 'Cannot clean imports from file %s' % filename
-
def create_of_const_enums(self):
for enum in self.java_model.enums:
diff --git a/java_gen/java_model.py b/java_gen/java_model.py
index 85a6c0d..83c89b5 100644
--- a/java_gen/java_model.py
+++ b/java_gen/java_model.py
@@ -79,8 +79,8 @@
"OFOxmEthSrcMasked": OxmMapEntry("MacAddress", "ETH_SRC", True),
"OFOxmEthType": OxmMapEntry("EthType", "ETH_TYPE", False),
"OFOxmEthTypeMasked": OxmMapEntry("EthType", "ETH_TYPE", True),
- "OFOxmVlanVid": OxmMapEntry("VlanVid", "VLAN_VID", False),
- "OFOxmVlanVidMasked": OxmMapEntry("VlanVid", "VLAN_VID", True),
+ "OFOxmVlanVid": OxmMapEntry("OFVlanVidMatch", "VLAN_VID", False),
+ "OFOxmVlanVidMasked": OxmMapEntry("OFVlanVidMatch", "VLAN_VID", True),
"OFOxmVlanPcp": OxmMapEntry("VlanPcp", "VLAN_PCP", False),
"OFOxmVlanPcpMasked": OxmMapEntry("VlanPcp", "VLAN_PCP", True),
"OFOxmIpDscp": OxmMapEntry("IpDscp", "IP_DSCP", False),
@@ -602,6 +602,7 @@
JavaVirtualMember(self, "mask", java_type.generic_t),
JavaVirtualMember(self, "matchField", java_type.make_match_field_jtype("T")),
JavaVirtualMember(self, "masked", java_type.boolean),
+ JavaVirtualMember(self, "canonical", java_type.make_oxm_jtype("T"))
]
elif self.parent_interface and self.parent_interface.startswith("OFOxm"):
field_type = java_type.make_match_field_jtype(model.oxm_map[self.name].type_name) \
@@ -611,6 +612,8 @@
virtual_members += [
JavaVirtualMember(self, "matchField", field_type),
JavaVirtualMember(self, "masked", java_type.boolean),
+ JavaVirtualMember(self, "canonical", java_type.make_oxm_jtype(model.oxm_map[self.name].type_name),
+ custom_template=lambda builder: "OFOxm{}_getCanonical.java".format(".Builder" if builder else "")),
]
if not find(lambda x: x.name == "mask", self.ir_model_members):
virtual_members.append(JavaVirtualMember(self, "mask", find(lambda x: x.name == "value", self.ir_model_members).java_type))
@@ -681,7 +684,7 @@
@property
def variable_name(self):
- return self.name[3:]
+ return self.name[2].lower() + self.name[3:]
@property
def length(self):
@@ -745,18 +748,21 @@
virtual_members += [
JavaVirtualMember(self, "matchField", java_type.make_match_field_jtype(oxm_entry.type_name), "MatchField.%s" % oxm_entry.value),
JavaVirtualMember(self, "masked", java_type.boolean, "true" if oxm_entry.masked else "false"),
- ]
+ ]
else:
virtual_members += [
JavaVirtualMember(self, "matchField", java_type.make_match_field_jtype(), "null"),
JavaVirtualMember(self, "masked", java_type.boolean, "false"),
- ]
-
+ ]
if not find(lambda m: m.name == "version", self.ir_model_members):
virtual_members.append(JavaVirtualMember(self, "version", java_type.of_version, "OFVersion.%s" % self.version.constant_version))
return tuple(virtual_members)
+ @memoize
+ def member_by_name(self, name):
+ return find(lambda m: m.name == name, self.members)
+
def all_versions(self):
return [ JavaOFVersion(int_version)
for int_version in of_g.unified[self.c_name]
@@ -983,9 +989,10 @@
class JavaVirtualMember(JavaMember):
""" Models a virtual property (member) of an openflow class that is not backed by a loxi ir member """
- def __init__(self, msg, name, java_type, value=None):
+ def __init__(self, msg, name, java_type, value=None, custom_template=None):
JavaMember.__init__(self, msg, name, java_type, member=None)
self._value = value
+ self.custom_template = custom_template
@property
def is_fixed_value(self):
diff --git a/java_gen/java_type.py b/java_gen/java_type.py
index 2772a86..333efd8 100644
--- a/java_gen/java_type.py
+++ b/java_gen/java_type.py
@@ -358,9 +358,11 @@
write="$name.write2Bytes(bb)",
default="EthType.NONE")
vlan_vid = JType("VlanVid")\
- .op(version=1, read="VlanVid.read2BytesOF10(bb)", write="$name.write2BytesOF10(bb)", default="VlanVid.NONE") \
- .op(version=2, read="VlanVid.read2BytesOF10(bb)", write="$name.write2BytesOF10(bb)", default="VlanVid.NONE") \
- .op(version=ANY, read="VlanVid.read2Bytes(bb)", write="$name.write2Bytes(bb)", default="VlanVid.NONE")
+ .op(version=ANY, read="VlanVid.read2Bytes(bb)", write="$name.write2Bytes(bb)", default="VlanVid.ZERO")
+vlan_vid_match = JType("OFVlanVidMatch")\
+ .op(version=1, read="OFVlanVidMatch.read2BytesOF10(bb)", write="$name.write2BytesOF10(bb)", default="OFVlanVidMatch.NONE") \
+ .op(version=2, read="OFVlanVidMatch.read2BytesOF10(bb)", write="$name.write2BytesOF10(bb)", default="OFVlanVidMatch.NONE") \
+ .op(version=ANY, read="OFVlanVidMatch.read2Bytes(bb)", write="$name.write2Bytes(bb)", default="OFVlanVidMatch.NONE")
vlan_pcp = JType("VlanPcp")\
.op(read="VlanPcp.readByte(bb)",
write="$name.writeByte(bb)",
@@ -523,8 +525,8 @@
'of_oxm_sctp_dst_masked' : { 'value' : transport_port, 'value_mask' : transport_port },
'of_oxm_eth_type' : { 'value' : eth_type },
'of_oxm_eth_type_masked' : { 'value' : eth_type, 'value_mask' : eth_type },
- 'of_oxm_vlan_vid' : { 'value' : vlan_vid },
- 'of_oxm_vlan_vid_masked' : { 'value' : vlan_vid, 'value_mask' : vlan_vid },
+ 'of_oxm_vlan_vid' : { 'value' : vlan_vid_match },
+ 'of_oxm_vlan_vid_masked' : { 'value' : vlan_vid_match, 'value_mask' : vlan_vid_match },
'of_oxm_vlan_pcp' : { 'value' : vlan_pcp },
'of_oxm_vlan_pcp_masked' : { 'value' : vlan_pcp, 'value_mask' : vlan_pcp },
'of_oxm_ip_dscp' : { 'value' : ip_dscp },
@@ -579,7 +581,7 @@
'of_oxm_bsn_l3_dst_class_id_masked' : { 'value' : class_id, 'value_mask' : class_id },
'of_table_stats_entry': { 'wildcards': table_stats_wildcards },
- 'of_match_v1': { 'vlan_vid' : vlan_vid, 'vlan_pcp': vlan_pcp,
+ 'of_match_v1': { 'vlan_vid' : vlan_vid_match, 'vlan_pcp': vlan_pcp,
'eth_type': eth_type, 'ip_dscp': ip_dscp, 'ip_proto': ip_proto,
'tcp_src': transport_port, 'tcp_dst': transport_port,
'in_port': of_port_match_v1
@@ -588,6 +590,19 @@
'of_bsn_set_l2_table_reply': { 'l2_table_enable': boolean },
'of_bsn_set_pktin_suppression_request': { 'enabled': boolean },
'of_flow_stats_request': { 'out_group': of_group_default_any },
+
+ 'of_action_bsn_mirror': { 'dest_port': of_port },
+ 'of_action_push_mpls': { 'ethertype': eth_type },
+ 'of_action_push_pbb': { 'ethertype': eth_type },
+ 'of_action_push_vlan': { 'ethertype': eth_type },
+ 'of_action_set_nw_dst': { 'nw_addr': ipv4 },
+ 'of_action_set_nw_ecn': { 'nw_ecn': ip_ecn },
+ 'of_action_set_nw_src': { 'nw_addr': ipv4 },
+ 'of_action_set_nw_dst': { 'tp_port': transport_port },
+ 'of_action_set_tp_dst': { 'tp_port': transport_port },
+ 'of_action_set_tp_src': { 'tp_port': transport_port },
+ 'of_action_set_vlan_pcp': { 'vlan_pcp': vlan_pcp },
+ 'of_action_set_vlan_vid': { 'vlan_vid': vlan_vid },
}
@@ -605,6 +620,8 @@
def make_match_field_jtype(sub_type_name="?"):
return JType("MatchField<{}>".format(sub_type_name))
+def make_oxm_jtype(sub_type_name="?"):
+ return JType("OFOxm<{}>".format(sub_type_name))
def list_cname_to_java_name(c_type):
m = re.match(r'list\(of_([a-zA-Z_]+)_t\)', c_type)
@@ -613,7 +630,6 @@
base_name = m.group(1)
return "OF" + name_c_to_caps_camel(base_name)
-
#### main entry point for conversion of LOXI types (c_types) Java types.
# FIXME: This badly needs a refactoring
diff --git a/java_gen/pre-written/pom.xml b/java_gen/pre-written/pom.xml
index 5715704..e516b6e 100644
--- a/java_gen/pre-written/pom.xml
+++ b/java_gen/pre-written/pom.xml
@@ -10,7 +10,7 @@
<groupId>org.projectfloodlight</groupId>
<artifactId>openflowj</artifactId>
- <version>0.3.0-SNAPSHOT</version>
+ <version>0.3.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>OpenFlowJ-Loxi</name>
@@ -55,6 +55,11 @@
<artifactId>guava</artifactId>
<version>15.0</version>
</dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-api</artifactId>
+ <version>1.7.5</version>
+ </dependency>
</dependencies>
<build>
<plugins>
diff --git a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/protocol/OFOxmList.java b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/protocol/OFOxmList.java
index c6ba116..7f66110 100644
--- a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/protocol/OFOxmList.java
+++ b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/protocol/OFOxmList.java
@@ -2,7 +2,6 @@
import java.util.EnumMap;
import java.util.Iterator;
-import java.util.List;
import java.util.Map;
import org.jboss.netty.buffer.ChannelBuffer;
@@ -13,11 +12,16 @@
import org.projectfloodlight.openflow.types.OFValueType;
import org.projectfloodlight.openflow.types.PrimitiveSinkable;
import org.projectfloodlight.openflow.util.ChannelUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import com.google.common.base.Objects;
import com.google.common.collect.ImmutableMap;
import com.google.common.hash.PrimitiveSink;
public class OFOxmList implements Iterable<OFOxm<?>>, Writeable, PrimitiveSinkable {
+ private static final Logger logger = LoggerFactory.getLogger(OFOxmList.class);
+
private final Map<MatchFields, OFOxm<?>> oxmMap;
public final static OFOxmList EMPTY = new OFOxmList(ImmutableMap.<MatchFields, OFOxm<?>>of());
@@ -51,7 +55,7 @@
}
public OFOxmList build() {
- return new OFOxmList(oxmMap);
+ return OFOxmList.ofList(oxmMap.values());
}
}
@@ -60,12 +64,19 @@
return oxmMap.values().iterator();
}
- public static OFOxmList ofList(List<OFOxm<?>> oxmList) {
+ public static OFOxmList ofList(Iterable<OFOxm<?>> oxmList) {
Map<MatchFields, OFOxm<?>> map = new EnumMap<MatchFields, OFOxm<?>>(
MatchFields.class);
for (OFOxm<?> o : oxmList) {
- // TODO: if fully masked, ignore oxm.
- map.put(o.getMatchField().id, o);
+ OFOxm<?> canonical = o.getCanonical();
+
+ if(logger.isDebugEnabled() && !Objects.equal(o, canonical)) {
+ logger.debug("OFOxmList: normalized non-canonical OXM {} to {}", o, canonical);
+ }
+
+ if(canonical != null)
+ map.put(canonical.getMatchField().id, canonical);
+
}
return new OFOxmList(map);
}
@@ -74,8 +85,14 @@
Map<MatchFields, OFOxm<?>> map = new EnumMap<MatchFields, OFOxm<?>>(
MatchFields.class);
for (OFOxm<?> o : oxms) {
- // TODO: if fully masked, ignore oxm.
- map.put(o.getMatchField().id, o);
+ OFOxm<?> canonical = o.getCanonical();
+
+ if(logger.isDebugEnabled() && !Objects.equal(o, canonical)) {
+ logger.debug("OFOxmList: normalized non-canonical OXM {} to {}", o, canonical);
+ }
+
+ if(canonical != null)
+ map.put(canonical.getMatchField().id, canonical);
}
return new OFOxmList(map);
}
diff --git a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/protocol/match/MatchField.java b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/protocol/match/MatchField.java
index 1831626..92d4878 100644
--- a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/protocol/match/MatchField.java
+++ b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/protocol/match/MatchField.java
@@ -18,12 +18,12 @@
import org.projectfloodlight.openflow.types.OFMetadata;
import org.projectfloodlight.openflow.types.OFPort;
import org.projectfloodlight.openflow.types.OFValueType;
+import org.projectfloodlight.openflow.types.OFVlanVidMatch;
import org.projectfloodlight.openflow.types.TransportPort;
import org.projectfloodlight.openflow.types.U32;
import org.projectfloodlight.openflow.types.U8;
-import org.projectfloodlight.openflow.types.VlanPcp;
-import org.projectfloodlight.openflow.types.VlanVid;
import org.projectfloodlight.openflow.types.VRF;
+import org.projectfloodlight.openflow.types.VlanPcp;
@SuppressWarnings("unchecked")
public class MatchField<F extends OFValueType<F>> {
@@ -56,12 +56,12 @@
public final static MatchField<EthType> ETH_TYPE =
new MatchField<EthType>("eth_type", MatchFields.ETH_TYPE);
- public final static MatchField<VlanVid> VLAN_VID =
- new MatchField<VlanVid>("vlan_vid", MatchFields.VLAN_VID);
+ public final static MatchField<OFVlanVidMatch> VLAN_VID =
+ new MatchField<OFVlanVidMatch>("vlan_vid", MatchFields.VLAN_VID);
public final static MatchField<VlanPcp> VLAN_PCP =
new MatchField<VlanPcp>("vlan_pcp", MatchFields.VLAN_PCP,
- new Prerequisite<VlanVid>(MatchField.VLAN_VID));
+ new Prerequisite<OFVlanVidMatch>(MatchField.VLAN_VID));
public final static MatchField<IpDscp> IP_DSCP =
new MatchField<IpDscp>("ip_dscp", MatchFields.IP_DSCP,
diff --git a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/ClassId.java b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/ClassId.java
index b082f8b..7d7c38e 100644
--- a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/ClassId.java
+++ b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/ClassId.java
@@ -14,6 +14,10 @@
private final static int NONE_VAL = 0;
public final static ClassId NONE = new ClassId(NONE_VAL);
+ private final static int NO_MASK_VAL = 0xFFFFFFFF;
+ public final static ClassId NO_MASK = new ClassId(NO_MASK_VAL);
+ public final static ClassId FULL_MASK = NONE;
+
private final int rawValue;
private ClassId(final int rawValue) {
@@ -23,7 +27,8 @@
public static ClassId of(final int raw) {
if(raw == NONE_VAL)
return NONE;
-
+ else if(raw == NO_MASK_VAL)
+ return NO_MASK;
return new ClassId(raw);
}
diff --git a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/IPv4AddressWithMask.java b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/IPv4AddressWithMask.java
index 67bbce4..f30fcbb 100644
--- a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/IPv4AddressWithMask.java
+++ b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/IPv4AddressWithMask.java
@@ -46,7 +46,7 @@
public static IPv4AddressWithMask of(final String string) {
int slashPos;
String ip = string;
- int maskBits = 0;
+ int maskBits = 32;
IPv4Address maskAddress = null;
// Read mask suffix
@@ -77,9 +77,12 @@
if (maskAddress != null) {
// Full address mask
return IPv4AddressWithMask.of(ipv4, maskAddress);
- } else if (maskBits == 0) {
+ } else if (maskBits == 32) {
// No mask
return IPv4AddressWithMask.of(ipv4, IPv4Address.NO_MASK);
+ } else if (maskBits == 0) {
+ // No mask
+ return IPv4AddressWithMask.of(ipv4, IPv4Address.FULL_MASK);
} else {
// With mask
int mask = (-1) << (32 - maskBits);
diff --git a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/IPv6AddressWithMask.java b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/IPv6AddressWithMask.java
index 727daf6..6faf0b8 100644
--- a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/IPv6AddressWithMask.java
+++ b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/IPv6AddressWithMask.java
@@ -40,7 +40,7 @@
public static IPv6AddressWithMask of(final String string) {
int slashPos;
String ip = string;
- int maskBits = 0;
+ int maskBits = 128;
IPv6Address maskAddress = null;
// Read mask suffix
@@ -71,10 +71,13 @@
if (maskAddress != null) {
// Full address mask
return IPv6AddressWithMask.of(ipv6, maskAddress);
- } else if (maskBits == 0) {
+ } else if (maskBits == 128) {
// No mask
return IPv6AddressWithMask.of(ipv6, IPv6Address.NO_MASK);
- } else {
+ } else if (maskBits == 0) {
+ // Entirely masked out
+ return IPv6AddressWithMask.of(ipv6, IPv6Address.FULL_MASK);
+ }else {
// With mask
BigInteger mask = BigInteger.ONE.negate().shiftLeft(128 - maskBits);
byte[] maskBytesTemp = mask.toByteArray();
diff --git a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/LagId.java b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/LagId.java
index 6d9421a..51364e1 100644
--- a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/LagId.java
+++ b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/LagId.java
@@ -15,11 +15,19 @@
private final static int NONE_VAL = 0;
public final static LagId NONE = new LagId(NONE_VAL);
+ private final static int NO_MASK_VAL = 0xFFFFFFFF;
+ public final static LagId NO_MASK = new LagId(NO_MASK_VAL);
+ public final static LagId FULL_MASK = NONE;
+
private LagId(final int rawValue) {
this.rawValue = rawValue;
}
public static LagId of(final int raw) {
+ if(raw == NONE_VAL)
+ return NONE;
+ else if (raw == NO_MASK_VAL)
+ return NO_MASK;
return new LagId(raw);
}
diff --git a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/OFBitMask128.java b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/OFBitMask128.java
index 5cec233..051d573 100644
--- a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/OFBitMask128.java
+++ b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/OFBitMask128.java
@@ -14,6 +14,9 @@
public static final OFBitMask128 ALL = new OFBitMask128(-1, -1);
public static final OFBitMask128 NONE = new OFBitMask128(0, 0);
+ public static final OFBitMask128 NO_MASK = ALL;
+ public static final OFBitMask128 FULL_MASK = NONE;
+
private OFBitMask128(long raw1, long raw2) {
this.raw1 = raw1;
this.raw2 = raw2;
diff --git a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/OFBooleanValue.java b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/OFBooleanValue.java
index b386e54..e276092 100644
--- a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/OFBooleanValue.java
+++ b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/OFBooleanValue.java
@@ -28,6 +28,9 @@
public final static OFBooleanValue TRUE = new OFBooleanValue(true);
public final static OFBooleanValue FALSE = new OFBooleanValue(false);
+ public final static OFBooleanValue NO_MASK = TRUE;
+ public final static OFBooleanValue FULL_MASK = FALSE;
+
private final boolean value;
private OFBooleanValue(boolean value) {
diff --git a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/OFPortBitMap.java b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/OFPortBitMap.java
index 49c8c4e..b9c2b75 100644
--- a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/OFPortBitMap.java
+++ b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/OFPortBitMap.java
@@ -1,5 +1,7 @@
package org.projectfloodlight.openflow.types;
+import javax.annotation.concurrent.Immutable;
+
/** User-facing object representing a bitmap of ports that can be matched on.
* This is implemented by the custom BSN OXM type of_oxm_bsn_in_ports_182.
@@ -20,8 +22,22 @@
* The second term cannot be represented in OXM, the second can.
*
* That said, all that craziness is hidden from the user of this object.
+ *
+ * <h2>Usage</h2>
+ * OFPortBitmap is meant to be used with MatchField <tt>BSN_IN_PORTS_128</tt> in place
+ * of the raw type Masked<OFBitMask128>.
+ *
+ * <h3>Example:</h3>:
+ * <pre>
+ * OFPortBitMap portBitMap;
+ * Match.Builder matchBuilder;
+ * // initialize
+ * matchBuilder.setMasked(MatchField.BSN_IN_PORTS_128, portBitmap);
+ * </pre>
+ *
* @author Andreas Wundsam <andreas.wundsam@bigswitch.com>
*/
+@Immutable
public class OFPortBitMap extends Masked<OFBitMask128> {
private OFPortBitMap(OFBitMask128 mask) {
diff --git a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/OFVlanVidMatch.java b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/OFVlanVidMatch.java
new file mode 100644
index 0000000..29d6e02
--- /dev/null
+++ b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/OFVlanVidMatch.java
@@ -0,0 +1,183 @@
+package org.projectfloodlight.openflow.types;
+
+import javax.annotation.Nullable;
+
+import org.jboss.netty.buffer.ChannelBuffer;
+import org.projectfloodlight.openflow.exceptions.OFParseError;
+
+import com.google.common.hash.PrimitiveSink;
+import com.google.common.primitives.Shorts;
+
+/** Represents an OpenFlow Vlan VID for use in Matches, as specified by the OpenFlow 1.3 spec.
+ *
+ * <b> Note: this is not just the 12-bit vlan tag. OpenFlow defines
+ * the additional mask bits 0x1000 to represent the presence of a vlan
+ * tag. This additional bit will be stripped when writing a OF1.0 value
+ * tag.
+ * </b>
+ *
+ *
+ * @author Andreas Wundsam <andreas.wundsam@bigswitch.com>
+ *
+ */
+public class OFVlanVidMatch implements OFValueType<OFVlanVidMatch> {
+
+ private static final short VALIDATION_MASK = 0x1FFF;
+ private static final short PRESENT_VAL = 0x1000;
+ private static final short VLAN_MASK = 0x0FFF;
+ private static final short NONE_VAL = 0x0000;
+ private static final short UNTAGGED_VAL_OF13 = (short) 0x0000;
+ private static final short UNTAGGED_VAL_OF10 = (short) 0xFFFF;
+ final static int LENGTH = 2;
+
+ /** presence of a VLAN tag is indicated by the presence of bit 0x1000 */
+ public static final OFVlanVidMatch PRESENT = new OFVlanVidMatch(PRESENT_VAL);
+
+ /** this value means 'not set' in OF1.0 (e.g., in a match). not used elsewhere */
+ public static final OFVlanVidMatch NONE = new OFVlanVidMatch(NONE_VAL);
+
+ /** for use with masking operations */
+ public static final OFVlanVidMatch NO_MASK = new OFVlanVidMatch((short)0xFFFF);
+ public static final OFVlanVidMatch FULL_MASK = NONE;
+
+ /** an untagged packet is specified as 0000 in OF 1.0, but 0xFFFF in OF1.0. Special case that. */
+ public static final OFVlanVidMatch UNTAGGED = new OFVlanVidMatch(NONE_VAL) {
+ @Override
+ public void write2BytesOF10(ChannelBuffer c) {
+ c.writeShort(UNTAGGED_VAL_OF10);
+ }
+ };
+
+ private final short vid;
+
+ private OFVlanVidMatch(short vid) {
+ this.vid = vid;
+ }
+
+ public static OFVlanVidMatch ofRawVid(short vid) {
+ if(vid == UNTAGGED_VAL_OF13)
+ return UNTAGGED;
+ else if(vid == PRESENT_VAL)
+ return PRESENT;
+ else if ((vid & VALIDATION_MASK) != vid)
+ throw new IllegalArgumentException(String.format("Illegal VLAN value: %x", vid));
+ return new OFVlanVidMatch(vid);
+ }
+
+ public static OFVlanVidMatch ofVlanVid(VlanVid vid) {
+ return ofVlan(vid.getVlan());
+ }
+
+
+ public static OFVlanVidMatch ofVlan(int vlan) {
+ if( (vlan & VLAN_MASK) != vlan)
+ throw new IllegalArgumentException(String.format("Illegal VLAN value: %x", vlan));
+ return ofRawVid( (short) (vlan | PRESENT_VAL));
+ }
+
+ public static OFVlanVidMatch ofVlanOF10(short of10vlan) {
+ if(of10vlan == NONE_VAL) {
+ return NONE;
+ } else if(of10vlan == UNTAGGED_VAL_OF10) {
+ return UNTAGGED;
+ } else {
+ return ofVlan(of10vlan);
+ }
+ }
+
+ /** @return whether or not this VlanId has the present (0x1000) bit set */
+ public boolean isPresentBitSet() {
+ return (vid & PRESENT_VAL) != 0;
+ }
+
+ /** @return the actual VLAN tag this vid identifies */
+ public short getVlan() {
+ return (short) (vid & VLAN_MASK);
+ }
+
+ /** @return the actual vlan tag this vid identifies as a VlanVid object, if this
+ * VlanVidMatch has the present bit set (i.e., identifies a tagged VLAN).
+ * Else, returns null.
+ */
+ @Nullable
+ public VlanVid getVlanVid() {
+ return isPresentBitSet() ? VlanVid.ofVlan((short) (vid & VLAN_MASK)) : null;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (!(obj instanceof OFVlanVidMatch))
+ return false;
+ OFVlanVidMatch other = (OFVlanVidMatch)obj;
+ if (other.vid != this.vid)
+ return false;
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int prime = 13873;
+ return this.vid * prime;
+ }
+
+ @Override
+ public String toString() {
+ return "0x" + Integer.toHexString(vid);
+ }
+
+ public short getRawVid() {
+ return vid;
+ }
+
+
+ @Override
+ public int getLength() {
+ return LENGTH;
+ }
+
+
+ volatile byte[] bytesCache = null;
+
+ public byte[] getBytes() {
+ if (bytesCache == null) {
+ synchronized (this) {
+ if (bytesCache == null) {
+ bytesCache =
+ new byte[] { (byte) ((vid >>> 8) & 0xFF),
+ (byte) ((vid >>> 0) & 0xFF) };
+ }
+ }
+ }
+ return bytesCache;
+ }
+
+ public void write2Bytes(ChannelBuffer c) {
+ c.writeShort(this.vid);
+ }
+
+ public void write2BytesOF10(ChannelBuffer c) {
+ c.writeShort(this.getVlan());
+ }
+
+ public static OFVlanVidMatch read2Bytes(ChannelBuffer c) throws OFParseError {
+ return OFVlanVidMatch.ofRawVid(c.readShort());
+ }
+
+ public static OFVlanVidMatch read2BytesOF10(ChannelBuffer c) throws OFParseError {
+ return OFVlanVidMatch.ofVlanOF10(c.readShort());
+ }
+
+ @Override
+ public OFVlanVidMatch applyMask(OFVlanVidMatch mask) {
+ return OFVlanVidMatch.ofRawVid((short)(this.vid & mask.vid));
+ }
+
+ @Override
+ public int compareTo(OFVlanVidMatch o) {
+ return Shorts.compare(vid, o.vid);
+ }
+ @Override
+ public void putTo(PrimitiveSink sink) {
+ sink.putShort(vid);
+ }
+}
diff --git a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/OFVlanVidMatchWithMask.java b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/OFVlanVidMatchWithMask.java
new file mode 100644
index 0000000..c91c28c
--- /dev/null
+++ b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/OFVlanVidMatchWithMask.java
@@ -0,0 +1,10 @@
+package org.projectfloodlight.openflow.types;
+
+public class OFVlanVidMatchWithMask extends Masked<OFVlanVidMatch> {
+ private OFVlanVidMatchWithMask(OFVlanVidMatch value, OFVlanVidMatch mask) {
+ super(value, mask);
+ }
+
+ /* a combination of Vlan Vid and mask that matches any tagged packet */
+ public final static OFVlanVidMatchWithMask ANY_TAGGED = new OFVlanVidMatchWithMask(OFVlanVidMatch.PRESENT, OFVlanVidMatch.PRESENT);
+}
diff --git a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/U32.java b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/U32.java
index 9fafc30..7f53374 100644
--- a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/U32.java
+++ b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/U32.java
@@ -29,6 +29,10 @@
private final static int ZERO_VAL = 0;
public final static U32 ZERO = new U32(ZERO_VAL);
+ private static final int NO_MASK_VAL = 0xFFffFFff;
+ public final static U32 NO_MASK = new U32(NO_MASK_VAL);
+ public static final U32 FULL_MASK = ZERO;
+
private final int raw;
private U32(int raw) {
@@ -42,6 +46,8 @@
public static U32 ofRaw(int raw) {
if(raw == ZERO_VAL)
return ZERO;
+ if(raw == NO_MASK_VAL)
+ return NO_MASK;
return new U32(raw);
}
diff --git a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/U8.java b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/U8.java
index 078a846..c644599 100644
--- a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/U8.java
+++ b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/U8.java
@@ -29,6 +29,10 @@
private final static byte ZERO_VAL = 0;
public final static U8 ZERO = new U8(ZERO_VAL);
+ private static final byte NO_MASK_VAL = (byte) 0xFF;
+ public static final U8 NO_MASK = new U8(NO_MASK_VAL);
+ public static final U8 FULL_MASK = ZERO;
+
private final byte raw;
private U8(byte raw) {
@@ -38,6 +42,8 @@
public static final U8 of(short value) {
if(value == ZERO_VAL)
return ZERO;
+ if(value == NO_MASK_VAL)
+ return NO_MASK;
return new U8(t(value));
}
diff --git a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/VlanVid.java b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/VlanVid.java
index d370711..8337eb6 100644
--- a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/VlanVid.java
+++ b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/VlanVid.java
@@ -6,45 +6,23 @@
import com.google.common.hash.PrimitiveSink;
import com.google.common.primitives.Shorts;
-/** Represents an OpenFlow Vlan VID, as specified by the OpenFlow 1.3 spec.
- *
- * <b> Note: this is not just the 12-bit vlan tag. OpenFlow defines
- * the additional mask bits 0x1000 to represent the presence of a vlan
- * tag. This additional bit will be stripped when writing a OF1.0 value
- * tag.
- * </b>
- *
+/** Represents an 802.1Q Vlan VID (12 bits).
*
* @author Andreas Wundsam <andreas.wundsam@bigswitch.com>
*
*/
public class VlanVid implements OFValueType<VlanVid> {
- private static final short VALIDATION_MASK = 0x1FFF;
- private static final short PRESENT_VAL = 0x1000;
- private static final short VLAN_MASK = 0x0FFF;
- private static final short NONE_VAL = 0x0000;
- private static final short UNTAGGED_VAL_OF13 = (short) 0x0000;
- private static final short UNTAGGED_VAL_OF10 = (short) 0xFFFF;
+ private static final short VALIDATION_MASK = 0x0FFF;
+ private static final short ZERO_VAL = 0x0000;
final static int LENGTH = 2;
- /** presence of a VLAN tag is idicated by the presence of bit 0x1000 */
- public static final VlanVid PRESENT = new VlanVid(PRESENT_VAL);
-
/** this value means 'not set' in OF1.0 (e.g., in a match). not used elsewhere */
- public static final VlanVid NONE = new VlanVid(NONE_VAL);
+ public static final VlanVid ZERO = new VlanVid(ZERO_VAL);
/** for use with masking operations */
public static final VlanVid NO_MASK = new VlanVid((short)0xFFFF);
- public static final VlanVid FULL_MASK = NONE;
-
- /** an untagged packet is specified as 0000 in OF 1.0, but 0xFFFF in OF1.0. Special case that. */
- public static final VlanVid UNTAGGED = new VlanVid(NONE_VAL) {
- @Override
- public void write2BytesOF10(ChannelBuffer c) {
- c.writeShort(UNTAGGED_VAL_OF10);
- }
- };
+ public static final VlanVid FULL_MASK = ZERO;
private final short vid;
@@ -52,40 +30,15 @@
this.vid = vid;
}
- public static VlanVid ofRawVid(short vid) {
- if(vid == UNTAGGED_VAL_OF13)
- return UNTAGGED;
- else if(vid == PRESENT_VAL)
- return PRESENT;
- else if ((vid & VALIDATION_MASK) != vid)
+ public static VlanVid ofVlan(int vid) {
+ if ((vid & VALIDATION_MASK) != vid)
throw new IllegalArgumentException(String.format("Illegal VLAN value: %x", vid));
- return new VlanVid(vid);
- }
-
- public static VlanVid ofVlan(int vlan) {
- if( (vlan & VLAN_MASK) != vlan)
- throw new IllegalArgumentException(String.format("Illegal VLAN value: %x", vlan));
- return ofRawVid( (short) (vlan | PRESENT_VAL));
- }
-
- public static VlanVid ofVlanOF10(short of10vlan) {
- if(of10vlan == NONE_VAL) {
- return NONE;
- } else if(of10vlan == UNTAGGED_VAL_OF10) {
- return UNTAGGED;
- } else {
- return ofVlan(of10vlan);
- }
- }
-
- /** @return whether or not this VlanId has the present (0x1000) bit set */
- public boolean isPresentBitSet() {
- return (vid & PRESENT_VAL) != 0;
+ return new VlanVid((short) vid);
}
/** @return the actual VLAN tag this vid identifies */
public short getVlan() {
- return (short) (vid & VLAN_MASK);
+ return vid;
}
@Override
@@ -109,17 +62,11 @@
return "0x" + Integer.toHexString(vid);
}
- public short getRawVid() {
- return vid;
- }
-
-
@Override
public int getLength() {
return LENGTH;
}
-
volatile byte[] bytesCache = null;
public byte[] getBytes() {
@@ -144,22 +91,19 @@
}
public static VlanVid read2Bytes(ChannelBuffer c) throws OFParseError {
- return VlanVid.ofRawVid(c.readShort());
- }
-
- public static VlanVid read2BytesOF10(ChannelBuffer c) throws OFParseError {
- return VlanVid.ofVlanOF10(c.readShort());
+ return VlanVid.ofVlan(c.readShort());
}
@Override
public VlanVid applyMask(VlanVid mask) {
- return VlanVid.ofRawVid((short)(this.vid & mask.vid));
+ return VlanVid.ofVlan((short)(this.vid & mask.vid));
}
@Override
public int compareTo(VlanVid o) {
return Shorts.compare(vid, o.vid);
}
+
@Override
public void putTo(PrimitiveSink sink) {
sink.putShort(vid);
diff --git a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/VlanVidWithMask.java b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/VlanVidWithMask.java
deleted file mode 100644
index cb81d31..0000000
--- a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/VlanVidWithMask.java
+++ /dev/null
@@ -1,11 +0,0 @@
-package org.projectfloodlight.openflow.types;
-
-public class VlanVidWithMask extends Masked<VlanVid> {
- private VlanVidWithMask(VlanVid value, VlanVid mask) {
- super(value, mask);
- }
-
- /* a combination of Vlan Vid and mask that matches any tagged packet */
- public final static VlanVidWithMask ANY_TAGGED = new VlanVidWithMask(VlanVid.PRESENT, VlanVid.PRESENT);
-
-}
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 13cfdc7..1a1ac6a 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
@@ -6,6 +6,8 @@
import org.projectfloodlight.openflow.exceptions.OFParseError;
import org.projectfloodlight.openflow.protocol.OFMessageReader;
import org.projectfloodlight.openflow.protocol.Writeable;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import com.google.common.base.Charsets;
import com.google.common.collect.ImmutableList;
@@ -18,6 +20,7 @@
*/
public class ChannelUtils {
+ private static final Logger logger = LoggerFactory.getLogger(ChannelUtils.class);
public static String readFixedLengthString(ChannelBuffer bb, int length) {
byte[] dst = new byte[length];
bb.readBytes(dst, 0, length);
@@ -56,8 +59,13 @@
public static <T> List<T> readList(ChannelBuffer bb, int length, OFMessageReader<T> reader) throws OFParseError {
int end = bb.readerIndex() + length;
Builder<T> builder = ImmutableList.<T>builder();
+ if(logger.isTraceEnabled())
+ logger.trace("readList(length={}, reader={})", length, reader.getClass());
while(bb.readerIndex() < end) {
- builder.add(reader.readFrom(bb));
+ T read = reader.readFrom(bb);
+ if(logger.isTraceEnabled())
+ logger.trace("readList: read={}, left={}", read, end - bb.readerIndex());
+ builder.add(read);
}
if(bb.readerIndex() != end) {
throw new IllegalStateException("Overread length: length="+length + " overread by "+ (bb.readerIndex() - end) + " reader: "+reader);
diff --git a/java_gen/pre-written/src/test/java/org/projectfloodlight/openflow/types/IPv4AddressTest.java b/java_gen/pre-written/src/test/java/org/projectfloodlight/openflow/types/IPv4AddressTest.java
index 4f3f968..38d60b3 100644
--- a/java_gen/pre-written/src/test/java/org/projectfloodlight/openflow/types/IPv4AddressTest.java
+++ b/java_gen/pre-written/src/test/java/org/projectfloodlight/openflow/types/IPv4AddressTest.java
@@ -2,8 +2,10 @@
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThat;
import static org.junit.Assert.fail;
+import org.hamcrest.CoreMatchers;
import org.jboss.netty.buffer.ChannelBuffers;
import org.junit.Test;
import org.projectfloodlight.openflow.exceptions.OFParseError;
@@ -47,20 +49,23 @@
"192.168.130.140/255.255.192.0",
"127.0.0.1/8",
"8.8.8.8",
+ "0.0.0.0/0"
};
boolean[] hasMask = {
true,
true,
true,
- false
+ false,
+ true
};
byte[][][] ipsWithMaskValues = {
new byte[][] { new byte[] { (byte)0x01, (byte)0x02, (byte)0x03, (byte)0x04 }, new byte[] { (byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0x00 } },
new byte[][] { new byte[] { (byte)0xC0, (byte)0xA8, (byte)0x82, (byte)0x8C }, new byte[] { (byte)0xFF, (byte)0xFF, (byte)0xC0, (byte)0x00 } },
new byte[][] { new byte[] { (byte)0x7F, (byte)0x00, (byte)0x00, (byte)0x01 }, new byte[] { (byte)0xFF, (byte)0x00, (byte)0x00, (byte)0x00 } },
- new byte[][] { new byte[] { (byte)0x08, (byte)0x08, (byte)0x08, (byte)0x08 }, null }
+ new byte[][] { new byte[] { (byte)0x08, (byte)0x08, (byte)0x08, (byte)0x08 }, null },
+ new byte[][] { new byte[] { (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00 }, new byte[] { (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00 } }
};
@@ -123,7 +128,8 @@
}
assertArrayEquals(ipBytes, value.getValue().getBytes());
- assertArrayEquals(ipsWithMaskValues[i][1], value.getMask().getBytes());
+ assertThat(String.format("Byte comparison for mask of %s (%s)", ipsWithMask[i], value),
+ value.getMask().getBytes(), CoreMatchers.equalTo(ipsWithMaskValues[i][1]));
}
}
}
diff --git a/java_gen/pre-written/src/test/java/org/projectfloodlight/openflow/types/IPv6AddressTest.java b/java_gen/pre-written/src/test/java/org/projectfloodlight/openflow/types/IPv6AddressTest.java
index 3fcfe23..672a0e1 100644
--- a/java_gen/pre-written/src/test/java/org/projectfloodlight/openflow/types/IPv6AddressTest.java
+++ b/java_gen/pre-written/src/test/java/org/projectfloodlight/openflow/types/IPv6AddressTest.java
@@ -2,16 +2,20 @@
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThat;
import static org.junit.Assert.fail;
import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.UnknownHostException;
+import org.hamcrest.CoreMatchers;
import org.jboss.netty.buffer.ChannelBuffers;
import org.junit.Test;
import org.projectfloodlight.openflow.exceptions.OFParseError;
+import com.google.common.io.BaseEncoding;
+
public class IPv6AddressTest {
String[] testStrings = {
@@ -21,61 +25,83 @@
"1:2:3:4:5:6:7:8"
};
- String[] ipsWithMask = {
- "1::1/80",
- "1:2:3:4::/ffff:ffff:ffff:ff00::",
- "ffff:ffee:1::/ff00:ff00:ff00:ff00::",
- "8:8:8:8:8:8:8:8",
- };
- byte[][] masks = {
- new byte[] { (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff,
- (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff,
- (byte)0xff, (byte)0xff, (byte)0x00, (byte)0x00,
- (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00 },
- new byte[] { (byte)0xff, (byte)0xff, (byte)0xff, (byte)0xff,
- (byte)0xff, (byte)0xff, (byte)0xff, (byte)0x00,
- (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,
- (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00 },
- new byte[] { (byte)0xff, (byte)0x00, (byte)0xff, (byte)0x00,
- (byte)0xff, (byte)0x00, (byte)0xff, (byte)0x00,
- (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,
- (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00 },
- new byte[] { (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,
- (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,
- (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00,
- (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00 }
- };
+ private final BaseEncoding hex = BaseEncoding.base16().omitPadding().lowerCase();
- boolean[] hasMask = {
- true,
- true,
- true,
- false
+ private class WithMaskTaskCase {
+ final String input;
+ boolean hasMask;
+ byte[] expectedMask = hex.decode("ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff".replaceAll(" ", ""));
+
+ public WithMaskTaskCase(String input) {
+ super();
+ this.input = input;
+ }
+
+ public WithMaskTaskCase hasMask() {
+ this.hasMask = true;
+ return this;
+ }
+
+ public WithMaskTaskCase maskLength(int l) {
+ this.hasMask = l < 128;
+ for(int j=0; j < 8; j++) {
+ int pos = j * 8;
+ int index = Math.max(0, Math.min(7, pos - l));
+
+ if(index == 0) {
+ expectedMask[j] = 0;
+ } else {
+ expectedMask[j] = (byte) (-1 << index);
+ }
+ }
+ return this;
+ }
+
+ public WithMaskTaskCase maskHex(String string) {
+ string = string.replaceAll(" ", "");
+ this.hasMask = true;
+ expectedMask = hex.decode(string);
+ return this;
+ }
+
+ }
+
+ WithMaskTaskCase[] withMasks = new WithMaskTaskCase[] {
+ new WithMaskTaskCase("1::1/80")
+ .maskHex("ff ff ff ff ff ff ff ff ff ff 00 00 00 00 00 00"),
+
+ new WithMaskTaskCase("ffff:ffee:1::/ff00:ff00:ff00:ff00::")
+ .maskHex("ff 00 ff 00 ff 00 ff 00 00 00 00 00 00 00 00 00"),
+ new WithMaskTaskCase("8:8:8:8:8:8:8:8"),
+ new WithMaskTaskCase("8:8:8:8:8:8:8:8"),
+ new WithMaskTaskCase("1:2:3:4:5:6:7:8/128"),
+ new WithMaskTaskCase("::/0")
+ .maskHex("00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00")
};
@Test
public void testMasked() throws UnknownHostException {
- for(int i=0; i < ipsWithMask.length; i++ ) {
- IPv6AddressWithMask value = IPv6AddressWithMask.of(ipsWithMask[i]);
- if (!hasMask[i]) {
+ for(WithMaskTaskCase w: withMasks) {
+ IPv6AddressWithMask value = IPv6AddressWithMask.of(w.input);
+ if (!w.hasMask) {
IPv6Address ip = value.getValue();
- InetAddress inetAddress = InetAddress.getByName(ipsWithMask[i]);
+ InetAddress inetAddress = InetAddress.getByName(w.input.split("/")[0]);
assertArrayEquals(ip.getBytes(), inetAddress.getAddress());
- assertEquals(ipsWithMask[i], ip.toString());
- } else if (value instanceof IPv6AddressWithMask && hasMask[i]) {
- InetAddress inetAddress = InetAddress.getByName(ipsWithMask[i].substring(0, ipsWithMask[i].indexOf('/')));
+ assertEquals(w.input.split("/")[0], ip.toString());
+ } else {
+ InetAddress inetAddress = InetAddress.getByName(w.input.substring(0, w.input.indexOf('/')));
byte[] address = inetAddress.getAddress();
assertEquals(address.length, value.getValue().getBytes().length);
for (int j = 0; j < address.length; j++) {
- address[j] &= masks[i][j];
+ address[j] &= w.expectedMask[j];
}
- assertArrayEquals(value.getValue().getBytes(), address);
- assertArrayEquals(masks[i], value.getMask().getBytes());
+ assertThat("Address bytes for input " + w.input + ", value=" + value, value.getValue().getBytes(), CoreMatchers.equalTo(address));
+ assertThat("mask check for input " + w.input + ", value=" + value, value.getMask().getBytes(), CoreMatchers.equalTo(w.expectedMask));
}
}
}
diff --git a/java_gen/pre-written/src/test/java/org/projectfloodlight/protocol/OFOxmListTest.java b/java_gen/pre-written/src/test/java/org/projectfloodlight/protocol/OFOxmListTest.java
new file mode 100644
index 0000000..39e8c0c
--- /dev/null
+++ b/java_gen/pre-written/src/test/java/org/projectfloodlight/protocol/OFOxmListTest.java
@@ -0,0 +1,41 @@
+package org.projectfloodlight.protocol;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertThat;
+
+import org.hamcrest.CoreMatchers;
+import org.junit.Before;
+import org.junit.Test;
+import org.projectfloodlight.openflow.protocol.OFFactories;
+import org.projectfloodlight.openflow.protocol.OFOxmList;
+import org.projectfloodlight.openflow.protocol.OFVersion;
+import org.projectfloodlight.openflow.protocol.match.MatchField;
+import org.projectfloodlight.openflow.protocol.oxm.OFOxmIpv6DstMasked;
+import org.projectfloodlight.openflow.protocol.oxm.OFOxmIpv6SrcMasked;
+import org.projectfloodlight.openflow.protocol.oxm.OFOxms;
+import org.projectfloodlight.openflow.types.IPv6AddressWithMask;
+
+public class OFOxmListTest {
+ private OFOxms oxms;
+
+ @Before
+ public void setup() {
+ oxms = OFFactories.getFactory(OFVersion.OF_13).oxms();
+ }
+
+ @Test
+ public void testCanonicalize() {
+ OFOxmList.Builder builder = new OFOxmList.Builder();
+ IPv6AddressWithMask fullMasked = IPv6AddressWithMask.of("::/0");
+ OFOxmIpv6DstMasked fullMaskedOxm = oxms.ipv6DstMasked(fullMasked.getValue(), fullMasked.getMask());
+ builder.set(fullMaskedOxm);
+
+ IPv6AddressWithMask address= IPv6AddressWithMask.of("1:2:3:4:5:6::8");
+ OFOxmIpv6SrcMasked addressSrcOxm = oxms.ipv6SrcMasked(address.getValue(), address.getMask());
+ builder.set(addressSrcOxm);
+
+ OFOxmList list = builder.build();
+ assertThat(list.get(MatchField.IPV6_DST), CoreMatchers.nullValue());
+ assertFalse(list.get(MatchField.IPV6_SRC).isMasked());
+ }
+}
diff --git a/java_gen/pre-written/src/test/java/org/projectfloodlight/protocol/OFOxmTest.java b/java_gen/pre-written/src/test/java/org/projectfloodlight/protocol/OFOxmTest.java
new file mode 100644
index 0000000..8482886
--- /dev/null
+++ b/java_gen/pre-written/src/test/java/org/projectfloodlight/protocol/OFOxmTest.java
@@ -0,0 +1,62 @@
+package org.projectfloodlight.protocol;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertThat;
+import static org.junit.Assert.assertTrue;
+
+import org.hamcrest.CoreMatchers;
+import org.junit.Before;
+import org.junit.Test;
+import org.projectfloodlight.openflow.protocol.OFFactories;
+import org.projectfloodlight.openflow.protocol.OFVersion;
+import org.projectfloodlight.openflow.protocol.oxm.OFOxm;
+import org.projectfloodlight.openflow.protocol.oxm.OFOxmIpv4Src;
+import org.projectfloodlight.openflow.protocol.oxm.OFOxmIpv4SrcMasked;
+import org.projectfloodlight.openflow.protocol.oxm.OFOxms;
+import org.projectfloodlight.openflow.types.IPv4Address;
+import org.projectfloodlight.openflow.types.IPv4AddressWithMask;
+
+public class OFOxmTest {
+ private OFOxms oxms;
+
+ @Before
+ public void setup() {
+ oxms = OFFactories.getFactory(OFVersion.OF_13).oxms();
+ }
+
+ @Test
+ public void testGetCanonicalFullMask() {
+ IPv4AddressWithMask empty = IPv4AddressWithMask.of("0.0.0.0/0");
+ assertEquals(IPv4Address.FULL_MASK, empty.getMask());
+ OFOxmIpv4SrcMasked ipv4SrcMasked = oxms.ipv4SrcMasked(empty.getValue(), empty.getMask());
+ // canonicalize should remove /0
+ assertNull(ipv4SrcMasked.getCanonical());
+ }
+
+ @Test
+ public void testGetCanonicalNoMask() {
+ IPv4AddressWithMask fullIp = IPv4AddressWithMask.of("1.2.3.4/32");
+ assertEquals(IPv4Address.NO_MASK, fullIp.getMask());
+ OFOxmIpv4SrcMasked ipv4SrcMasked = oxms.ipv4SrcMasked(fullIp.getValue(), fullIp.getMask());
+ assertTrue(ipv4SrcMasked.isMasked());
+ assertEquals(IPv4Address.NO_MASK, ipv4SrcMasked.getMask());
+
+ // canonicalize should convert the masked oxm to the non-masked one
+ OFOxm<IPv4Address> canonical = ipv4SrcMasked.getCanonical();
+ assertThat(canonical, CoreMatchers.instanceOf(OFOxmIpv4Src.class));
+ assertFalse(canonical.isMasked());
+ }
+
+ @Test
+ public void testGetCanonicalNormalMask() {
+ IPv4AddressWithMask ip = IPv4AddressWithMask.of("1.2.3.0/24");
+ OFOxmIpv4SrcMasked ipv4SrcMasked = oxms.ipv4SrcMasked(ip.getValue(), ip.getMask());
+ assertTrue(ipv4SrcMasked.isMasked());
+
+ // canonicalize should convert the masked oxm to the non-masked one
+ OFOxm<IPv4Address> canonical = ipv4SrcMasked.getCanonical();
+ assertEquals(ipv4SrcMasked, canonical);
+ }
+}
diff --git a/java_gen/templates/_field_accessors.java b/java_gen/templates/_field_accessors.java
index c7aa3a0..030388c 100644
--- a/java_gen/templates/_field_accessors.java
+++ b/java_gen/templates/_field_accessors.java
@@ -1,10 +1,13 @@
//:: import os
//:: for prop in msg.interface.members:
-//:: getter_template_file_name = "%s/custom/%s_%s.java" % (template_dir, msg.name if not builder else msg.name + '.Builder', prop.getter_name)
-//:: if os.path.exists(getter_template_file_name):
-//:: include(getter_template_file_name, msg=msg, builder=builder, has_parent=has_parent)
-
-//:: else:
+//:: if hasattr(prop, "custom_template") and prop.custom_template != None:
+//:: getter_template_file_name = "%s/custom/%s" % (template_dir, prop.custom_template(builder=builder))
+//:: else:
+//:: getter_template_file_name = "%s/custom/%s_%s.java" % (template_dir, msg.name if not builder else msg.name + '.Builder', prop.getter_name)
+//:: #endif
+//:: if os.path.exists(getter_template_file_name):
+//:: include(getter_template_file_name, msg=msg, builder=builder, has_parent=has_parent, prop=prop)
+//:: else:
@Override
public ${prop.java_type.public_type} ${prop.getter_name}()${ "" if prop in msg.members else "throws UnsupportedOperationException"} {
//:: if prop in msg.members:
diff --git a/java_gen/templates/_imports.java b/java_gen/templates/_imports.java
index 55e9a2d..2187bab 100644
--- a/java_gen/templates/_imports.java
+++ b/java_gen/templates/_imports.java
@@ -14,6 +14,8 @@
import org.projectfloodlight.openflow.types.*;
import org.projectfloodlight.openflow.util.*;
import org.projectfloodlight.openflow.exceptions.*;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.buffer.ChannelBuffers;
import com.google.common.collect.ImmutableList;
diff --git a/java_gen/templates/custom/OFMatchV1Ver10.Builder.java b/java_gen/templates/custom/OFMatchV1Ver10.Builder.java
index 239828e..396e3a0 100644
--- a/java_gen/templates/custom/OFMatchV1Ver10.Builder.java
+++ b/java_gen/templates/custom/OFMatchV1Ver10.Builder.java
@@ -381,7 +381,7 @@
wildcards &= ~OFPFW_DL_VLAN_PCP;
break;
case VLAN_VID:
- setVlanVid((VlanVid) value);
+ setVlanVid((OFVlanVidMatch) value);
wildcards &= ~OFPFW_DL_VLAN;
break;
default:
@@ -492,7 +492,7 @@
wildcards |= OFPFW_DL_VLAN_PCP;
break;
case VLAN_VID:
- setVlanVid(VlanVid.NONE);
+ setVlanVid(OFVlanVidMatch.NONE);
wildcards |= OFPFW_DL_VLAN;
break;
default:
diff --git a/java_gen/templates/custom/OFMatchV3Ver13.Builder.java b/java_gen/templates/custom/OFMatchV3Ver13.Builder.java
index 48f8b70..79cbdbc 100644
--- a/java_gen/templates/custom/OFMatchV3Ver13.Builder.java
+++ b/java_gen/templates/custom/OFMatchV3Ver13.Builder.java
@@ -1,13 +1,13 @@
private OFOxmList.Builder oxmListBuilder;
- private synchronized void initBuilder() {
+ private void initBuilder() {
if (oxmListBuilder != null)
return;
oxmListBuilder = new OFOxmList.Builder();
}
- private synchronized void updateOxmList() {
+ private void updateOxmList() {
this.oxmList = this.oxmListBuilder.build();
this.oxmListSet = true;
}
@@ -21,7 +21,7 @@
}
@Override
- public synchronized <F extends OFValueType<F>> F get(MatchField<F> field)
+ public <F extends OFValueType<F>> F get(MatchField<F> field)
throws UnsupportedOperationException {
OFOxm<F> value = getOxm(field);
if (value == null)
@@ -30,7 +30,7 @@
}
@Override
- public synchronized <F extends OFValueType<F>> Masked<F> getMasked(MatchField<F> field)
+ public <F extends OFValueType<F>> Masked<F> getMasked(MatchField<F> field)
throws UnsupportedOperationException {
OFOxm<F> value = getOxm(field);
if (value == null || !value.isMasked())
@@ -50,25 +50,25 @@
}
@Override
- public synchronized boolean isExact(MatchField<?> field) {
+ public boolean isExact(MatchField<?> field) {
OFOxm<?> value = getOxm(field);
return (value != null && !value.isMasked());
}
@Override
- public synchronized boolean isFullyWildcarded(MatchField<?> field) {
+ public boolean isFullyWildcarded(MatchField<?> field) {
OFOxm<?> value = getOxm(field);
return (value == null);
}
@Override
- public synchronized boolean isPartiallyMasked(MatchField<?> field) {
+ public boolean isPartiallyMasked(MatchField<?> field) {
OFOxm<?> value = getOxm(field);
return (value != null && value.isMasked());
}
@Override
- public synchronized <F extends OFValueType<F>> Match.Builder setExact(
+ public <F extends OFValueType<F>> Match.Builder setExact(
MatchField<F> field, F value) {
initBuilder();
OFOxm<F> oxm = OFFactories.getFactory(OFVersion.OF_13).oxms().fromValue(value, field);
@@ -78,7 +78,7 @@
}
@Override
- public synchronized <F extends OFValueType<F>> Match.Builder setMasked(
+ public <F extends OFValueType<F>> Match.Builder setMasked(
MatchField<F> field, F value, F mask) {
initBuilder();
OFOxm<F> oxm = OFFactories.getFactory(OFVersion.OF_13).oxms().fromValueAndMask(value, mask, field);
@@ -88,7 +88,7 @@
}
@Override
- public synchronized <F extends OFValueType<F>> Match.Builder setMasked(
+ public <F extends OFValueType<F>> Match.Builder setMasked(
MatchField<F> field, Masked<F> valueWithMask) {
initBuilder();
OFOxm<F> oxm = OFFactories.getFactory(OFVersion.OF_13).oxms().fromMasked(valueWithMask, field);
@@ -98,7 +98,7 @@
}
@Override
- public synchronized <F extends OFValueType<F>> Match.Builder wildcard(MatchField<F> field) {
+ public <F extends OFValueType<F>> Match.Builder wildcard(MatchField<F> field) {
initBuilder();
this.oxmListBuilder.unset(field);
updateOxmList();
diff --git a/java_gen/templates/custom/OFMatchV3Ver13.java b/java_gen/templates/custom/OFMatchV3Ver13.java
index a4cc51c..8955e1e 100644
--- a/java_gen/templates/custom/OFMatchV3Ver13.java
+++ b/java_gen/templates/custom/OFMatchV3Ver13.java
@@ -62,6 +62,7 @@
case IPV6_SRC:
case IPV6_DST:
case IPV6_FLABEL:
+ case BSN_IN_PORTS_128:
return true;
default:
return false;
@@ -106,4 +107,4 @@
OFOxm<?> oxm = this.oxmList.get(field);
return oxm != null && oxm.isMasked();
- }
\ No newline at end of file
+ }
diff --git a/java_gen/templates/custom/OFOxm_getCanonical.java b/java_gen/templates/custom/OFOxm_getCanonical.java
new file mode 100644
index 0000000..6681870
--- /dev/null
+++ b/java_gen/templates/custom/OFOxm_getCanonical.java
@@ -0,0 +1,17 @@
+//:: import re
+ public ${prop.java_type.public_type} getCanonical() {
+ //:: if not msg.member_by_name("masked").value == "true":
+ // exact match OXM is always canonical
+ return this;
+ //:: else:
+ //:: mask_type = msg.member_by_name("mask").java_type.public_type
+ if (${mask_type}.NO_MASK.equals(mask)) {
+ //:: unmasked = re.sub(r'(.*)Masked(Ver.*)', r'\1\2', msg.name)
+ return new ${unmasked}(value);
+ } else if(${mask_type}.FULL_MASK.equals(mask)) {
+ return null;
+ } else {
+ return this;
+ }
+ //:: #endif
+ }
diff --git a/java_gen/templates/of_class.java b/java_gen/templates/of_class.java
index 7b3b762..36d407c 100644
--- a/java_gen/templates/of_class.java
+++ b/java_gen/templates/of_class.java
@@ -38,6 +38,9 @@
//:: include("_imports.java", msg=msg)
class ${impl_class} implements ${msg.interface.inherited_declaration()} {
+//:: if genopts.instrument:
+ private static final Logger logger = LoggerFactory.getLogger(${impl_class}.class);
+//:: #endif
// version: ${version}
final static byte WIRE_VERSION = ${version.int_version};
//:: if msg.is_fixed_length:
@@ -216,6 +219,10 @@
bb.readerIndex(start);
return null;
}
+ //:: if genopts.instrument:
+ if(logger.isTraceEnabled())
+ logger.trace("readFrom - length={}", ${prop.name});
+ //:: #endif
//:: elif prop.is_fixed_value:
// fixed value property ${prop.name} == ${prop.value}
${prop.java_type.priv_type} ${prop.name} = ${prop.java_type.read_op(version, pub_type=False)};
@@ -242,11 +249,20 @@
//:: if os.path.exists("%s/custom/%s.Reader_normalize_stanza.java" % (template_dir, msg.name)):
//:: include("custom/%s.Reader_normalize_stanza.java" % msg.name, msg=msg, has_parent=False)
//:: #endif
- return new ${impl_class}(
+ ${impl_class} ${msg.variable_name} = new ${impl_class}(
${",\n ".join(
[ prop.name for prop in msg.data_members])}
);
+ //:: if genopts.instrument:
+ if(logger.isTraceEnabled())
+ logger.trace("readFrom - read={}", ${msg.variable_name});
+ //:: #endif
+ return ${msg.variable_name};
//:: else:
+ //:: if genopts.instrument:
+ if(logger.isTraceEnabled())
+ logger.trace("readFrom - returning shared instance={}", INSTANCE);
+ //:: #endif
return INSTANCE;
//:: #endif
}
diff --git a/wireshark_gen/field_info.py b/wireshark_gen/field_info.py
index 4a80a8e..ec81665 100644
--- a/wireshark_gen/field_info.py
+++ b/wireshark_gen/field_info.py
@@ -113,9 +113,52 @@
('of_instruction_write_actions', 'type'): 'ofp_instruction_type',
('of_group_mod', 'group_type'): 'ofp_group_type',
('of_group_mod', 'type'): 'ofp_type',
- ('of_group_mod', 'command'): 'ofp_group_mod_commane',
+ ('of_group_mod', 'command'): 'ofp_group_mod_command',
('of_group_mod', 'group_id'): 'ofp_group',
-
+ ('of_packet_out', 'type'): 'ofp_type',
+ ('of_packet_in', 'type'): 'ofp_type',
+ ('of_packet_in', 'reason'): 'ofp_packet_in_reason',
+ ('of_flow_stats_request', 'type'): 'ofp_type',
+ ('of_flow_stats_request', 'stats_type'): 'ofp_stats_type',
+ ('of_desc_stats_request', 'type'): 'ofp_type',
+ ('of_desc_stats_request', 'stats_type'): 'ofp_stats_type',
+ ('of_queue_stats_request', 'type'): 'ofp_type',
+ ('of_queue_stats_request', 'stats_type'): 'ofp_stats_type',
+ ('of_port_stats_request', 'type'): 'ofp_type',
+ ('of_port_stats_request', 'stats_type'): 'ofp_stats_type',
+ ('of_table_stats_request', 'type'): 'ofp_type',
+ ('of_table_stats_request', 'stats_type'): 'ofp_stats_type',
+ ('of_port_desc_stats_request', 'type'): 'ofp_type',
+ ('of_port_desc_stats_request', 'stats_type'): 'ofp_stats_type',
+ ('of_meter_stats_request', 'type'): 'ofp_type',
+ ('of_meter_stats_request', 'stats_type'): 'ofp_stats_type',
+ ('of_meter_features_stats_request', 'type'): 'ofp_type',
+ ('of_meter_features_stats_request', 'stats_type'): 'ofp_stats_type',
+ ('of_meter_config_stats_request', 'type'): 'ofp_type',
+ ('of_meter_config_stats_request', 'stats_type'): 'ofp_stats_type',
+ ('of_group_stats_request', 'type'): 'ofp_type',
+ ('of_group_stats_request', 'stats_type'): 'ofp_stats_type',
+ ('of_group_features_stats_request', 'type'): 'ofp_type',
+ ('of_group_features_stats_request', 'stats_type'): 'ofp_stats_type',
+ ('of_group_desc_stats_request', 'type'): 'ofp_type',
+ ('of_group_desc_stats_request', 'stats_type'): 'ofp_stats_type',
+ ('of_aggregate_stats_request', 'type'): 'ofp_type',
+ ('of_aggregate_stats_request', 'stats_type'): 'ofp_stats_type',
+ ('of_async_get_request', 'type'): 'ofp_type',
+ ('of_flow_stats_reply', 'type'): 'ofp_type',
+ ('of_flow_stats_reply', 'stats_type'): 'ofp_stats_type',
+ ('of_desc_stats_reply', 'type'): 'ofp_type',
+ ('of_desc_stats_reply', 'stats_type'): 'ofp_stats_type',
+ ('of_queue_stats_reply', 'type'): 'ofp_type',
+ ('of_queue_stats_reply', 'stats_type'): 'ofp_stats_type',
+ ('of_port_stats_reply', 'type'): 'ofp_type',
+ ('of_port_stats_reply', 'stats_type'): 'ofp_stats_type',
+ ('of_table_stats_reply', 'type'): 'ofp_type',
+ ('of_table_stats_reply', 'stats_type'): 'ofp_stats_type',
+ ('of_port_desc_stats_reply', 'type'): 'ofp_type',
+ ('of_port_desc_stats_reply', 'stats_type'): 'ofp_stats_type',
+ ('of_aggregate_stats_reply', 'type'): 'ofp_type',
+ ('of_aggregate_stats_reply', 'stats_type'): 'ofp_stats_type',
}
# Override oftype_to_base for certain field names
diff --git a/wireshark_gen/templates/_oftype_readers.lua b/wireshark_gen/templates/_oftype_readers.lua
index 4f5d7f9..9a5e4fa 100644
--- a/wireshark_gen/templates/_oftype_readers.lua
+++ b/wireshark_gen/templates/_oftype_readers.lua
@@ -81,6 +81,10 @@
end
end
+function read_of_port_name_t(reader, version, subtree, field_name)
+ read_scalar(reader, subtree, field_name, 16)
+end
+
function read_of_mac_addr_t(reader, version, subtree, field_name)
read_scalar(reader, subtree, field_name, 6)
end
@@ -106,10 +110,30 @@
return
end
- local list = subtree:add(fields[field_name], reader.peek_all(0))
- while not reader.is_empty() do
- local action_len = reader.peek(2, 2):uint()
- local child_reader = reader.slice(action_len)
+ local list_len = 0
+
+ if string.find(field_name,'packet_out') then
+ if version == 1 then
+ list_len = reader.peek(-2,2):uint()
+ else
+ list_len = reader.peek(-8,2):uint()
+ end
+ end
+
+ local list = nil
+ local reader2 = nil
+
+ if list_len == 0 then
+ list = subtree:add(fields[field_name], reader.peek_all(0))
+ reader2 = reader
+ else
+ list = subtree:add(fields[field_name], reader.peek(0, list_len))
+ reader2 = reader.slice(list_len)
+ end
+
+ while not reader2.is_empty() do
+ local action_len = reader2.peek(2, 2):uint()
+ local child_reader = reader2.slice(action_len)
local child_subtree = list:add(fields[field_name], child_reader.peek_all(0))
local info = dissect_of_action(child_reader, child_subtree, version)
child_subtree:set_text(info)
@@ -118,11 +142,91 @@
end
function read_list_of_port_desc_t(reader, version, subtree, field_name)
- -- TODO
+ if reader.is_empty() then
+ return
+ end
+ local list = subtree:add(fields[field_name], reader.peek_all(0))
+ list:set_text("List of port descriptions")
+ while not reader.is_empty() do
+ local port_desc_len = 64
+ local child_reader = reader.slice(port_desc_len)
+ local child_subtree = list:add(fields[field_name], child_reader.peek_all(0))
+ local info = dissect_of_port_desc(child_reader, child_subtree, version)
+ child_subtree:set_text(info)
+ end
+end
+
+function read_list_of_flow_stats_entry_t(reader, version, subtree, field_name)
+ if reader.is_empty() then
+ return
+ end
+ local list = subtree:add(fields[field_name], reader.peek_all(0))
+ list:set_text("List of flow stats entries")
+ while not reader.is_empty() do
+ local stats_len = reader.peek(0,2):uint()
+ local child_reader = reader.slice(stats_len)
+ local child_subtree = list:add(fields[field_name], child_reader.peek_all(0))
+ local info = dissect_of_flow_stats_entry(child_reader, child_subtree, version)
+ child_subtree:set_text(info)
+ end
+end
+
+function read_list_of_port_stats_entry_t(reader, version, subtree, field_name)
+ if reader.is_empty() then
+ return
+ end
+ local list = subtree:add(fields[field_name], reader.peek_all(0))
+ list:set_text("List of port stats entries")
+ while not reader.is_empty() do
+ local stats_len = 112
+ local child_reader = reader.slice(stats_len)
+ local child_subtree = list:add(fields[field_name], child_reader.peek_all(0))
+ local info = dissect_of_port_stats_entry(child_reader, child_subtree, version)
+ child_subtree:set_text(info)
+ end
+end
+
+function read_list_of_table_stats_entry_t(reader, version, subtree, field_name)
+ if reader.is_empty() then
+ return
+ end
+ local list = subtree:add(fields[field_name], reader.peek_all(0))
+ list:set_text("List of table stats entries")
+ while not reader.is_empty() do
+ local stats_len = 24
+ local child_reader = reader.slice(stats_len)
+ local child_subtree = list:add(fields[field_name], child_reader.peek_all(0))
+ local info = dissect_of_table_stats_entry(child_reader, child_subtree, version)
+ child_subtree:set_text(info)
+ end
+end
+
+function read_list_of_queue_stats_entry_t(reader, version, subtree, field_name)
+ if reader.is_empty() then
+ return
+ end
+ local list = subtree:add(fields[field_name], reader.peek_all(0))
+ list:set_text("List of flow stats entries")
+ while not reader.is_empty() do
+ local stats_len = 40
+ local child_reader = reader.slice(stats_len)
+ local child_subtree = list:add(fields[field_name], child_reader.peek_all(0))
+ local info = dissect_of_queue_stats_entry(child_reader, child_subtree, version)
+ child_subtree:set_text(info)
+ end
end
function read_list_of_packet_queue_t(reader, version, subtree, field_name)
-- TODO
+ read_of_octets_t()
+end
+
+function read_of_desc_str_t(reader, version, subtree, field_name)
+ read_scalar(reader, subtree, field_name, 256)
+end
+
+function read_of_serial_num_t(reader, version, subtree, field_name)
+ read_scalar(reader, subtree, field_name, 32)
end
function read_list_of_oxm_t(reader, version, subtree, field_name)
diff --git a/wireshark_gen/templates/openflow.lua b/wireshark_gen/templates/openflow.lua
index f2791d1..841e502 100644
--- a/wireshark_gen/templates/openflow.lua
+++ b/wireshark_gen/templates/openflow.lua
@@ -125,6 +125,48 @@
:: #endfor
}
+local of_port_desc_dissectors = {
+:: for version in ir:
+ [${version}] = dissect_of_port_desc_v${version},
+:: #endfor
+}
+
+local of_stats_reply_dissectors = {
+:: for version in ir:
+ [${version}] = of_stats_reply_v${version}_dissectors,
+:: #endfor
+}
+
+local of_stats_request_dissectors = {
+:: for version in ir:
+ [${version}] = of_stats_request_v${version}_dissectors,
+:: #endfor
+}
+
+local of_flow_stats_entry_dissectors = {
+:: for version in ir:
+ [${version}] = dissect_of_flow_stats_entry_v${version},
+:: #endfor
+}
+
+local of_port_stats_entry_dissectors = {
+:: for version in ir:
+ [${version}] = dissect_of_port_stats_entry_v${version},
+:: #endfor
+}
+
+local of_table_stats_entry_dissectors = {
+:: for version in ir:
+ [${version}] = dissect_of_table_stats_entry_v${version},
+:: #endfor
+}
+
+local of_queue_stats_entry_dissectors = {
+:: for version in ir:
+ [${version}] = dissect_of_queue_stats_entry_v${version},
+:: #endfor
+}
+
function dissect_of_message(buf, root)
local reader = OFReader.new(buf)
local subtree = root:add(p_of, buf(0))
@@ -137,7 +179,13 @@
end
local info = "unknown"
- if of_message_dissectors[version_val] and of_message_dissectors[version_val][type_val] then
+ if type_val == 19 then
+ local stats_type = buf(8,2):uint()
+ info = of_stats_reply_dissectors[version_val][stats_type](reader,subtree)
+ elseif type_val == 18 then
+ local stats_type = buf(8,2):uint()
+ info = of_stats_request_dissectors[version_val][stats_type](reader,subtree)
+ elseif of_message_dissectors[version_val] and of_message_dissectors[version_val][type_val] then
info = of_message_dissectors[version_val][type_val](reader, subtree)
end
@@ -183,6 +231,51 @@
return info
end
+function dissect_of_port_desc(reader, subtree, version_val)
+ local info = "unknown"
+ if of_port_desc_dissectors[version_val] then
+ info = of_port_desc_dissectors[version_val](reader, subtree)
+ end
+
+ return info
+end
+
+function dissect_of_flow_stats_entry(reader, subtree, version_val)
+ local info = "unknown"
+ if of_flow_stats_entry_dissectors[version_val] then
+ info = of_flow_stats_entry_dissectors[version_val](reader, subtree)
+ end
+
+ return info
+end
+
+function dissect_of_port_stats_entry(reader, subtree, version_val)
+ local info = "unknown"
+ if of_port_stats_entry_dissectors[version_val] then
+ info = of_port_stats_entry_dissectors[version_val](reader, subtree)
+ end
+
+ return info
+end
+
+function dissect_of_table_stats_entry(reader, subtree, version_val)
+ local info = "unknown"
+ if of_table_stats_entry_dissectors[version_val] then
+ info = of_table_stats_entry_dissectors[version_val](reader, subtree)
+ end
+
+ return info
+end
+
+function dissect_of_queue_stats_entry(reader, subtree, version_val)
+ local info = "unknown"
+ if of_queue_stats_entry_dissectors[version_val] then
+ info = of_queue_stats_entry_dissectors[version_val](reader, subtree)
+ end
+
+ return info
+end
+
-- of dissector function
function p_of.dissector (buf, pkt, root)
local offset = 0