--- /dev/null
+/**
+* Copyright 2011, Big Switch Networks, Inc.
+* Originally created by David Erickson & Rob Sherwood, Stanford University
+*
+* Licensed under the Apache License, Version 2.0 (the "License"); you may
+* not use this file except in compliance with the License. You may obtain
+* a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+* License for the specific language governing permissions and limitations
+* under the License.
+**/
+
+package org.openflow.protocol.vendor;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.jboss.netty.buffer.ChannelBuffer;
+import org.openflow.protocol.Instantiable;
+
+/**
+ * Basic subclass of OFVendorId that works with any vendor data format where
+ * the data begins with an integral data type value.
+ *
+ * @author Rob Vaterlaus (rob.vaterlaus@bigswitch.com)
+ */
+public class OFBasicVendorId extends OFVendorId {
+
+ /**
+ * The size of the data type value at the beginning of all vendor
+ * data associated with this vendor id. The data type size must be
+ * either 1, 2, 4 or 8.
+ */
+ protected int dataTypeSize;
+
+ /**
+ * Map of the vendor data types that have been registered for this
+ * vendor id.
+ */
+ protected Map<Long, OFBasicVendorDataType> dataTypeMap =
+ new HashMap<Long, OFBasicVendorDataType>();
+
+ /**
+ * Construct an OFVendorId that where the vendor data begins
+ * with a data type value whose size is dataTypeSize.
+ * @param id the id of the vendor, typically the OUI of a vendor
+ * prefixed with 0.
+ * @param dataTypeSize the size of the integral data type value
+ * at the beginning of the vendor data. The value must be the
+ * size of an integeral data type (i.e. either 1,2,4 or 8).
+ */
+ public OFBasicVendorId(int id, int dataTypeSize) {
+ super(id);
+ assert (dataTypeSize == 1) || (dataTypeSize == 2) ||
+ (dataTypeSize == 4) || (dataTypeSize == 8);
+ this.dataTypeSize = dataTypeSize;
+ }
+
+ /**
+ * Get the size of the data type value at the beginning of the vendor
+ * data. OFBasicVendorId assumes that this value is common across all of
+ * the vendor data formats associated with a given vendor id.
+ * @return
+ */
+ public int getDataTypeSize() {
+ return dataTypeSize;
+ }
+
+ /**
+ * Register a vendor data type with this vendor id.
+ * @param vendorDataType
+ */
+ public void registerVendorDataType(OFBasicVendorDataType vendorDataType) {
+ dataTypeMap.put(vendorDataType.getTypeValue(), vendorDataType);
+ }
+
+ /**
+ * Lookup the OFVendorDataType instance that has been registered with
+ * this vendor id.
+ *
+ * @param vendorDataType the integer code that was parsed from the
+ * @return
+ */
+ public OFVendorDataType lookupVendorDataType(int vendorDataType) {
+ return dataTypeMap.get(Long.valueOf(vendorDataType));
+ }
+
+ /**
+ * This function parses enough of the data from the buffer to be able
+ * to determine the appropriate OFVendorDataType for the data. It is meant
+ * to be a reasonably generic implementation that will work for most
+ * formats of vendor extensions. If the vendor data doesn't fit the
+ * assumptions listed below, then this method will need to be overridden
+ * to implement custom parsing.
+ *
+ * This implementation assumes that the vendor data begins with a data
+ * type code that is used to distinguish different formats of vendor
+ * data associated with a particular vendor ID.
+ * The exact format of the data is vendor-defined, so we don't know how
+ * how big the code is (or really even if there is a code). This code
+ * assumes that the common case will be that the data does include
+ * an initial type code (i.e. so that the vendor can have multiple
+ * message/data types) and that the size is either 1, 2 or 4 bytes.
+ * The size of the initial type code is configured by the subclass of
+ * OFVendorId.
+ *
+ * @param data the channel buffer containing the vendor data.
+ * @param length the length to the end of the enclosing message
+ * @return the OFVendorDataType that can be used to instantiate the
+ * appropriate subclass of OFVendorData.
+ */
+ public OFVendorDataType parseVendorDataType(ChannelBuffer data, int length) {
+ OFVendorDataType vendorDataType = null;
+
+ // Parse out the type code from the vendor data.
+ long dataTypeValue = 0;
+ if ((length == 0) || (length >= dataTypeSize)) {
+ switch (dataTypeSize) {
+ case 1:
+ dataTypeValue = data.readByte();
+ break;
+ case 2:
+ dataTypeValue = data.readShort();
+ break;
+ case 4:
+ dataTypeValue = data.readInt();
+ break;
+ case 8:
+ dataTypeValue = data.readLong();
+ break;
+ default:
+ // This would be indicative of a coding error where the
+ // dataTypeSize was specified incorrectly. This should have been
+ // caught in the constructor for OFVendorId.
+ assert false;
+ }
+
+ vendorDataType = dataTypeMap.get(dataTypeValue);
+ }
+
+ // If we weren't able to parse/map the data to a known OFVendorDataType,
+ // then map it to a generic vendor data type.
+ if (vendorDataType == null) {
+ vendorDataType = new OFBasicVendorDataType(dataTypeValue,
+ new Instantiable<OFVendorData>() {
+ @Override
+ public OFVendorData instantiate() {
+ return new OFByteArrayVendorData();
+ }
+ }
+ );
+ }
+
+ return vendorDataType;
+ }
+
+}