Remove jenkins links and git clone from OFP docs
[docs.git] / docs / developer-guide / openflow-plugin-project-developer-guide.rst
1 OpenFlow Plugin Project Developer Guide
2 =======================================
3
4 This section covers topics which are developer specific and which have
5 not been covered in the user guide. Please see the OpenFlow
6 plugin user guide first.
7
8 It can be found on `the OpenDaylight software download
9 page <https://www.opendaylight.org/downloads>`__.
10
11 Event Sequences
12 ---------------
13
14 Session Establishment
15 ~~~~~~~~~~~~~~~~~~~~~
16
17 The :ref:`OpenFlow Protocol
18 Library <openflow-protocol-library>` provides
19 interface **SwitchConnectionHandler** which contains method
20 *onSwitchConnected* (step 1). This event is raised in the OpenFlow
21 Protocol Library when an OpenFlow device connects to OpenDaylight and
22 caught in the **ConnectionManagerImpl** class in the OpenFlow plugin.
23
24 There the plugin creates a new instance of the **ConnectionContextImpl**
25 class (step 1.1) and also instances of **HandshakeManagerImpl** (which
26 uses **HandshakeListenerImpl**) and **ConnectionReadyListenerImpl**.
27 **ConnectionReadyListenerImpl** contains method *onConnectionReady()*
28 which is called when connection is prepared. This method starts the
29 handshake with the OpenFlow device (switch) from the OpenFlow plugin
30 side. Then handshake can be also started from device side. In this case
31 method *shake()* from **HandshakeManagerImpl** is called (steps 1.1.1
32 and 2).
33
34 The handshake consists of an exchange of HELLO messages in addition to
35 an exchange of device features (steps 2.1. and 3). The handshake is
36 completed by **HandshakeManagerImpl**. After receiving device features,
37 the **HandshakeListenerImpl** is notifed via the
38 *onHanshakeSuccessfull()* method. After this, the device features, node
39 id and connection state are stored in a **ConnectionContext** and the
40 method *deviceConnected()* of **DeviceManagerImpl** is called.
41
42 When *deviceConnected()* is called, it does the following:
43
44 1. creates a new transaction chain (step 4.1)
45
46 2. creates a new instance of **DeviceContext** (step 4.2.2)
47
48 3. initializes the device context: the static context of device is
49    populated by calling *createDeviceFeaturesForOF<version>()* to
50    populate table, group, meter features and port descriptions (step
51    4.2.1 and 4.2.1.1)
52
53 4. creates an instance of **RequestContext** for each type of feature
54
55 When the OpenFlow device responds to these requests (step 4.2.1.1) with
56 multipart replies (step 5) they are processed and stored to MD-SAL
57 operational datastore. The *createDeviceFeaturesForOF<version>()* method
58 returns a **Future** which is processed in the callback (step 5.1) (part
59 of *initializeDeviceContext()* in the *deviceConnected()* method) by
60 calling the method *onDeviceCtxLevelUp()* from **StatisticsManager**
61 (step 5.1.1).
62
63 The call to *createDeviceFeaturesForOF<version>()*: . creates a new
64 instance of **StatisticsContextImpl** (step 5.1.1.1).
65
66 1. calls *gatherDynamicStatistics()* on that instance which returns a
67    **Future** which will produce a value when done
68
69    a. this method calls methods to get dynamic data (flows, tables,
70       groups) from the device (step 5.1.1.2, 5.1.1.2.1, 5.1.1.2.1.1)
71
72    b. if everything works, this data is also stored in the MD-SAL
73       operational datastore
74
75 If the **Future** is successful, it is processed (step 6.1.1) in a
76 callback in **StatisticsManagerImpl** which:
77
78 1. schedules the next time to poll the device for statistics
79
80 2. sets the device state to synchronized (step 6.1.1.2)
81
82 3. calls *onDeviceContextLevelUp()* in **RpcManagerImpl**
83
84 The *onDeviceContextLevelUp()* call:
85
86 1. creates a new instance of **RequestContextImpl**
87
88 2. registers implementation for supported services
89
90 3. calls *onDeviceContextLevelUp()* in **DeviceManagerImpl** (step
91    6.1.1.2.1.2) which causes the information about the new device be be
92    written to the MD-SAL operational datastore (step 6.1.1.2.2)
93
94 .. figure:: ./images/openflowplugin/odl-ofp-session-establishment.jpg
95    :alt: Session establishment
96
97    Session establishment
98
99 Handshake
100 ~~~~~~~~~
101
102 The first thing that happens when an OpenFlow device connects to
103 OpenDaylight is that the OpenFlow plugin gathers basic information about
104 the device and establishes agreement on key facts like the version of
105 OpenFlow which will be used. This process is called the handshake.
106
107 The handshake starts with HELLO message which can be sent either by the
108 OpenFlow device or the OpenFlow plugin. After this, there are several
109 scenarios which can happen:
110
111 1. if the first HELLO message contains a *version bitmap*, it is
112    possible to determine if there is a common version of OpenFlow or
113    not:
114
115    a. if there is a single common version use it and the **VERSION IS
116       SETTLED**
117
118    b. if there are more than one common versions, use the highest
119       (newest) protocol and the **VERSION IS SETTLED**
120
121    c. if there are no common versions, the device is **DISCONNECTED**
122
123 2. if the first HELLO message does not contain a *version bitmap*, then
124    STEB-BY-STEP negotiation is used
125
126 3. if second (or more) HELLO message is received, then STEP-BY-STEP
127    negotiation is used
128
129 STEP-BY-STEP negotiation:
130 ^^^^^^^^^^^^^^^^^^^^^^^^^
131
132 -  if last version proposed by the OpenFlow plugin is the same as the
133    version received from the OpenFlow device, then the **VERSION IS
134    SETTLED**
135
136 -  if the version received in the current HELLO message from the device
137    is the same as from previous then negotiation has failed and the
138    device is **DISCONNECTED**
139
140 -  if the last version from the device is greater than the last version
141    proposed from the plugin, wait for the next HELLO message in the hope
142    that it will advertise support for a lower version
143
144 -  if the last version from the device is is less than the last version
145    proposed from the plugin:
146
147    -  propose the highest version the plugin supports that is less than
148       or equal to the version received from the device and wait for the
149       next HELLO message
150
151    -  if if the plugin doesn’t support a lower version, the device is
152       **DISCONNECTED**
153
154 After selecting of version we can say that the **VERSION IS SETTLED**
155 and the OpenFlow plugin can ask device for its features. At this point
156 handshake ends.
157
158 .. figure:: ./images/openflowplugin/odl-ofp-handshake.png
159    :alt: Handshake process
160
161    Handshake process
162
163 Adding a Flow
164 ~~~~~~~~~~~~~
165
166 There are two ways to add a flow in in the OpenFlow plugin: adding it to
167 the MD-SAL config datastore or calling an RPC. Both of these can either
168 be done using the native MD-SAL interfaces or using RESTCONF. This
169 discussion focuses on calling the RPC.
170
171 If user send flow via REST interface (step 1) it will cause that
172 *invokeRpc()* is called on **RpcBroker**. The **RpcBroker** then looks
173 for an appropriate implementation of the interface. In the case of the
174 OpenFlow plugin, this is the *addFlow()* method of
175 **SalFlowServiceImpl** (step 1.1). The same thing happens if the RPC is
176 called directly from the native MD-SAL interfaces.
177
178 The *addFlow()* method then
179
180 1. calls the *commitEntry()* method (step 2) from the OpenFlow Protocol
181    Library which is responsible for sending the flow to the device
182
183 2. creates a new **RequestContext** by calling *createRequestContext()*
184    (step 3)
185
186 3. creates a callback to handle any events that happen because of
187    sending the flow to the device
188
189 The callback method is triggered when a barrier reply message (step 2.1)
190 is received from the device indicating that the flow was either
191 installed or an appropriate error message was sent. If the flow was
192 successfully sent to the device, the RPC result is set to success (step
193 5). // **SalFlowService** contains inside method *addFlow()* other
194 callback which caught notification from callback for barrier message.
195
196 At this point, no information pertaining to the flow has been added to
197 the MD-SAL operational datastore. That is accomplished by the periodic
198 gathering of statistics from OpenFlow devices.
199
200 The **StatisticsContext** for each given OpenFlow device periodically
201 polls it using *gatherStatistics()* of **StatisticsGatheringUtil** which
202 issues an OpenFlow OFPT\_MULTIPART\_REQUEST - OFPMP\_FLOW. The response
203 to this request (step 7) is processed in **StatisticsGatheringUtil**
204 class where flow data is written to the MD-SAL operational datastore via
205 the *writeToTransaction()* method of **DeviceContext**.
206
207 .. figure:: ./images/openflowplugin/odl-ofp-add-flow.png
208    :alt: Add flow
209
210    Add flow
211
212 Description of OpenFlow Plugin Modules
213 --------------------------------------
214
215 The OpenFlow plugin project contains a variety of OpenDaylight modules,
216 which are loaded using the configuration subsystem. This section
217 describes the YANG files used to model each module.
218
219 **General model (interfaces)** - openflow-plugin-cfg.yang.
220
221 -  the provided module is defined (``identity openflow-provider``)
222
223 -  and target implementation is assigned (``...OpenflowPluginProvider``)
224
225 .. code:: yang
226
227     module openflow-provider {
228        yang-version 1;
229        namespace "urn:opendaylight:params:xml:ns:yang:openflow:common:config[urn:opendaylight:params:xml:ns:yang:openflow:common:config]";
230        prefix "ofplugin-cfg";
231
232        import config {prefix config; revision-date 2013-04-05; }
233        description
234            "openflow-plugin-custom-config";
235        revision "2014-03-26" {
236            description
237                "Initial revision";
238        }
239        identity openflow-provider{
240            base config:service-type;
241            config:java-class "org.opendaylight.openflowplugin.openflow.md.core.sal.OpenflowPluginProvider";
242        }
243     }
244
245 **Implementation model** - openflow-plugin-cfg-impl.yang
246
247 -  the implementation of module is defined
248    (``identity openflow-provider-impl``)
249
250    -  class name of generated implementation is defined
251       (ConfigurableOpenFlowProvider)
252
253 -  via augmentation the configuration of module is defined:
254
255    -  this module requires instance of binding-aware-broker
256       (``container binding-aware-broker``)
257
258    -  and list of openflow-switch-connection-provider (those are
259       provided by openflowjava, one plugin instance will orchestrate
260       multiple openflowjava modules)
261
262 .. code:: yang
263
264     module openflow-provider-impl {
265        yang-version 1;
266        namespace "urn:opendaylight:params:xml:ns:yang:openflow:common:config:impl[urn:opendaylight:params:xml:ns:yang:openflow:common:config:impl]";
267        prefix "ofplugin-cfg-impl";
268
269        import config {prefix config; revision-date 2013-04-05;}
270        import openflow-provider {prefix openflow-provider;}
271        import openflow-switch-connection-provider {prefix openflow-switch-connection-provider;revision-date 2014-03-28;}
272        import opendaylight-md-sal-binding { prefix md-sal-binding; revision-date 2013-10-28;}
273
274
275        description
276            "openflow-plugin-custom-config-impl";
277
278        revision "2014-03-26" {
279            description
280                "Initial revision";
281        }
282
283        identity openflow-provider-impl {
284            base config:module-type;
285            config:provided-service openflow-provider:openflow-provider;
286            config:java-name-prefix ConfigurableOpenFlowProvider;
287        }
288
289        augment "/config:modules/config:module/config:configuration" {
290            case openflow-provider-impl {
291                when "/config:modules/config:module/config:type = 'openflow-provider-impl'";
292
293                container binding-aware-broker {
294                    uses config:service-ref {
295                        refine type {
296                            mandatory true;
297                            config:required-identity md-sal-binding:binding-broker-osgi-registry;
298                        }
299                    }
300                }
301                list openflow-switch-connection-provider {
302                    uses config:service-ref {
303                        refine type {
304                            mandatory true;
305                            config:required-identity openflow-switch-connection-provider:openflow-switch-connection-provider;
306                        }
307                    }
308                }
309            }
310        }
311     }
312
313 Generating config and sal classes out of yangs
314 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
315
316 In order to involve suitable code generators, this is needed in pom:
317
318 .. code:: xml
319
320     <build> ...
321       <plugins>
322         <plugin>
323           <groupId>org.opendaylight.yangtools</groupId>
324           <artifactId>yang-maven-plugin</artifactId>
325           <executions>
326             <execution>
327               <goals>
328                 <goal>generate-sources</goal>
329               </goals>
330               <configuration>
331                 <codeGenerators>
332                   <generator>
333                     <codeGeneratorClass>
334                       org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator
335                     </codeGeneratorClass>
336                     <outputBaseDir>${project.build.directory}/generated-sources/config</outputBaseDir>
337                     <additionalConfiguration>
338                       <namespaceToPackage1>
339                         urn:opendaylight:params:xml:ns:yang:controller==org.opendaylight.controller.config.yang
340                       </namespaceToPackage1>
341                     </additionalConfiguration>
342                   </generator>
343                   <generator>
344                     <codeGeneratorClass>
345                       org.opendaylight.yangtools.maven.sal.api.gen.plugin.CodeGeneratorImpl
346                     </codeGeneratorClass>
347                     <outputBaseDir>${project.build.directory}/generated-sources/sal</outputBaseDir>
348                   </generator>
349                   <generator>
350                     <codeGeneratorClass>org.opendaylight.yangtools.yang.unified.doc.generator.maven.DocumentationGeneratorImpl</codeGeneratorClass>
351                     <outputBaseDir>${project.build.directory}/site/models</outputBaseDir>
352                   </generator>
353                 </codeGenerators>
354                 <inspectDependencies>true</inspectDependencies>
355               </configuration>
356             </execution>
357           </executions>
358           <dependencies>
359             <dependency>
360               <groupId>org.opendaylight.controller</groupId>
361               <artifactId>yang-jmx-generator-plugin</artifactId>
362               <version>0.2.5-SNAPSHOT</version>
363             </dependency>
364             <dependency>
365               <groupId>org.opendaylight.yangtools</groupId>
366               <artifactId>maven-sal-api-gen-plugin</artifactId>
367               <version>${yangtools.version}</version>
368               <type>jar</type>
369             </dependency>
370           </dependencies>
371         </plugin>
372         ...
373
374 -  JMX generator (target/generated-sources/config)
375
376 -  sal CodeGeneratorImpl (target/generated-sources/sal)
377
378 Altering generated files
379 ~~~~~~~~~~~~~~~~~~~~~~~~
380
381 Those files were generated under src/main/java in package as referred in
382 yangs (if exist, generator will not overwrite them):
383
384 -  ConfigurableOpenFlowProviderModuleFactory
385
386        here the **instantiateModule** methods are extended in order to
387        capture and inject osgi BundleContext into module, so it can be
388        injected into final implementation - **OpenflowPluginProvider** +
389        ``module.setBundleContext(bundleContext);``
390
391 -  ConfigurableOpenFlowProviderModule
392
393        here the **createInstance** method is extended in order to inject
394        osgi BundleContext into module implementation +
395        ``pluginProvider.setContext(bundleContext);``
396
397 Configuration xml file
398 ~~~~~~~~~~~~~~~~~~~~~~
399
400 Configuration file contains
401
402 -  required capabilities
403
404    -  modules definitions from openflowjava
405
406    -  modules definitions from openflowplugin
407
408 -  modules definition
409
410    -  openflow:switch:connection:provider:impl (listening on port 6633,
411       name=openflow-switch-connection-provider-legacy-impl)
412
413    -  openflow:switch:connection:provider:impl (listening on port 6653,
414       name=openflow-switch-connection-provider-default-impl)
415
416    -  openflow:common:config:impl (having 2 services (wrapping those 2
417       previous modules) and binding-broker-osgi-registry injected)
418
419 -  provided services
420
421    -  openflow-switch-connection-provider-default
422
423    -  openflow-switch-connection-provider-legacy
424
425    -  openflow-provider
426
427 .. code:: xml
428
429     <snapshot>
430      <required-capabilities>
431        <capability>urn:opendaylight:params:xml:ns:yang:openflow:switch:connection:provider:impl?module=openflow-switch-connection-provider-impl&revision=2014-03-28</capability>
432        <capability>urn:opendaylight:params:xml:ns:yang:openflow:switch:connection:provider?module=openflow-switch-connection-provider&revision=2014-03-28</capability>
433        <capability>urn:opendaylight:params:xml:ns:yang:openflow:common:config:impl?module=openflow-provider-impl&revision=2014-03-26</capability>
434        <capability>urn:opendaylight:params:xml:ns:yang:openflow:common:config?module=openflow-provider&revision=2014-03-26</capability>
435      </required-capabilities>
436
437      <configuration>
438
439
440          <modules xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
441            <module>
442              <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:openflow:switch:connection:provider:impl">prefix:openflow-switch-connection-provider-impl</type>
443              <name>openflow-switch-connection-provider-default-impl</name>
444              <port>6633</port>
445              <switch-idle-timeout>15000</switch-idle-timeout>
446            </module>
447            <module>
448              <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:openflow:switch:connection:provider:impl">prefix:openflow-switch-connection-provider-impl</type>
449              <name>openflow-switch-connection-provider-legacy-impl</name>
450              <port>6653</port>
451              <switch-idle-timeout>15000</switch-idle-timeout>
452            </module>
453
454
455            <module>
456              <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:openflow:common:config:impl">prefix:openflow-provider-impl</type>
457              <name>openflow-provider-impl</name>
458
459              <openflow-switch-connection-provider>
460                <type xmlns:ofSwitch="urn:opendaylight:params:xml:ns:yang:openflow:switch:connection:provider">ofSwitch:openflow-switch-connection-provider</type>
461                <name>openflow-switch-connection-provider-default</name>
462              </openflow-switch-connection-provider>
463              <openflow-switch-connection-provider>
464                <type xmlns:ofSwitch="urn:opendaylight:params:xml:ns:yang:openflow:switch:connection:provider">ofSwitch:openflow-switch-connection-provider</type>
465                <name>openflow-switch-connection-provider-legacy</name>
466              </openflow-switch-connection-provider>
467
468
469              <binding-aware-broker>
470                <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-broker-osgi-registry</type>
471                <name>binding-osgi-broker</name>
472              </binding-aware-broker>
473            </module>
474          </modules>
475
476          <services xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
477            <service>
478              <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:openflow:switch:connection:provider">prefix:openflow-switch-connection-provider</type>
479              <instance>
480                <name>openflow-switch-connection-provider-default</name>
481                <provider>/modules/module[type='openflow-switch-connection-provider-impl'][name='openflow-switch-connection-provider-default-impl']</provider>
482              </instance>
483              <instance>
484                <name>openflow-switch-connection-provider-legacy</name>
485                <provider>/modules/module[type='openflow-switch-connection-provider-impl'][name='openflow-switch-connection-provider-legacy-impl']</provider>
486              </instance>
487            </service>
488
489            <service>
490              <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:openflow:common:config">prefix:openflow-provider</type>
491              <instance>
492                <name>openflow-provider</name>
493                <provider>/modules/module[type='openflow-provider-impl'][name='openflow-provider-impl']</provider>
494              </instance>
495            </service>
496          </services>
497
498
499      </configuration>
500     </snapshot>
501
502 API changes
503 ~~~~~~~~~~~
504
505 In order to provide multiple instances of modules from openflowjava
506 there is an API change. Previously OFPlugin got access to
507 SwitchConnectionProvider exposed by OFJava and injected collection of
508 configurations so that for each configuration new instance of tcp
509 listening server was created. Now those configurations are provided by
510 configSubsystem and configured modules (wrapping the original
511 SwitchConnectionProvider) are injected into OFPlugin (wrapping
512 SwitchConnectionHandler).
513
514 Providing config file (IT, local distribution/base, integration/distributions/base)
515 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
516
517 openflowplugin-it
518 ^^^^^^^^^^^^^^^^^
519
520 Here the whole configuration is contained in one file (controller.xml).
521 Required entries needed in order to startup and wire OEPlugin + OFJava
522 are simply added there.
523
524 OFPlugin/distribution/base
525 ^^^^^^^^^^^^^^^^^^^^^^^^^^
526
527 Here new config file has been added
528 (src/main/resources/configuration/initial/42-openflow-protocol-impl.xml)
529 and is being copied to config/initial subfolder of build.
530
531 integration/distributions/build
532 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
533
534 In order to push the actual config into config/initial subfolder of
535 distributions/base in integration project there was a new artifact in
536 OFPlugin created - **openflowplugin-controller-config**, containing only
537 the config xml file under src/main/resources. Another change was
538 committed into integration project. During build this config xml is
539 being extracted and copied to the final folder in order to be accessible
540 during controller run.
541
542 Internal message statistics API
543 -------------------------------
544
545 To aid in testing and diagnosis, the OpenFlow plugin provides
546 information about the number and rate of different internal events.
547
548 The implementation does two things: collects event counts and exposes
549 counts. Event counts are grouped by message type, e.g.,
550 **PacketInMessage**, and checkpoint, e.g.,
551 *TO\_SWITCH\_ENQUEUED\_SUCCESS*. Once gathered, the results are logged
552 as well as being exposed using OSGi command line (deprecated) and JMX.
553
554 Collect
555 ~~~~~~~
556
557 Each message is counted as it passes through various processing
558 checkpoints. The following checkpoints are defined as a Java enum and
559 tracked:
560
561 .. code:: java
562
563       /**
564         * statistic groups overall in OFPlugin
565         */
566       enum STATISTIC_GROUP {
567            /** message from switch, enqueued for processing */
568            FROM_SWITCH_ENQUEUED,
569            /** message from switch translated successfully - source */
570            FROM_SWITCH_TRANSLATE_IN_SUCCESS,
571            /** message from switch translated successfully - target */
572            FROM_SWITCH_TRANSLATE_OUT_SUCCESS,
573            /** message from switch where translation failed - source */
574            FROM_SWITCH_TRANSLATE_SRC_FAILURE,
575            /** message from switch finally published into MD-SAL */
576            FROM_SWITCH_PUBLISHED_SUCCESS,
577            /** message from switch - publishing into MD-SAL failed */
578            FROM_SWITCH_PUBLISHED_FAILURE,
579
580            /** message from MD-SAL to switch via RPC enqueued */
581            TO_SWITCH_ENQUEUED_SUCCESS,
582            /** message from MD-SAL to switch via RPC NOT enqueued */
583            TO_SWITCH_ENQUEUED_FAILED,
584            /** message from MD-SAL to switch - sent to OFJava successfully */
585            TO_SWITCH_SUBMITTED_SUCCESS,
586            /** message from MD-SAL to switch - sent to OFJava but failed*/
587            TO_SWITCH_SUBMITTED_FAILURE
588       }
589
590 When a message passes through any of those checkpoints then counter
591 assigned to corresponding checkpoint and message is incremented by 1.
592
593 Expose statistics
594 ~~~~~~~~~~~~~~~~~
595
596 As described above, there are three ways to access the statistics:
597
598 -  OSGi command line (this is considered deprecated)
599
600        ``osgi> dumpMsgCount``
601
602 -  OpenDaylight logging console (statistics are logged here every 10
603    seconds)
604
605        required logback settings :
606        ``<logger name="org.opendaylight.openflowplugin.openflow.md.queue.MessageSpyCounterImpl" level="DEBUG"\/>``
607
608 -  JMX (via JConsole)
609
610        start OpenFlow plugin with the ``-jmx`` parameter
611
612        start JConsole by running ``jconsole``
613
614        the JConsole MBeans tab should contain
615        org.opendaylight.controller
616
617        RuntimeBean has a msg-spy-service-impl
618
619        Operations provides makeMsgStatistics report functionality
620
621 Example results
622 ^^^^^^^^^^^^^^^
623
624 .. figure:: ./images/openflowplugin/odl-ofp-ofplugin-debug-stats.png
625    :alt: OFplugin Debug stats.png
626
627    OFplugin Debug stats.png
628
629 ::
630
631     DEBUG o.o.o.s.MessageSpyCounterImpl - FROM_SWITCH_ENQUEUED: MSG[PortStatusMessage] -> +0 | 1
632     DEBUG o.o.o.s.MessageSpyCounterImpl - FROM_SWITCH_ENQUEUED: MSG[MultipartReplyMessage] -> +24 | 81
633     DEBUG o.o.o.s.MessageSpyCounterImpl - FROM_SWITCH_ENQUEUED: MSG[PacketInMessage] -> +8 | 111
634     DEBUG o.o.o.s.MessageSpyCounterImpl - FROM_SWITCH_TRANSLATE_IN_SUCCESS: MSG[PortStatusMessage] -> +0 | 1
635     DEBUG o.o.o.s.MessageSpyCounterImpl - FROM_SWITCH_TRANSLATE_IN_SUCCESS: MSG[MultipartReplyMessage] -> +24 | 81
636     DEBUG o.o.o.s.MessageSpyCounterImpl - FROM_SWITCH_TRANSLATE_IN_SUCCESS: MSG[PacketInMessage] -> +8 | 111
637     DEBUG o.o.o.s.MessageSpyCounterImpl - FROM_SWITCH_TRANSLATE_OUT_SUCCESS: MSG[QueueStatisticsUpdate] -> +3 | 7
638     DEBUG o.o.o.s.MessageSpyCounterImpl - FROM_SWITCH_TRANSLATE_OUT_SUCCESS: MSG[NodeUpdated] -> +0 | 3
639     DEBUG o.o.o.s.MessageSpyCounterImpl - FROM_SWITCH_TRANSLATE_OUT_SUCCESS: MSG[NodeConnectorStatisticsUpdate] -> +3 | 7
640     DEBUG o.o.o.s.MessageSpyCounterImpl - FROM_SWITCH_TRANSLATE_OUT_SUCCESS: MSG[GroupDescStatsUpdated] -> +3 | 7
641     DEBUG o.o.o.s.MessageSpyCounterImpl - FROM_SWITCH_TRANSLATE_OUT_SUCCESS: MSG[FlowsStatisticsUpdate] -> +3 | 19
642     DEBUG o.o.o.s.MessageSpyCounterImpl - FROM_SWITCH_TRANSLATE_OUT_SUCCESS: MSG[PacketReceived] -> +8 | 111
643     DEBUG o.o.o.s.MessageSpyCounterImpl - FROM_SWITCH_TRANSLATE_OUT_SUCCESS: MSG[MeterFeaturesUpdated] -> +0 | 3
644     DEBUG o.o.o.s.MessageSpyCounterImpl - FROM_SWITCH_TRANSLATE_OUT_SUCCESS: MSG[GroupStatisticsUpdated] -> +3 | 7
645     DEBUG o.o.o.s.MessageSpyCounterImpl - FROM_SWITCH_TRANSLATE_OUT_SUCCESS: MSG[GroupFeaturesUpdated] -> +0 | 3
646     DEBUG o.o.o.s.MessageSpyCounterImpl - FROM_SWITCH_TRANSLATE_OUT_SUCCESS: MSG[MeterConfigStatsUpdated] -> +3 | 7
647     DEBUG o.o.o.s.MessageSpyCounterImpl - FROM_SWITCH_TRANSLATE_OUT_SUCCESS: MSG[MeterStatisticsUpdated] -> +3 | 7
648     DEBUG o.o.o.s.MessageSpyCounterImpl - FROM_SWITCH_TRANSLATE_OUT_SUCCESS: MSG[NodeConnectorUpdated] -> +0 | 12
649     DEBUG o.o.o.s.MessageSpyCounterImpl - FROM_SWITCH_TRANSLATE_OUT_SUCCESS: MSG[FlowTableStatisticsUpdate] -> +3 | 8
650     DEBUG o.o.o.s.MessageSpyCounterImpl - FROM_SWITCH_TRANSLATE_SRC_FAILURE: no activity detected
651     DEBUG o.o.o.s.MessageSpyCounterImpl - FROM_SWITCH_PUBLISHED_SUCCESS: MSG[QueueStatisticsUpdate] -> +3 | 7
652     DEBUG o.o.o.s.MessageSpyCounterImpl - FROM_SWITCH_PUBLISHED_SUCCESS: MSG[NodeUpdated] -> +0 | 3
653     DEBUG o.o.o.s.MessageSpyCounterImpl - FROM_SWITCH_PUBLISHED_SUCCESS: MSG[NodeConnectorStatisticsUpdate] -> +3 | 7
654     DEBUG o.o.o.s.MessageSpyCounterImpl - FROM_SWITCH_PUBLISHED_SUCCESS: MSG[GroupDescStatsUpdated] -> +3 | 7
655     DEBUG o.o.o.s.MessageSpyCounterImpl - FROM_SWITCH_PUBLISHED_SUCCESS: MSG[FlowsStatisticsUpdate] -> +3 | 19
656     DEBUG o.o.o.s.MessageSpyCounterImpl - FROM_SWITCH_PUBLISHED_SUCCESS: MSG[PacketReceived] -> +8 | 111
657     DEBUG o.o.o.s.MessageSpyCounterImpl - FROM_SWITCH_PUBLISHED_SUCCESS: MSG[MeterFeaturesUpdated] -> +0 | 3
658     DEBUG o.o.o.s.MessageSpyCounterImpl - FROM_SWITCH_PUBLISHED_SUCCESS: MSG[GroupStatisticsUpdated] -> +3 | 7
659     DEBUG o.o.o.s.MessageSpyCounterImpl - FROM_SWITCH_PUBLISHED_SUCCESS: MSG[GroupFeaturesUpdated] -> +0 | 3
660     DEBUG o.o.o.s.MessageSpyCounterImpl - FROM_SWITCH_PUBLISHED_SUCCESS: MSG[MeterConfigStatsUpdated] -> +3 | 7
661     DEBUG o.o.o.s.MessageSpyCounterImpl - FROM_SWITCH_PUBLISHED_SUCCESS: MSG[MeterStatisticsUpdated] -> +3 | 7
662     DEBUG o.o.o.s.MessageSpyCounterImpl - FROM_SWITCH_PUBLISHED_SUCCESS: MSG[NodeConnectorUpdated] -> +0 | 12
663     DEBUG o.o.o.s.MessageSpyCounterImpl - FROM_SWITCH_PUBLISHED_SUCCESS: MSG[FlowTableStatisticsUpdate] -> +3 | 8
664     DEBUG o.o.o.s.MessageSpyCounterImpl - FROM_SWITCH_PUBLISHED_FAILURE: no activity detected
665     DEBUG o.o.o.s.MessageSpyCounterImpl - TO_SWITCH_ENQUEUED_SUCCESS: MSG[AddFlowInput] -> +0 | 12
666     DEBUG o.o.o.s.MessageSpyCounterImpl - TO_SWITCH_ENQUEUED_FAILED: no activity detected
667     DEBUG o.o.o.s.MessageSpyCounterImpl - TO_SWITCH_SUBMITTED_SUCCESS: MSG[AddFlowInput] -> +0 | 12
668     DEBUG o.o.o.s.MessageSpyCounterImpl - TO_SWITCH_SUBMITTED_FAILURE: no activity detected
669
670 Application: Forwarding Rules Synchronizer
671 ------------------------------------------
672
673 Basics
674 ~~~~~~
675
676 Description
677 ^^^^^^^^^^^
678
679 Forwarding Rules Synchronizer (FRS) is a newer version of Forwarding
680 Rules Manager (FRM). It was created to solve most shortcomings of FRM.
681 FRS solving errors with retry mechanism. Sending barrier if needed.
682 Using one service for flows, groups and meters. And it has less changes
683 requests send to device since calculating difference and using
684 compression queue.
685
686 It is located in the Java package:
687
688 .. code:: java
689
690     package org.opendaylight.openflowplugin.applications.frsync;
691
692 Listeners
693 ^^^^^^^^^
694
695 -  1x config - FlowCapableNode
696
697 -  1x operational - Node
698
699 System of work
700 ^^^^^^^^^^^^^^
701
702 -  one listener in config datastore waiting for changes
703
704    -  update cache
705
706    -  skip event if operational not present for node
707
708    -  send syncup entry to reactor for synchronization
709
710       -  node added: after part of modification and whole operational
711          snapshot
712
713       -  node updated: after and before part of modification
714
715       -  node deleted: null and before part of modification
716
717 -  one listener in operational datastore waiting for changes
718
719    -  update cache
720
721    -  on device connected
722
723       -  register for cluster services
724
725    -  on device disconnected remove from cache
726
727       -  remove from cache
728
729       -  unregister for cluster services
730
731    -  if registered for reconciliation
732
733       -  do reconciliation through syncup (only when config present)
734
735 -  reactor *(provides syncup w/decorators assembled in this order)*
736
737    -  Cluster decorator - skip action if not master for device
738
739    -  FutureZip decorator (FutureZip extends Future decorator)
740
741       -  Future - run delegate syncup in future - submit task to
742          executor service
743
744       -  FutureZip - provides state compression - compress optimized
745          config delta if waiting for execution with new one
746
747    -  Guard decorator - per device level locking
748
749    -  Retry decorator - register for reconciliation if syncup failed
750
751    -  Reactor impl - calculate diff from after/before parts of syncup
752       entry and execute
753
754 Strategy
755 ^^^^^^^^
756
757 In the *old* FRM uses an incremental strategy with all changes made one
758 by one, where FRS uses a flat batch system with changes made in bulk. It
759 uses one service SalFlatBatchService instead of three (flow, group,
760 meter).
761
762 Boron release
763 ^^^^^^^^^^^^^
764
765 FRS is used in Boron as separate feature and it is not loaded by any
766 other feature. It has to be run separately.
767
768 ::
769
770     odl-openflowplugin-app-forwardingrules-sync
771
772 FRS additions
773 ~~~~~~~~~~~~~
774
775 Retry mechanism
776 ^^^^^^^^^^^^^^^
777
778 -  is started when change request to device return as failed (register
779    for reconcile)
780
781 -  wait for next consistent operational and do reconciliation with
782    actual config (not only diff)
783
784 ZipQueue
785 ^^^^^^^^
786
787 -  only the diff (before/after) between last config changes is sent to
788    device
789
790 -  when there are more config changes for device in a row waiting to be
791    processed they are compressed into one entry (after is still replaced
792    with the latest)
793
794 Cluster-aware
795 ^^^^^^^^^^^^^
796
797 -  FRS is cluster aware using ClusteringSingletonServiceProvider from
798    the MD-SAL
799
800 -  on mastership change reconciliation is done (register for reconcile)
801
802 SalFlatBatchService
803 ^^^^^^^^^^^^^^^^^^^
804
805 FRS uses service with implemented barrier waiting logic between
806 dependent objects
807
808 Service: SalFlatBatchService
809 ----------------------------
810
811 Basics
812 ~~~~~~
813
814 SalFlatBatchService was created along forwardingrules-sync application
815 as the service that should application used by default. This service uses
816 only one input with bag of flow/group/meter objects and their common
817 add/update/remove action. So you practically send only one input (of specific
818 bags) to this service.
819
820 -  interface: *org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.SalFlatBatchService*
821
822 -  implementation: *org.opendaylight.openflowplugin.impl.services.SalFlatBatchServiceImpl*
823
824 -  method: *processFlatBatch(input)*
825
826 -  input: *org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.ProcessFlatBatchInput*
827
828 Usage benefits
829 ^^^^^^^^^^^^^^
830
831 -  possibility to use only one input bag with particular failure analysis preserved
832
833 -  automatic barrier decision (chain+wait)
834
835 -  less RPC routing in cluster environment (since one call encapsulates all others)
836
837 ProcessFlatBatchInput
838 ~~~~~~~~~~~~~~~~~~~~~
839
840 Input for SalFlatBatchService (ProcessFlatBatchInput object) consists of:
841
842 -  node - NodeRef
843
844 -  batch steps - List<Batch> - defined action + bag of objects + order for failures analysis
845
846    -  BatchChoice - yang-modeled action choice (e.g. FlatBatchAddFlowCase) containing batch bag of objects (e.g. flows to be added)
847
848    -  BatchOrder - (integer) order of batch step (should be incremented by single action)
849
850 -  exitOnFirstError - boolean flag
851
852 Workflow
853 ~~~~~~~~
854 #. prepare **list of steps** based on input
855
856 #. **mark barriers** in steps where needed
857
858 #. prepare particular **F/G/M-batch** service calls from **Flat-batch** steps
859
860    -  F/G/M-batch services encapsulate bulk of single service calls
861
862    -  they actually chain barrier after processing all single calls if actual step is marked as barrier-needed
863
864 #. **chain** futures and **start** executing
865
866    - start all actions that can be run simultaneously (chain all on one starting point)
867
868    -  in case there is a step marked as barrier-needed
869
870       -  wait for all fired jobs up to one with barrier
871
872       - merge rpc results (status, errors, batch failures) into single one
873
874       - the latest job with barrier is new starting point for chaining
875
876 Services encapsulation
877 ^^^^^^^^^^^^^^^^^^^^^^
878
879 -  SalFlatBatchService
880
881    -  SalFlowBatchService
882
883       -  SalFlowService
884
885    -  SalGroupBatchService
886
887       -  SalGroupService
888
889    -  SalMeterBatchService
890
891       -  SalMeterService
892
893 Barrier decision
894 ^^^^^^^^^^^^^^^^
895
896 -  decide on actual step and all previous steps since the latest barrier
897
898 -  if condition in table below is satisfied the latest step before actual is marked as barrier-needed
899
900 +---------------------------+------------------------------------------------------------------+
901 | actual step               | previous steps contain                                           |
902 +===========================+==================================================================+
903 | FLOW_ADD *or* FLOW_UPDATE | GROUP_ADD *or* METER_ADD                                         |
904 +---------------------------+------------------------------------------------------------------+
905 | GROUP_ADD                 | GROUP_ADD *or* GROUP_UPDATE                                      |
906 +---------------------------+------------------------------------------------------------------+
907 | GROUP_REMOVE              | FLOW_UPDATE *or* FLOW_REMOVE *or* GROUP_UPDATE *or* GROUP_REMOVE |
908 +---------------------------+------------------------------------------------------------------+
909 | METER_REMOVE              | FLOW_UPDATE *or* FLOW_REMOVE                                     |
910 +---------------------------+------------------------------------------------------------------+
911
912 Error handling
913 ^^^^^^^^^^^^^^
914
915 There is flag in ProcessFlatBatchInput to stop process on the first error.
916
917 -  *true* - if partial step is not successful stop whole processing
918
919 -  *false* (default) - try to process all steps regardless partial results
920
921 If error occurs in any of partial steps upper FlatBatchService call will return as unsuccessful in both cases.
922 However every partial error is attached to general flat batch result along with BatchFailure (contains BatchOrder
923 and BatchItemIdChoice to identify failed step).
924
925 Cluster singleton approach in plugin
926 ------------------------------------
927
928 Basics
929 ~~~~~~
930
931 Description
932 ^^^^^^^^^^^
933
934 The existing OpenDaylight service deployment model assumes symmetric
935 clusters, where all services are activated on all nodes in the cluster.
936 However, many services require that there is a single active service
937 instance per cluster. We call such services *singleton services*. The
938 Entity Ownership Service (EOS) represents the base Leadership choice for
939 one Entity instance. Every Cluster Singleton service **type** must have
940 its own Entity and every Cluster Singleton service **instance** must
941 have its own Entity Candidate. Every registered Entity Candidate should
942 be notified about its actual role. All this "work" is done by MD-SAL so
943 the Openflowplugin need "only" to register as service in
944 **SingletonClusteringServiceProvider** given by MD-SAL.
945
946 Change against using EOS service listener
947 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
948
949 In this new clustering singleton approach plugin uses API from the
950 MD-SAL project: SingletonClusteringService which comes with three
951 methods.
952
953 ::
954
955     instantiateServiceInstance()
956     closeServiceInstance()
957     getIdentifier()
958
959 This service has to be registered to a
960 SingletonClusteringServiceProvider from MD-SAL which take care if
961 mastership is changed in cluster environment.
962
963 First method in SingletonClusteringService is being called when the
964 cluster node becomes a MASTER. Second is being called when status
965 changes to SLAVE or device is disconnected from cluster. Last method
966 plugins returns NodeId as ServiceGroupIdentifier Startup after device is
967 connected
968
969 On the start up the plugin we need to initialize first four managers for
970 each working area providing information and services
971
972 -  Device manager
973
974 -  RPC manager
975
976 -  Role manager
977
978 -  Statistics manager
979
980 After connection the device the listener Device manager get the event
981 and start up to creating the context for this connection. Startup after
982 device connection
983
984 Services are managed by SinlgetonClusteringServiceProvider from MD-SAL
985 project. So in startup we simply create a instance of LifecycleService
986 and register all contexts into it.
987
988 Role change
989 ~~~~~~~~~~~
990
991 Plugin is no longer registered as Entity Ownership Service (EOS)
992 listener therefore does not need to and cannot respond on EOS ownership
993 changes.
994
995 Service start
996 ^^^^^^^^^^^^^
997
998 Services start asynchronously but the start is managed by
999 LifecycleService. If something goes wrong LifecycleService stop starting
1000 services in context and this speeds up the reconnect process. But the
1001 services haven’t changed and plugin need to start all this:
1002
1003 -  Activating transaction chain manager
1004
1005 -  Initial gathering of device statistics
1006
1007 -  Initial submit to DS
1008
1009 -  Sending role MASTER to device
1010
1011 -  RPC services registration
1012
1013 -  Statistics gathering start
1014
1015 Service stop
1016 ^^^^^^^^^^^^
1017
1018 If closeServiceInstance occurred plugin just simply try to store all
1019 unsubmitted transactions and close the transaction chain manager, stop
1020 RPC services, stop Statistics gathering and after that all unregister
1021 txEntity from EOS.
1022
1023 Yang models and API
1024 -------------------
1025
1026 +--------------------------------------------------------+
1027 | Model                                                  |
1028 +========================================================+
1029 | ***Openflow basic types***                             |
1030 +--------------------------------------------------------+
1031 | `opendaylight-table-types.yang <https://git.opendaylig |
1032 | ht.org/gerrit/gitweb?p=openflowplugin.git;f=model/mode |
1033 | l-flow-base/src/main/yang/opendaylight-table-types.yan |
1034 | g;a=blob;hb=refs/heads/stable/boron>`__                |
1035 +--------------------------------------------------------+
1036 | `opendaylight-action-types.yang <https://git.opendayli |
1037 | ght.org/gerrit/gitweb?p=openflowplugin.git;f=model/mod |
1038 | el-flow-base/src/main/yang/opendaylight-action-types.y |
1039 | ang;a=blob;hb=refs/heads/stable/boron>`__              |
1040 +--------------------------------------------------------+
1041 | `opendaylight-flow-types.yang <https://git.opendayligh |
1042 | t.org/gerrit/gitweb?p=openflowplugin.git;f=model/model |
1043 | -flow-base/src/main/yang/opendaylight-flow-types.yang; |
1044 | a=blob;hb=refs/heads/stable/boron>`__                  |
1045 +--------------------------------------------------------+
1046 | `opendaylight-meter-types.yang <https://git.opendaylig |
1047 | ht.org/gerrit/gitweb?p=openflowplugin.git;f=model/mode |
1048 | l-flow-base/src/main/yang/opendaylight-meter-types.yan |
1049 | g;a=blob;hb=refs/heads/stable/boron>`__                |
1050 +--------------------------------------------------------+
1051 | `opendaylight-group-types.yang <https://git.opendaylig |
1052 | ht.org/gerrit/gitweb?p=openflowplugin.git;f=model/mode |
1053 | l-flow-base/src/main/yang/opendaylight-group-types.yan |
1054 | g;a=blob;hb=refs/heads/stable/boron>`__                |
1055 +--------------------------------------------------------+
1056 | `opendaylight-match-types.yang <https://git.opendaylig |
1057 | ht.org/gerrit/gitweb?p=openflowplugin.git;f=model/mode |
1058 | l-flow-base/src/main/yang/opendaylight-match-types.yan |
1059 | g;a=blob;hb=refs/heads/stable/boron>`__                |
1060 +--------------------------------------------------------+
1061 | `opendaylight-port-types.yang <https://git.opendayligh |
1062 | t.org/gerrit/gitweb?p=openflowplugin.git;f=model/model |
1063 | -flow-base/src/main/yang/opendaylight-port-types.yang; |
1064 | a=blob;hb=refs/heads/stable/boron>`__                  |
1065 +--------------------------------------------------------+
1066 | `opendaylight-queue-types.yang <https://git.opendaylig |
1067 | ht.org/gerrit/gitweb?p=openflowplugin.git;f=model/mode |
1068 | l-flow-base/src/main/yang/opendaylight-queue-types.yan |
1069 | g;a=blob;hb=refs/heads/stable/boron>`__                |
1070 +--------------------------------------------------------+
1071 | ***Openflow services***                                |
1072 +--------------------------------------------------------+
1073 | `sal-table.yang <https://git.opendaylight.org/gerrit/g |
1074 | itweb?p=openflowplugin.git;f=model/model-flow-service/ |
1075 | src/main/yang/sal-table.yang;a=blob;hb=refs/heads/stab |
1076 | le/boron>`__                                           |
1077 +--------------------------------------------------------+
1078 | `sal-group.yang <https://git.opendaylight.org/gerrit/g |
1079 | itweb?p=openflowplugin.git;f=model/model-flow-service/ |
1080 | src/main/yang/sal-group.yang;a=blob;hb=refs/heads/stab |
1081 | le/boron>`__                                           |
1082 +--------------------------------------------------------+
1083 | `sal-queue.yang <https://git.opendaylight.org/gerrit/g |
1084 | itweb?p=openflowplugin.git;f=model/model-flow-service/ |
1085 | src/main/yang/sal-queue.yang;a=blob;hb=refs/heads/stab |
1086 | le/boron>`__                                           |
1087 +--------------------------------------------------------+
1088 | `flow-errors.yang <https://git.opendaylight.org/gerrit |
1089 | /gitweb?p=openflowplugin.git;f=model/model-flow-servic |
1090 | e/src/main/yang/flow-errors.yang;a=blob;hb=refs/heads/ |
1091 | stable/boron>`__                                       |
1092 +--------------------------------------------------------+
1093 | `flow-capable-transaction.yang <https://git.opendaylig |
1094 | ht.org/gerrit/gitweb?p=openflowplugin.git;f=model/mode |
1095 | l-flow-service/src/main/yang/flow-capable-transaction. |
1096 | yang;a=blob;hb=refs/heads/stable/boron>`__             |
1097 +--------------------------------------------------------+
1098 | `sal-flow.yang <https://git.opendaylight.org/gerrit/gi |
1099 | tweb?p=openflowplugin.git;f=model/model-flow-service/s |
1100 | rc/main/yang/sal-flow.yang;a=blob;hb=refs/heads/stable |
1101 | /boron>`__                                             |
1102 +--------------------------------------------------------+
1103 | `sal-meter.yang <https://git.opendaylight.org/gerrit/g |
1104 | itweb?p=openflowplugin.git;f=model/model-flow-service/ |
1105 | src/main/yang/sal-meter.yang;a=blob;hb=refs/heads/stab |
1106 | le/boron>`__                                           |
1107 +--------------------------------------------------------+
1108 | `flow-topology-discovery.yang <https://git.opendayligh |
1109 | t.org/gerrit/gitweb?p=openflowplugin.git;f=model/model |
1110 | -flow-service/src/main/yang/flow-topology-discovery.ya |
1111 | ng;a=blob;hb=refs/heads/stable/boron>`__               |
1112 +--------------------------------------------------------+
1113 | `node-errors.yang <https://git.opendaylight.org/gerrit |
1114 | /gitweb?p=openflowplugin.git;f=model/model-flow-servic |
1115 | e/src/main/yang/node-errors.yang;a=blob;hb=refs/heads/ |
1116 | stable/boron>`__                                       |
1117 +--------------------------------------------------------+
1118 | `node-config.yang <https://git.opendaylight.org/gerrit |
1119 | /gitweb?p=openflowplugin.git;f=model/model-flow-servic |
1120 | e/src/main/yang/node-config.yang;a=blob;hb=refs/heads/ |
1121 | stable/boron>`__                                       |
1122 +--------------------------------------------------------+
1123 | `sal-echo.yang <https://git.opendaylight.org/gerrit/gi |
1124 | tweb?p=openflowplugin.git;f=model/model-flow-service/s |
1125 | rc/main/yang/sal-echo.yang;a=blob;hb=refs/heads/stable |
1126 | /boron>`__                                             |
1127 +--------------------------------------------------------+
1128 | `sal-port.yang <https://git.opendaylight.org/gerrit/gi |
1129 | tweb?p=openflowplugin.git;f=model/model-flow-service/s |
1130 | rc/main/yang/sal-port.yang;a=blob;hb=refs/heads/stable |
1131 | /boron>`__                                             |
1132 +--------------------------------------------------------+
1133 | `packet-processing.yang <https://git.opendaylight.org/ |
1134 | gerrit/gitweb?p=openflowplugin.git;f=model/model-flow- |
1135 | service/src/main/yang/packet-processing.yang;a=blob;hb |
1136 | =refs/heads/stable/boron>`__                           |
1137 +--------------------------------------------------------+
1138 | `flow-node-inventory.yang <https://git.opendaylight.or |
1139 | g/gerrit/gitweb?p=openflowplugin.git;f=model/model-flo |
1140 | w-service/src/main/yang/flow-node-inventory.yang;a=blo |
1141 | b;hb=refs/heads/stable/boron>`__                       |
1142 +--------------------------------------------------------+
1143 | ***Openflow statistics***                              |
1144 +--------------------------------------------------------+
1145 | `opendaylight-queue-statistics.yang <https://git.opend |
1146 | aylight.org/gerrit/gitweb?p=openflowplugin.git;f=model |
1147 | /model-flow-statistics/src/main/yang/opendaylight-queu |
1148 | e-statistics.yang;a=blob;hb=refs/heads/stable/boron>`_ |
1149 +--------------------------------------------------------+
1150 | `opendaylight-flow-table-statistics.yang <https://git. |
1151 | opendaylight.org/gerrit/gitweb?p=openflowplugin.git;f= |
1152 | model/model-flow-statistics/src/main/yang/opendaylight |
1153 | -flow-table-statistics.yang;a=blob;hb=refs/heads/stabl |
1154 | e/boron>`__                                            |
1155 +--------------------------------------------------------+
1156 | `opendaylight-port-statistics.yang <https://git.openda |
1157 | ylight.org/gerrit/gitweb?p=openflowplugin.git;f=model/ |
1158 | model-flow-statistics/src/main/yang/opendaylight-port- |
1159 | statistics.yang;a=blob;hb=refs/heads/stable/boron>`__  |
1160 +--------------------------------------------------------+
1161 | `opendaylight-statistics-types.yang <https://git.opend |
1162 | aylight.org/gerrit/gitweb?p=openflowplugin.git;f=model |
1163 | /model-flow-statistics/src/main/yang/opendaylight-stat |
1164 | istics-types.yang;a=blob;hb=refs/heads/stable/boron>`_ |
1165 +--------------------------------------------------------+
1166 | `opendaylight-group-statistics.yang <https://git.opend |
1167 | aylight.org/gerrit/gitweb?p=openflowplugin.git;f=model |
1168 | /model-flow-statistics/src/main/yang/opendaylight-grou |
1169 | p-statistics.yang;a=blob;hb=refs/heads/stable/boron>`_ |
1170 +--------------------------------------------------------+
1171 | `opendaylight-flow-statistics.yang <https://git.openda |
1172 | ylight.org/gerrit/gitweb?p=openflowplugin.git;f=model/ |
1173 | model-flow-statistics/src/main/yang/opendaylight-flow- |
1174 | statistics.yang;a=blob;hb=refs/heads/stable/boron>`__  |
1175 +--------------------------------------------------------+
1176 | `opendaylight-meter-statistics.yang <https://git.opend |
1177 | aylight.org/gerrit/gitweb?p=openflowplugin.git;f=model |
1178 | /model-flow-statistics/src/main/yang/opendaylight-mete |
1179 | r-statistics.yang;a=blob;hb=refs/heads/stable/boron>`_ |
1180 +--------------------------------------------------------+
1181
1182 Karaf feature tree
1183 ------------------
1184
1185 .. figure:: ./images/openflowplugin/odl-ofp-feature-tree.png
1186    :alt: Openflow plugin karaf feature tree
1187
1188    Openflow plugin karaf feature tree
1189
1190 Short
1191 `HOWTO <https://wiki.opendaylight.org/view/OpenDaylight_OpenFlow_Plugin:FeatureTreeHowto>`__
1192 create such a tree.
1193
1194 Wiring up notifications
1195 -----------------------
1196
1197 Introduction
1198 ~~~~~~~~~~~~
1199
1200 We need to translate OpenFlow messages coming up from the :ref:`OpenFlow
1201 Protocol Library <openflow-protocol-library>` into
1202 MD-SAL Notification objects and then publish them to the MD-SAL.
1203
1204 Mechanics
1205 ~~~~~~~~~
1206
1207 1. Create a Translator class
1208
1209 2. Register the Translator
1210
1211 3. Register the notificationPopListener to handle your Notification
1212    Objects
1213
1214 Create a Translator class
1215 ^^^^^^^^^^^^^^^^^^^^^^^^^
1216
1217 You can see an example in
1218 `PacketInTranslator.java <https://git.opendaylight.org/gerrit/gitweb?p=openflowplugin.git;a=blob;f=openflowplugin/src/main/java/org/opendaylight/openflowplugin/openflow/md/core/translator/PacketInTranslator.java;hb=refs/heads/stable/boron>`__.
1219
1220 First, simply create the class
1221
1222 ::
1223
1224     public class PacketInTranslator implements IMDMessageTranslator<OfHeader, List<DataObject>> {
1225
1226 Then implement the translate function:
1227
1228 ::
1229
1230     public class PacketInTranslator implements IMDMessageTranslator<OfHeader, List<DataObject>> {
1231
1232         protected static final Logger LOG = LoggerFactory
1233                 .getLogger(PacketInTranslator.class);
1234         @Override
1235         public PacketReceived translate(SwitchConnectionDistinguisher cookie,
1236                 SessionContext sc, OfHeader msg) {
1237                 ...
1238         }
1239
1240 Make sure to check that you are dealing with the expected type and cast
1241 it:
1242
1243 ::
1244
1245     if(msg instanceof PacketInMessage) {
1246         PacketInMessage message = (PacketInMessage)msg;
1247         List<DataObject> list = new CopyOnWriteArrayList<DataObject>();
1248
1249 Do your transation work and return
1250
1251 ::
1252
1253     PacketReceived pktInEvent = pktInBuilder.build();
1254     list.add(pktInEvent);
1255     return list;
1256
1257 Register your Translator Class
1258 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1259
1260 Next you need to go to
1261 `MDController.java <https://git.opendaylight.org/gerrit/gitweb?p=openflowplugin.git;a=blob;f=openflowplugin/src/main/java/org/opendaylight/openflowplugin/openflow/md/core/MDController.java;hb=refs/heads/stable/boron>`__
1262 and in init() add register your Translator:
1263
1264 ::
1265
1266     public void init() {
1267             LOG.debug("Initializing!");
1268             messageTranslators = new ConcurrentHashMap<>();
1269             popListeners = new ConcurrentHashMap<>();
1270             //TODO: move registration to factory
1271             addMessageTranslator(ErrorMessage.class, OF10, new ErrorTranslator());
1272             addMessageTranslator(ErrorMessage.class, OF13, new ErrorTranslator());
1273             addMessageTranslator(PacketInMessage.class,OF10, new PacketInTranslator());
1274             addMessageTranslator(PacketInMessage.class,OF13, new PacketInTranslator());
1275
1276 Notice that there is a separate registration for each of OpenFlow 1.0
1277 and OpenFlow 1.3. Basically, you indicate the type of OpenFlow Protocol
1278 Library message you wish to translate for, the OpenFlow version, and an
1279 instance of your Translator.
1280
1281 Register your MD-SAL Message for Notification to the MD-SAL
1282 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1283
1284 Now, also in MDController.init() register to have the
1285 notificationPopListener handle your MD-SAL Message:
1286
1287 ::
1288
1289     addMessagePopListener(PacketReceived.class, new NotificationPopListener<DataObject>());
1290
1291 You are done
1292 ^^^^^^^^^^^^
1293
1294 That’s all there is to it. Now when a message comes up from the OpenFlow
1295 Protocol Library, it will be translated and published to the MD-SAL.
1296
1297 Message Order Preservation
1298 --------------------------
1299
1300 While the Helium release of OpenFlow Plugin relied on queues to ensure
1301 messages were delivered in order, subsequent releases instead ensure
1302 that all the messages from a given device are delivered using the same
1303 thread and thus message order is guaranteed without queues. The OpenFlow
1304 plugin allocates a number of threads equal to twice the number of
1305 processor cores on machine it is run, e.g., 8 threads if the machine has
1306 4 cores.
1307
1308 .. note::
1309
1310     While each device is assigned to one thread, multiple devices can be
1311     assigned to the same thread.
1312