5f789dc3f9a661c8dc84d74904b209e004bef215
[controller.git] / third-party / openflowj_netty / src / main / java / org / openflow / protocol / vendor / OFBasicVendorId.java
1 /**
2 *    Copyright 2011, Big Switch Networks, Inc. 
3 *    Originally created by David Erickson & Rob Sherwood, Stanford University
4
5 *    Licensed under the Apache License, Version 2.0 (the "License"); you may
6 *    not use this file except in compliance with the License. You may obtain
7 *    a copy of the License at
8 *
9 *         http://www.apache.org/licenses/LICENSE-2.0
10 *
11 *    Unless required by applicable law or agreed to in writing, software
12 *    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13 *    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14 *    License for the specific language governing permissions and limitations
15 *    under the License.
16 **/
17
18 package org.openflow.protocol.vendor;
19
20 import java.util.HashMap;
21 import java.util.Map;
22
23 import org.jboss.netty.buffer.ChannelBuffer;
24 import org.openflow.protocol.Instantiable;
25
26 /**
27  * Basic subclass of OFVendorId that works with any vendor data format where
28  * the data begins with an integral data type value.
29  * 
30  * @author Rob Vaterlaus (rob.vaterlaus@bigswitch.com)
31  */
32 public class OFBasicVendorId extends OFVendorId {
33     
34     /**
35      * The size of the data type value at the beginning of all vendor
36      * data associated with this vendor id. The data type size must be
37      * either 1, 2, 4 or 8.
38      */
39     protected int dataTypeSize;
40     
41     /**
42      * Map of the vendor data types that have been registered for this
43      * vendor id.
44      */
45     protected Map<Long, OFBasicVendorDataType> dataTypeMap =
46             new HashMap<Long, OFBasicVendorDataType>();
47     
48     /**
49      * Construct an OFVendorId that where the vendor data begins
50      * with a data type value whose size is dataTypeSize.
51      * @param id the id of the vendor, typically the OUI of a vendor
52      *     prefixed with 0.
53      * @param dataTypeSize the size of the integral data type value
54      *     at the beginning of the vendor data. The value must be the
55      *     size of an integeral data type (i.e. either 1,2,4 or 8).
56      */
57     public OFBasicVendorId(int id, int dataTypeSize) {
58         super(id);
59         assert (dataTypeSize == 1) || (dataTypeSize == 2) ||
60                (dataTypeSize == 4) || (dataTypeSize == 8);
61         this.dataTypeSize = dataTypeSize;
62     }
63
64     /**
65      * Get the size of the data type value at the beginning of the vendor
66      * data. OFBasicVendorId assumes that this value is common across all of
67      * the vendor data formats associated with a given vendor id.
68      * @return
69      */
70     public int getDataTypeSize() {
71         return dataTypeSize;
72     }
73     
74     /**
75      * Register a vendor data type with this vendor id.
76      * @param vendorDataType
77      */
78     public void registerVendorDataType(OFBasicVendorDataType vendorDataType) {
79         dataTypeMap.put(vendorDataType.getTypeValue(), vendorDataType);
80     }
81     
82     /**
83      * Lookup the OFVendorDataType instance that has been registered with
84      * this vendor id.
85      * 
86      * @param vendorDataType the integer code that was parsed from the 
87      * @return
88      */
89     public OFVendorDataType lookupVendorDataType(int vendorDataType) {
90         return dataTypeMap.get(Long.valueOf(vendorDataType));
91     }
92
93     /**
94      * This function parses enough of the data from the buffer to be able
95      * to determine the appropriate OFVendorDataType for the data. It is meant
96      * to be a reasonably generic implementation that will work for most
97      * formats of vendor extensions. If the vendor data doesn't fit the
98      * assumptions listed below, then this method will need to be overridden
99      * to implement custom parsing.
100      * 
101      * This implementation assumes that the vendor data begins with a data
102      * type code that is used to distinguish different formats of vendor
103      * data associated with a particular vendor ID.
104      * The exact format of the data is vendor-defined, so we don't know how
105      * how big the code is (or really even if there is a code). This code
106      * assumes that the common case will be that the data does include
107      * an initial type code (i.e. so that the vendor can have multiple
108      * message/data types) and that the size is either 1, 2 or 4 bytes.
109      * The size of the initial type code is configured by the subclass of
110      * OFVendorId.
111      * 
112      * @param data the channel buffer containing the vendor data.
113      * @param length the length to the end of the enclosing message
114      * @return the OFVendorDataType that can be used to instantiate the
115      *         appropriate subclass of OFVendorData.
116      */
117     public OFVendorDataType parseVendorDataType(ChannelBuffer data, int length) {
118         OFVendorDataType vendorDataType = null;
119         
120         // Parse out the type code from the vendor data.
121         long dataTypeValue = 0;
122         if ((length == 0) || (length >= dataTypeSize)) {
123             switch (dataTypeSize) {
124                 case 1:
125                     dataTypeValue = data.readByte();
126                     break;
127                 case 2:
128                     dataTypeValue = data.readShort();
129                     break;
130                 case 4:
131                     dataTypeValue = data.readInt();
132                     break;
133                 case 8:
134                     dataTypeValue = data.readLong();
135                     break;
136                 default:
137                     // This would be indicative of a coding error where the
138                     // dataTypeSize was specified incorrectly. This should have been
139                     // caught in the constructor for OFVendorId.
140                     assert false;
141             }
142             
143             vendorDataType = dataTypeMap.get(dataTypeValue);
144         }
145         
146         // If we weren't able to parse/map the data to a known OFVendorDataType,
147         // then map it to a generic vendor data type.
148         if (vendorDataType == null) {
149             vendorDataType = new OFBasicVendorDataType(dataTypeValue,
150                 new Instantiable<OFVendorData>() {
151                     @Override
152                     public OFVendorData instantiate() {
153                         return new OFByteArrayVendorData();
154                     }
155                 }
156             );
157         }
158         
159         return vendorDataType;
160     }
161
162 }