package net.floodlightcontroller.core.internal; import java.util.List; import org.projectfloodlight.openflow.protocol.OFTableFeatureProp; import org.projectfloodlight.openflow.protocol.OFTableFeaturePropApplyActions; import org.projectfloodlight.openflow.protocol.OFTableFeaturePropApplyActionsMiss; import org.projectfloodlight.openflow.protocol.OFTableFeaturePropApplySetfield; import org.projectfloodlight.openflow.protocol.OFTableFeaturePropApplySetfieldMiss; import org.projectfloodlight.openflow.protocol.OFTableFeaturePropExperimenter; import org.projectfloodlight.openflow.protocol.OFTableFeaturePropExperimenterMiss; import org.projectfloodlight.openflow.protocol.OFTableFeaturePropInstructions; import org.projectfloodlight.openflow.protocol.OFTableFeaturePropInstructionsMiss; import org.projectfloodlight.openflow.protocol.OFTableFeaturePropMatch; import org.projectfloodlight.openflow.protocol.OFTableFeaturePropNextTables; import org.projectfloodlight.openflow.protocol.OFTableFeaturePropNextTablesMiss; import org.projectfloodlight.openflow.protocol.OFTableFeaturePropTableSyncFrom; import org.projectfloodlight.openflow.protocol.OFTableFeaturePropType; import org.projectfloodlight.openflow.protocol.OFTableFeaturePropWildcards; import org.projectfloodlight.openflow.protocol.OFTableFeaturePropWriteActions; import org.projectfloodlight.openflow.protocol.OFTableFeaturePropWriteActionsMiss; import org.projectfloodlight.openflow.protocol.OFTableFeaturePropWriteSetfield; import org.projectfloodlight.openflow.protocol.OFTableFeaturePropWriteSetfieldMiss; import org.projectfloodlight.openflow.protocol.OFTableFeatures; import org.projectfloodlight.openflow.protocol.ver13.OFTableFeaturePropTypeSerializerVer13; import org.projectfloodlight.openflow.protocol.ver14.OFTableFeaturePropTypeSerializerVer14; import org.projectfloodlight.openflow.types.TableId; import org.projectfloodlight.openflow.types.U64; /** * A small, immutable container for organizing the features of a * particular table on a switch. OFTableFeatures is pretty much the * same, but it doesn't easily expose the properties for quick access. * * This class will sacrifice the added time to instantiate instead * of during each access to a particular property. Had the properties * been in a Map of some sort, this might not be necessary. The * assumption is that we won't ever change switch table properties * frequently. It's more of a setup/initialization task. Otherwise, * frequently making these would be quite inefficient considering * the amount of data within and the number of tables switches can have. * * <b> FIXME: OFTableFeatureProp types don't override equals in Loxi... </b> * * @author Ryan Izard, rizard@g.clemson.edu, ryan.izard@bigswitch.com * */ public class TableFeatures { /* OF1.3+ */ private OFTableFeaturePropApplyActions aa; private OFTableFeaturePropApplyActionsMiss aam; private OFTableFeaturePropApplySetfield asf; private OFTableFeaturePropApplySetfieldMiss asfm; private OFTableFeaturePropExperimenter e; private OFTableFeaturePropExperimenterMiss em; private OFTableFeaturePropInstructions i; private OFTableFeaturePropInstructionsMiss im; private OFTableFeaturePropMatch m; private OFTableFeaturePropNextTables nt; private OFTableFeaturePropNextTablesMiss ntm; private OFTableFeaturePropWildcards w; private OFTableFeaturePropWriteActions wa; private OFTableFeaturePropWriteActionsMiss wam; private OFTableFeaturePropWriteSetfield wsf; private OFTableFeaturePropWriteSetfieldMiss wsfm; /* OF1.4+ */ private OFTableFeaturePropTableSyncFrom tsf; private long config; private long maxEntries; private U64 metadataMatch; private U64 metadataWrite; private String tableName; private TableId tableId; /* * Loxi-style constructor for familiarity. Also eliminates * the need to use the new keyword. */ public static TableFeatures of(OFTableFeatures tableFeatures) { return new TableFeatures(tableFeatures); } /* * Make default constructor inaccessible. We don't set default * values so, we must start with an OFTableFeatures. */ private TableFeatures() {} /* * Called from of(OFTableFeatures tableFeatures) above. * Private to avoid confusion. */ private TableFeatures(OFTableFeatures tf) { /* * First, get the properties. */ List<OFTableFeatureProp> properties = tf.getProperties(); for (OFTableFeatureProp p : properties) { OFTableFeaturePropType pt = getTableFeaturePropType(p); switch (pt) { case APPLY_ACTIONS: aa = (OFTableFeaturePropApplyActions) p; break; case APPLY_ACTIONS_MISS: aam = (OFTableFeaturePropApplyActionsMiss) p; break; case APPLY_SETFIELD: asf = (OFTableFeaturePropApplySetfield) p; break; case APPLY_SETFIELD_MISS: asfm = (OFTableFeaturePropApplySetfieldMiss) p; break; case EXPERIMENTER: e = (OFTableFeaturePropExperimenter) p; break; case EXPERIMENTER_MISS: em = (OFTableFeaturePropExperimenterMiss) p; break; case INSTRUCTIONS: i = (OFTableFeaturePropInstructions) p; break; case INSTRUCTIONS_MISS: im = (OFTableFeaturePropInstructionsMiss) p; break; case MATCH: m = (OFTableFeaturePropMatch) p; break; case NEXT_TABLES: nt = (OFTableFeaturePropNextTables) p; break; case NEXT_TABLES_MISS: ntm = (OFTableFeaturePropNextTablesMiss) p; break; case TABLE_SYNC_FROM: tsf = (OFTableFeaturePropTableSyncFrom) p; break; case WILDCARDS: w = (OFTableFeaturePropWildcards) p; break; case WRITE_ACTIONS: wa = (OFTableFeaturePropWriteActions) p; break; case WRITE_ACTIONS_MISS: wam = (OFTableFeaturePropWriteActionsMiss) p; break; case WRITE_SETFIELD: wsf = (OFTableFeaturePropWriteSetfield) p; break; case WRITE_SETFIELD_MISS: wsfm = (OFTableFeaturePropWriteSetfieldMiss) p; break; default: throw new UnsupportedOperationException("OFTableFeaturePropType " + pt.toString() + " not accounted for in " + this.getClass().getCanonicalName()); } } /* * Next, get the other info e.g. name, ID, etc. */ config = tf.getConfig(); maxEntries = tf.getMaxEntries(); metadataMatch = tf.getMetadataMatch(); metadataWrite = tf.getMetadataWrite(); tableId = tf.getTableId(); tableName = tf.getName(); } /* * Internal helper function to deserialize the property type in a version-agnostic way * from the perspective of the calling function. */ private static OFTableFeaturePropType getTableFeaturePropType(OFTableFeatureProp p) { switch (p.getVersion()) { case OF_13: return OFTableFeaturePropTypeSerializerVer13.ofWireValue((short) p.getType()); case OF_14: return OFTableFeaturePropTypeSerializerVer14.ofWireValue((short) p.getType()); default: throw new IllegalArgumentException("OFVersion " + p.getVersion().toString() + " does not support OFTableFeature messages."); } } public long getConfig() { return config; } public long getMaxEntries() { return maxEntries; } public U64 getMetadataMatch() { return metadataMatch; } public U64 getMetadataWrite() { return metadataWrite; } public String getTableName() { return tableName; } public TableId getTableId() { return tableId; } public OFTableFeaturePropApplyActions getPropApplyActions() { return aa; } public OFTableFeaturePropApplyActionsMiss getPropApplyActionsMiss() { return aam; } public OFTableFeaturePropApplySetfield getPropApplySetField() { return asf; } public OFTableFeaturePropApplySetfieldMiss getPropApplySetFieldMiss() { return asfm; } public OFTableFeaturePropExperimenter getPropExperimenter() { return e; } public OFTableFeaturePropExperimenterMiss getPropExperimenterMiss() { return em; } public OFTableFeaturePropInstructions getPropInstructions() { return i; } public OFTableFeaturePropInstructionsMiss getPropInstructionsMiss() { return im; } public OFTableFeaturePropMatch getPropMatch() { return m; } public OFTableFeaturePropNextTables getPropNextTables() { return nt; } public OFTableFeaturePropNextTablesMiss getPropNextTablesMiss() { return ntm; } public OFTableFeaturePropWildcards getPropWildcards() { return w; } public OFTableFeaturePropWriteActions getPropWriteActions() { return wa; } public OFTableFeaturePropWriteActionsMiss getPropWriteActionsMiss() { return wam; } public OFTableFeaturePropWriteSetfield getPropWriteSetField() { return wsf; } public OFTableFeaturePropWriteSetfieldMiss getPropWriteSetFieldMiss() { return wsfm; } public OFTableFeaturePropTableSyncFrom getPropTableSyncFrom() { return tsf; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((aa == null) ? 0 : aa.hashCode()); result = prime * result + ((aam == null) ? 0 : aam.hashCode()); result = prime * result + ((asf == null) ? 0 : asf.hashCode()); result = prime * result + ((asfm == null) ? 0 : asfm.hashCode()); result = prime * result + (int) (config ^ (config >>> 32)); result = prime * result + ((e == null) ? 0 : e.hashCode()); result = prime * result + ((em == null) ? 0 : em.hashCode()); result = prime * result + ((i == null) ? 0 : i.hashCode()); result = prime * result + ((im == null) ? 0 : im.hashCode()); result = prime * result + ((m == null) ? 0 : m.hashCode()); result = prime * result + (int) (maxEntries ^ (maxEntries >>> 32)); result = prime * result + ((metadataMatch == null) ? 0 : metadataMatch.hashCode()); result = prime * result + ((metadataWrite == null) ? 0 : metadataWrite.hashCode()); result = prime * result + ((nt == null) ? 0 : nt.hashCode()); result = prime * result + ((ntm == null) ? 0 : ntm.hashCode()); result = prime * result + ((tableId == null) ? 0 : tableId.hashCode()); result = prime * result + ((tableName == null) ? 0 : tableName.hashCode()); result = prime * result + ((tsf == null) ? 0 : tsf.hashCode()); result = prime * result + ((w == null) ? 0 : w.hashCode()); result = prime * result + ((wa == null) ? 0 : wa.hashCode()); result = prime * result + ((wam == null) ? 0 : wam.hashCode()); result = prime * result + ((wsf == null) ? 0 : wsf.hashCode()); result = prime * result + ((wsfm == null) ? 0 : wsfm.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; TableFeatures other = (TableFeatures) obj; if (aa == null) { if (other.aa != null) return false; } else if (!aa.equals(other.aa)) return false; if (aam == null) { if (other.aam != null) return false; } else if (!aam.equals(other.aam)) return false; if (asf == null) { if (other.asf != null) return false; } else if (!asf.equals(other.asf)) return false; if (asfm == null) { if (other.asfm != null) return false; } else if (!asfm.equals(other.asfm)) return false; if (config != other.config) return false; if (e == null) { if (other.e != null) return false; } else if (!e.equals(other.e)) return false; if (em == null) { if (other.em != null) return false; } else if (!em.equals(other.em)) return false; if (i == null) { if (other.i != null) return false; } else if (!i.equals(other.i)) return false; if (im == null) { if (other.im != null) return false; } else if (!im.equals(other.im)) return false; if (m == null) { if (other.m != null) return false; } else if (!m.equals(other.m)) return false; if (maxEntries != other.maxEntries) return false; if (metadataMatch == null) { if (other.metadataMatch != null) return false; } else if (!metadataMatch.equals(other.metadataMatch)) return false; if (metadataWrite == null) { if (other.metadataWrite != null) return false; } else if (!metadataWrite.equals(other.metadataWrite)) return false; if (nt == null) { if (other.nt != null) return false; } else if (!nt.equals(other.nt)) return false; if (ntm == null) { if (other.ntm != null) return false; } else if (!ntm.equals(other.ntm)) return false; if (tableId == null) { if (other.tableId != null) return false; } else if (!tableId.equals(other.tableId)) return false; if (tableName == null) { if (other.tableName != null) return false; } else if (!tableName.equals(other.tableName)) return false; if (tsf == null) { if (other.tsf != null) return false; } else if (!tsf.equals(other.tsf)) return false; if (w == null) { if (other.w != null) return false; } else if (!w.equals(other.w)) return false; if (wa == null) { if (other.wa != null) return false; } else if (!wa.equals(other.wa)) return false; if (wam == null) { if (other.wam != null) return false; } else if (!wam.equals(other.wam)) return false; if (wsf == null) { if (other.wsf != null) return false; } else if (!wsf.equals(other.wsf)) return false; if (wsfm == null) { if (other.wsfm != null) return false; } else if (!wsfm.equals(other.wsfm)) return false; return true; } @Override public String toString() { return "TableFeatures [TableName=" + tableName + ", TableId=" + tableId + ", Config=" + config + ", MaxEntries=" + maxEntries + ", MetadataMatch=" + metadataMatch + ", MetadataWrite=" + metadataWrite + ", ApplyActions=" + aa + ", ApplyActionsMiss=" + aam + ", ApplySetField=" + asf + ", ApplySetFieldMiss=" + asfm + ", Experimenter=" + e + ", ExperimenterMiss=" + em + ", Instructions=" + i + ", InstructionsMiss=" + im + ", Match=" + m + ", NextTable=" + nt + ", NextTableMiss=" + ntm + ", Wildcards=" + w + ", WriteActions=" + wa + ", WriteActionsMiss=" + wam + ", WriteSetField=" + wsf + ", WriteSetFieldMiss=" + wsfm + ", TableSyncFrom=" + tsf + "]"; } }