Merge into master from pull request #79:
Fixes to java_gen (https://github.com/floodlight/loxigen/pull/79)
diff --git a/java_gen/java_model.py b/java_gen/java_model.py
index f30ab1b..f631483 100644
--- a/java_gen/java_model.py
+++ b/java_gen/java_model.py
@@ -140,7 +140,7 @@
class JavaModel(object):
# registry for enums that should not be generated
# set(${java_enum_name})
- enum_blacklist = set(("OFDefinitions", "OFPortNo",))
+ enum_blacklist = set(("OFDefinitions", "OFPortNo", "OFVlanId"))
# registry for enum *entry* that should not be generated
# map: ${java_enum_name} -> set(${java_entry_entry_name})
enum_entry_blacklist = defaultdict(lambda: set(), OFFlowWildcards=set([ "NW_DST_BITS", "NW_SRC_BITS", "NW_SRC_SHIFT", "NW_DST_SHIFT" ]))
diff --git a/java_gen/java_type.py b/java_gen/java_type.py
index 82510d2..f50d29a 100644
--- a/java_gen/java_type.py
+++ b/java_gen/java_type.py
@@ -227,7 +227,8 @@
# FIXME: This list needs to be pruned / cleaned up. Most of these are schematic.
u8 = JType('short', 'byte') \
- .op(read='bb.readByte()', write='bb.writeByte($name)')
+ .op(read='U8.f(bb.readByte())', write='bb.writeByte(U8.t($name))', pub_type=True) \
+ .op(read='bb.readByte()', write='bb.writeByte($name)', pub_type=False)
u8_list = JType('List<U8>') \
.op(read='ChannelUtils.readList(bb, $length, U8.READER)', write='ChannelUtils.writeList(bb, $name)')
u16 = JType('int', 'short') \
@@ -323,9 +324,9 @@
write="$name.write2Bytes(bb)",
default="EthType.NONE")
vlan_vid = JType("VlanVid")\
- .op(read="VlanVid.read2Bytes(bb)",
- write="$name.write2Bytes(bb)",
- default="VlanVid.NONE")
+ .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")
vlan_pcp = JType("VlanPcp")\
.op(read="VlanPcp.readByte(bb)",
write="$name.writeByte(bb)",
@@ -549,6 +550,10 @@
return JType("OFActionType", 'short') \
.op(read='bb.readShort()', write='bb.writeShort($name)', pub_type=False)\
.op(read="OFActionTypeSerializerVer$version.readFrom(bb)", write="OFActionTypeSerializerVer$version.writeTo(bb, $name)", pub_type=True)
+ elif field_name == "type" and re.match(r'of_instruction.*', obj_name):
+ return JType("OFInstructionType", 'short') \
+ .op(read='bb.readShort()', write='bb.writeShort($name)', pub_type=False)\
+ .op(read="OFInstructionTypeSerializerVer$version.readFrom(bb)", write="OFInstructionTypeSerializerVer$version.writeTo(bb, $name)", pub_type=True)
elif field_name == "table_id" and c_type == "uint8_t":
return table_id
elif field_name == "version" and c_type == "uint8_t":
diff --git a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/Metadata.java b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/ClassId.java
similarity index 73%
rename from java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/Metadata.java
rename to java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/ClassId.java
index 4764747..a6f2106 100644
--- a/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/Metadata.java
+++ b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/ClassId.java
@@ -5,23 +5,23 @@
import com.google.common.primitives.UnsignedInts;
@Immutable
-public class Metadata implements OFValueType<Metadata> {
+public class ClassId implements OFValueType<ClassId> {
static final int LENGTH = 4;
private final static int NONE_VAL = 0;
- public final static Metadata NONE = new Metadata(NONE_VAL);
+ public final static ClassId NONE = new ClassId(NONE_VAL);
private final int rawValue;
- private Metadata(final int rawValue) {
+ private ClassId(final int rawValue) {
this.rawValue = rawValue;
}
- public static Metadata of(final int raw) {
+ public static ClassId of(final int raw) {
if(raw == NONE_VAL)
return NONE;
- return new Metadata(raw);
+ return new ClassId(raw);
}
public int getInt() {
@@ -39,8 +39,8 @@
}
@Override
- public Metadata applyMask(Metadata mask) {
- return Metadata.of(rawValue & mask.rawValue); }
+ public ClassId applyMask(ClassId mask) {
+ return ClassId.of(rawValue & mask.rawValue); }
@Override
public int hashCode() {
@@ -58,14 +58,14 @@
return false;
if (getClass() != obj.getClass())
return false;
- Metadata other = (Metadata) obj;
+ ClassId other = (ClassId) obj;
if (rawValue != other.rawValue)
return false;
return true;
}
@Override
- public int compareTo(Metadata o) {
+ public int compareTo(ClassId o) {
return UnsignedInts.compare(rawValue, rawValue);
}
}
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 d6f65d5..6bd7581 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
@@ -5,15 +5,45 @@
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>
+ *
+ *
+ * @author Andreas Wundsam <andreas.wundsam@bigswitch.com>
+ *
+ */
public class VlanVid implements OFValueType<VlanVid> {
- private static final short VALIDATION_MASK = 0x0FFF;
+ 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 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);
+
+ /** for use with masking operations */
public static final VlanVid NO_MASK = new VlanVid((short)0xFFFF);
- public static final VlanVid FULL_MASK = VlanVid.of((short)0x0);
+ 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);
+ }
+ };
private final short vid;
@@ -21,14 +51,42 @@
this.vid = vid;
}
- public static VlanVid of(short vid) {
- if(vid == NONE_VAL)
- return NONE;
+ 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)
- throw new IllegalArgumentException("Illegal VLAN VID value: " + 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 the actual VLAN tag this vid identifies */
+ public short getVlan() {
+ return (short) (vid & VLAN_MASK);
+ }
+
@Override
public boolean equals(Object obj) {
if (!(obj instanceof VlanVid))
@@ -50,10 +108,11 @@
return "0x" + Integer.toHexString(vid);
}
- public short getValue() {
+ public short getRawVid() {
return vid;
}
+
@Override
public int getLength() {
return LENGTH;
@@ -79,13 +138,21 @@
c.writeShort(this.vid);
}
+ public void write2BytesOF10(ChannelBuffer c) {
+ c.writeShort(this.getVlan());
+ }
+
public static VlanVid read2Bytes(ChannelBuffer c) throws OFParseError {
- return VlanVid.of(c.readShort());
+ return VlanVid.ofRawVid(c.readShort());
+ }
+
+ public static VlanVid read2BytesOF10(ChannelBuffer c) throws OFParseError {
+ return VlanVid.ofVlanOF10(c.readShort());
}
@Override
public VlanVid applyMask(VlanVid mask) {
- return VlanVid.of((short)(this.vid & mask.vid));
+ return VlanVid.ofRawVid((short)(this.vid & mask.vid));
}
@Override
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
new file mode 100644
index 0000000..cb81d31
--- /dev/null
+++ b/java_gen/pre-written/src/main/java/org/projectfloodlight/openflow/types/VlanVidWithMask.java
@@ -0,0 +1,11 @@
+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/templates/of_class.java b/java_gen/templates/of_class.java
index aa68d04..8a8d09d 100644
--- a/java_gen/templates/of_class.java
+++ b/java_gen/templates/of_class.java
@@ -195,27 +195,30 @@
//:: elif prop.is_pad:
// pad: ${prop.length} bytes
bb.skipBytes(${prop.length});
-//:: 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)};
- if(${prop.name} != ${prop.priv_value})
- throw new OFParseError("Wrong ${prop.name}: Expected=${prop.enum_value}(${prop.value}), got="+${prop.name});
//:: elif prop.is_length_value:
- ${prop.java_type.public_type} ${prop.name} = ${prop.java_type.read_op(version, pub_type=False)};
+ ${prop.java_type.public_type} ${prop.name} = ${prop.java_type.read_op(version, pub_type=True)};
+ //:: if prop.is_fixed_value:
+ if(${prop.name} != ${prop.value})
+ throw new OFParseError("Wrong ${prop.name}: Expected=${prop.enum_value}(${prop.value}), got="+${prop.name});
+ //:: else:
if(${prop.name} < MINIMUM_LENGTH)
throw new OFParseError("Wrong ${prop.name}: Expected to be >= " + MINIMUM_LENGTH + ", was: " + ${prop.name});
-//:: elif prop.is_field_length_value:
-//:: fields_with_length_member[prop.member.field_name] = prop.name
- int ${prop.name} = ${prop.java_type.read_op(version, pub_type=False)};
-//:: else:
- // fixme: todo ${prop.name}
-//:: #endif
-//:: if prop.is_length_value or prop.is_field_length_value:
+ //:: #endif
if(bb.readableBytes() + (bb.readerIndex() - start) < ${prop.name}) {
// Buffer does not have all data yet
bb.readerIndex(start);
return null;
}
+//:: 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)};
+ if(${prop.name} != ${prop.priv_value})
+ throw new OFParseError("Wrong ${prop.name}: Expected=${prop.enum_value}(${prop.value}), got="+${prop.name});
+//:: elif prop.is_field_length_value:
+//:: fields_with_length_member[prop.member.field_name] = prop.name
+ ${prop.java_type.public_type} ${prop.name} = ${prop.java_type.read_op(version, pub_type=True)};
+//:: else:
+ // fixme: todo ${prop.name}
//:: #endif
//:: #endfor
//:: if msg.align: