Migrate OpenFlow Protocol dev docs to rst 97/44197/3
authorColin Dixon <colin@colindixon.com>
Wed, 17 Aug 2016 17:31:22 +0000 (13:31 -0400)
committerColin Dixon <colin@colindixon.com>
Wed, 17 Aug 2016 19:10:36 +0000 (19:10 +0000)
Change-Id: I5aa13525709408dc83a5d52aed97c4140fc7c495
Signed-off-by: Colin Dixon <colin@colindixon.com>
docs/developer-guide/images/openflowjava/500px-UdpChannelPipeline.png [new file with mode: 0644]
docs/developer-guide/images/openflowjava/800px-Extensibility.png [new file with mode: 0644]
docs/developer-guide/images/openflowjava/800px-Extensibility2.png [new file with mode: 0644]
docs/developer-guide/images/openflowjava/Library_lifecycle.png [new file with mode: 0644]
docs/developer-guide/openflow-protocol-library-developer-guide.rst [new file with mode: 0644]
manuals/developer-guide/src/main/asciidoc/openflowjava/odl-openflowjava-protocol-dev.adoc

diff --git a/docs/developer-guide/images/openflowjava/500px-UdpChannelPipeline.png b/docs/developer-guide/images/openflowjava/500px-UdpChannelPipeline.png
new file mode 100644 (file)
index 0000000..84b7589
Binary files /dev/null and b/docs/developer-guide/images/openflowjava/500px-UdpChannelPipeline.png differ
diff --git a/docs/developer-guide/images/openflowjava/800px-Extensibility.png b/docs/developer-guide/images/openflowjava/800px-Extensibility.png
new file mode 100644 (file)
index 0000000..b4fc160
Binary files /dev/null and b/docs/developer-guide/images/openflowjava/800px-Extensibility.png differ
diff --git a/docs/developer-guide/images/openflowjava/800px-Extensibility2.png b/docs/developer-guide/images/openflowjava/800px-Extensibility2.png
new file mode 100644 (file)
index 0000000..1e2c97b
Binary files /dev/null and b/docs/developer-guide/images/openflowjava/800px-Extensibility2.png differ
diff --git a/docs/developer-guide/images/openflowjava/Library_lifecycle.png b/docs/developer-guide/images/openflowjava/Library_lifecycle.png
new file mode 100644 (file)
index 0000000..ae56d8c
Binary files /dev/null and b/docs/developer-guide/images/openflowjava/Library_lifecycle.png differ
diff --git a/docs/developer-guide/openflow-protocol-library-developer-guide.rst b/docs/developer-guide/openflow-protocol-library-developer-guide.rst
new file mode 100644 (file)
index 0000000..62e193d
--- /dev/null
@@ -0,0 +1,1093 @@
+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**
+
index ff4ed2463629c75973e6a33bff142ffbb3bacf45..86ab46928e42586968ba496b1ce270d3da54fd35 100644 (file)
@@ -1,810 +1,3 @@
 == 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)
