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