Implementation of the Match porcelain interface for OF version 1.3:
1. Renamed ENUM values in MatchFields to conform with the OF spec to allow unified code generation.
2. Extended OFOxms factory with methods for creating OXM objects from a given field and value. This code is automatically generated from the oxm_map in java_model.
3. Implemented OFMatchV3Ver13.java custom template.
4. Implemented OFMatchV3Ver13.Builder.java custom template.
Tested new implementation on demo controller and it works.
diff --git a/java_gen/templates/custom/OFMatchV3Ver13.Builder.java b/java_gen/templates/custom/OFMatchV3Ver13.Builder.java
index 81e8d4e..b5fa630 100644
--- a/java_gen/templates/custom/OFMatchV3Ver13.Builder.java
+++ b/java_gen/templates/custom/OFMatchV3Ver13.Builder.java
@@ -1,73 +1,108 @@
- @Override
- public <F extends OFValueType<F>> F get(MatchField<F> field)
- throws UnsupportedOperationException {
- // FIXME yotam - please replace with real implementation
- return null;
+ private OFOxmList.Builder oxmListBuilder;
+
+ private synchronized void initBuilder() {
+ if (oxmListBuilder != null)
+ return;
+ oxmListBuilder = new OFOxmList.Builder();
+ }
+
+ private synchronized void updateOxmList() {
+ this.oxmList = this.oxmListBuilder.build();
+ this.oxmListSet = true;
+ }
+
+ private <F extends OFValueType<F>> OFOxm<F> getOxm(MatchField<F> field) {
+//:: if has_parent:
+ return this.oxmListSet ? this.oxmList.get(field) : parentMessage.oxmList.get(field);
+//:: else:
+ return this.oxmListSet ? this.oxmList.get(field) : null;
+//:: #endif
}
@Override
- public <F extends OFValueType<F>> Masked<F> getMasked(MatchField<F> field)
+ public synchronized <F extends OFValueType<F>> F get(MatchField<F> field)
throws UnsupportedOperationException {
- // FIXME yotam - please replace with real implementation
- return null;
+ OFOxm<F> value = getOxm(field);
+ if (value == null)
+ return null;
+ return value.getValue();
+ }
+
+ @Override
+ public synchronized <F extends OFValueType<F>> Masked<F> getMasked(MatchField<F> field)
+ throws UnsupportedOperationException {
+ OFOxm<F> value = getOxm(field);
+ if (value == null || !value.isMasked())
+ return null;
+ // TODO: If changing OXMs to extend Masked, then use it here
+ return Masked.of(value.getValue(), value.getMask());
}
@Override
public boolean supports(MatchField<?> field) {
- // FIXME yotam - please replace with real implementation
- return false;
+ return supportsField(field);
}
@Override
public boolean supportsMasked(MatchField<?> field) {
- // FIXME yotam - please replace with real implementation
- return false;
+ return supportsField(field);
}
@Override
- public boolean isExact(MatchField<?> field) {
- // FIXME yotam - please replace with real implementation
- return false;
+ public synchronized boolean isExact(MatchField<?> field) {
+ OFOxm<?> value = getOxm(field);
+ return (value != null && !value.isMasked());
}
@Override
- public boolean isFullyWildcarded(MatchField<?> field) {
- // FIXME yotam - please replace with real implementation
- return false;
+ public synchronized boolean isFullyWildcarded(MatchField<?> field) {
+ OFOxm<?> value = getOxm(field);
+ return (value == null);
}
@Override
- public boolean isPartiallyMasked(MatchField<?> field) {
- // FIXME yotam - please replace with real implementation
- return false;
+ public synchronized boolean isPartiallyMasked(MatchField<?> field) {
+ OFOxm<?> value = getOxm(field);
+ return (value != null && value.isMasked());
}
@Override
- public <F extends OFValueType<F>> Match.Builder setExact(
+ public synchronized <F extends OFValueType<F>> Match.Builder setExact(
MatchField<F> field, F value) {
- // FIXME yotam - please replace with real implementation
- return null;
+ initBuilder();
+ OFOxm<F> oxm = OFFactories.getFactory(OFVersion.OF_13).oxms().fromValue(value, field);
+ this.oxmListBuilder.set(oxm);
+ updateOxmList();
+ return this;
}
@Override
- public <F extends OFValueType<F>> Match.Builder setMasked(
+ public synchronized <F extends OFValueType<F>> Match.Builder setMasked(
MatchField<F> field, F value, F mask) {
- // FIXME yotam - please replace with real implementation
- return null;
+ initBuilder();
+ OFOxm<F> oxm = OFFactories.getFactory(OFVersion.OF_13).oxms().fromValueAndMask(value, mask, field);
+ this.oxmListBuilder.set(oxm);
+ updateOxmList();
+ return this;
}
@Override
- public <F extends OFValueType<F>> Match.Builder setMasked(
+ public synchronized <F extends OFValueType<F>> Match.Builder setMasked(
MatchField<F> field, Masked<F> valueWithMask) {
- // FIXME yotam - please replace with real implementation
- return null;
+ initBuilder();
+ OFOxm<F> oxm = OFFactories.getFactory(OFVersion.OF_13).oxms().fromMasked(valueWithMask, field);
+ this.oxmListBuilder.set(oxm);
+ updateOxmList();
+ return this;
}
@Override
- public <F extends OFValueType<F>> Match.Builder wildcard(MatchField<F> field) {
- // FIXME yotam - please replace with real implementation
- return null;
+ public synchronized <F extends OFValueType<F>> Match.Builder wildcard(MatchField<F> field) {
+ initBuilder();
+ this.oxmListBuilder.unset(field);
+ updateOxmList();
+ return this;
}
@Override
@@ -77,6 +112,6 @@
@Override
public void writeTo(ChannelBuffer bb) {
- // FIXME yotam - please replace with real implementation
- }
-
+ // TODO: What should this write?
+ throw new UnsupportedOperationException("Builder cannot be written");
+ }
\ No newline at end of file
diff --git a/java_gen/templates/custom/OFMatchV3Ver13.java b/java_gen/templates/custom/OFMatchV3Ver13.java
index ec7bfcc..a4cc51c 100644
--- a/java_gen/templates/custom/OFMatchV3Ver13.java
+++ b/java_gen/templates/custom/OFMatchV3Ver13.java
@@ -2,43 +2,108 @@
@Override
public <F extends OFValueType<F>> F get(MatchField<F> field)
throws UnsupportedOperationException {
- // FIXME yotam - please replace with real implementation
- return null;
+ if (!supports(field))
+ throw new UnsupportedOperationException("OFMatchV3Ver13 does not support matching on field " + field.getName());
+
+ OFOxm<F> oxm = this.oxmList.get(field);
+
+ if (oxm == null || !field.arePrerequisitesOK(this))
+ return null;
+
+ return oxm.getValue();
}
@Override
public <F extends OFValueType<F>> Masked<F> getMasked(MatchField<F> field)
throws UnsupportedOperationException {
- // FIXME yotam - please replace with real implementation
- return null;
+ if (!supportsMasked(field))
+ throw new UnsupportedOperationException("OFMatchV3Ver13 does not support masked matching on field " + field.getName());
+
+ OFOxm<F> oxm = this.oxmList.get(field);
+
+ if (oxm == null || !field.arePrerequisitesOK(this))
+ return null;
+
+ if (oxm.getMask() == null)
+ return null;
+
+ // TODO: Make OfOxm extend Masked and just return the OXM?
+ return Masked.of(oxm.getValue(), oxm.getMask());
+ }
+
+ private static boolean supportsField(MatchField<?> field) {
+ switch (field.id) {
+ case IN_PORT:
+ case IN_PHY_PORT:
+ case METADATA:
+ case ETH_DST:
+ case ETH_SRC:
+ case ETH_TYPE:
+ case VLAN_VID:
+ case VLAN_PCP:
+ case IP_DSCP:
+ case IP_ECN:
+ case IP_PROTO:
+ case IPV4_SRC:
+ case IPV4_DST:
+ case TCP_SRC:
+ case TCP_DST:
+ case UDP_SRC:
+ case UDP_DST:
+ case SCTP_SRC:
+ case SCTP_DST:
+ case ICMPV4_TYPE:
+ case ICMPV4_CODE:
+ case ARP_OP:
+ case ARP_SPA:
+ case ARP_TPA:
+ case ARP_SHA:
+ case ARP_THA:
+ case IPV6_SRC:
+ case IPV6_DST:
+ case IPV6_FLABEL:
+ return true;
+ default:
+ return false;
+ }
}
@Override
public boolean supports(MatchField<?> field) {
- // FIXME yotam - please replace with real implementation
- return false;
+ return supportsField(field);
}
@Override
public boolean supportsMasked(MatchField<?> field) {
- // FIXME yotam - please replace with real implementation
- return false;
+ return supportsField(field);
}
@Override
public boolean isExact(MatchField<?> field) {
- // FIXME yotam - please replace with real implementation
- return false;
+ if (!supports(field))
+ throw new UnsupportedOperationException("OFMatchV3Ver13 does not support matching on field " + field.getName());
+
+ OFOxm<?> oxm = this.oxmList.get(field);
+
+ return oxm != null && !oxm.isMasked();
}
@Override
public boolean isFullyWildcarded(MatchField<?> field) {
- // FIXME yotam - please replace with real implementation
- return false;
+ if (!supports(field))
+ throw new UnsupportedOperationException("OFMatchV3Ver13 does not support matching on field " + field.getName());
+
+ OFOxm<?> oxm = this.oxmList.get(field);
+
+ return oxm == null;
}
@Override
public boolean isPartiallyMasked(MatchField<?> field) {
- // FIXME yotam - please replace with real implementation
- return false;
- }
+ if (!supports(field))
+ throw new UnsupportedOperationException("OFMatchV3Ver13 does not support matching on field " + field.getName());
+
+ OFOxm<?> oxm = this.oxmList.get(field);
+
+ return oxm != null && oxm.isMasked();
+ }
\ No newline at end of file
diff --git a/java_gen/templates/of_class.java b/java_gen/templates/of_class.java
index bcaf961..4ea6ac9 100644
--- a/java_gen/templates/of_class.java
+++ b/java_gen/templates/of_class.java
@@ -106,7 +106,7 @@
);
}
//:: if os.path.exists("%s/custom/%s.Builder.java" % (template_dir, msg.name)):
- //:: include("custom/%s.Builder.java" % msg.name, msg=msg)
+ //:: include("custom/%s.Builder.java" % msg.name, msg=msg, has_parent=True)
//:: #endif
}
@@ -129,7 +129,7 @@
);
}
//:: if os.path.exists("%s/custom/%s.Builder.java" % (template_dir, msg.name)):
- //:: include("custom/%s.Builder.java" % msg.name, msg=msg)
+ //:: include("custom/%s.Builder.java" % msg.name, msg=msg, has_parent=False)
//:: #endif
}
diff --git a/java_gen/templates/of_factory_class.java b/java_gen/templates/of_factory_class.java
index e83344b..503c492 100644
--- a/java_gen/templates/of_factory_class.java
+++ b/java_gen/templates/of_factory_class.java
@@ -85,4 +85,60 @@
//:: #endif
}
+//:: if factory.interface.name == 'OFOxms':
+ @SuppressWarnings("unchecked")
+ public <F extends OFValueType<F>> OFOxm<F> fromValue(F value, MatchField<F> field) {
+ switch (field.id) {
+ //:: for oxm_name in model.oxm_map:
+ //:: type_name, value, masked = model.oxm_map[oxm_name]
+ //:: if masked:
+ //:: continue
+ //:: #endif
+ //:: method_name = oxm_name.replace('OFOxm', '')
+ //:: method_name = method_name[0].lower() + method_name[1:]
+ case ${value}:
+ return (OFOxm<F>)${method_name}((${type_name})value);
+ //:: #endfor
+ default:
+ return null;
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ public <F extends OFValueType<F>> OFOxm<F> fromValueAndMask(F value, F mask, MatchField<F> field) {
+ switch (field.id) {
+ //:: for oxm_name in model.oxm_map:
+ //:: type_name, value, masked = model.oxm_map[oxm_name]
+ //:: if not masked:
+ //:: continue
+ //:: #endif
+ //:: method_name = oxm_name.replace('OFOxm', '')
+ //:: method_name = method_name[0].lower() + method_name[1:]
+ case ${value}:
+ return (OFOxm<F>)${method_name}((${type_name})value, (${type_name})mask);
+ //:: #endfor
+ default:
+ return null;
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ public <F extends OFValueType<F>> OFOxm<F> fromMasked(Masked<F> masked, MatchField<F> field) {
+ switch (field.id) {
+ //:: for oxm_name in model.oxm_map:
+ //:: type_name, value, masked = model.oxm_map[oxm_name]
+ //:: if not masked:
+ //:: continue
+ //:: #endif
+ //:: method_name = oxm_name.replace('OFOxm', '')
+ //:: method_name = method_name[0].lower() + method_name[1:]
+ case ${value}:
+ return (OFOxm<F>)${method_name}((${type_name})(masked.getValue()), (${type_name})(masked.getMask()));
+ //:: #endfor
+ default:
+ return null;
+ }
+ }
+//:: #endif
+
}
diff --git a/java_gen/templates/of_factory_interface.java b/java_gen/templates/of_factory_interface.java
index fcb690f..329539f 100644
--- a/java_gen/templates/of_factory_interface.java
+++ b/java_gen/templates/of_factory_interface.java
@@ -54,4 +54,10 @@
//:: #endfor
OFMessageReader<${factory.base_class}> getReader();
+
+//:: if factory.name == 'OFOxms':
+ public <F extends OFValueType<F>> OFOxm<F> fromValue(F value, MatchField<F> field);
+ public <F extends OFValueType<F>> OFOxm<F> fromValueAndMask(F value, F mask, MatchField<F> field);
+ public <F extends OFValueType<F>> OFOxm<F> fromMasked(Masked<F> masked, MatchField<F> field);
+//:: #endif
}