Update release schedule
[docs.git] / docs / developer-guide / openflow-protocol-library-developer-guide.rst
diff --git a/docs/developer-guide/openflow-protocol-library-developer-guide.rst b/docs/developer-guide/openflow-protocol-library-developer-guide.rst
deleted file mode 100644 (file)
index a3071ae..0000000
+++ /dev/null
@@ -1,1095 +0,0 @@
-.. _openflow-protocol-library-dev-guide:
-
-OpenFlow Protocol Library Developer Guide
-=========================================
-
-Introduction
-------------
-
-OpenFlow Protocol Library is component in OpenDaylight, that mediates
-communication between OpenDaylight controller and hardware devices
-supporting OpenFlow protocol. Primary goal is to provide user (or upper
-layers of OpenDaylight) communication channel, that can be used for
-managing network hardware devices.
-
-Features Overview
------------------
-
-There are three features inside openflowjava:
-
--  **odl-openflowjava-protocol** provides all openflowjava bundles, that
-   are needed for communication with openflow devices. It ensures
-   message translation and handles network connections. It also provides
-   openflow protocol specific model.
-
--  **odl-openflowjava-all** currently contains only
-   odl-openflowjava-protocol feature.
-
--  **odl-openflowjava-stats** provides mechanism for message counting
-   and reporting. Can be used for performance analysis.
-
-odl-openflowjava-protocol Architecture
---------------------------------------
-
-Basic bundles contained in this feature are openflow-protocol-api,
-openflow-protocol-impl, openflow-protocol-spi and util.
-
--  **openflow-protocol-api** - contains openflow model, constants and
-   keys used for (de)serializer registration.
-
--  **openflow-protocol-impl** - contains message factories, that
-   translate binary messages into DataObjects and vice versa. Bundle
-   also contains network connection handlers - servers, netty pipeline
-   handlers, …
-
--  **openflow-protocol-spi** - entry point for openflowjava
-   configuration, startup and close. Basically starts implementation.
-
--  **util** - utility classes for binary-Java conversions and to ease
-   experimenter key creation
-
-odl-openflowjava-stats Feature
-------------------------------
-
-Runs over odl-openflowjava-protocol. It counts various message types /
-events and reports counts in specified time periods. Statistics
-collection can be configured in
-openflowjava-config/src/main/resources/45-openflowjava-stats.xml
-
-Key APIs and Interfaces
------------------------
-
-Basic API / SPI classes are ConnectionAdapter (Rpc/notifications) and
-SwitchConnectionProcider (configure, start, shutdown)
-
-Installation
-------------
-
-Pull the code and import project into your IDE.
-
-::
-
-    git clone ssh://<username>@git.opendaylight.org:29418/openflowjava.git
-
-Configuration
--------------
-
-Current implementation allows to configure:
-
--  listening port (mandatory)
-
--  transfer protocol (mandatory)
-
--  switch idle timeout (mandatory)
-
--  TLS configuration (optional)
-
--  thread count (optional)
-
-You can find exemplary Openflow Protocol Library instance configuration
-below:
-
-::
-
-    <data xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
-      <modules xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
-        <!-- default OF-switch-connection-provider (port 6633) -->
-        <module>
-          <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:openflow:switch:connection:provider:impl">prefix:openflow-switch-connection-provider-impl</type>
-          <name>openflow-switch-connection-provider-default-impl</name>
-          <port>6633</port>
-    <!--  Possible transport-protocol options: TCP, TLS, UDP -->
-          <transport-protocol>TCP</transport-protocol>
-          <switch-idle-timeout>15000</switch-idle-timeout>
-    <!--       Exemplary TLS configuration:
-                - uncomment the <tls> tag
-                - copy exemplary-switch-privkey.pem, exemplary-switch-cert.pem and exemplary-cacert.pem
-                  files into your virtual machine
-                - set VM encryption options to use copied keys
-                - start communication
-               Please visit OpenflowPlugin or Openflow Protocol Library#Documentation wiki pages
-               for detailed information regarding TLS -->
-    <!--       <tls>
-                 <keystore>/exemplary-ctlKeystore</keystore>
-                 <keystore-type>JKS</keystore-type>
-                 <keystore-path-type>CLASSPATH</keystore-path-type>
-                 <keystore-password>opendaylight</keystore-password>
-                 <truststore>/exemplary-ctlTrustStore</truststore>
-                 <truststore-type>JKS</truststore-type>
-                 <truststore-path-type>CLASSPATH</truststore-path-type>
-                 <truststore-password>opendaylight</truststore-password>
-                 <certificate-password>opendaylight</certificate-password>
-               </tls> -->
-    <!--       Exemplary thread model configuration. Uncomment <threads> tag below to adjust default thread model -->
-    <!--       <threads>
-                 <boss-threads>2</boss-threads>
-                 <worker-threads>8</worker-threads>
-               </threads> -->
-        </module>
-
-::
-
-        <!-- default OF-switch-connection-provider (port 6653) -->
-        <module>
-          <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:openflow:switch:connection:provider:impl">prefix:openflow-switch-connection-provider-impl</type>
-          <name>openflow-switch-connection-provider-legacy-impl</name>
-          <port>6653</port>
-    <!--  Possible transport-protocol options: TCP, TLS, UDP -->
-          <transport-protocol>TCP</transport-protocol>
-          <switch-idle-timeout>15000</switch-idle-timeout>
-    <!--       Exemplary TLS configuration:
-                - uncomment the <tls> tag
-                - copy exemplary-switch-privkey.pem, exemplary-switch-cert.pem and exemplary-cacert.pem
-                  files into your virtual machine
-                - set VM encryption options to use copied keys
-                - start communication
-               Please visit OpenflowPlugin or Openflow Protocol Library#Documentation wiki pages
-               for detailed information regarding TLS -->
-    <!--       <tls>
-                 <keystore>/exemplary-ctlKeystore</keystore>
-                 <keystore-type>JKS</keystore-type>
-                 <keystore-path-type>CLASSPATH</keystore-path-type>
-                 <keystore-password>opendaylight</keystore-password>
-                 <truststore>/exemplary-ctlTrustStore</truststore>
-                 <truststore-type>JKS</truststore-type>
-                 <truststore-path-type>CLASSPATH</truststore-path-type>
-                 <truststore-password>opendaylight</truststore-password>
-                 <certificate-password>opendaylight</certificate-password>
-               </tls> -->
-    <!--       Exemplary thread model configuration. Uncomment <threads> tag below to adjust default thread model -->
-    <!--       <threads>
-                 <boss-threads>2</boss-threads>
-                 <worker-threads>8</worker-threads>
-               </threads> -->
-        </module>
-
-::
-
-        <module>
-          <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:openflow:common:config:impl">prefix:openflow-provider-impl</type>
-          <name>openflow-provider-impl</name>
-          <openflow-switch-connection-provider>
-            <type xmlns:ofSwitch="urn:opendaylight:params:xml:ns:yang:openflow:switch:connection:provider">ofSwitch:openflow-switch-connection-provider</type>
-            <name>openflow-switch-connection-provider-default</name>
-          </openflow-switch-connection-provider>
-          <openflow-switch-connection-provider>
-            <type xmlns:ofSwitch="urn:opendaylight:params:xml:ns:yang:openflow:switch:connection:provider">ofSwitch:openflow-switch-connection-provider</type>
-            <name>openflow-switch-connection-provider-legacy</name>
-          </openflow-switch-connection-provider>
-          <binding-aware-broker>
-            <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-broker-osgi-registry</type>
-            <name>binding-osgi-broker</name>
-          </binding-aware-broker>
-        </module>
-      </modules>
-
-Possible transport-protocol options:
-
--  TCP
-
--  TLS
-
--  UDP
-
-Switch-idle timeout specifies time needed to detect idle state of
-switch. When no message is received from switch within this time, upper
-layers are notified on switch idleness. To be able to use this exemplary
-TLS configuration:
-
--  uncomment the ``<tls>`` tag
-
--  copy *exemplary-switch-privkey.pem*, *exemplary-switch-cert.pem* and
-   *exemplary-cacert.pem* files into your virtual machine
-
--  set VM encryption options to use copied keys (please visit TLS
-   support wiki page for detailed information regarding TLS)
-
--  start communication
-
-Thread model configuration specifies how many threads are desired to
-perform Netty’s I/O operations.
-
--  boss-threads specifies the number of threads that register incoming
-   connections
-
--  worker-threads specifies the number of threads performing read /
-   write (+ serialization / deserialization) operations.
-
-Architecture
-------------
-
-Public API ``(openflow-protocol-api)``
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-Set of interfaces and builders for immutable data transfer objects
-representing Openflow Protocol structures.
-
-Transfer objects and service APIs are infered from several YANG models
-using code generator to reduce verbosity of definition and repeatibility
-of code.
-
-The following YANG modules are defined:
-
--  openflow-types - defines common Openflow specific types
-
--  openflow-instruction - defines base Openflow instructions
-
--  openflow-action - defines base Openflow actions
-
--  openflow-augments - defines object augmentations
-
--  openflow-extensible-match - defines Openflow OXM match
-
--  openflow-protocol - defines Openflow Protocol messages
-
--  system-notifications - defines system notification objects
-
--  openflow-configuration - defines structures used in ConfigSubsystem
-
-This modules also reuse types from following YANG modules:
-
--  ietf-inet-types - IP adresses, IP prefixes, IP-protocol related types
-
--  ietf-yang-types - Mac Address, etc.
-
-The use of predefined types is to make APIs contracts more safe, better
-readable and documented (e.g using MacAddress instead of byte array…)
-
-TCP Channel pipeline ``(openflow-protocol-impl)``
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-Creates channel processing pipeline based on configuration and support.
-
-**TCP Channel pipeline.**
-
-imageopenflowjava/500px-TCPChannelPipeline.png[width=500]
-
-**Switch Connection Provider.**
-
-Implementation of connection point for other projects. Library exposes
-its functionality through this class. Library can be configured, started
-and shutdowned here. There are also methods for custom (de)serializer
-registration.
-
-**Tcp Connection Initializer.**
-
-In order to initialize TCP connection to a device (switch), OF Plugin
-calls method ``initiateConnection()`` in ``SwitchConnectionProvider``.
-This method in turn initializes (Bootstrap) server side channel towards
-the device.
-
-**TCP Handler.**
-
-Represents single server that is handling incoming connections over TCP
-/ TLS protocol. TCP Handler creates a single instance of TCP Channel
-Initializer that will initialize channels. After that it binds to
-configured InetAddress and port. When a new device connects, TCP Handler
-registers its channel and passes control to TCP Channel Initializer.
-
-**TCP Channel Initializer.**
-
-This class is used for channel initialization / rejection and passing
-arguments. After a new channel has been registered it calls Switch
-Connection Handler’s (OF Plugin) accept method to decide if the library
-should keep the newly registered channel or if the channel should be
-closed. If the channel has been accepted, TCP Channel Initializer
-creates the whole pipeline with needed handlers and also with
-ConnectionAdapter instance. After the channel pipeline is ready, Switch
-Connection Handler is notified with ``onConnectionReady`` notification.
-OpenFlow Plugin can now start sending messages downstream.
-
-**Idle Handler.**
-
-If there are no messages received for more than time specified, this
-handler triggers idle state notification. The switch idle timeout is
-received as a parameter from ConnectionConfiguration settings. Idle
-State Handler is inactive while there are messages received within the
-switch idle timeout. If there are no messages received for more than
-timeout specified, handler creates SwitchIdleEvent message and sends it
-upstream.
-
-**TLS Handler.**
-
-It encrypts and decrypts messages over TLS protocol. Engaging TLS
-Handler into pipeline is matter of configuration (``<tls>`` tag). TLS
-communication is either unsupported or required. TLS Handler is
-represented as a Netty’s SslHandler.
-
-**OF Frame Decoder.**
-
-Parses input stream into correct length message frames for further
-processing. Framing is based on Openflow header length. If received
-message is shorter than minimal length of OpenFlow message (8 bytes), OF
-Frame Decoder waits for more data. After receiving at least 8 bytes the
-decoder checks length in OpenFlow header. If there are still some bytes
-missing, the decoder waits for them. Else the OF Frame Decoder sends
-correct length message to next handler in the channel pipeline.
-
-**OF Version Detector.**
-
-Detects version of used OpenFlow Protocol and discards unsupported
-version messages. If the detected version is supported, OF Version
-Detector creates ``VersionMessageWrapper`` object containing the
-detected version and byte message and sends this object upstream.
-
-**OF Decoder.**
-
-Chooses correct deserilization factory (based on message type) and
-deserializes messages into generated DTOs (Data Transfer Object). OF
-Decoder receives ``VersionMessageWrapper`` object and passes it to
-``DeserializationFactory`` which will return translated DTO.
-``DeserializationFactory`` creates ``MessageCodeKey`` object with
-version and type of received message and Class of object that will be
-the received message deserialized into. This object is used as key when
-searching for appropriate decoder in ``DecoderTable``. ``DecoderTable``
-is basically a map storing decoders. Found decoder translates received
-message into DTO. If there was no decoder found, null is returned. After
-returning translated DTO back to OF Decoder, the decoder checks if it is
-null or not. When the DTO is null, the decoder logs this state and
-throws an Exception. Else it passes the DTO further upstream. Finally,
-the OF Decoder releases ByteBuf containing received and decoded byte
-message.
-
-**OF Encoder.**
-
-Chooses correct serialization factory (based on type of DTO) and
-serializes DTOs into byte messages. OF Encoder does the opposite than
-the OF Decoder using the same principle. OF Encoder receives DTO, passes
-it for translation and if the result is not null, it sends translated
-DTO downstream as a ByteBuf. Searching for appropriate encoder is done
-via MessageTypeKey, based on version and class of received DTO.
-
-**Delegating Inbound Handler.**
-
-Delegates received DTOs to Connection Adapter. It also reacts on
-channelInactive and channelUnregistered events. Upon one of these events
-is triggered, DelegatingInboundHandler creates DisconnectEvent message
-and sends it upstream, notifying upper layers about switch
-disconnection.
-
-**Channel Outbound Queue.**
-
-Message flushing handler. Stores outgoing messages (DTOs) and flushes
-them. Flush is performed based on time expired and on the number of
-messages enqueued.
-
-**Connection Adapter.**
-
-Provides a facade on top of pipeline, which hides netty.io specifics.
-Provides a set of methods to register for incoming messages and to send
-messages to particular channel / session. ConnectionAdapterImpl
-basically implements three interfaces (unified in one superinterface
-ConnectionFacade):
-
--  ConnectionAdapter
-
--  MessageConsumer
-
--  OpenflowProtocolService
-
-**ConnectionAdapter** interface has methods for setting up listeners
-(message, system and connection ready listener), method to check if all
-listeners are set, checking if the channel is alive and disconnect
-method. Disconnect method clears responseCache and disables consuming of
-new messages.
-
-**MessageConsumer** interface holds only one method: ``consume()``.
-``Consume()`` method is called from DelegatingInboundHandler. This
-method processes received DTO’s based on their type. There are three
-types of received objects:
-
--  System notifications - invoke system notifications in OpenFlow Plugin
-   (systemListener set). In case of ``DisconnectEvent`` message, the
-   Connection Adapter clears response cache and disables consume()
-   method processing,
-
--  OpenFlow asynchronous messages (from switch) - invoke corresponding
-   notifications in OpenFlow Plugin,
-
--  OpenFlow symmetric messages (replies to requests) - create
-   ``RpcResponseKey`` with XID and DTO’s class set. This
-   ``RpcResponseKey`` is then used to find corresponding future object
-   in responseCache. Future object is set with success flag, received
-   message and errors (if any occurred). In case no corresponding future
-   was found in responseCache, Connection Adapter logs warning and
-   discards the message. Connection Adapter also logs warning when an
-   unknown DTO is received.
-
-**OpenflowProtocolService** interface contains all rpc-methods for
-sending messages from upper layers (OpenFlow Plugin) downstream and
-responding. Request messages return Future filled with expected reply
-message, otherwise the expected Future is of type Void.
-
-**NOTE:** MultipartRequest message is the only exception. Basically it
-is request - reply Message type, but it wouldn’t be able to process more
-following MultipartReply messages if this was implemented as rpc (only
-one Future). This is why MultipartReply is implemented as notification.
-OpenFlow Plugin takes care of correct message processing.
-
-UDP Channel pipeline (openflow-protocol-impl)
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-Creates UDP channel processing pipeline based on configuration and
-support. **Switch Connection Provider**, **Channel Outbound Queue** and
-**Connection Adapter** fulfill the same role as in case of TCP
-connection / channel pipeline (please see above).
-
-.. figure:: ./images/openflowjava/500px-UdpChannelPipeline.png
-   :alt: UDP Channel pipeline
-
-   UDP Channel pipeline
-
-**UDP Handler.**
-
-Represents single server that is handling incoming connections over UDP
-(DTLS) protocol. UDP Handler creates a single instance of UDP Channel
-Initializer that will initialize channels. After that it binds to
-configured InetAddress and port. When a new device connects, UDP Handler
-registers its channel and passes control to UDP Channel Initializer.
-
-**UDP Channel Initializer.**
-
-This class is used for channel initialization and passing arguments.
-After a new channel has been registered (for UDP there is always only
-one channel) UDP Channel Initializer creates whole pipeline with needed
-handlers.
-
-**DTLS Handler.**
-
-Haven’t been implemented yet. Will take care of secure DTLS connections.
-
-**OF Datagram Packet Handler.**
-
-Combines functionality of OF Frame Decoder and OF Version Detector.
-Extracts messages from received datagram packets and checks if message
-version is supported. If there is a message received from yet unknown
-sender, OF Datagram Packet Handler creates Connection Adapter for this
-sender and stores it under sender’s address in ``UdpConnectionMap``.
-This map is also used for sending the messages and for correct
-Connection Adapter lookup - to delegate messages from one channel to
-multiple sessions.
-
-**OF Datagram Packet Decoder.**
-
-Chooses correct deserilization factory (based on message type) and
-deserializes messages into generated DTOs. OF Decoder receives
-``VersionMessageUdpWrapper`` object and passes it to
-``DeserializationFactory`` which will return translated DTO.
-``DeserializationFactory`` creates ``MessageCodeKey`` object with
-version and type of received message and Class of object that will be
-the received message deserialized into. This object is used as key when
-searching for appropriate decoder in ``DecoderTable``. ``DecoderTable``
-is basically a map storing decoders. Found decoder translates received
-message into DTO (DataTransferObject). If there was no decoder found,
-null is returned. After returning translated DTO back to OF Datagram
-Packet Decoder, the decoder checks if it is null or not. When the DTO is
-null, the decoder logs this state. Else it looks up appropriate
-Connection Adapter in ``UdpConnectionMap`` and passes the DTO to found
-Connection Adapter. Finally, the OF Decoder releases ``ByteBuf``
-containing received and decoded byte message.
-
-**OF Datagram Packet Encoder.**
-
-Chooses correct serialization factory (based on type of DTO) and
-serializes DTOs into byte messages. OF Datagram Packet Encoder does the
-opposite than the OF Datagram Packet Decoder using the same principle.
-OF Encoder receives DTO, passes it for translation and if the result is
-not null, it sends translated DTO downstream as a datagram packet.
-Searching for appropriate encoder is done via MessageTypeKey, based on
-version and class of received DTO.
-
-SPI (openflow-protocol-spi)
-~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-Defines interface for library’s connection point for other projects.
-Library exposes its functionality through this interface.
-
-Integration test (openflow-protocol-it)
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-Testing communication with simple client.
-
-Simple client(simple-client)
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-Lightweight switch simulator - programmable with desired scenarios.
-
-Utility (util)
-~~~~~~~~~~~~~~
-
-Contains utility classes, mainly for work with ByteBuf.
-
-Library’s lifecycle
--------------------
-
-Steps (after the library’s bundle is started):
-
--  [1] Library is configured by ConfigSubsystem (adress, ports,
-   encryption, …)
-
--  [2] Plugin injects its SwitchConnectionHandler into the Library
-
--  [3] Plugin starts the Library
-
--  [4] Library creates configured protocol handler (e.g. TCP Handler)
-
--  [5] Protocol Handler creates Channel Initializer
-
--  [6] Channel Initializer asks plugin whether to accept incoming
-   connection on each new switch connection
-
--  [7] Plugin responds:
-
-   -  true - continue building pipeline
-
-   -  false - reject connection / disconnect channel
-
--  [8] Library notifies Plugin with onSwitchConnected(ConnectionAdapter)
-   notification, passing reference to ConnectionAdapter, that will
-   handle the connection
-
--  [9] Plugin registers its system and message listeners
-
--  [10] FireConnectionReadyNotification() is triggered, announcing that
-   pipeline handlers needed for communication have been created and
-   Plugin can start communication
-
--  [11] Plugin shutdowns the Library when desired
-
-.. figure:: ./images/openflowjava/Library_lifecycle.png
-   :alt: Library lifecycle
-
-   Library lifecycle
-
-Statistics collection
----------------------
-
-Introduction
-~~~~~~~~~~~~
-
-Statistics collection collects message statistics. Current collected
-statistics (``DS`` - downstream, ``US`` - upstream):
-
--  ``DS_ENTERED_OFJAVA`` - all messages that entered openflowjava
-   (picked up from openflowplugin)
-
--  ``DS_ENCODE_SUCCESS`` - successfully encoded messages
-
--  ``DS_ENCODE_FAIL`` - messages that failed during encoding
-   (serialization) process
-
--  ``DS_FLOW_MODS_ENTERED`` - all flow-mod messages that entered
-   openflowjava
-
--  ``DS_FLOW_MODS_SENT`` - all flow-mod messages that were successfully
-   sent
-
--  ``US_RECEIVED_IN_OFJAVA`` - messages received from switch
-
--  ``US_DECODE_SUCCESS`` - successfully decoded messages
-
--  ``US_DECODE_FAIL`` - messages that failed during decoding
-   (deserialization) process
-
--  ``US_MESSAGE_PASS`` - messages handed over to openflowplugin
-
-Karaf
-~~~~~
-
-In orded to start statistics, it is needed to feature:install
-odl-openflowjava-stats. To see the logs one should use log:set DEBUG
-org.opendaylight.openflowjava.statistics and than probably log:display
-(you can log:list to see if the logging has been set). To adjust
-collection settings it is enough to modify 45-openflowjava-stats.xml.
-
-JConsole
-~~~~~~~~
-
-JConsole provides two commands for the statistics collection:
-
--  printing current statistics
-
--  resetting statistic counters
-
-After attaching JConsole to correct process, one only needs to go into
-MBeans
-``tab → org.opendaylight.controller → RuntimeBean → statistics-collection-service-impl
-→ statistics-collection-service-impl → Operations`` to be able to use
-this commands.
-
-TLS Support
------------
-
-.. note::
-
-    see OpenFlow Plugin Developper Guide
-
-Extensibility
--------------
-
-Introduction
-~~~~~~~~~~~~
-
-Entry point for the extensibility is ``SwitchConnectionProvider``.
-``SwitchConnectionProvider`` contains methods for (de)serializer
-registration. To register deserializer it is needed to use
-.register\*Deserializer(key, impl). To register serializer one must use
-.register\*Serializer(key, impl). Registration can occur either during
-configuration or at runtime.
-
-**NOTE**: In case when experimenter message is received and no
-(de)serializer was registered, the library will throw
-``IllegalArgumentException``.
-
-Basic Principle
-~~~~~~~~~~~~~~~
-
-In order to use extensions it is needed to augment existing model and
-register new (de)serializers.
-
-Augmenting the model: 1. Create new augmentation
-
-Register (de)serializers: 1. Create your (de)serializer 2. Let it
-implement ``OFDeserializer<>`` / ``OFSerializer<>`` - in case the
-structure you are (de)serializing needs to be used in Multipart
-TableFeatures messages, let it implement ``HeaderDeserializer<>`` /
-``HeaderSerializer`` 3. Implement prescribed methods 4. Register your
-deserializer under appropriate key (in our case
-``ExperimenterActionDeserializerKey``) 5. Register your serializer under
-appropriate key (in our case ``ExperimenterActionSerializerKey``) 6.
-Done, test your implementation
-
-**NOTE**: If you don’t know what key should be used with your
-(de)serializer implementation, please visit `Registration
-keys <#registration_keys>`__ page.
-
-Example
-~~~~~~~
-
-Let’s say we have vendor / experimenter action represented by this
-structure:
-
-::
-
-    struct foo_action {
-        uint16_t type;
-        uint16_t length;
-        uint32_t experimenter;
-        uint16_t first;
-        uint16_t second;
-        uint8_t  pad[4];
-    }
-
-First, we have to augment existing model. We create new module, which
-imports "``openflow-types.yang``" (don’t forget to update your
-``pom.xml`` with api dependency). Now we create foo action identity:
-
-::
-
-    import openflow-types {prefix oft;}
-    identity foo {
-        description "Foo action description";
-        base oft:action-base;
-    }
-
-This will be used as type in our structure. Now we must augment existing
-action structure, so that we will have the desired fields first and
-second. In order to create new augmentation, our module has to import
-"``openflow-action.yang``". The augment should look like this:
-
-::
-
-    import openflow-action {prefix ofaction;}
-    augment "/ofaction:actions-container/ofaction:action" {
-        ext:augment-identifier "foo-action";
-            leaf first {
-                type uint16;
-            }
-            leaf second {
-                type uint16;
-            }
-        }
-
-We are finished with model changes. Run mvn clean compile to generate
-sources. After generation is done, we need to implement our
-(de)serializer.
-
-Deserializer:
-
-::
-
-    public class FooActionDeserializer extends OFDeserializer<Action> {
-       @Override
-       public Action deserialize(ByteBuf input) {
-           ActionBuilder builder = new ActionBuilder();
-           input.skipBytes(SIZE_OF_SHORT_IN_BYTES); *// we know the type of action*
-           builder.setType(Foo.class);
-           input.skipBytes(SIZE_OF_SHORT_IN_BYTES); *// we don't need length*
-           *// now create experimenterIdAugmentation - so that openflowplugin can
-           differentiate correct vendor codec*
-           ExperimenterIdActionBuilder expIdBuilder = new ExperimenterIdActionBuilder();
-           expIdBuilder.setExperimenter(new ExperimenterId(input.readUnsignedInt()));
-           builder.addAugmentation(ExperimenterIdAction.class, expIdBuilder.build());
-           FooActionBuilder fooBuilder = new FooActionBuilder();
-           fooBuilder.setFirst(input.readUnsignedShort());
-           fooBuilder.setSecond(input.readUnsignedShort());
-           builder.addAugmentation(FooAction.class, fooBuilder.build());
-           input.skipBytes(4); *// padding*
-           return builder.build();
-       }
-    }
-
-Serializer:
-
-::
-
-    public class FooActionSerializer extends OFSerializer<Action> {
-       @Override
-       public void serialize(Action action, ByteBuf outBuffer) {
-           outBuffer.writeShort(FOO_CODE);
-           outBuffer.writeShort(16);
-           *// we don't have to check for ExperimenterIdAction augmentation - our
-           serializer*
-           *// was called based on the vendor / experimenter ID, so we simply write
-           it to buffer*
-           outBuffer.writeInt(VENDOR / EXPERIMENTER ID);
-           FooAction foo = action.getAugmentation(FooAction.class);
-           outBuffer.writeShort(foo.getFirst());
-           outBuffer.writeShort(foo.getSecond());
-           outBuffer.writeZero(4); //write padding
-       }
-    }
-
-Register both deserializer and serializer:
-``SwitchConnectionProvider.registerDeserializer(new
-ExperimenterActionDeserializerKey(0x04, VENDOR / EXPERIMENTER ID),
-new FooActionDeserializer());``
-``SwitchConnectionProvider.registerSerializer(new
-ExperimenterActionSerializerKey(0x04, VENDOR / EXPERIMENTER ID),
-new FooActionSerializer());``
-
-We are ready to test our implementation.
-
-**NOTE:** Vendor / Experimenter structures define only vendor /
-experimenter ID as common distinguisher (besides action type). Vendor /
-Experimenter ID is unique for all vendor messages - that’s why vendor is
-able to register only one class under
-ExperimenterAction(De)SerializerKey. And that’s why vendor has to switch
-/ choose between his subclasses / subtypes on his own.
-
-Detailed walkthrough: Deserialization extensibility
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-**External interface & class description.**
-
-**OFGeneralDeserializer:**
-
--  ``OFDeserializer<E extends DataObject>``
-
-   -  *deserialize(ByteBuf)* - deserializes given ByteBuf
-
--  ``HeaderDeserializer<E extends DataObject>``
-
-   -  *deserializeHeaders(ByteBuf)* - deserializes only E headers (used
-      in Multipart TableFeatures messages)
-
-**DeserializerRegistryInjector**
-
--  ``injectDeserializerRegistry(DeserializerRegistry)`` - injects
-   deserializer registry into deserializer. Useful when custom
-   deserializer needs access to other deserializers.
-
-**NOTE:** DeserializerRegistryInjector is not OFGeneralDeserializer
-descendand. It is a standalone interface.
-
-**MessageCodeKey and its descendants** These keys are used as for
-deserializer lookup in DeserializerRegistry. MessageCodeKey should is
-used in general, while its descendants are used in more special cases.
-For Example ActionDeserializerKey is used for Action deserializer lookup
-and (de)registration. Vendor is provided with special keys, which
-contain only the most necessary fields. These keys usually start with
-"Experimenter" prefix (MatchEntryDeserializerKey is an exception).
-
-MessageCodeKey has these fields:
-
--  short version - Openflow wire version number
-
--  int value - value read from byte message
-
--  Class<?> clazz - class of object being creating
-
--  [1] The scenario starts in a custom bundle which wants to extend
-   library’s functionality. The custom bundle creates deserializers
-   which implement exposed ``OFDeserializer`` / ``HeaderDeserializer``
-   interfaces (wrapped under ``OFGeneralDeserializer`` unifying super
-   interface).
-
--  [2] Created deserializers are paired with corresponding
-   ExperimenterKeys, which are used for deserializer lookup. If you
-   don’t know what key should be used with your (de)serializer
-   implementation, please visit `Registration
-   keys <#registration_keys>`__ page.
-
--  [3] Paired deserializers are passed to the OF Library via
-   **SwitchConnectionProvider**.\ *registerCustomDeserializer(key,
-   impl)*. Library registers the deserializer.
-
-   -  While registering, Library checks if the deserializer is an
-      instance of **DeserializerRegistryInjector** interface. If yes,
-      the DeserializerRegistry (which stores all deserializer
-      references) is injected into the deserializer.
-
-This is particularly useful when the deserializer needs access to other
-deserializers. For example ``IntructionsDeserializer`` needs access to
-``ActionsDeserializer`` in order to be able to process
-OFPIT\_WRITE\_ACTIONS/OFPIT\_APPLY\_ACTIONS instructions.
-
-.. figure:: ./images/openflowjava/800px-Extensibility.png
-   :alt: Deserialization scenario walkthrough
-
-   Deserialization scenario walkthrough
-
-Detailed walkthrough: Serialization extensibility
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-**External interface & class description.**
-
-**OFGeneralSerializer:**
-
--  OFSerializer<E extends DataObject>
-
-   -  *serialize(E,ByteBuf)* - serializes E into given ByteBuf
-
--  ``HeaderSerializer<E extends DataObject>``
-
-   -  *serializeHeaders(E,ByteBuf)* - serializes E headers (used in
-      Multipart TableFeatures messages)
-
-**SerializerRegistryInjector** \*
-``injectSerializerRegistry(SerializerRegistry)`` - injects serializer
-registry into serializer. Useful when custom serializer needs access to
-other serializers.
-
-**NOTE:** SerializerRegistryInjector is not OFGeneralSerializer
-descendand.
-
-**MessageTypeKey and its descendants** These keys are used as for
-serializer lookup in SerializerRegistry. MessageTypeKey should is used
-in general, while its descendants are used in more special cases. For
-Example ActionSerializerKey is used for Action serializer lookup and
-(de)registration. Vendor is provided with special keys, which contain
-only the most necessary fields. These keys usually start with
-"Experimenter" prefix (MatchEntrySerializerKey is an exception).
-
-MessageTypeKey has these fields:
-
--  *short version* - Openflow wire version number
-
--  *Class<E> msgType* - DTO class
-
-Scenario walkthrough
-
--  [1] Serialization extensbility principles are similar to the
-   deserialization principles. The scenario starts in a custom bundle.
-   The custom bundle creates serializers which implement exposed
-   OFSerializer / HeaderSerializer interfaces (wrapped under
-   OFGeneralSerializer unifying super interface).
-
--  [2] Created serializers are paired with their ExperimenterKeys, which
-   are used for serializer lookup. If you don’t know what key should be
-   used with your serializer implementation, please visit `Registration
-   keys <#registration_keys>`__ page.
-
--  [3] Paired serializers are passed to the OF Library via
-   **SwitchConnectionProvider**.\ *registerCustomSerializer(key, impl)*.
-   Library registers the serializer.
-
--  While registering, Library checks if the serializer is an instance of
-   **SerializerRegistryInjector** interface. If yes, the
-   SerializerRegistry (which stores all serializer references) is
-   injected into the serializer.
-
-This is particularly useful when the serializer needs access to other
-deserializers. For example IntructionsSerializer needs access to
-ActionsSerializer in order to be able to process
-OFPIT\_WRITE\_ACTIONS/OFPIT\_APPLY\_ACTIONS instructions.
-
-.. figure:: ./images/openflowjava/800px-Extensibility2.png
-   :alt: Serialization scenario walkthrough
-
-   Serialization scenario walkthrough
-
-Internal description
-~~~~~~~~~~~~~~~~~~~~
-
-**SwitchConnectionProvider** ``SwitchConnectionProvider`` constructs and
-initializes both deserializer and serializer registries with default
-(de)serializers. It also injects the ``DeserializerRegistry`` into the
-``DeserializationFactory``, the ``SerializerRegistry`` into the
-``SerializationFactory``. When call to register custom (de)serializer is
-made, ``SwitchConnectionProvider`` calls register method on appropriate
-registry.
-
-**DeserializerRegistry / SerializerRegistry** Both registries contain
-init() method to initialize default (de)serializers. Registration checks
-if key or (de)serializer implementation are not ``null``. If at least
-one of the is ``null``, ``NullPointerException`` is thrown. Else the
-(de)serializer implementation is checked if it is
-``(De)SerializerRegistryInjector`` instance. If it is an instance of
-this interface, the registry is injected into this (de)serializer
-implementation.
-
-``GetSerializer(key)`` or ``GetDeserializer(key)`` performs registry
-lookup. Because there are two separate interfaces that might be put into
-the registry, the registry uses their unifying super interface.
-Get(De)Serializer(key) method casts the super interface to desired type.
-There is also a null check for the (de)serializer received from the
-registry. If the deserializer wasn’t found, ``NullPointerException``
-with key description is thrown.
-
-Registration keys
-~~~~~~~~~~~~~~~~~
-
-**Deserialization.**
-
-**Possible openflow extensions and their keys**
-
-There are three vendor specific extensions in Openflow v1.0 and eight in
-Openflow v1.3. These extensions are registered under registration keys,
-that are shown in table below:
-
-+----------------+---------+------------------------------+-----------------------+
-| Extension type | OpenFlo | Registration key             | Utility class         |
-|                | w       |                              |                       |
-+================+=========+==============================+=======================+
-| Vendor message | 1.0     | ExperimenterIdDeserializerKe | ExperimenterDeseriali |
-|                |         | y(1,                         | zerKeyFactory         |
-|                |         | experimenterId,              |                       |
-|                |         | ExperimenterMessage.class)   |                       |
-+----------------+---------+------------------------------+-----------------------+
-| Action         | 1.0     | ExperimenterActionDeserializ | .                     |
-|                |         | erKey(1,                     |                       |
-|                |         | experimenter ID)             |                       |
-+----------------+---------+------------------------------+-----------------------+
-| Stats message  | 1.0     | ExperimenterMultipartReplyMe | ExperimenterDeseriali |
-|                |         | ssageDeserializerKey(1,      | zerKeyFactory         |
-|                |         | experimenter ID)             |                       |
-+----------------+---------+------------------------------+-----------------------+
-| Experimenter   | 1.3     | ExperimenterIdDeserializerKe | ExperimenterDeseriali |
-| message        |         | y(4,                         | zerKeyFactory         |
-|                |         | experimenterId,              |                       |
-|                |         | ExperimenterMessage.class)   |                       |
-+----------------+---------+------------------------------+-----------------------+
-| Match entry    | 1.3     | MatchEntryDeserializerKey(4, | .                     |
-|                |         | (number) ${oxm\_class},      |                       |
-|                |         | (number) ${oxm\_field});     |                       |
-+----------------+---------+------------------------------+-----------------------+
-|                |         | key.setExperimenterId(experi | .                     |
-|                |         | menter                       |                       |
-|                |         | ID);                         |                       |
-+----------------+---------+------------------------------+-----------------------+
-| Action         | 1.3     | ExperimenterActionDeserializ | .                     |
-|                |         | erKey(4,                     |                       |
-|                |         | experimenter ID)             |                       |
-+----------------+---------+------------------------------+-----------------------+
-| Instruction    | 1.3     | ExperimenterInstructionDeser | .                     |
-|                |         | ializerKey(4,                |                       |
-|                |         | experimenter ID)             |                       |
-+----------------+---------+------------------------------+-----------------------+
-| Multipart      | 1.3     | ExperimenterIdDeserializerKe | ExperimenterDeseriali |
-|                |         | y(4,                         | zerKeyFactory         |
-|                |         | experimenterId,              |                       |
-|                |         | MultipartReplyMessage.class) |                       |
-+----------------+---------+------------------------------+-----------------------+
-| Multipart -    | 1.3     | ExperimenterIdDeserializerKe | ExperimenterDeseriali |
-| Table features |         | y(4,                         | zerKeyFactory         |
-|                |         | experimenterId,              |                       |
-|                |         | TableFeatureProperties.class |                       |
-|                |         | )                            |                       |
-+----------------+---------+------------------------------+-----------------------+
-| Error          | 1.3     | ExperimenterIdDeserializerKe | ExperimenterDeseriali |
-|                |         | y(4,                         | zerKeyFactory         |
-|                |         | experimenterId,              |                       |
-|                |         | ErrorMessage.class)          |                       |
-+----------------+---------+------------------------------+-----------------------+
-| Queue property | 1.3     | ExperimenterIdDeserializerKe | ExperimenterDeseriali |
-|                |         | y(4,                         | zerKeyFactory         |
-|                |         | experimenterId,              |                       |
-|                |         | QueueProperty.class)         |                       |
-+----------------+---------+------------------------------+-----------------------+
-| Meter band     | 1.3     | ExperimenterIdDeserializerKe | ExperimenterDeseriali |
-| type           |         | y(4,                         | zerKeyFactory         |
-|                |         | experimenterId,              |                       |
-|                |         | MeterBandExperimenterCase.cl |                       |
-|                |         | ass)                         |                       |
-+----------------+---------+------------------------------+-----------------------+
-
-Table: **Deserialization**
-
-**Serialization.**
-
-**Possible openflow extensions and their keys**
-
-There are three vendor specific extensions in Openflow v1.0 and seven
-Openflow v1.3. These extensions are registered under registration keys,
-that are shown in table below:
-
-+----------------+---------+------------------------------+-----------------------+
-| Extension type | OpenFlo | Registration key             | Utility class         |
-|                | w       |                              |                       |
-+================+=========+==============================+=======================+
-| Vendor message | 1.0     | ExperimenterIdSerializerKey< | ExperimenterSerialize |
-|                |         | >(1,                         | rKeyFactory           |
-|                |         | experimenterId,              |                       |
-|                |         | ExperimenterInput.class)     |                       |
-+----------------+---------+------------------------------+-----------------------+
-| Action         | 1.0     | ExperimenterActionSerializer | .                     |
-|                |         | Key(1,                       |                       |
-|                |         | experimenterId, sub-type)    |                       |
-+----------------+---------+------------------------------+-----------------------+
-| Stats message  | 1.0     | ExperimenterMultipartRequest | ExperimenterSerialize |
-|                |         | SerializerKey(1,             | rKeyFactory           |
-|                |         | experimenter ID)             |                       |
-+----------------+---------+------------------------------+-----------------------+
-| Experimenter   | 1.3     | ExperimenterIdSerializerKey< | ExperimenterSerialize |
-| message        |         | >(4,                         | rKeyFactory           |
-|                |         | experimenterId,              |                       |
-|                |         | ExperimenterInput.class)     |                       |
-+----------------+---------+------------------------------+-----------------------+
-| Match entry    | 1.3     | MatchEntrySerializerKey<>(4, | .                     |
-|                |         | (class) ${oxm\_class},       |                       |
-|                |         | (class) ${oxm\_field});      |                       |
-+----------------+---------+------------------------------+-----------------------+
-|                |         | key.setExperimenterId(experi | .                     |
-|                |         | menter                       |                       |
-|                |         | ID)                          |                       |
-+----------------+---------+------------------------------+-----------------------+
-| Action         | 1.3     | ExperimenterActionSerializer | .                     |
-|                |         | Key(4,                       |                       |
-|                |         | experimenterId, sub-type)    |                       |
-+----------------+---------+------------------------------+-----------------------+
-| Instruction    | 1.3     | ExperimenterInstructionSeria | .                     |
-|                |         | lizerKey(4,                  |                       |
-|                |         | experimenter ID)             |                       |
-+----------------+---------+------------------------------+-----------------------+
-| Multipart      | 1.3     | ExperimenterIdSerializerKey< | ExperimenterSerialize |
-|                |         | >(4,                         | rKeyFactory           |
-|                |         | experimenterId,              |                       |
-|                |         | MultipartRequestExperimenter |                       |
-|                |         | Case.class)                  |                       |
-+----------------+---------+------------------------------+-----------------------+
-| Multipart -    | 1.3     | ExperimenterIdSerializerKey< | ExperimenterSerialize |
-| Table features |         | >(4,                         | rKeyFactory           |
-|                |         | experimenterId,              |                       |
-|                |         | TableFeatureProperties.class |                       |
-|                |         | )                            |                       |
-+----------------+---------+------------------------------+-----------------------+
-| Meter band     | 1.3     | ExperimenterIdSerializerKey< | ExperimenterSerialize |
-| type           |         | >(4,                         | rKeyFactory           |
-|                |         | experimenterId,              |                       |
-|                |         | MeterBandExperimenterCase.cl |                       |
-|                |         | ass)                         |                       |
-+----------------+---------+------------------------------+-----------------------+
-
-Table: **Serialization**
-