/** * 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; } }