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