-
-//=== API Reference Documentation
-//Provide links to JavaDoc, REST API documentation, etc.  [TBD]
-
-=== 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).
-
-.UDP Channel pipeline
-image::openflowjava/500px-UdpChannelPipeline.png[width=500]
-
-.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
-
-.Library lifecycle
-image::openflowjava/Library_lifecycle.png[width=500]
-
-
-=== 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
-
-.Scenario walkthrough
-* [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.
-
-.Deserialization scenario walkthrough
-image::openflowjava/800px-Extensibility.png[width=500]
-
-==== 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.
-
-.Serialization scenario walkthrough
-image::openflowjava/800px-Extensibility2.png[width=500]
-
-==== 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]]
-==== 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: 
-
-.*Deserialization*
-[options="header",cols="20%,10%,40%,30%"]
-|========================================================================================================================================================
-|Extension type            |OpenFlow|Registration key                                                                 |Utility class
-|Vendor message            |1.0     |ExperimenterIdDeserializerKey(1, experimenterId, ExperimenterMessage.class)      |ExperimenterDeserializerKeyFactory
-|Action                    |1.0     |ExperimenterActionDeserializerKey(1, experimenter ID)                            |.
-|Stats message             |1.0     |ExperimenterMultipartReplyMessageDeserializerKey(1, experimenter ID)             |ExperimenterDeserializerKeyFactory
-|Experimenter message      |1.3     |ExperimenterIdDeserializerKey(4, experimenterId, ExperimenterMessage.class)      |ExperimenterDeserializerKeyFactory
-|Match entry               |1.3     |MatchEntryDeserializerKey(4, (number) ${oxm_Class}, (number) ${oxm_Field});      |.
-|                          |        |key.setExperimenterId(experimenter ID);                                          |.
-|Action                    |1.3     |ExperimenterActionDeserializerKey(4, experimenter ID)                            |.
-|Instruction               |1.3     |ExperimenterInstructionDeserializerKey(4, experimenter ID)                       |.
-|Multipart                 |1.3     |ExperimenterIdDeserializerKey(4, experimenterId, MultipartReplyMessage.class)    |ExperimenterDeserializerKeyFactory
-|Multipart - Table features|1.3     |ExperimenterIdDeserializerKey(4, experimenterId, TableFeatureProperties.class)   |ExperimenterDeserializerKeyFactory
-|Error                     |1.3     |ExperimenterIdDeserializerKey(4, experimenterId, ErrorMessage.class)             |ExperimenterDeserializerKeyFactory
-|Queue property            |1.3     |ExperimenterIdDeserializerKey(4, experimenterId, QueueProperty.class)            |ExperimenterDeserializerKeyFactory
-|Meter band type           |1.3     |ExperimenterIdDeserializerKey(4, experimenterId, MeterBandExperimenterCase.class)|ExperimenterDeserializerKeyFactory
-|========================================================================================================================================================
-
-.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:
-
-
-.*Serialization*
-[options="header",cols="20%,10%,40%,30%"]
-|=============================================================================================================================================================
-|Extension type            |OpenFlow|Registration key                                                                        |Utility class
-|Vendor message            |1.0     |ExperimenterIdSerializerKey<>(1, experimenterId, ExperimenterInput.class)               |ExperimenterSerializerKeyFactory
-|Action                    |1.0     |ExperimenterActionSerializerKey(1, experimenterId, sub-type)                            |.
-|Stats message             |1.0     |ExperimenterMultipartRequestSerializerKey(1, experimenter ID)                           |ExperimenterSerializerKeyFactory
-|Experimenter message      |1.3     |ExperimenterIdSerializerKey<>(4, experimenterId, ExperimenterInput.class)               |ExperimenterSerializerKeyFactory
-|Match entry               |1.3     |MatchEntrySerializerKey<>(4, (class) ${oxm_Class}, (class) ${oxm_Field});               |.
-|                          |        |key.setExperimenterId(experimenter ID)                                                  |.
-|Action                    |1.3     |ExperimenterActionSerializerKey(4, experimenterId, sub-type)                            |.
-|Instruction               |1.3     |ExperimenterInstructionSerializerKey(4, experimenter ID)                                |.
-|Multipart                 |1.3     |ExperimenterIdSerializerKey<>(4, experimenterId, MultipartRequestExperimenterCase.class)|ExperimenterSerializerKeyFactory
-|Multipart - Table features|1.3     |ExperimenterIdSerializerKey<>(4, experimenterId, TableFeatureProperties.class)          |ExperimenterSerializerKeyFactory
-|Meter band type           |1.3     |ExperimenterIdSerializerKey<>(4, experimenterId, MeterBandExperimenterCase.class)       |ExperimenterSerializerKeyFactory 
-|=============================================================================================================================================================
+This content has been migrated to: http://docs.opendaylight.org/en/stable-boron/developer-guide/openflow-protocol-library-developer-guide.html