Update download page for Ca
[docs.git] / docs / developer-guide / openflow-protocol-library-developer-guide.rst
1 .. _openflow-protocol-library:
2
3 OpenFlow Protocol Library Developer Guide
4 =========================================
5
6 Introduction
7 ------------
8
9 OpenFlow Protocol Library is component in OpenDaylight, that mediates
10 communication between OpenDaylight controller and hardware devices
11 supporting OpenFlow protocol. Primary goal is to provide user (or upper
12 layers of OpenDaylight) communication channel, that can be used for
13 managing network hardware devices.
14
15 Features Overview
16 -----------------
17
18 There are three features inside openflowjava:
19
20 -  **odl-openflowjava-protocol** provides all openflowjava bundles, that
21    are needed for communication with openflow devices. It ensures
22    message translation and handles network connections. It also provides
23    openflow protocol specific model.
24
25 -  **odl-openflowjava-all** currently contains only
26    odl-openflowjava-protocol feature.
27
28 -  **odl-openflowjava-stats** provides mechanism for message counting
29    and reporting. Can be used for performance analysis.
30
31 odl-openflowjava-protocol Architecture
32 --------------------------------------
33
34 Basic bundles contained in this feature are openflow-protocol-api,
35 openflow-protocol-impl, openflow-protocol-spi and util.
36
37 -  **openflow-protocol-api** - contains openflow model, constants and
38    keys used for (de)serializer registration.
39
40 -  **openflow-protocol-impl** - contains message factories, that
41    translate binary messages into DataObjects and vice versa. Bundle
42    also contains network connection handlers - servers, netty pipeline
43    handlers, …
44
45 -  **openflow-protocol-spi** - entry point for openflowjava
46    configuration, startup and close. Basically starts implementation.
47
48 -  **util** - utility classes for binary-Java conversions and to ease
49    experimenter key creation
50
51 odl-openflowjava-stats Feature
52 ------------------------------
53
54 Runs over odl-openflowjava-protocol. It counts various message types /
55 events and reports counts in specified time periods. Statistics
56 collection can be configured in
57 openflowjava-config/src/main/resources/45-openflowjava-stats.xml
58
59 Key APIs and Interfaces
60 -----------------------
61
62 Basic API / SPI classes are ConnectionAdapter (Rpc/notifications) and
63 SwitchConnectionProcider (configure, start, shutdown)
64
65 Installation
66 ------------
67
68 Pull the code and import project into your IDE.
69
70 ::
71
72     git clone ssh://<username>@git.opendaylight.org:29418/openflowjava.git
73
74 Configuration
75 -------------
76
77 Current implementation allows to configure:
78
79 -  listening port (mandatory)
80
81 -  transfer protocol (mandatory)
82
83 -  switch idle timeout (mandatory)
84
85 -  TLS configuration (optional)
86
87 -  thread count (optional)
88
89 You can find exemplary Openflow Protocol Library instance configuration
90 below:
91
92 ::
93
94     <data xmlns="urn:ietf:params:xml:ns:netconf:base:1.0">
95       <modules xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
96         <!-- default OF-switch-connection-provider (port 6633) -->
97         <module>
98           <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:openflow:switch:connection:provider:impl">prefix:openflow-switch-connection-provider-impl</type>
99           <name>openflow-switch-connection-provider-default-impl</name>
100           <port>6633</port>
101     <!--  Possible transport-protocol options: TCP, TLS, UDP -->
102           <transport-protocol>TCP</transport-protocol>
103           <switch-idle-timeout>15000</switch-idle-timeout>
104     <!--       Exemplary TLS configuration:
105                 - uncomment the <tls> tag
106                 - copy exemplary-switch-privkey.pem, exemplary-switch-cert.pem and exemplary-cacert.pem
107                   files into your virtual machine
108                 - set VM encryption options to use copied keys
109                 - start communication
110                Please visit OpenflowPlugin or Openflow Protocol Library#Documentation wiki pages
111                for detailed information regarding TLS -->
112     <!--       <tls>
113                  <keystore>/exemplary-ctlKeystore</keystore>
114                  <keystore-type>JKS</keystore-type>
115                  <keystore-path-type>CLASSPATH</keystore-path-type>
116                  <keystore-password>opendaylight</keystore-password>
117                  <truststore>/exemplary-ctlTrustStore</truststore>
118                  <truststore-type>JKS</truststore-type>
119                  <truststore-path-type>CLASSPATH</truststore-path-type>
120                  <truststore-password>opendaylight</truststore-password>
121                  <certificate-password>opendaylight</certificate-password>
122                </tls> -->
123     <!--       Exemplary thread model configuration. Uncomment <threads> tag below to adjust default thread model -->
124     <!--       <threads>
125                  <boss-threads>2</boss-threads>
126                  <worker-threads>8</worker-threads>
127                </threads> -->
128         </module>
129
130 ::
131
132         <!-- default OF-switch-connection-provider (port 6653) -->
133         <module>
134           <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:openflow:switch:connection:provider:impl">prefix:openflow-switch-connection-provider-impl</type>
135           <name>openflow-switch-connection-provider-legacy-impl</name>
136           <port>6653</port>
137     <!--  Possible transport-protocol options: TCP, TLS, UDP -->
138           <transport-protocol>TCP</transport-protocol>
139           <switch-idle-timeout>15000</switch-idle-timeout>
140     <!--       Exemplary TLS configuration:
141                 - uncomment the <tls> tag
142                 - copy exemplary-switch-privkey.pem, exemplary-switch-cert.pem and exemplary-cacert.pem
143                   files into your virtual machine
144                 - set VM encryption options to use copied keys
145                 - start communication
146                Please visit OpenflowPlugin or Openflow Protocol Library#Documentation wiki pages
147                for detailed information regarding TLS -->
148     <!--       <tls>
149                  <keystore>/exemplary-ctlKeystore</keystore>
150                  <keystore-type>JKS</keystore-type>
151                  <keystore-path-type>CLASSPATH</keystore-path-type>
152                  <keystore-password>opendaylight</keystore-password>
153                  <truststore>/exemplary-ctlTrustStore</truststore>
154                  <truststore-type>JKS</truststore-type>
155                  <truststore-path-type>CLASSPATH</truststore-path-type>
156                  <truststore-password>opendaylight</truststore-password>
157                  <certificate-password>opendaylight</certificate-password>
158                </tls> -->
159     <!--       Exemplary thread model configuration. Uncomment <threads> tag below to adjust default thread model -->
160     <!--       <threads>
161                  <boss-threads>2</boss-threads>
162                  <worker-threads>8</worker-threads>
163                </threads> -->
164         </module>
165
166 ::
167
168         <module>
169           <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:openflow:common:config:impl">prefix:openflow-provider-impl</type>
170           <name>openflow-provider-impl</name>
171           <openflow-switch-connection-provider>
172             <type xmlns:ofSwitch="urn:opendaylight:params:xml:ns:yang:openflow:switch:connection:provider">ofSwitch:openflow-switch-connection-provider</type>
173             <name>openflow-switch-connection-provider-default</name>
174           </openflow-switch-connection-provider>
175           <openflow-switch-connection-provider>
176             <type xmlns:ofSwitch="urn:opendaylight:params:xml:ns:yang:openflow:switch:connection:provider">ofSwitch:openflow-switch-connection-provider</type>
177             <name>openflow-switch-connection-provider-legacy</name>
178           </openflow-switch-connection-provider>
179           <binding-aware-broker>
180             <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-broker-osgi-registry</type>
181             <name>binding-osgi-broker</name>
182           </binding-aware-broker>
183         </module>
184       </modules>
185
186 Possible transport-protocol options:
187
188 -  TCP
189
190 -  TLS
191
192 -  UDP
193
194 Switch-idle timeout specifies time needed to detect idle state of
195 switch. When no message is received from switch within this time, upper
196 layers are notified on switch idleness. To be able to use this exemplary
197 TLS configuration:
198
199 -  uncomment the ``<tls>`` tag
200
201 -  copy *exemplary-switch-privkey.pem*, *exemplary-switch-cert.pem* and
202    *exemplary-cacert.pem* files into your virtual machine
203
204 -  set VM encryption options to use copied keys (please visit TLS
205    support wiki page for detailed information regarding TLS)
206
207 -  start communication
208
209 Thread model configuration specifies how many threads are desired to
210 perform Netty’s I/O operations.
211
212 -  boss-threads specifies the number of threads that register incoming
213    connections
214
215 -  worker-threads specifies the number of threads performing read /
216    write (+ serialization / deserialization) operations.
217
218 Architecture
219 ------------
220
221 Public API ``(openflow-protocol-api)``
222 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
223
224 Set of interfaces and builders for immutable data transfer objects
225 representing Openflow Protocol structures.
226
227 Transfer objects and service APIs are infered from several YANG models
228 using code generator to reduce verbosity of definition and repeatibility
229 of code.
230
231 The following YANG modules are defined:
232
233 -  openflow-types - defines common Openflow specific types
234
235 -  openflow-instruction - defines base Openflow instructions
236
237 -  openflow-action - defines base Openflow actions
238
239 -  openflow-augments - defines object augmentations
240
241 -  openflow-extensible-match - defines Openflow OXM match
242
243 -  openflow-protocol - defines Openflow Protocol messages
244
245 -  system-notifications - defines system notification objects
246
247 -  openflow-configuration - defines structures used in ConfigSubsystem
248
249 This modules also reuse types from following YANG modules:
250
251 -  ietf-inet-types - IP adresses, IP prefixes, IP-protocol related types
252
253 -  ietf-yang-types - Mac Address, etc.
254
255 The use of predefined types is to make APIs contracts more safe, better
256 readable and documented (e.g using MacAddress instead of byte array…)
257
258 TCP Channel pipeline ``(openflow-protocol-impl)``
259 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
260
261 Creates channel processing pipeline based on configuration and support.
262
263 **TCP Channel pipeline.**
264
265 imageopenflowjava/500px-TCPChannelPipeline.png[width=500]
266
267 **Switch Connection Provider.**
268
269 Implementation of connection point for other projects. Library exposes
270 its functionality through this class. Library can be configured, started
271 and shutdowned here. There are also methods for custom (de)serializer
272 registration.
273
274 **Tcp Connection Initializer.**
275
276 In order to initialize TCP connection to a device (switch), OF Plugin
277 calls method ``initiateConnection()`` in ``SwitchConnectionProvider``.
278 This method in turn initializes (Bootstrap) server side channel towards
279 the device.
280
281 **TCP Handler.**
282
283 Represents single server that is handling incoming connections over TCP
284 / TLS protocol. TCP Handler creates a single instance of TCP Channel
285 Initializer that will initialize channels. After that it binds to
286 configured InetAddress and port. When a new device connects, TCP Handler
287 registers its channel and passes control to TCP Channel Initializer.
288
289 **TCP Channel Initializer.**
290
291 This class is used for channel initialization / rejection and passing
292 arguments. After a new channel has been registered it calls Switch
293 Connection Handler’s (OF Plugin) accept method to decide if the library
294 should keep the newly registered channel or if the channel should be
295 closed. If the channel has been accepted, TCP Channel Initializer
296 creates the whole pipeline with needed handlers and also with
297 ConnectionAdapter instance. After the channel pipeline is ready, Switch
298 Connection Handler is notified with ``onConnectionReady`` notification.
299 OpenFlow Plugin can now start sending messages downstream.
300
301 **Idle Handler.**
302
303 If there are no messages received for more than time specified, this
304 handler triggers idle state notification. The switch idle timeout is
305 received as a parameter from ConnectionConfiguration settings. Idle
306 State Handler is inactive while there are messages received within the
307 switch idle timeout. If there are no messages received for more than
308 timeout specified, handler creates SwitchIdleEvent message and sends it
309 upstream.
310
311 **TLS Handler.**
312
313 It encrypts and decrypts messages over TLS protocol. Engaging TLS
314 Handler into pipeline is matter of configuration (``<tls>`` tag). TLS
315 communication is either unsupported or required. TLS Handler is
316 represented as a Netty’s SslHandler.
317
318 **OF Frame Decoder.**
319
320 Parses input stream into correct length message frames for further
321 processing. Framing is based on Openflow header length. If received
322 message is shorter than minimal length of OpenFlow message (8 bytes), OF
323 Frame Decoder waits for more data. After receiving at least 8 bytes the
324 decoder checks length in OpenFlow header. If there are still some bytes
325 missing, the decoder waits for them. Else the OF Frame Decoder sends
326 correct length message to next handler in the channel pipeline.
327
328 **OF Version Detector.**
329
330 Detects version of used OpenFlow Protocol and discards unsupported
331 version messages. If the detected version is supported, OF Version
332 Detector creates ``VersionMessageWrapper`` object containing the
333 detected version and byte message and sends this object upstream.
334
335 **OF Decoder.**
336
337 Chooses correct deserilization factory (based on message type) and
338 deserializes messages into generated DTOs (Data Transfer Object). OF
339 Decoder receives ``VersionMessageWrapper`` object and passes it to
340 ``DeserializationFactory`` which will return translated DTO.
341 ``DeserializationFactory`` creates ``MessageCodeKey`` object with
342 version and type of received message and Class of object that will be
343 the received message deserialized into. This object is used as key when
344 searching for appropriate decoder in ``DecoderTable``. ``DecoderTable``
345 is basically a map storing decoders. Found decoder translates received
346 message into DTO. If there was no decoder found, null is returned. After
347 returning translated DTO back to OF Decoder, the decoder checks if it is
348 null or not. When the DTO is null, the decoder logs this state and
349 throws an Exception. Else it passes the DTO further upstream. Finally,
350 the OF Decoder releases ByteBuf containing received and decoded byte
351 message.
352
353 **OF Encoder.**
354
355 Chooses correct serialization factory (based on type of DTO) and
356 serializes DTOs into byte messages. OF Encoder does the opposite than
357 the OF Decoder using the same principle. OF Encoder receives DTO, passes
358 it for translation and if the result is not null, it sends translated
359 DTO downstream as a ByteBuf. Searching for appropriate encoder is done
360 via MessageTypeKey, based on version and class of received DTO.
361
362 **Delegating Inbound Handler.**
363
364 Delegates received DTOs to Connection Adapter. It also reacts on
365 channelInactive and channelUnregistered events. Upon one of these events
366 is triggered, DelegatingInboundHandler creates DisconnectEvent message
367 and sends it upstream, notifying upper layers about switch
368 disconnection.
369
370 **Channel Outbound Queue.**
371
372 Message flushing handler. Stores outgoing messages (DTOs) and flushes
373 them. Flush is performed based on time expired and on the number of
374 messages enqueued.
375
376 **Connection Adapter.**
377
378 Provides a facade on top of pipeline, which hides netty.io specifics.
379 Provides a set of methods to register for incoming messages and to send
380 messages to particular channel / session. ConnectionAdapterImpl
381 basically implements three interfaces (unified in one superinterface
382 ConnectionFacade):
383
384 -  ConnectionAdapter
385
386 -  MessageConsumer
387
388 -  OpenflowProtocolService
389
390 **ConnectionAdapter** interface has methods for setting up listeners
391 (message, system and connection ready listener), method to check if all
392 listeners are set, checking if the channel is alive and disconnect
393 method. Disconnect method clears responseCache and disables consuming of
394 new messages.
395
396 **MessageConsumer** interface holds only one method: ``consume()``.
397 ``Consume()`` method is called from DelegatingInboundHandler. This
398 method processes received DTO’s based on their type. There are three
399 types of received objects:
400
401 -  System notifications - invoke system notifications in OpenFlow Plugin
402    (systemListener set). In case of ``DisconnectEvent`` message, the
403    Connection Adapter clears response cache and disables consume()
404    method processing,
405
406 -  OpenFlow asynchronous messages (from switch) - invoke corresponding
407    notifications in OpenFlow Plugin,
408
409 -  OpenFlow symmetric messages (replies to requests) - create
410    ``RpcResponseKey`` with XID and DTO’s class set. This
411    ``RpcResponseKey`` is then used to find corresponding future object
412    in responseCache. Future object is set with success flag, received
413    message and errors (if any occurred). In case no corresponding future
414    was found in responseCache, Connection Adapter logs warning and
415    discards the message. Connection Adapter also logs warning when an
416    unknown DTO is received.
417
418 **OpenflowProtocolService** interface contains all rpc-methods for
419 sending messages from upper layers (OpenFlow Plugin) downstream and
420 responding. Request messages return Future filled with expected reply
421 message, otherwise the expected Future is of type Void.
422
423 **NOTE:** MultipartRequest message is the only exception. Basically it
424 is request - reply Message type, but it wouldn’t be able to process more
425 following MultipartReply messages if this was implemented as rpc (only
426 one Future). This is why MultipartReply is implemented as notification.
427 OpenFlow Plugin takes care of correct message processing.
428
429 UDP Channel pipeline (openflow-protocol-impl)
430 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
431
432 Creates UDP channel processing pipeline based on configuration and
433 support. **Switch Connection Provider**, **Channel Outbound Queue** and
434 **Connection Adapter** fulfill the same role as in case of TCP
435 connection / channel pipeline (please see above).
436
437 .. figure:: ./images/openflowjava/500px-UdpChannelPipeline.png
438    :alt: UDP Channel pipeline
439
440    UDP Channel pipeline
441
442 **UDP Handler.**
443
444 Represents single server that is handling incoming connections over UDP
445 (DTLS) protocol. UDP Handler creates a single instance of UDP Channel
446 Initializer that will initialize channels. After that it binds to
447 configured InetAddress and port. When a new device connects, UDP Handler
448 registers its channel and passes control to UDP Channel Initializer.
449
450 **UDP Channel Initializer.**
451
452 This class is used for channel initialization and passing arguments.
453 After a new channel has been registered (for UDP there is always only
454 one channel) UDP Channel Initializer creates whole pipeline with needed
455 handlers.
456
457 **DTLS Handler.**
458
459 Haven’t been implemented yet. Will take care of secure DTLS connections.
460
461 **OF Datagram Packet Handler.**
462
463 Combines functionality of OF Frame Decoder and OF Version Detector.
464 Extracts messages from received datagram packets and checks if message
465 version is supported. If there is a message received from yet unknown
466 sender, OF Datagram Packet Handler creates Connection Adapter for this
467 sender and stores it under sender’s address in ``UdpConnectionMap``.
468 This map is also used for sending the messages and for correct
469 Connection Adapter lookup - to delegate messages from one channel to
470 multiple sessions.
471
472 **OF Datagram Packet Decoder.**
473
474 Chooses correct deserilization factory (based on message type) and
475 deserializes messages into generated DTOs. OF Decoder receives
476 ``VersionMessageUdpWrapper`` object and passes it to
477 ``DeserializationFactory`` which will return translated DTO.
478 ``DeserializationFactory`` creates ``MessageCodeKey`` object with
479 version and type of received message and Class of object that will be
480 the received message deserialized into. This object is used as key when
481 searching for appropriate decoder in ``DecoderTable``. ``DecoderTable``
482 is basically a map storing decoders. Found decoder translates received
483 message into DTO (DataTransferObject). If there was no decoder found,
484 null is returned. After returning translated DTO back to OF Datagram
485 Packet Decoder, the decoder checks if it is null or not. When the DTO is
486 null, the decoder logs this state. Else it looks up appropriate
487 Connection Adapter in ``UdpConnectionMap`` and passes the DTO to found
488 Connection Adapter. Finally, the OF Decoder releases ``ByteBuf``
489 containing received and decoded byte message.
490
491 **OF Datagram Packet Encoder.**
492
493 Chooses correct serialization factory (based on type of DTO) and
494 serializes DTOs into byte messages. OF Datagram Packet Encoder does the
495 opposite than the OF Datagram Packet Decoder using the same principle.
496 OF Encoder receives DTO, passes it for translation and if the result is
497 not null, it sends translated DTO downstream as a datagram packet.
498 Searching for appropriate encoder is done via MessageTypeKey, based on
499 version and class of received DTO.
500
501 SPI (openflow-protocol-spi)
502 ~~~~~~~~~~~~~~~~~~~~~~~~~~~
503
504 Defines interface for library’s connection point for other projects.
505 Library exposes its functionality through this interface.
506
507 Integration test (openflow-protocol-it)
508 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
509
510 Testing communication with simple client.
511
512 Simple client(simple-client)
513 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
514
515 Lightweight switch simulator - programmable with desired scenarios.
516
517 Utility (util)
518 ~~~~~~~~~~~~~~
519
520 Contains utility classes, mainly for work with ByteBuf.
521
522 Library’s lifecycle
523 -------------------
524
525 Steps (after the library’s bundle is started):
526
527 -  [1] Library is configured by ConfigSubsystem (adress, ports,
528    encryption, …)
529
530 -  [2] Plugin injects its SwitchConnectionHandler into the Library
531
532 -  [3] Plugin starts the Library
533
534 -  [4] Library creates configured protocol handler (e.g. TCP Handler)
535
536 -  [5] Protocol Handler creates Channel Initializer
537
538 -  [6] Channel Initializer asks plugin whether to accept incoming
539    connection on each new switch connection
540
541 -  [7] Plugin responds:
542
543    -  true - continue building pipeline
544
545    -  false - reject connection / disconnect channel
546
547 -  [8] Library notifies Plugin with onSwitchConnected(ConnectionAdapter)
548    notification, passing reference to ConnectionAdapter, that will
549    handle the connection
550
551 -  [9] Plugin registers its system and message listeners
552
553 -  [10] FireConnectionReadyNotification() is triggered, announcing that
554    pipeline handlers needed for communication have been created and
555    Plugin can start communication
556
557 -  [11] Plugin shutdowns the Library when desired
558
559 .. figure:: ./images/openflowjava/Library_lifecycle.png
560    :alt: Library lifecycle
561
562    Library lifecycle
563
564 Statistics collection
565 ---------------------
566
567 Introduction
568 ~~~~~~~~~~~~
569
570 Statistics collection collects message statistics. Current collected
571 statistics (``DS`` - downstream, ``US`` - upstream):
572
573 -  ``DS_ENTERED_OFJAVA`` - all messages that entered openflowjava
574    (picked up from openflowplugin)
575
576 -  ``DS_ENCODE_SUCCESS`` - successfully encoded messages
577
578 -  ``DS_ENCODE_FAIL`` - messages that failed during encoding
579    (serialization) process
580
581 -  ``DS_FLOW_MODS_ENTERED`` - all flow-mod messages that entered
582    openflowjava
583
584 -  ``DS_FLOW_MODS_SENT`` - all flow-mod messages that were successfully
585    sent
586
587 -  ``US_RECEIVED_IN_OFJAVA`` - messages received from switch
588
589 -  ``US_DECODE_SUCCESS`` - successfully decoded messages
590
591 -  ``US_DECODE_FAIL`` - messages that failed during decoding
592    (deserialization) process
593
594 -  ``US_MESSAGE_PASS`` - messages handed over to openflowplugin
595
596 Karaf
597 ~~~~~
598
599 In orded to start statistics, it is needed to feature:install
600 odl-openflowjava-stats. To see the logs one should use log:set DEBUG
601 org.opendaylight.openflowjava.statistics and than probably log:display
602 (you can log:list to see if the logging has been set). To adjust
603 collection settings it is enough to modify 45-openflowjava-stats.xml.
604
605 JConsole
606 ~~~~~~~~
607
608 JConsole provides two commands for the statistics collection:
609
610 -  printing current statistics
611
612 -  resetting statistic counters
613
614 After attaching JConsole to correct process, one only needs to go into
615 MBeans
616 ``tab → org.opendaylight.controller → RuntimeBean → statistics-collection-service-impl
617 → statistics-collection-service-impl → Operations`` to be able to use
618 this commands.
619
620 TLS Support
621 -----------
622
623 .. note::
624
625     see OpenFlow Plugin Developper Guide
626
627 Extensibility
628 -------------
629
630 Introduction
631 ~~~~~~~~~~~~
632
633 Entry point for the extensibility is ``SwitchConnectionProvider``.
634 ``SwitchConnectionProvider`` contains methods for (de)serializer
635 registration. To register deserializer it is needed to use
636 .register\*Deserializer(key, impl). To register serializer one must use
637 .register\*Serializer(key, impl). Registration can occur either during
638 configuration or at runtime.
639
640 **NOTE**: In case when experimenter message is received and no
641 (de)serializer was registered, the library will throw
642 ``IllegalArgumentException``.
643
644 Basic Principle
645 ~~~~~~~~~~~~~~~
646
647 In order to use extensions it is needed to augment existing model and
648 register new (de)serializers.
649
650 Augmenting the model: 1. Create new augmentation
651
652 Register (de)serializers: 1. Create your (de)serializer 2. Let it
653 implement ``OFDeserializer<>`` / ``OFSerializer<>`` - in case the
654 structure you are (de)serializing needs to be used in Multipart
655 TableFeatures messages, let it implement ``HeaderDeserializer<>`` /
656 ``HeaderSerializer`` 3. Implement prescribed methods 4. Register your
657 deserializer under appropriate key (in our case
658 ``ExperimenterActionDeserializerKey``) 5. Register your serializer under
659 appropriate key (in our case ``ExperimenterActionSerializerKey``) 6.
660 Done, test your implementation
661
662 **NOTE**: If you don’t know what key should be used with your
663 (de)serializer implementation, please visit `Registration
664 keys <#registration_keys>`__ page.
665
666 Example
667 ~~~~~~~
668
669 Let’s say we have vendor / experimenter action represented by this
670 structure:
671
672 ::
673
674     struct foo_action {
675         uint16_t type;
676         uint16_t length;
677         uint32_t experimenter;
678         uint16_t first;
679         uint16_t second;
680         uint8_t  pad[4];
681     }
682
683 First, we have to augment existing model. We create new module, which
684 imports "``openflow-types.yang``" (don’t forget to update your
685 ``pom.xml`` with api dependency). Now we create foo action identity:
686
687 ::
688
689     import openflow-types {prefix oft;}
690     identity foo {
691         description "Foo action description";
692         base oft:action-base;
693     }
694
695 This will be used as type in our structure. Now we must augment existing
696 action structure, so that we will have the desired fields first and
697 second. In order to create new augmentation, our module has to import
698 "``openflow-action.yang``". The augment should look like this:
699
700 ::
701
702     import openflow-action {prefix ofaction;}
703     augment "/ofaction:actions-container/ofaction:action" {
704         ext:augment-identifier "foo-action";
705             leaf first {
706                 type uint16;
707             }
708             leaf second {
709                 type uint16;
710             }
711         }
712
713 We are finished with model changes. Run mvn clean compile to generate
714 sources. After generation is done, we need to implement our
715 (de)serializer.
716
717 Deserializer:
718
719 ::
720
721     public class FooActionDeserializer extends OFDeserializer<Action> {
722        @Override
723        public Action deserialize(ByteBuf input) {
724            ActionBuilder builder = new ActionBuilder();
725            input.skipBytes(SIZE_OF_SHORT_IN_BYTES); *// we know the type of action*
726            builder.setType(Foo.class);
727            input.skipBytes(SIZE_OF_SHORT_IN_BYTES); *// we don't need length*
728            *// now create experimenterIdAugmentation - so that openflowplugin can
729            differentiate correct vendor codec*
730            ExperimenterIdActionBuilder expIdBuilder = new ExperimenterIdActionBuilder();
731            expIdBuilder.setExperimenter(new ExperimenterId(input.readUnsignedInt()));
732            builder.addAugmentation(ExperimenterIdAction.class, expIdBuilder.build());
733            FooActionBuilder fooBuilder = new FooActionBuilder();
734            fooBuilder.setFirst(input.readUnsignedShort());
735            fooBuilder.setSecond(input.readUnsignedShort());
736            builder.addAugmentation(FooAction.class, fooBuilder.build());
737            input.skipBytes(4); *// padding*
738            return builder.build();
739        }
740     }
741
742 Serializer:
743
744 ::
745
746     public class FooActionSerializer extends OFSerializer<Action> {
747        @Override
748        public void serialize(Action action, ByteBuf outBuffer) {
749            outBuffer.writeShort(FOO_CODE);
750            outBuffer.writeShort(16);
751            *// we don't have to check for ExperimenterIdAction augmentation - our
752            serializer*
753            *// was called based on the vendor / experimenter ID, so we simply write
754            it to buffer*
755            outBuffer.writeInt(VENDOR / EXPERIMENTER ID);
756            FooAction foo = action.getAugmentation(FooAction.class);
757            outBuffer.writeShort(foo.getFirst());
758            outBuffer.writeShort(foo.getSecond());
759            outBuffer.writeZero(4); //write padding
760        }
761     }
762
763 Register both deserializer and serializer:
764 ``SwitchConnectionProvider.registerDeserializer(new
765 ExperimenterActionDeserializerKey(0x04, VENDOR / EXPERIMENTER ID),
766 new FooActionDeserializer());``
767 ``SwitchConnectionProvider.registerSerializer(new
768 ExperimenterActionSerializerKey(0x04, VENDOR / EXPERIMENTER ID),
769 new FooActionSerializer());``
770
771 We are ready to test our implementation.
772
773 **NOTE:** Vendor / Experimenter structures define only vendor /
774 experimenter ID as common distinguisher (besides action type). Vendor /
775 Experimenter ID is unique for all vendor messages - that’s why vendor is
776 able to register only one class under
777 ExperimenterAction(De)SerializerKey. And that’s why vendor has to switch
778 / choose between his subclasses / subtypes on his own.
779
780 Detailed walkthrough: Deserialization extensibility
781 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
782
783 **External interface & class description.**
784
785 **OFGeneralDeserializer:**
786
787 -  ``OFDeserializer<E extends DataObject>``
788
789    -  *deserialize(ByteBuf)* - deserializes given ByteBuf
790
791 -  ``HeaderDeserializer<E extends DataObject>``
792
793    -  *deserializeHeaders(ByteBuf)* - deserializes only E headers (used
794       in Multipart TableFeatures messages)
795
796 **DeserializerRegistryInjector**
797
798 -  ``injectDeserializerRegistry(DeserializerRegistry)`` - injects
799    deserializer registry into deserializer. Useful when custom
800    deserializer needs access to other deserializers.
801
802 **NOTE:** DeserializerRegistryInjector is not OFGeneralDeserializer
803 descendand. It is a standalone interface.
804
805 **MessageCodeKey and its descendants** These keys are used as for
806 deserializer lookup in DeserializerRegistry. MessageCodeKey should is
807 used in general, while its descendants are used in more special cases.
808 For Example ActionDeserializerKey is used for Action deserializer lookup
809 and (de)registration. Vendor is provided with special keys, which
810 contain only the most necessary fields. These keys usually start with
811 "Experimenter" prefix (MatchEntryDeserializerKey is an exception).
812
813 MessageCodeKey has these fields:
814
815 -  short version - Openflow wire version number
816
817 -  int value - value read from byte message
818
819 -  Class<?> clazz - class of object being creating
820
821 -  [1] The scenario starts in a custom bundle which wants to extend
822    library’s functionality. The custom bundle creates deserializers
823    which implement exposed ``OFDeserializer`` / ``HeaderDeserializer``
824    interfaces (wrapped under ``OFGeneralDeserializer`` unifying super
825    interface).
826
827 -  [2] Created deserializers are paired with corresponding
828    ExperimenterKeys, which are used for deserializer lookup. If you
829    don’t know what key should be used with your (de)serializer
830    implementation, please visit `Registration
831    keys <#registration_keys>`__ page.
832
833 -  [3] Paired deserializers are passed to the OF Library via
834    **SwitchConnectionProvider**.\ *registerCustomDeserializer(key,
835    impl)*. Library registers the deserializer.
836
837    -  While registering, Library checks if the deserializer is an
838       instance of **DeserializerRegistryInjector** interface. If yes,
839       the DeserializerRegistry (which stores all deserializer
840       references) is injected into the deserializer.
841
842 This is particularly useful when the deserializer needs access to other
843 deserializers. For example ``IntructionsDeserializer`` needs access to
844 ``ActionsDeserializer`` in order to be able to process
845 OFPIT\_WRITE\_ACTIONS/OFPIT\_APPLY\_ACTIONS instructions.
846
847 .. figure:: ./images/openflowjava/800px-Extensibility.png
848    :alt: Deserialization scenario walkthrough
849
850    Deserialization scenario walkthrough
851
852 Detailed walkthrough: Serialization extensibility
853 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
854
855 **External interface & class description.**
856
857 **OFGeneralSerializer:**
858
859 -  OFSerializer<E extends DataObject>
860
861    -  *serialize(E,ByteBuf)* - serializes E into given ByteBuf
862
863 -  ``HeaderSerializer<E extends DataObject>``
864
865    -  *serializeHeaders(E,ByteBuf)* - serializes E headers (used in
866       Multipart TableFeatures messages)
867
868 **SerializerRegistryInjector** \*
869 ``injectSerializerRegistry(SerializerRegistry)`` - injects serializer
870 registry into serializer. Useful when custom serializer needs access to
871 other serializers.
872
873 **NOTE:** SerializerRegistryInjector is not OFGeneralSerializer
874 descendand.
875
876 **MessageTypeKey and its descendants** These keys are used as for
877 serializer lookup in SerializerRegistry. MessageTypeKey should is used
878 in general, while its descendants are used in more special cases. For
879 Example ActionSerializerKey is used for Action serializer lookup and
880 (de)registration. Vendor is provided with special keys, which contain
881 only the most necessary fields. These keys usually start with
882 "Experimenter" prefix (MatchEntrySerializerKey is an exception).
883
884 MessageTypeKey has these fields:
885
886 -  *short version* - Openflow wire version number
887
888 -  *Class<E> msgType* - DTO class
889
890 Scenario walkthrough
891
892 -  [1] Serialization extensbility principles are similar to the
893    deserialization principles. The scenario starts in a custom bundle.
894    The custom bundle creates serializers which implement exposed
895    OFSerializer / HeaderSerializer interfaces (wrapped under
896    OFGeneralSerializer unifying super interface).
897
898 -  [2] Created serializers are paired with their ExperimenterKeys, which
899    are used for serializer lookup. If you don’t know what key should be
900    used with your serializer implementation, please visit `Registration
901    keys <#registration_keys>`__ page.
902
903 -  [3] Paired serializers are passed to the OF Library via
904    **SwitchConnectionProvider**.\ *registerCustomSerializer(key, impl)*.
905    Library registers the serializer.
906
907 -  While registering, Library checks if the serializer is an instance of
908    **SerializerRegistryInjector** interface. If yes, the
909    SerializerRegistry (which stores all serializer references) is
910    injected into the serializer.
911
912 This is particularly useful when the serializer needs access to other
913 deserializers. For example IntructionsSerializer needs access to
914 ActionsSerializer in order to be able to process
915 OFPIT\_WRITE\_ACTIONS/OFPIT\_APPLY\_ACTIONS instructions.
916
917 .. figure:: ./images/openflowjava/800px-Extensibility2.png
918    :alt: Serialization scenario walkthrough
919
920    Serialization scenario walkthrough
921
922 Internal description
923 ~~~~~~~~~~~~~~~~~~~~
924
925 **SwitchConnectionProvider** ``SwitchConnectionProvider`` constructs and
926 initializes both deserializer and serializer registries with default
927 (de)serializers. It also injects the ``DeserializerRegistry`` into the
928 ``DeserializationFactory``, the ``SerializerRegistry`` into the
929 ``SerializationFactory``. When call to register custom (de)serializer is
930 made, ``SwitchConnectionProvider`` calls register method on appropriate
931 registry.
932
933 **DeserializerRegistry / SerializerRegistry** Both registries contain
934 init() method to initialize default (de)serializers. Registration checks
935 if key or (de)serializer implementation are not ``null``. If at least
936 one of the is ``null``, ``NullPointerException`` is thrown. Else the
937 (de)serializer implementation is checked if it is
938 ``(De)SerializerRegistryInjector`` instance. If it is an instance of
939 this interface, the registry is injected into this (de)serializer
940 implementation.
941
942 ``GetSerializer(key)`` or ``GetDeserializer(key)`` performs registry
943 lookup. Because there are two separate interfaces that might be put into
944 the registry, the registry uses their unifying super interface.
945 Get(De)Serializer(key) method casts the super interface to desired type.
946 There is also a null check for the (de)serializer received from the
947 registry. If the deserializer wasn’t found, ``NullPointerException``
948 with key description is thrown.
949
950 Registration keys
951 ~~~~~~~~~~~~~~~~~
952
953 **Deserialization.**
954
955 **Possible openflow extensions and their keys**
956
957 There are three vendor specific extensions in Openflow v1.0 and eight in
958 Openflow v1.3. These extensions are registered under registration keys,
959 that are shown in table below:
960
961 +----------------+---------+------------------------------+-----------------------+
962 | Extension type | OpenFlo | Registration key             | Utility class         |
963 |                | w       |                              |                       |
964 +================+=========+==============================+=======================+
965 | Vendor message | 1.0     | ExperimenterIdDeserializerKe | ExperimenterDeseriali |
966 |                |         | y(1,                         | zerKeyFactory         |
967 |                |         | experimenterId,              |                       |
968 |                |         | ExperimenterMessage.class)   |                       |
969 +----------------+---------+------------------------------+-----------------------+
970 | Action         | 1.0     | ExperimenterActionDeserializ | .                     |
971 |                |         | erKey(1,                     |                       |
972 |                |         | experimenter ID)             |                       |
973 +----------------+---------+------------------------------+-----------------------+
974 | Stats message  | 1.0     | ExperimenterMultipartReplyMe | ExperimenterDeseriali |
975 |                |         | ssageDeserializerKey(1,      | zerKeyFactory         |
976 |                |         | experimenter ID)             |                       |
977 +----------------+---------+------------------------------+-----------------------+
978 | Experimenter   | 1.3     | ExperimenterIdDeserializerKe | ExperimenterDeseriali |
979 | message        |         | y(4,                         | zerKeyFactory         |
980 |                |         | experimenterId,              |                       |
981 |                |         | ExperimenterMessage.class)   |                       |
982 +----------------+---------+------------------------------+-----------------------+
983 | Match entry    | 1.3     | MatchEntryDeserializerKey(4, | .                     |
984 |                |         | (number) ${oxm\_class},      |                       |
985 |                |         | (number) ${oxm\_field});     |                       |
986 +----------------+---------+------------------------------+-----------------------+
987 |                |         | key.setExperimenterId(experi | .                     |
988 |                |         | menter                       |                       |
989 |                |         | ID);                         |                       |
990 +----------------+---------+------------------------------+-----------------------+
991 | Action         | 1.3     | ExperimenterActionDeserializ | .                     |
992 |                |         | erKey(4,                     |                       |
993 |                |         | experimenter ID)             |                       |
994 +----------------+---------+------------------------------+-----------------------+
995 | Instruction    | 1.3     | ExperimenterInstructionDeser | .                     |
996 |                |         | ializerKey(4,                |                       |
997 |                |         | experimenter ID)             |                       |
998 +----------------+---------+------------------------------+-----------------------+
999 | Multipart      | 1.3     | ExperimenterIdDeserializerKe | ExperimenterDeseriali |
1000 |                |         | y(4,                         | zerKeyFactory         |
1001 |                |         | experimenterId,              |                       |
1002 |                |         | MultipartReplyMessage.class) |                       |
1003 +----------------+---------+------------------------------+-----------------------+
1004 | Multipart -    | 1.3     | ExperimenterIdDeserializerKe | ExperimenterDeseriali |
1005 | Table features |         | y(4,                         | zerKeyFactory         |
1006 |                |         | experimenterId,              |                       |
1007 |                |         | TableFeatureProperties.class |                       |
1008 |                |         | )                            |                       |
1009 +----------------+---------+------------------------------+-----------------------+
1010 | Error          | 1.3     | ExperimenterIdDeserializerKe | ExperimenterDeseriali |
1011 |                |         | y(4,                         | zerKeyFactory         |
1012 |                |         | experimenterId,              |                       |
1013 |                |         | ErrorMessage.class)          |                       |
1014 +----------------+---------+------------------------------+-----------------------+
1015 | Queue property | 1.3     | ExperimenterIdDeserializerKe | ExperimenterDeseriali |
1016 |                |         | y(4,                         | zerKeyFactory         |
1017 |                |         | experimenterId,              |                       |
1018 |                |         | QueueProperty.class)         |                       |
1019 +----------------+---------+------------------------------+-----------------------+
1020 | Meter band     | 1.3     | ExperimenterIdDeserializerKe | ExperimenterDeseriali |
1021 | type           |         | y(4,                         | zerKeyFactory         |
1022 |                |         | experimenterId,              |                       |
1023 |                |         | MeterBandExperimenterCase.cl |                       |
1024 |                |         | ass)                         |                       |
1025 +----------------+---------+------------------------------+-----------------------+
1026
1027 Table: **Deserialization**
1028
1029 **Serialization.**
1030
1031 **Possible openflow extensions and their keys**
1032
1033 There are three vendor specific extensions in Openflow v1.0 and seven
1034 Openflow v1.3. These extensions are registered under registration keys,
1035 that are shown in table below:
1036
1037 +----------------+---------+------------------------------+-----------------------+
1038 | Extension type | OpenFlo | Registration key             | Utility class         |
1039 |                | w       |                              |                       |
1040 +================+=========+==============================+=======================+
1041 | Vendor message | 1.0     | ExperimenterIdSerializerKey< | ExperimenterSerialize |
1042 |                |         | >(1,                         | rKeyFactory           |
1043 |                |         | experimenterId,              |                       |
1044 |                |         | ExperimenterInput.class)     |                       |
1045 +----------------+---------+------------------------------+-----------------------+
1046 | Action         | 1.0     | ExperimenterActionSerializer | .                     |
1047 |                |         | Key(1,                       |                       |
1048 |                |         | experimenterId, sub-type)    |                       |
1049 +----------------+---------+------------------------------+-----------------------+
1050 | Stats message  | 1.0     | ExperimenterMultipartRequest | ExperimenterSerialize |
1051 |                |         | SerializerKey(1,             | rKeyFactory           |
1052 |                |         | experimenter ID)             |                       |
1053 +----------------+---------+------------------------------+-----------------------+
1054 | Experimenter   | 1.3     | ExperimenterIdSerializerKey< | ExperimenterSerialize |
1055 | message        |         | >(4,                         | rKeyFactory           |
1056 |                |         | experimenterId,              |                       |
1057 |                |         | ExperimenterInput.class)     |                       |
1058 +----------------+---------+------------------------------+-----------------------+
1059 | Match entry    | 1.3     | MatchEntrySerializerKey<>(4, | .                     |
1060 |                |         | (class) ${oxm\_class},       |                       |
1061 |                |         | (class) ${oxm\_field});      |                       |
1062 +----------------+---------+------------------------------+-----------------------+
1063 |                |         | key.setExperimenterId(experi | .                     |
1064 |                |         | menter                       |                       |
1065 |                |         | ID)                          |                       |
1066 +----------------+---------+------------------------------+-----------------------+
1067 | Action         | 1.3     | ExperimenterActionSerializer | .                     |
1068 |                |         | Key(4,                       |                       |
1069 |                |         | experimenterId, sub-type)    |                       |
1070 +----------------+---------+------------------------------+-----------------------+
1071 | Instruction    | 1.3     | ExperimenterInstructionSeria | .                     |
1072 |                |         | lizerKey(4,                  |                       |
1073 |                |         | experimenter ID)             |                       |
1074 +----------------+---------+------------------------------+-----------------------+
1075 | Multipart      | 1.3     | ExperimenterIdSerializerKey< | ExperimenterSerialize |
1076 |                |         | >(4,                         | rKeyFactory           |
1077 |                |         | experimenterId,              |                       |
1078 |                |         | MultipartRequestExperimenter |                       |
1079 |                |         | Case.class)                  |                       |
1080 +----------------+---------+------------------------------+-----------------------+
1081 | Multipart -    | 1.3     | ExperimenterIdSerializerKey< | ExperimenterSerialize |
1082 | Table features |         | >(4,                         | rKeyFactory           |
1083 |                |         | experimenterId,              |                       |
1084 |                |         | TableFeatureProperties.class |                       |
1085 |                |         | )                            |                       |
1086 +----------------+---------+------------------------------+-----------------------+
1087 | Meter band     | 1.3     | ExperimenterIdSerializerKey< | ExperimenterSerialize |
1088 | type           |         | >(4,                         | rKeyFactory           |
1089 |                |         | experimenterId,              |                       |
1090 |                |         | MeterBandExperimenterCase.cl |                       |
1091 |                |         | ass)                         |                       |
1092 +----------------+---------+------------------------------+-----------------------+
1093
1094 Table: **Serialization**
1095