Changes between Version 7 and Version 8 of Internal/OpenFlow/VendorTutorial


Ignore:
Timestamp:
Jan 2, 2013, 10:17:34 PM (12 years ago)
Author:
akoshibe
Comment:

Legend:

Unmodified
Added
Removed
Modified
  • Internal/OpenFlow/VendorTutorial

    v7 v8  
    44We'll mostly use snippets of the Nicira vendor messages, found in org.openflow.vendor.nicira of the Floodlight source, as working examples in this page. The Nicira extensions add !OpenFlow role features, introduced in !OpenFlow v1.2, to the v1.0 protocol used in Floodlight.
    55
    6 == 1. Overview: The Vendor Message ==
     6== 1. Overview: The Vendor Message == #intro
    77!OpenFlow provides a vendor message type as a way to offer third parties a way to customize the protocol without going out of spec. Although called the "Vendor message", this message type provides a handy way for a developer to implement and test out experimental features without wantonly modifying the protocol.
    88
     
    4444     * at the beginning of the vendor data
    4545     */
    46     protected int dataType;         
     46    protected int dataType;                          (1)       
    4747...
    4848}}}
    49 This class is extended to implement the Request and Reply message types (`OFRoleRequestVendorData` and `OFRoleReplyVendorData`, respectively). Note how the value of dataType is not set here - this value is set with the values declared in each subclass, as we can see here in    `OFRoleReplyVendorData`:
    50 {{{
    51     /**
    52      * The data type value for a role reply
    53      */
    54     public static final int NXT_ROLE_REPLY = 11;
    55 
    56     /**
    57      * Construct a role reply vendor data with an unspecified role value.
    58      */
    59     public OFRoleReplyVendorData() {
    60         super(NXT_ROLE_REPLY);
    61     }
    62 }}}
    63 super() refers to `OFRoleVendorData`, a subclass of `OFNiciraVendorData`. Tracing back a step further, we end up in `OFNiciraVendorData` whose constructor sets the value of dataType:
     49This class is extended to implement the Request and Reply message types (`OFRoleRequestVendorData` and `OFRoleReplyVendorData`, respectively). Note how at (1) the value of dataType is not set here - this value is set through the base class's constructor, which takes a integer value for the !dataType:
    6450{{{
    6551   /**
     
    7157    }
    7258}}}
     59The values passed to this constructor are declared in each subclass that represents a message type, as we can see here in `OFRoleReplyVendorData`:
     60{{{
     61    /**
     62     * The data type value for a role reply
     63     */
     64    public static final int NXT_ROLE_REPLY = 11;     
     65
     66    /**
     67     * Construct a role reply vendor data with an unspecified role value.
     68     */
     69    public OFRoleReplyVendorData() {
     70        super(NXT_ROLE_REPLY);               
     71    }
     72}}}
     73If we trace back, we learn that super() above refers to the constructor of `OFRoleVendorData`, a subclass of `OFNiciraVendorData`. `OFRoleVendorData` takes the value passed to it by `OFRoleReplyVendorData` and passes it to the constructor of its parent class.
     74
     75This organization isn't a requirement, but makes code reuse easier. The "nesting" of message classes can be thought of as implementing the message structure in layers - Each subclass implements message components that are encapsulated by components implemented in its parent class.   
    7376
    7477The Vendor ID and data type are the only requirements in terms of vendor header content. Given that the methods required by `OFVendorData` are provided, along with those required for message registration, the message implementation may be structured as needed. The usual additions are various message fields and their getters and setters. 
    7578
    7679=== 2.2 Message Registration ===
    77 As expected from the variable structure of vendor messages, a given vendor message must be registered before openflowj can handle it properly. Registration is a two step process:
     80As expected from the variable structure of vendor messages, a given vendor message must be registered with openflowj before it can handle your messages properly. Registration is a two step process:
    7881
    7982 1. Vendor ID registration
     
    105108Where, as seen earlier, NXT_ROLE_REQUEST and NXT_ROLE_REPLY are the request and reply data type values for the two Nicira vendor message data types.
    106109
    107 There are several things to point out here:
     110There are two things to point out here:
    108111 1. Since vendor IDs may vary in length, we indicate the length in bytes that the vendor ID is when we instantiate the OFBasicVendorId. In (1) we provide the constructor with the value 4 along with the actual Vendor ID, indicating that the Nicira vendor ID is an integer (4 bytes long).
    109112 
    110  2. As seen above in (2) and (3), the class implementing the vendor data should include a way to provide an instantiator. The instantiator provides `OFBasicVendorDataType` with a format that allows it to avoid making assumptions about the structure of the vendor data. The method ''getInstantiable()'' returns an instantiator for the class.   
     113 2. As seen above in (2) and (3), the class implementing vendor data must provide an instantiator. The instantiator provides `OFBasicVendorDataType` with a format that allows it to safely avoid making assumptions about the structure of the vendor data. The method ''getInstantiable()'' returns an instantiator for the class.   
    111114
    112 Point 2. indicates that we need a ''getInstantiable()'' (or something of equal function) in our vendor data. The following snippet was taken from `OFRoleRequestVendorData`, but the structure will pretty much be the same for any vendor data class (e.g. replace OFRoleRequestVendorData below with your class):
     115The second point indicates that we need a ''getInstantiable()'' (or something of equal function) in our vendor data class. The following snippet was taken from `OFRoleRequestVendorData`, but the structure will pretty much be the same for any vendor data class (e.g. replace OFRoleRequestVendorData below with your class):
    113116{{{
    114117    protected static Instantiable<OFVendorData> instantiable =
     
    127130    }
    128131}}}
    129 A non-registered Vendor message data payload is interpreted simply as a byte array (OFByteArrayVendorData to be precise), and cannot be cast to your message (sub)class(es) for further handling. Aside from throwing a !ClassCastException, this is inconvenient since you won't be able to invoke the class methods specific to your vendor data class for message-specific processing. 
     132A non-registered Vendor message data payload is interpreted simply as a byte array (an OFByteArrayVendorData object, to be precise), and cannot be cast to your message (sub)class(es) for further handling. Aside from throwing a !ClassCastException if you try, this is inconvenient since you won't be able to invoke the class methods specific to your vendor data class for message-specific processing. 
    130133
    131134=== 2.3 Message Serialization === #serial
    132 As mentioned [#iface earlier], a class implementing OFVendorData must have a readFrom(!ChannelBuffer data, int length) and writeTo(!ChannelBuffer data) method for reading and writing the data from/to a !ChannelBuffer. A getLength() method that returns the size of the vendor data sans the Vendor ID in bytes is also required for properly reading/writing from the !ChannelBuffer. We do not count the !OpenFlow header length since helper methods take it into account along with the Vendor ID length to produce the full message length.
     135As mentioned [#iface earlier], a class implementing OFVendorData must have a readFrom(!ChannelBuffer data, int length) and writeTo(!ChannelBuffer data) method for reading and writing the data from/to a !ChannelBuffer. A getLength() method that returns the size in bytes of the vendor data, minus the Vendor ID length, is also required for properly reading/writing from the !ChannelBuffer. We do not count the !OpenFlow header length since helper methods take it into account along with the Vendor ID length to produce the full message length.
    133136
    134137The packet structure is determined by the order in which the various fields are written to the !ChannelBuffer, so readFrom() and writeTo() should read/write the fields to/from the !ChannelBuffer in the same order.
     
    139142    [OpenFlow Header][ 0x00002320  ][    10|11   ][      0|1|2       ]
    140143}}}
    141 Where the values within the square brackets separated by pipes are the various decimal values that the fields can take. What we had dubbed the vendor payload is one integral value of 4 bytes, used to indicate controller role. The packet structure is reflected in readFrom() and writeTo():
     144Where the values within the square brackets separated by pipes are the various decimal values that the fields can take. For this message, what we had dubbed the vendor message payload in section [#intro 1] is one integral value of 4 bytes, used to indicate controller role. The packet structure is reflected in readFrom() and writeTo():
    142145{{{
    143146    public void readFrom(ChannelBuffer data, int length) {