1 OpenFlow Plugin Project Developer Guide
2 =======================================
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.
8 It can be found on `the OpenDaylight software download
9 page <https://www.opendaylight.org/downloads>`__.
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.
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
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.
42 When *deviceConnected()* is called, it does the following:
44 1. creates a new transaction chain (step 4.1)
46 2. creates a new instance of **DeviceContext** (step 4.2.2)
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
53 4. creates an instance of **RequestContext** for each type of feature
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**
63 The call to *createDeviceFeaturesForOF<version>()*: . creates a new
64 instance of **StatisticsContextImpl** (step 5.1.1.1).
66 1. calls *gatherDynamicStatistics()* on that instance which returns a
67 **Future** which will produce a value when done
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)
72 b. if everything works, this data is also stored in the MD-SAL
75 If the **Future** is successful, it is processed (step 6.1.1) in a
76 callback in **StatisticsManagerImpl** which:
78 1. schedules the next time to poll the device for statistics
80 2. sets the device state to synchronized (step 6.1.1.2)
82 3. calls *onDeviceContextLevelUp()* in **RpcManagerImpl**
84 The *onDeviceContextLevelUp()* call:
86 1. creates a new instance of **RequestContextImpl**
88 2. registers implementation for supported services
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)
94 .. figure:: ./images/openflowplugin/odl-ofp-session-establishment.jpg
95 :alt: Session establishment
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.
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:
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
115 a. if there is a single common version use it and the **VERSION IS
118 b. if there are more than one common versions, use the highest
119 (newest) protocol and the **VERSION IS SETTLED**
121 c. if there are no common versions, the device is **DISCONNECTED**
123 2. if the first HELLO message does not contain a *version bitmap*, then
124 STEB-BY-STEP negotiation is used
126 3. if second (or more) HELLO message is received, then STEP-BY-STEP
129 STEP-BY-STEP negotiation:
130 ^^^^^^^^^^^^^^^^^^^^^^^^^
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
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**
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
144 - if the last version from the device is is less than the last version
145 proposed from the plugin:
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
151 - if if the plugin doesn’t support a lower version, the device is
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
158 .. figure:: ./images/openflowplugin/odl-ofp-handshake.png
159 :alt: Handshake process
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.
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.
178 The *addFlow()* method then
180 1. calls the *commitEntry()* method (step 2) from the OpenFlow Protocol
181 Library which is responsible for sending the flow to the device
183 2. creates a new **RequestContext** by calling *createRequestContext()*
186 3. creates a callback to handle any events that happen because of
187 sending the flow to the device
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.
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.
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**.
207 .. figure:: ./images/openflowplugin/odl-ofp-add-flow.png
212 Description of OpenFlow Plugin Modules
213 --------------------------------------
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.
219 **General model (interfaces)** - openflow-plugin-cfg.yang.
221 - the provided module is defined (``identity openflow-provider``)
223 - and target implementation is assigned (``...OpenflowPluginProvider``)
227 module openflow-provider {
229 namespace "urn:opendaylight:params:xml:ns:yang:openflow:common:config[urn:opendaylight:params:xml:ns:yang:openflow:common:config]";
230 prefix "ofplugin-cfg";
232 import config {prefix config; revision-date 2013-04-05; }
234 "openflow-plugin-custom-config";
235 revision "2014-03-26" {
239 identity openflow-provider{
240 base config:service-type;
241 config:java-class "org.opendaylight.openflowplugin.openflow.md.core.sal.OpenflowPluginProvider";
245 **Implementation model** - openflow-plugin-cfg-impl.yang
247 - the implementation of module is defined
248 (``identity openflow-provider-impl``)
250 - class name of generated implementation is defined
251 (ConfigurableOpenFlowProvider)
253 - via augmentation the configuration of module is defined:
255 - this module requires instance of binding-aware-broker
256 (``container binding-aware-broker``)
258 - and list of openflow-switch-connection-provider (those are
259 provided by openflowjava, one plugin instance will orchestrate
260 multiple openflowjava modules)
264 module openflow-provider-impl {
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";
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;}
276 "openflow-plugin-custom-config-impl";
278 revision "2014-03-26" {
283 identity openflow-provider-impl {
284 base config:module-type;
285 config:provided-service openflow-provider:openflow-provider;
286 config:java-name-prefix ConfigurableOpenFlowProvider;
289 augment "/config:modules/config:module/config:configuration" {
290 case openflow-provider-impl {
291 when "/config:modules/config:module/config:type = 'openflow-provider-impl'";
293 container binding-aware-broker {
294 uses config:service-ref {
297 config:required-identity md-sal-binding:binding-broker-osgi-registry;
301 list openflow-switch-connection-provider {
302 uses config:service-ref {
305 config:required-identity openflow-switch-connection-provider:openflow-switch-connection-provider;
313 Generating config and sal classes out of yangs
314 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
316 In order to involve suitable code generators, this is needed in pom:
323 <groupId>org.opendaylight.yangtools</groupId>
324 <artifactId>yang-maven-plugin</artifactId>
328 <goal>generate-sources</goal>
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>
345 org.opendaylight.yangtools.maven.sal.api.gen.plugin.CodeGeneratorImpl
346 </codeGeneratorClass>
347 <outputBaseDir>${project.build.directory}/generated-sources/sal</outputBaseDir>
350 <codeGeneratorClass>org.opendaylight.yangtools.yang.unified.doc.generator.maven.DocumentationGeneratorImpl</codeGeneratorClass>
351 <outputBaseDir>${project.build.directory}/site/models</outputBaseDir>
354 <inspectDependencies>true</inspectDependencies>
360 <groupId>org.opendaylight.controller</groupId>
361 <artifactId>yang-jmx-generator-plugin</artifactId>
362 <version>0.2.5-SNAPSHOT</version>
365 <groupId>org.opendaylight.yangtools</groupId>
366 <artifactId>maven-sal-api-gen-plugin</artifactId>
367 <version>${yangtools.version}</version>
374 - JMX generator (target/generated-sources/config)
376 - sal CodeGeneratorImpl (target/generated-sources/sal)
378 - documentation generator (target/site/models):
379 `openflow-provider.html <https://jenkins.opendaylight.org/openflowplugin/job/openflowplugin-merge/ws/openflowplugin/target/site/models/openflow-provider.html>`__,
380 `openflow-provider-impl.html <https://jenkins.opendaylight.org/openflowplugin/job/openflowplugin-merge/ws/openflowplugin/target/site/models/openflow-provider-impl.html>`__
382 Altering generated files
383 ~~~~~~~~~~~~~~~~~~~~~~~~
385 Those files were generated under src/main/java in package as referred in
386 yangs (if exist, generator will not overwrite them):
388 - ConfigurableOpenFlowProviderModuleFactory
390 here the **instantiateModule** methods are extended in order to
391 capture and inject osgi BundleContext into module, so it can be
392 injected into final implementation - **OpenflowPluginProvider** +
393 ``module.setBundleContext(bundleContext);``
395 - ConfigurableOpenFlowProviderModule
397 here the **createInstance** method is extended in order to inject
398 osgi BundleContext into module implementation +
399 ``pluginProvider.setContext(bundleContext);``
401 Configuration xml file
402 ~~~~~~~~~~~~~~~~~~~~~~
404 Configuration file contains
406 - required capabilities
408 - modules definitions from openflowjava
410 - modules definitions from openflowplugin
414 - openflow:switch:connection:provider:impl (listening on port 6633,
415 name=openflow-switch-connection-provider-legacy-impl)
417 - openflow:switch:connection:provider:impl (listening on port 6653,
418 name=openflow-switch-connection-provider-default-impl)
420 - openflow:common:config:impl (having 2 services (wrapping those 2
421 previous modules) and binding-broker-osgi-registry injected)
425 - openflow-switch-connection-provider-default
427 - openflow-switch-connection-provider-legacy
434 <required-capabilities>
435 <capability>urn:opendaylight:params:xml:ns:yang:openflow:switch:connection:provider:impl?module=openflow-switch-connection-provider-impl&revision=2014-03-28</capability>
436 <capability>urn:opendaylight:params:xml:ns:yang:openflow:switch:connection:provider?module=openflow-switch-connection-provider&revision=2014-03-28</capability>
437 <capability>urn:opendaylight:params:xml:ns:yang:openflow:common:config:impl?module=openflow-provider-impl&revision=2014-03-26</capability>
438 <capability>urn:opendaylight:params:xml:ns:yang:openflow:common:config?module=openflow-provider&revision=2014-03-26</capability>
439 </required-capabilities>
444 <modules xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
446 <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:openflow:switch:connection:provider:impl">prefix:openflow-switch-connection-provider-impl</type>
447 <name>openflow-switch-connection-provider-default-impl</name>
449 <switch-idle-timeout>15000</switch-idle-timeout>
452 <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:openflow:switch:connection:provider:impl">prefix:openflow-switch-connection-provider-impl</type>
453 <name>openflow-switch-connection-provider-legacy-impl</name>
455 <switch-idle-timeout>15000</switch-idle-timeout>
460 <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:openflow:common:config:impl">prefix:openflow-provider-impl</type>
461 <name>openflow-provider-impl</name>
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-default</name>
466 </openflow-switch-connection-provider>
467 <openflow-switch-connection-provider>
468 <type xmlns:ofSwitch="urn:opendaylight:params:xml:ns:yang:openflow:switch:connection:provider">ofSwitch:openflow-switch-connection-provider</type>
469 <name>openflow-switch-connection-provider-legacy</name>
470 </openflow-switch-connection-provider>
473 <binding-aware-broker>
474 <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">binding:binding-broker-osgi-registry</type>
475 <name>binding-osgi-broker</name>
476 </binding-aware-broker>
480 <services xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
482 <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:openflow:switch:connection:provider">prefix:openflow-switch-connection-provider</type>
484 <name>openflow-switch-connection-provider-default</name>
485 <provider>/modules/module[type='openflow-switch-connection-provider-impl'][name='openflow-switch-connection-provider-default-impl']</provider>
488 <name>openflow-switch-connection-provider-legacy</name>
489 <provider>/modules/module[type='openflow-switch-connection-provider-impl'][name='openflow-switch-connection-provider-legacy-impl']</provider>
494 <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:openflow:common:config">prefix:openflow-provider</type>
496 <name>openflow-provider</name>
497 <provider>/modules/module[type='openflow-provider-impl'][name='openflow-provider-impl']</provider>
509 In order to provide multiple instances of modules from openflowjava
510 there is an API change. Previously OFPlugin got access to
511 SwitchConnectionProvider exposed by OFJava and injected collection of
512 configurations so that for each configuration new instance of tcp
513 listening server was created. Now those configurations are provided by
514 configSubsystem and configured modules (wrapping the original
515 SwitchConnectionProvider) are injected into OFPlugin (wrapping
516 SwitchConnectionHandler).
518 Providing config file (IT, local distribution/base, integration/distributions/base)
519 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
524 Here the whole configuration is contained in one file (controller.xml).
525 Required entries needed in order to startup and wire OEPlugin + OFJava
526 are simply added there.
528 OFPlugin/distribution/base
529 ^^^^^^^^^^^^^^^^^^^^^^^^^^
531 Here new config file has been added
532 (src/main/resources/configuration/initial/42-openflow-protocol-impl.xml)
533 and is being copied to config/initial subfolder of build.
535 integration/distributions/build
536 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
538 In order to push the actual config into config/initial subfolder of
539 distributions/base in integration project there was a new artifact in
540 OFPlugin created - **openflowplugin-controller-config**, containing only
541 the config xml file under src/main/resources. Another change was
542 committed into integration project. During build this config xml is
543 being extracted and copied to the final folder in order to be accessible
544 during controller run.
546 Internal message statistics API
547 -------------------------------
549 To aid in testing and diagnosis, the OpenFlow plugin provides
550 information about the number and rate of different internal events.
552 The implementation does two things: collects event counts and exposes
553 counts. Event counts are grouped by message type, e.g.,
554 **PacketInMessage**, and checkpoint, e.g.,
555 *TO\_SWITCH\_ENQUEUED\_SUCCESS*. Once gathered, the results are logged
556 as well as being exposed using OSGi command line (deprecated) and JMX.
561 Each message is counted as it passes through various processing
562 checkpoints. The following checkpoints are defined as a Java enum and
568 * statistic groups overall in OFPlugin
570 enum STATISTIC_GROUP {
571 /** message from switch, enqueued for processing */
572 FROM_SWITCH_ENQUEUED,
573 /** message from switch translated successfully - source */
574 FROM_SWITCH_TRANSLATE_IN_SUCCESS,
575 /** message from switch translated successfully - target */
576 FROM_SWITCH_TRANSLATE_OUT_SUCCESS,
577 /** message from switch where translation failed - source */
578 FROM_SWITCH_TRANSLATE_SRC_FAILURE,
579 /** message from switch finally published into MD-SAL */
580 FROM_SWITCH_PUBLISHED_SUCCESS,
581 /** message from switch - publishing into MD-SAL failed */
582 FROM_SWITCH_PUBLISHED_FAILURE,
584 /** message from MD-SAL to switch via RPC enqueued */
585 TO_SWITCH_ENQUEUED_SUCCESS,
586 /** message from MD-SAL to switch via RPC NOT enqueued */
587 TO_SWITCH_ENQUEUED_FAILED,
588 /** message from MD-SAL to switch - sent to OFJava successfully */
589 TO_SWITCH_SUBMITTED_SUCCESS,
590 /** message from MD-SAL to switch - sent to OFJava but failed*/
591 TO_SWITCH_SUBMITTED_FAILURE
594 When a message passes through any of those checkpoints then counter
595 assigned to corresponding checkpoint and message is incremented by 1.
600 As described above, there are three ways to access the statistics:
602 - OSGi command line (this is considered deprecated)
604 ``osgi> dumpMsgCount``
606 - OpenDaylight logging console (statistics are logged here every 10
609 required logback settings :
610 ``<logger name="org.opendaylight.openflowplugin.openflow.md.queue.MessageSpyCounterImpl" level="DEBUG"\/>``
614 start OpenFlow plugin with the ``-jmx`` parameter
616 start JConsole by running ``jconsole``
618 the JConsole MBeans tab should contain
619 org.opendaylight.controller
621 RuntimeBean has a msg-spy-service-impl
623 Operations provides makeMsgStatistics report functionality
628 .. figure:: ./images/openflowplugin/odl-ofp-ofplugin-debug-stats.png
629 :alt: OFplugin Debug stats.png
631 OFplugin Debug stats.png
635 DEBUG o.o.o.s.MessageSpyCounterImpl - FROM_SWITCH_ENQUEUED: MSG[PortStatusMessage] -> +0 | 1
636 DEBUG o.o.o.s.MessageSpyCounterImpl - FROM_SWITCH_ENQUEUED: MSG[MultipartReplyMessage] -> +24 | 81
637 DEBUG o.o.o.s.MessageSpyCounterImpl - FROM_SWITCH_ENQUEUED: MSG[PacketInMessage] -> +8 | 111
638 DEBUG o.o.o.s.MessageSpyCounterImpl - FROM_SWITCH_TRANSLATE_IN_SUCCESS: MSG[PortStatusMessage] -> +0 | 1
639 DEBUG o.o.o.s.MessageSpyCounterImpl - FROM_SWITCH_TRANSLATE_IN_SUCCESS: MSG[MultipartReplyMessage] -> +24 | 81
640 DEBUG o.o.o.s.MessageSpyCounterImpl - FROM_SWITCH_TRANSLATE_IN_SUCCESS: MSG[PacketInMessage] -> +8 | 111
641 DEBUG o.o.o.s.MessageSpyCounterImpl - FROM_SWITCH_TRANSLATE_OUT_SUCCESS: MSG[QueueStatisticsUpdate] -> +3 | 7
642 DEBUG o.o.o.s.MessageSpyCounterImpl - FROM_SWITCH_TRANSLATE_OUT_SUCCESS: MSG[NodeUpdated] -> +0 | 3
643 DEBUG o.o.o.s.MessageSpyCounterImpl - FROM_SWITCH_TRANSLATE_OUT_SUCCESS: MSG[NodeConnectorStatisticsUpdate] -> +3 | 7
644 DEBUG o.o.o.s.MessageSpyCounterImpl - FROM_SWITCH_TRANSLATE_OUT_SUCCESS: MSG[GroupDescStatsUpdated] -> +3 | 7
645 DEBUG o.o.o.s.MessageSpyCounterImpl - FROM_SWITCH_TRANSLATE_OUT_SUCCESS: MSG[FlowsStatisticsUpdate] -> +3 | 19
646 DEBUG o.o.o.s.MessageSpyCounterImpl - FROM_SWITCH_TRANSLATE_OUT_SUCCESS: MSG[PacketReceived] -> +8 | 111
647 DEBUG o.o.o.s.MessageSpyCounterImpl - FROM_SWITCH_TRANSLATE_OUT_SUCCESS: MSG[MeterFeaturesUpdated] -> +0 | 3
648 DEBUG o.o.o.s.MessageSpyCounterImpl - FROM_SWITCH_TRANSLATE_OUT_SUCCESS: MSG[GroupStatisticsUpdated] -> +3 | 7
649 DEBUG o.o.o.s.MessageSpyCounterImpl - FROM_SWITCH_TRANSLATE_OUT_SUCCESS: MSG[GroupFeaturesUpdated] -> +0 | 3
650 DEBUG o.o.o.s.MessageSpyCounterImpl - FROM_SWITCH_TRANSLATE_OUT_SUCCESS: MSG[MeterConfigStatsUpdated] -> +3 | 7
651 DEBUG o.o.o.s.MessageSpyCounterImpl - FROM_SWITCH_TRANSLATE_OUT_SUCCESS: MSG[MeterStatisticsUpdated] -> +3 | 7
652 DEBUG o.o.o.s.MessageSpyCounterImpl - FROM_SWITCH_TRANSLATE_OUT_SUCCESS: MSG[NodeConnectorUpdated] -> +0 | 12
653 DEBUG o.o.o.s.MessageSpyCounterImpl - FROM_SWITCH_TRANSLATE_OUT_SUCCESS: MSG[FlowTableStatisticsUpdate] -> +3 | 8
654 DEBUG o.o.o.s.MessageSpyCounterImpl - FROM_SWITCH_TRANSLATE_SRC_FAILURE: no activity detected
655 DEBUG o.o.o.s.MessageSpyCounterImpl - FROM_SWITCH_PUBLISHED_SUCCESS: MSG[QueueStatisticsUpdate] -> +3 | 7
656 DEBUG o.o.o.s.MessageSpyCounterImpl - FROM_SWITCH_PUBLISHED_SUCCESS: MSG[NodeUpdated] -> +0 | 3
657 DEBUG o.o.o.s.MessageSpyCounterImpl - FROM_SWITCH_PUBLISHED_SUCCESS: MSG[NodeConnectorStatisticsUpdate] -> +3 | 7
658 DEBUG o.o.o.s.MessageSpyCounterImpl - FROM_SWITCH_PUBLISHED_SUCCESS: MSG[GroupDescStatsUpdated] -> +3 | 7
659 DEBUG o.o.o.s.MessageSpyCounterImpl - FROM_SWITCH_PUBLISHED_SUCCESS: MSG[FlowsStatisticsUpdate] -> +3 | 19
660 DEBUG o.o.o.s.MessageSpyCounterImpl - FROM_SWITCH_PUBLISHED_SUCCESS: MSG[PacketReceived] -> +8 | 111
661 DEBUG o.o.o.s.MessageSpyCounterImpl - FROM_SWITCH_PUBLISHED_SUCCESS: MSG[MeterFeaturesUpdated] -> +0 | 3
662 DEBUG o.o.o.s.MessageSpyCounterImpl - FROM_SWITCH_PUBLISHED_SUCCESS: MSG[GroupStatisticsUpdated] -> +3 | 7
663 DEBUG o.o.o.s.MessageSpyCounterImpl - FROM_SWITCH_PUBLISHED_SUCCESS: MSG[GroupFeaturesUpdated] -> +0 | 3
664 DEBUG o.o.o.s.MessageSpyCounterImpl - FROM_SWITCH_PUBLISHED_SUCCESS: MSG[MeterConfigStatsUpdated] -> +3 | 7
665 DEBUG o.o.o.s.MessageSpyCounterImpl - FROM_SWITCH_PUBLISHED_SUCCESS: MSG[MeterStatisticsUpdated] -> +3 | 7
666 DEBUG o.o.o.s.MessageSpyCounterImpl - FROM_SWITCH_PUBLISHED_SUCCESS: MSG[NodeConnectorUpdated] -> +0 | 12
667 DEBUG o.o.o.s.MessageSpyCounterImpl - FROM_SWITCH_PUBLISHED_SUCCESS: MSG[FlowTableStatisticsUpdate] -> +3 | 8
668 DEBUG o.o.o.s.MessageSpyCounterImpl - FROM_SWITCH_PUBLISHED_FAILURE: no activity detected
669 DEBUG o.o.o.s.MessageSpyCounterImpl - TO_SWITCH_ENQUEUED_SUCCESS: MSG[AddFlowInput] -> +0 | 12
670 DEBUG o.o.o.s.MessageSpyCounterImpl - TO_SWITCH_ENQUEUED_FAILED: no activity detected
671 DEBUG o.o.o.s.MessageSpyCounterImpl - TO_SWITCH_SUBMITTED_SUCCESS: MSG[AddFlowInput] -> +0 | 12
672 DEBUG o.o.o.s.MessageSpyCounterImpl - TO_SWITCH_SUBMITTED_FAILURE: no activity detected
674 Application: Forwarding Rules Synchronizer
675 ------------------------------------------
683 Forwarding Rules Synchronizer (FRS) is a newer version of Forwarding
684 Rules Manager (FRM). It was created to solve most shortcomings of FRM.
685 FRS solving errors with retry mechanism. Sending barrier if needed.
686 Using one service for flows, groups and meters. And it has less changes
687 requests send to device since calculating difference and using
690 It is located in the Java package:
694 package org.opendaylight.openflowplugin.applications.frsync;
699 - 1x config - FlowCapableNode
701 - 1x operational - Node
706 - one listener in config datastore waiting for changes
710 - skip event if operational not present for node
712 - send syncup entry to reactor for synchronization
714 - node added: after part of modification and whole operational
717 - node updated: after and before part of modification
719 - node deleted: null and before part of modification
721 - one listener in operational datastore waiting for changes
725 - on device connected
727 - register for cluster services
729 - on device disconnected remove from cache
733 - unregister for cluster services
735 - if registered for reconciliation
737 - do reconciliation through syncup (only when config present)
739 - reactor *(provides syncup w/decorators assembled in this order)*
741 - Cluster decorator - skip action if not master for device
743 - FutureZip decorator (FutureZip extends Future decorator)
745 - Future - run delegate syncup in future - submit task to
748 - FutureZip - provides state compression - compress optimized
749 config delta if waiting for execution with new one
751 - Guard decorator - per device level locking
753 - Retry decorator - register for reconciliation if syncup failed
755 - Reactor impl - calculate diff from after/before parts of syncup
761 In the *old* FRM uses an incremental strategy with all changes made one
762 by one, where FRS uses a flat batch system with changes made in bulk. It
763 uses one service SalFlatBatchService instead of three (flow, group,
769 FRS is used in Boron as separate feature and it is not loaded by any
770 other feature. It has to be run separately.
774 odl-openflowplugin-app-forwardingrules-sync
782 - is started when change request to device return as failed (register
785 - wait for next consistent operational and do reconciliation with
786 actual config (not only diff)
791 - only the diff (before/after) between last config changes is sent to
794 - when there are more config changes for device in a row waiting to be
795 processed they are compressed into one entry (after is still replaced
801 - FRS is cluster aware using ClusteringSingletonServiceProvider from
804 - on mastership change reconciliation is done (register for reconcile)
809 FRS uses service with implemented barrier waiting logic between
812 Service: SalFlatBatchService
813 ----------------------------
818 SalFlatBatchService was created along forwardingrules-sync application
819 as the service that should application used by default. This service uses
820 only one input with bag of flow/group/meter objects and their common
821 add/update/remove action. So you practically send only one input (of specific
822 bags) to this service.
824 - interface: *org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.SalFlatBatchService*
826 - implementation: *org.opendaylight.openflowplugin.impl.services.SalFlatBatchServiceImpl*
828 - method: *processFlatBatch(input)*
830 - input: *org.opendaylight.yang.gen.v1.urn.opendaylight.flat.batch.service.rev160321.ProcessFlatBatchInput*
835 - possibility to use only one input bag with particular failure analysis preserved
837 - automatic barrier decision (chain+wait)
839 - less RPC routing in cluster environment (since one call encapsulates all others)
841 ProcessFlatBatchInput
842 ~~~~~~~~~~~~~~~~~~~~~
844 Input for SalFlatBatchService (ProcessFlatBatchInput object) consists of:
848 - batch steps - List<Batch> - defined action + bag of objects + order for failures analysis
850 - BatchChoice - yang-modeled action choice (e.g. FlatBatchAddFlowCase) containing batch bag of objects (e.g. flows to be added)
852 - BatchOrder - (integer) order of batch step (should be incremented by single action)
854 - exitOnFirstError - boolean flag
858 #. prepare **list of steps** based on input
860 #. **mark barriers** in steps where needed
862 #. prepare particular **F/G/M-batch** service calls from **Flat-batch** steps
864 - F/G/M-batch services encapsulate bulk of single service calls
866 - they actually chain barrier after processing all single calls if actual step is marked as barrier-needed
868 #. **chain** futures and **start** executing
870 - start all actions that can be run simultaneously (chain all on one starting point)
872 - in case there is a step marked as barrier-needed
874 - wait for all fired jobs up to one with barrier
876 - merge rpc results (status, errors, batch failures) into single one
878 - the latest job with barrier is new starting point for chaining
880 Services encapsulation
881 ^^^^^^^^^^^^^^^^^^^^^^
883 - SalFlatBatchService
885 - SalFlowBatchService
889 - SalGroupBatchService
893 - SalMeterBatchService
900 - decide on actual step and all previous steps since the latest barrier
902 - if condition in table below is satisfied the latest step before actual is marked as barrier-needed
904 +---------------------------+------------------------------------------------------------------+
905 | actual step | previous steps contain |
906 +===========================+==================================================================+
907 | FLOW_ADD *or* FLOW_UPDATE | GROUP_ADD *or* METER_ADD |
908 +---------------------------+------------------------------------------------------------------+
909 | GROUP_ADD | GROUP_ADD *or* GROUP_UPDATE |
910 +---------------------------+------------------------------------------------------------------+
911 | GROUP_REMOVE | FLOW_UPDATE *or* FLOW_REMOVE *or* GROUP_UPDATE *or* GROUP_REMOVE |
912 +---------------------------+------------------------------------------------------------------+
913 | METER_REMOVE | FLOW_UPDATE *or* FLOW_REMOVE |
914 +---------------------------+------------------------------------------------------------------+
919 There is flag in ProcessFlatBatchInput to stop process on the first error.
921 - *true* - if partial step is not successful stop whole processing
923 - *false* (default) - try to process all steps regardless partial results
925 If error occurs in any of partial steps upper FlatBatchService call will return as unsuccessful in both cases.
926 However every partial error is attached to general flat batch result along with BatchFailure (contains BatchOrder
927 and BatchItemIdChoice to identify failed step).
929 Cluster singleton approach in plugin
930 ------------------------------------
938 The existing OpenDaylight service deployment model assumes symmetric
939 clusters, where all services are activated on all nodes in the cluster.
940 However, many services require that there is a single active service
941 instance per cluster. We call such services *singleton services*. The
942 Entity Ownership Service (EOS) represents the base Leadership choice for
943 one Entity instance. Every Cluster Singleton service **type** must have
944 its own Entity and every Cluster Singleton service **instance** must
945 have its own Entity Candidate. Every registered Entity Candidate should
946 be notified about its actual role. All this "work" is done by MD-SAL so
947 the Openflowplugin need "only" to register as service in
948 **SingletonClusteringServiceProvider** given by MD-SAL.
950 Change against using EOS service listener
951 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
953 In this new clustering singleton approach plugin uses API from the
954 MD-SAL project: SingletonClusteringService which comes with three
959 instantiateServiceInstance()
960 closeServiceInstance()
963 This service has to be registered to a
964 SingletonClusteringServiceProvider from MD-SAL which take care if
965 mastership is changed in cluster environment.
967 First method in SingletonClusteringService is being called when the
968 cluster node becomes a MASTER. Second is being called when status
969 changes to SLAVE or device is disconnected from cluster. Last method
970 plugins returns NodeId as ServiceGroupIdentifier Startup after device is
973 On the start up the plugin we need to initialize first four managers for
974 each working area providing information and services
984 After connection the device the listener Device manager get the event
985 and start up to creating the context for this connection. Startup after
988 Services are managed by SinlgetonClusteringServiceProvider from MD-SAL
989 project. So in startup we simply create a instance of LifecycleService
990 and register all contexts into it.
995 Plugin is no longer registered as Entity Ownership Service (EOS)
996 listener therefore does not need to and cannot respond on EOS ownership
1002 Services start asynchronously but the start is managed by
1003 LifecycleService. If something goes wrong LifecycleService stop starting
1004 services in context and this speeds up the reconnect process. But the
1005 services haven’t changed and plugin need to start all this:
1007 - Activating transaction chain manager
1009 - Initial gathering of device statistics
1011 - Initial submit to DS
1013 - Sending role MASTER to device
1015 - RPC services registration
1017 - Statistics gathering start
1022 If closeServiceInstance occurred plugin just simply try to store all
1023 unsubmitted transactions and close the transaction chain manager, stop
1024 RPC services, stop Statistics gathering and after that all unregister
1030 +--------------------------------------------------------+-------------------+
1032 +========================================================+===================+
1033 | ***Openflow basic types*** | |
1034 +--------------------------------------------------------+-------------------+
1035 | `opendaylight-table-types.yang <https://git.opendaylig | `YangDOC <https:/ |
1036 | ht.org/gerrit/gitweb?p=openflowplugin.git;f=model/mode | /jenkins.opendayl |
1037 | l-flow-base/src/main/yang/opendaylight-table-types.yan | ight.org/releng/v |
1038 | g;a=blob;hb=refs/heads/stable/boron>`__ | iew/openflowplugi |
1039 | | n/job/openflowplu |
1040 | | gin-merge-boron/l |
1041 | | astSuccessfulBuil |
1042 | | d/artifact/model/ |
1043 | | model-flow-base/t |
1044 | | arget/site/models |
1045 | | /opendaylight-tab |
1046 | | le-types.html>`__ |
1047 +--------------------------------------------------------+-------------------+
1048 | `opendaylight-action-types.yang <https://git.opendayli | `YangDOC <https:/ |
1049 | ght.org/gerrit/gitweb?p=openflowplugin.git;f=model/mod | /jenkins.opendayl |
1050 | el-flow-base/src/main/yang/opendaylight-action-types.y | ight.org/releng/v |
1051 | ang;a=blob;hb=refs/heads/stable/boron>`__ | iew/openflowplugi |
1052 | | n/job/openflowplu |
1053 | | gin-merge-boron/l |
1054 | | astSuccessfulBuil |
1055 | | d/artifact/model/ |
1056 | | model-flow-base/t |
1057 | | arget/site/models |
1058 | | /opendaylight-act |
1059 | | ion-types.html>`_ |
1060 +--------------------------------------------------------+-------------------+
1061 | `opendaylight-flow-types.yang <https://git.opendayligh | `YangDOC <https:/ |
1062 | t.org/gerrit/gitweb?p=openflowplugin.git;f=model/model | /jenkins.opendayl |
1063 | -flow-base/src/main/yang/opendaylight-flow-types.yang; | ight.org/releng/v |
1064 | a=blob;hb=refs/heads/stable/boron>`__ | iew/openflowplugi |
1065 | | n/job/openflowplu |
1066 | | gin-merge-boron/l |
1067 | | astSuccessfulBuil |
1068 | | d/artifact/model/ |
1069 | | model-flow-base/t |
1070 | | arget/site/models |
1071 | | /opendaylight-flo |
1072 | | w-types.html>`__ |
1073 +--------------------------------------------------------+-------------------+
1074 | `opendaylight-meter-types.yang <https://git.opendaylig | `YangDOC <https:/ |
1075 | ht.org/gerrit/gitweb?p=openflowplugin.git;f=model/mode | /jenkins.opendayl |
1076 | l-flow-base/src/main/yang/opendaylight-meter-types.yan | ight.org/releng/v |
1077 | g;a=blob;hb=refs/heads/stable/boron>`__ | iew/openflowplugi |
1078 | | n/job/openflowplu |
1079 | | gin-merge-boron/l |
1080 | | astSuccessfulBuil |
1081 | | d/artifact/model/ |
1082 | | model-flow-base/t |
1083 | | arget/site/models |
1084 | | /opendaylight-met |
1085 | | er-types.html>`__ |
1086 +--------------------------------------------------------+-------------------+
1087 | `opendaylight-group-types.yang <https://git.opendaylig | `YangDOC <https:/ |
1088 | ht.org/gerrit/gitweb?p=openflowplugin.git;f=model/mode | /jenkins.opendayl |
1089 | l-flow-base/src/main/yang/opendaylight-group-types.yan | ight.org/releng/v |
1090 | g;a=blob;hb=refs/heads/stable/boron>`__ | iew/openflowplugi |
1091 | | n/job/openflowplu |
1092 | | gin-merge-boron/l |
1093 | | astSuccessfulBuil |
1094 | | d/artifact/model/ |
1095 | | model-flow-base/t |
1096 | | arget/site/models |
1097 | | /opendaylight-gro |
1098 | | up-types.html>`__ |
1099 +--------------------------------------------------------+-------------------+
1100 | `opendaylight-match-types.yang <https://git.opendaylig | `YangDOC <https:/ |
1101 | ht.org/gerrit/gitweb?p=openflowplugin.git;f=model/mode | /jenkins.opendayl |
1102 | l-flow-base/src/main/yang/opendaylight-match-types.yan | ight.org/releng/v |
1103 | g;a=blob;hb=refs/heads/stable/boron>`__ | iew/openflowplugi |
1104 | | n/job/openflowplu |
1105 | | gin-merge-boron/l |
1106 | | astSuccessfulBuil |
1107 | | d/artifact/model/ |
1108 | | model-flow-base/t |
1109 | | arget/site/models |
1110 | | /opendaylight-mat |
1111 | | ch-types.html>`__ |
1112 +--------------------------------------------------------+-------------------+
1113 | `opendaylight-port-types.yang <https://git.opendayligh | `YangDOC <https:/ |
1114 | t.org/gerrit/gitweb?p=openflowplugin.git;f=model/model | /jenkins.opendayl |
1115 | -flow-base/src/main/yang/opendaylight-port-types.yang; | ight.org/releng/v |
1116 | a=blob;hb=refs/heads/stable/boron>`__ | iew/openflowplugi |
1117 | | n/job/openflowplu |
1118 | | gin-merge-boron/l |
1119 | | astSuccessfulBuil |
1120 | | d/artifact/model/ |
1121 | | model-flow-base/t |
1122 | | arget/site/models |
1123 | | /opendaylight-por |
1124 | | t-types.html>`__ |
1125 +--------------------------------------------------------+-------------------+
1126 | `opendaylight-queue-types.yang <https://git.opendaylig | `YangDOC <https:/ |
1127 | ht.org/gerrit/gitweb?p=openflowplugin.git;f=model/mode | /jenkins.opendayl |
1128 | l-flow-base/src/main/yang/opendaylight-queue-types.yan | ight.org/releng/v |
1129 | g;a=blob;hb=refs/heads/stable/boron>`__ | iew/openflowplugi |
1130 | | n/job/openflowplu |
1131 | | gin-merge-boron/l |
1132 | | astSuccessfulBuil |
1133 | | d/artifact/model/ |
1134 | | model-flow-base/t |
1135 | | arget/site/models |
1136 | | /opendaylight-que |
1137 | | ue-types.html>`__ |
1138 +--------------------------------------------------------+-------------------+
1139 | ***Openflow services*** | |
1140 +--------------------------------------------------------+-------------------+
1141 | `sal-table.yang <https://git.opendaylight.org/gerrit/g | `YangDOC <https:/ |
1142 | itweb?p=openflowplugin.git;f=model/model-flow-service/ | /jenkins.opendayl |
1143 | src/main/yang/sal-table.yang;a=blob;hb=refs/heads/stab | ight.org/releng/v |
1144 | le/boron>`__ | iew/openflowplugi |
1145 | | n/job/openflowplu |
1146 | | gin-merge-boron/l |
1147 | | astSuccessfulBuil |
1148 | | d/artifact/model/ |
1149 | | model-flow-servic |
1150 | | e/target/site/mod |
1151 | | els/sal-table.htm |
1153 +--------------------------------------------------------+-------------------+
1154 | `sal-group.yang <https://git.opendaylight.org/gerrit/g | `YangDOC <https:/ |
1155 | itweb?p=openflowplugin.git;f=model/model-flow-service/ | /jenkins.opendayl |
1156 | src/main/yang/sal-group.yang;a=blob;hb=refs/heads/stab | ight.org/releng/v |
1157 | le/boron>`__ | iew/openflowplugi |
1158 | | n/job/openflowplu |
1159 | | gin-merge-boron/l |
1160 | | astSuccessfulBuil |
1161 | | d/artifact/model/ |
1162 | | model-flow-servic |
1163 | | e/target/site/mod |
1164 | | els/sal-group.htm |
1166 +--------------------------------------------------------+-------------------+
1167 | `sal-queue.yang <https://git.opendaylight.org/gerrit/g | `YangDOC <https:/ |
1168 | itweb?p=openflowplugin.git;f=model/model-flow-service/ | /jenkins.opendayl |
1169 | src/main/yang/sal-queue.yang;a=blob;hb=refs/heads/stab | ight.org/releng/v |
1170 | le/boron>`__ | iew/openflowplugi |
1171 | | n/job/openflowplu |
1172 | | gin-merge-boron/l |
1173 | | astSuccessfulBuil |
1174 | | d/artifact/model/ |
1175 | | model-flow-servic |
1176 | | e/target/site/mod |
1177 | | els/sal-queue.htm |
1179 +--------------------------------------------------------+-------------------+
1180 | `flow-errors.yang <https://git.opendaylight.org/gerrit | `YangDOC <https:/ |
1181 | /gitweb?p=openflowplugin.git;f=model/model-flow-servic | /jenkins.opendayl |
1182 | e/src/main/yang/flow-errors.yang;a=blob;hb=refs/heads/ | ight.org/releng/v |
1183 | stable/boron>`__ | iew/openflowplugi |
1184 | | n/job/openflowplu |
1185 | | gin-merge-boron/l |
1186 | | astSuccessfulBuil |
1187 | | d/artifact/model/ |
1188 | | model-flow-servic |
1189 | | e/target/site/mod |
1190 | | els/flow-errors.h |
1192 +--------------------------------------------------------+-------------------+
1193 | `flow-capable-transaction.yang <https://git.opendaylig | `YangDOC <https:/ |
1194 | ht.org/gerrit/gitweb?p=openflowplugin.git;f=model/mode | /jenkins.opendayl |
1195 | l-flow-service/src/main/yang/flow-capable-transaction. | ight.org/releng/v |
1196 | yang;a=blob;hb=refs/heads/stable/boron>`__ | iew/openflowplugi |
1197 | | n/job/openflowplu |
1198 | | gin-merge-boron/l |
1199 | | astSuccessfulBuil |
1200 | | d/artifact/model/ |
1201 | | model-flow-servic |
1202 | | e/target/site/mod |
1203 | | els/flow-capable- |
1204 | | transaction.htm |
1206 +--------------------------------------------------------+-------------------+
1207 | `sal-flow.yang <https://git.opendaylight.org/gerrit/gi | `YangDOC <https:/ |
1208 | tweb?p=openflowplugin.git;f=model/model-flow-service/s | /jenkins.opendayl |
1209 | rc/main/yang/sal-flow.yang;a=blob;hb=refs/heads/stable | ight.org/releng/v |
1210 | /boron>`__ | iew/openflowplugi |
1211 | | n/job/openflowplu |
1212 | | gin-merge-boron/l |
1213 | | astSuccessfulBuil |
1214 | | d/artifact/model/ |
1215 | | model-flow-servic |
1216 | | e/target/site/mod |
1217 | | els/sal-flow.htm |
1219 +--------------------------------------------------------+-------------------+
1220 | `sal-meter.yang <https://git.opendaylight.org/gerrit/g | `YangDOC <https:/ |
1221 | itweb?p=openflowplugin.git;f=model/model-flow-service/ | /jenkins.opendayl |
1222 | src/main/yang/sal-meter.yang;a=blob;hb=refs/heads/stab | ight.org/releng/v |
1223 | le/boron>`__ | iew/openflowplugi |
1224 | | n/job/openflowplu |
1225 | | gin-merge-boron/l |
1226 | | astSuccessfulBuil |
1227 | | d/artifact/model/ |
1228 | | model-flow-servic |
1229 | | e/target/site/mod |
1230 | | els/sal-meter.htm |
1232 +--------------------------------------------------------+-------------------+
1233 | `flow-topology-discovery.yang <https://git.opendayligh | `YangDOC <https:/ |
1234 | t.org/gerrit/gitweb?p=openflowplugin.git;f=model/model | /jenkins.opendayl |
1235 | -flow-service/src/main/yang/flow-topology-discovery.ya | ight.org/releng/v |
1236 | ng;a=blob;hb=refs/heads/stable/boron>`__ | iew/openflowplugi |
1237 | | n/job/openflowplu |
1238 | | gin-merge-boron/l |
1239 | | astSuccessfulBuil |
1240 | | d/artifact/model/ |
1241 | | model-flow-servic |
1242 | | e/target/site/mod |
1243 | | els/flow-topology |
1244 | | -discovery.htm |
1246 +--------------------------------------------------------+-------------------+
1247 | `node-errors.yang <https://git.opendaylight.org/gerrit | `YangDOC <https:/ |
1248 | /gitweb?p=openflowplugin.git;f=model/model-flow-servic | /jenkins.opendayl |
1249 | e/src/main/yang/node-errors.yang;a=blob;hb=refs/heads/ | ight.org/releng/v |
1250 | stable/boron>`__ | iew/openflowplugi |
1251 | | n/job/openflowplu |
1252 | | gin-merge-boron/l |
1253 | | astSuccessfulBuil |
1254 | | d/artifact/model/ |
1255 | | model-flow-servic |
1256 | | e/target/site/mod |
1257 | | els/node-errors.h |
1259 +--------------------------------------------------------+-------------------+
1260 | `node-config.yang <https://git.opendaylight.org/gerrit | `YangDOC <https:/ |
1261 | /gitweb?p=openflowplugin.git;f=model/model-flow-servic | /jenkins.opendayl |
1262 | e/src/main/yang/node-config.yang;a=blob;hb=refs/heads/ | ight.org/releng/v |
1263 | stable/boron>`__ | iew/openflowplugi |
1264 | | n/job/openflowplu |
1265 | | gin-merge-boron/l |
1266 | | astSuccessfulBuil |
1267 | | d/artifact/model/ |
1268 | | model-flow-servic |
1269 | | e/target/site/mod |
1270 | | els/node-config.h |
1272 +--------------------------------------------------------+-------------------+
1273 | `sal-echo.yang <https://git.opendaylight.org/gerrit/gi | `YangDOC <https:/ |
1274 | tweb?p=openflowplugin.git;f=model/model-flow-service/s | /jenkins.opendayl |
1275 | rc/main/yang/sal-echo.yang;a=blob;hb=refs/heads/stable | ight.org/releng/v |
1276 | /boron>`__ | iew/openflowplugi |
1277 | | n/job/openflowplu |
1278 | | gin-merge-boron/l |
1279 | | astSuccessfulBuil |
1280 | | d/artifact/model/ |
1281 | | model-flow-servic |
1282 | | e/target/site/mod |
1283 | | els/sal-echo.htm |
1285 +--------------------------------------------------------+-------------------+
1286 | `sal-port.yang <https://git.opendaylight.org/gerrit/gi | `YangDOC <https:/ |
1287 | tweb?p=openflowplugin.git;f=model/model-flow-service/s | /jenkins.opendayl |
1288 | rc/main/yang/sal-port.yang;a=blob;hb=refs/heads/stable | ight.org/releng/v |
1289 | /boron>`__ | iew/openflowplugi |
1290 | | n/job/openflowplu |
1291 | | gin-merge-boron/l |
1292 | | astSuccessfulBuil |
1293 | | d/artifact/model/ |
1294 | | model-flow-servic |
1295 | | e/target/site/mod |
1296 | | els/sal-port.htm |
1298 +--------------------------------------------------------+-------------------+
1299 | `packet-processing.yang <https://git.opendaylight.org/ | `YangDOC <https:/ |
1300 | gerrit/gitweb?p=openflowplugin.git;f=model/model-flow- | /jenkins.opendayl |
1301 | service/src/main/yang/packet-processing.yang;a=blob;hb | ight.org/releng/v |
1302 | =refs/heads/stable/boron>`__ | iew/openflowplugi |
1303 | | n/job/openflowplu |
1304 | | gin-merge-boron/l |
1305 | | astSuccessfulBuil |
1306 | | d/artifact/model/ |
1307 | | model-flow-servic |
1308 | | e/target/site/mod |
1309 | | els/packet-proces |
1311 +--------------------------------------------------------+-------------------+
1312 | `flow-node-inventory.yang <https://git.opendaylight.or | `YangDOC <https:/ |
1313 | g/gerrit/gitweb?p=openflowplugin.git;f=model/model-flo | /jenkins.opendayl |
1314 | w-service/src/main/yang/flow-node-inventory.yang;a=blo | ight.org/releng/v |
1315 | b;hb=refs/heads/stable/boron>`__ | iew/openflowplugi |
1316 | | n/job/openflowplu |
1317 | | gin-merge-boron/l |
1318 | | astSuccessfulBuil |
1319 | | d/artifact/model/ |
1320 | | model-flow-servic |
1321 | | e/target/site/mod |
1322 | | els/flow-node-inv |
1323 | | entory.html>`__ |
1324 +--------------------------------------------------------+-------------------+
1325 | ***Openflow statistics*** | |
1326 +--------------------------------------------------------+-------------------+
1327 | `opendaylight-queue-statistics.yang <https://git.opend | `YangDOC <https:/ |
1328 | aylight.org/gerrit/gitweb?p=openflowplugin.git;f=model | /jenkins.opendayl |
1329 | /model-flow-statistics/src/main/yang/opendaylight-queu | ight.org/releng/v |
1330 | e-statistics.yang;a=blob;hb=refs/heads/stable/boron>`_ | iew/openflowplugi |
1331 | _ | n/job/openflowplu |
1332 | | gin-merge-boron/l |
1333 | | astSuccessfulBuil |
1334 | | d/artifact/model/ |
1335 | | model-flow-statis |
1336 | | tics/target/site/ |
1337 | | models/opendaylig |
1338 | | ht-queue-statisti |
1340 +--------------------------------------------------------+-------------------+
1341 | `opendaylight-flow-table-statistics.yang <https://git. | `YangDOC <https:/ |
1342 | opendaylight.org/gerrit/gitweb?p=openflowplugin.git;f= | /jenkins.opendayl |
1343 | model/model-flow-statistics/src/main/yang/opendaylight | ight.org/releng/v |
1344 | -flow-table-statistics.yang;a=blob;hb=refs/heads/stabl | iew/openflowplugi |
1345 | e/boron>`__ | n/job/openflowplu |
1346 | | gin-merge-boron/l |
1347 | | astSuccessfulBuil |
1348 | | d/artifact/model/ |
1349 | | model-flow-statis |
1350 | | tics/target/site/ |
1351 | | models/opendaylig |
1352 | | ht-flow-table-sta |
1353 | | tistics.html>`__ |
1354 +--------------------------------------------------------+-------------------+
1355 | `opendaylight-port-statistics.yang <https://git.openda | `YangDOC <https:/ |
1356 | ylight.org/gerrit/gitweb?p=openflowplugin.git;f=model/ | /jenkins.opendayl |
1357 | model-flow-statistics/src/main/yang/opendaylight-port- | ight.org/releng/v |
1358 | statistics.yang;a=blob;hb=refs/heads/stable/boron>`__ | iew/openflowplugi |
1359 | | n/job/openflowplu |
1360 | | gin-merge-boron/l |
1361 | | astSuccessfulBuil |
1362 | | d/artifact/model/ |
1363 | | model-flow-statis |
1364 | | tics/target/site/ |
1365 | | models/opendaylig |
1366 | | ht-port-statistic |
1368 +--------------------------------------------------------+-------------------+
1369 | `opendaylight-statistics-types.yang <https://git.opend | `YangDOC <https:/ |
1370 | aylight.org/gerrit/gitweb?p=openflowplugin.git;f=model | /jenkins.opendayl |
1371 | /model-flow-statistics/src/main/yang/opendaylight-stat | ight.org/releng/v |
1372 | istics-types.yang;a=blob;hb=refs/heads/stable/boron>`_ | iew/openflowplugi |
1373 | _ | n/job/openflowplu |
1374 | | gin-merge-boron/l |
1375 | | astSuccessfulBuil |
1376 | | d/artifact/model/ |
1377 | | model-flow-statis |
1378 | | tics/target/site/ |
1379 | | models/opendaylig |
1380 | | ht-statistics-typ |
1382 +--------------------------------------------------------+-------------------+
1383 | `opendaylight-group-statistics.yang <https://git.opend | `YangDOC <https:/ |
1384 | aylight.org/gerrit/gitweb?p=openflowplugin.git;f=model | /jenkins.opendayl |
1385 | /model-flow-statistics/src/main/yang/opendaylight-grou | ight.org/releng/v |
1386 | p-statistics.yang;a=blob;hb=refs/heads/stable/boron>`_ | iew/openflowplugi |
1387 | _ | n/job/openflowplu |
1388 | | gin-merge-boron/l |
1389 | | astSuccessfulBuil |
1390 | | d/artifact/model/ |
1391 | | model-flow-statis |
1392 | | tics/target/site/ |
1393 | | models/opendaylig |
1394 | | ht-group-statisti |
1396 +--------------------------------------------------------+-------------------+
1397 | `opendaylight-flow-statistics.yang <https://git.openda | `YangDOC <https:/ |
1398 | ylight.org/gerrit/gitweb?p=openflowplugin.git;f=model/ | /jenkins.opendayl |
1399 | model-flow-statistics/src/main/yang/opendaylight-flow- | ight.org/releng/v |
1400 | statistics.yang;a=blob;hb=refs/heads/stable/boron>`__ | iew/openflowplugi |
1401 | | n/job/openflowplu |
1402 | | gin-merge-boron/l |
1403 | | astSuccessfulBuil |
1404 | | d/artifact/model/ |
1405 | | model-flow-statis |
1406 | | tics/target/site/ |
1407 | | models/opendaylig |
1408 | | ht-flow-statistic |
1410 +--------------------------------------------------------+-------------------+
1411 | `opendaylight-meter-statistics.yang <https://git.opend | `YangDOC <https:/ |
1412 | aylight.org/gerrit/gitweb?p=openflowplugin.git;f=model | /jenkins.opendayl |
1413 | /model-flow-statistics/src/main/yang/opendaylight-mete | ight.org/releng/v |
1414 | r-statistics.yang;a=blob;hb=refs/heads/stable/boron>`_ | iew/openflowplugi |
1415 | _ | n/job/openflowplu |
1416 | | gin-merge-boron/l |
1417 | | astSuccessfulBuil |
1418 | | d/artifact/model/ |
1419 | | model-flow-statis |
1420 | | tics/target/site/ |
1421 | | models/opendaylig |
1422 | | ht-meter-statisti |
1424 +--------------------------------------------------------+-------------------+
1429 .. figure:: ./images/openflowplugin/odl-ofp-feature-tree.png
1430 :alt: Openflow plugin karaf feature tree
1432 Openflow plugin karaf feature tree
1435 `HOWTO <https://wiki.opendaylight.org/view/OpenDaylight_OpenFlow_Plugin:FeatureTreeHowto>`__
1438 Wiring up notifications
1439 -----------------------
1444 We need to translate OpenFlow messages coming up from the :ref:`OpenFlow
1445 Protocol Library <openflow-protocol-library>` into
1446 MD-SAL Notification objects and then publish them to the MD-SAL.
1451 1. Create a Translator class
1453 2. Register the Translator
1455 3. Register the notificationPopListener to handle your Notification
1458 Create a Translator class
1459 ^^^^^^^^^^^^^^^^^^^^^^^^^
1461 You can see an example in
1462 `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>`__.
1464 First, simply create the class
1468 public class PacketInTranslator implements IMDMessageTranslator<OfHeader, List<DataObject>> {
1470 Then implement the translate function:
1474 public class PacketInTranslator implements IMDMessageTranslator<OfHeader, List<DataObject>> {
1476 protected static final Logger LOG = LoggerFactory
1477 .getLogger(PacketInTranslator.class);
1479 public PacketReceived translate(SwitchConnectionDistinguisher cookie,
1480 SessionContext sc, OfHeader msg) {
1484 Make sure to check that you are dealing with the expected type and cast
1489 if(msg instanceof PacketInMessage) {
1490 PacketInMessage message = (PacketInMessage)msg;
1491 List<DataObject> list = new CopyOnWriteArrayList<DataObject>();
1493 Do your transation work and return
1497 PacketReceived pktInEvent = pktInBuilder.build();
1498 list.add(pktInEvent);
1501 Register your Translator Class
1502 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1504 Next you need to go to
1505 `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>`__
1506 and in init() add register your Translator:
1510 public void init() {
1511 LOG.debug("Initializing!");
1512 messageTranslators = new ConcurrentHashMap<>();
1513 popListeners = new ConcurrentHashMap<>();
1514 //TODO: move registration to factory
1515 addMessageTranslator(ErrorMessage.class, OF10, new ErrorTranslator());
1516 addMessageTranslator(ErrorMessage.class, OF13, new ErrorTranslator());
1517 addMessageTranslator(PacketInMessage.class,OF10, new PacketInTranslator());
1518 addMessageTranslator(PacketInMessage.class,OF13, new PacketInTranslator());
1520 Notice that there is a separate registration for each of OpenFlow 1.0
1521 and OpenFlow 1.3. Basically, you indicate the type of OpenFlow Protocol
1522 Library message you wish to translate for, the OpenFlow version, and an
1523 instance of your Translator.
1525 Register your MD-SAL Message for Notification to the MD-SAL
1526 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1528 Now, also in MDController.init() register to have the
1529 notificationPopListener handle your MD-SAL Message:
1533 addMessagePopListener(PacketReceived.class, new NotificationPopListener<DataObject>());
1538 That’s all there is to it. Now when a message comes up from the OpenFlow
1539 Protocol Library, it will be translated and published to the MD-SAL.
1541 Message Order Preservation
1542 --------------------------
1544 While the Helium release of OpenFlow Plugin relied on queues to ensure
1545 messages were delivered in order, subsequent releases instead ensure
1546 that all the messages from a given device are delivered using the same
1547 thread and thus message order is guaranteed without queues. The OpenFlow
1548 plugin allocates a number of threads equal to twice the number of
1549 processor cores on machine it is run, e.g., 8 threads if the machine has
1554 While each device is assigned to one thread, multiple devices can be
1555 assigned to the same thread.