X-Git-Url: https://git.opendaylight.org/gerrit/gitweb?a=blobdiff_plain;ds=sidebyside;f=docs%2Fdeveloper-guide%2Fopenflow-protocol-library-developer-guide.rst;h=37a8fcd85f0a2111ae59a7e2e74d60cd3ce5e110;hb=HEAD;hp=a3071ae78be25b3fe6c3ef6863c1e7f7d6eff25b;hpb=0f3fea03ff0d1ec7dba4ca417ff877dd0333d76f;p=docs.git 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 index a3071ae78..000000000 --- a/docs/developer-guide/openflow-protocol-library-developer-guide.rst +++ /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://@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: - -:: - - - - - - prefix:openflow-switch-connection-provider-impl - openflow-switch-connection-provider-default-impl - 6633 - - TCP - 15000 - - - - - - -:: - - - - prefix:openflow-switch-connection-provider-impl - openflow-switch-connection-provider-legacy-impl - 6653 - - TCP - 15000 - - - - - - -:: - - - prefix:openflow-provider-impl - openflow-provider-impl - - ofSwitch:openflow-switch-connection-provider - openflow-switch-connection-provider-default - - - ofSwitch:openflow-switch-connection-provider - openflow-switch-connection-provider-legacy - - - binding:binding-broker-osgi-registry - binding-osgi-broker - - - - -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 ```` 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 (```` 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 { - @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 { - @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`` - - - *deserialize(ByteBuf)* - deserializes given ByteBuf - -- ``HeaderDeserializer`` - - - *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 - - - *serialize(E,ByteBuf)* - serializes E into given ByteBuf - -- ``HeaderSerializer`` - - - *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 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** -