3 .OpenFlow plugin: Component map
6 | Artifact ID | Component | Description
7 | openflowplugin | openflowplugin | Main implementation of OFPlugin
8 | openflowplugin-it test-provider drop-test test-scripts | test | Support for end-to-end, integration, and regression testing
9 | openflowplugin-controller-config | configSubsystem | Default configuration files for config subsystem
10 | distributions-openflowplugin-base | distribution | OFPlugin distribution, based on the distribution of the controller,
11 but the old (OF-1.0 only) plugin is replaced with the new plugin(OF-1.0+1.3)
12 | learning-switch sample-consumer | sample | Sample projects demonstrating MD-SAL usage
13 | vagrant | util | Materialize testing virtual machine containing mininet+ovs
16 === OpenFlow Plugin: Sequence diagrams
19 image::MessageLifecycle.jpg[width=500]
22 image::Handshake.png[width=500]
24 .Connection Sequence (Handshake) Flow Diagram
25 image::OF1_0_Switch_Handshake_Sequence.png[width=500]
27 .Message Order Preservation
28 image::MessageOrderPreservation.jpg[width=500]
31 image::Add_flow.png[width=500]
33 .Generic Notification Sequence
34 image::Generic_notification.png[width=500]
36 === OpenFlow Plugin:Config subsystem
37 ==== Model provided modules by yang
38 *General model (interfaces)* - openflow-plugin-cfg.yang. +
40 * The provided module is defined (identity openflow-provider)
42 * The target implementation is assigned (...OpenflowPluginProvider)
44 module openflow-provider {
46 namespace "urn:opendaylight:params:xml:ns:yang:openflow:common:config";
47 prefix "ofplugin-cfg";
49 import config {prefix config; revision-date 2013-04-05; }
51 "openflow-plugin-custom-config";
52 revision "2014-03-26" {
56 identity openflow-provider{
57 base config:service-type;
58 config:java-class "org.opendaylight.openflowplugin.openflow.md.core.sal.OpenflowPluginProvider";
62 *Implementation model* - openflow-plugin-cfg-impl.yang +
64 * The implementation of module is defined (+identity openflow-provider-impl+).
66 ** The class name of the generated implementation is defined (ConfigurableOpenFlowProvider).
68 * The configuration of the module is defined through augmentation:
69 ** This module requires an instance of a binding-aware-broker (container binding-aware-broker).
70 ** Also required is a list of openflow-switch-connection-providers. (Those are provided by openflowjava: one plugin instance will orchester multiple openflowjava modules.)
72 module openflow-provider-impl {
74 namespace "urn:opendaylight:params:xml:ns:yang:openflow:common:config:impl";
75 prefix "ofplugin-cfg-impl";
77 import config {prefix config; revision-date 2013-04-05;}
78 import openflow-provider {prefix openflow-provider;}
79 import openflow-switch-connection-provider {prefix openflow-switch-connection-provider;revision-date 2014-03-28;}
80 import opendaylight-md-sal-binding { prefix md-sal-binding; revision-date 2013-10-28;}
84 "openflow-plugin-custom-config-impl";
86 revision "2014-03-26" {
91 identity openflow-provider-impl {
92 base config:module-type;
93 config:provided-service openflow-provider:openflow-provider;
94 config:java-name-prefix ConfigurableOpenFlowProvider;
97 augment "/config:modules/config:module/config:configuration" {
98 case openflow-provider-impl {
99 when "/config:modules/config:module/config:type = 'openflow-provider-impl'";
101 container binding-aware-broker {
102 uses config:service-ref {
105 config:required-identity md-sal-binding:binding-broker-osgi-registry;
109 list openflow-switch-connection-provider {
110 uses config:service-ref {
113 config:required-identity openflow-switch-connection-provider:openflow-switch-connection-provider;
121 ==== Generating config and sal classes from yangs
122 NOTE: Suitable code generators, needed in pom, are involved.
128 <groupId>org.opendaylight.yangtools</groupId>
129 <artifactId>yang-maven-plugin</artifactId>
133 <goal>generate-sources</goal>
139 org.opendaylight.controller.config.yangjmxgenerator.plugin.JMXGenerator
140 </codeGeneratorClass>
141 <outputBaseDir>${project.build.directory}/generated-sources/config</outputBaseDir>
142 <additionalConfiguration>
143 <namespaceToPackage1>
144 urn:opendaylight:params:xml:ns:yang:controller==org.opendaylight.controller.config.yang
145 </namespaceToPackage1>
146 </additionalConfiguration>
150 org.opendaylight.yangtools.maven.sal.api.gen.plugin.CodeGeneratorImpl
151 </codeGeneratorClass>
152 <outputBaseDir>${project.build.directory}/generated-sources/sal</outputBaseDir>
155 <codeGeneratorClass>org.opendaylight.yangtools.yang.unified.doc.generator.maven.DocumentationGeneratorImpl</codeGeneratorClass>
156 <outputBaseDir>${project.build.directory}/site/models</outputBaseDir>
159 <inspectDependencies>true</inspectDependencies>
165 <groupId>org.opendaylight.controller</groupId>
166 <artifactId>yang-jmx-generator-plugin</artifactId>
167 <version>0.2.5-SNAPSHOT</version>
170 <groupId>org.opendaylight.yangtools</groupId>
171 <artifactId>maven-sal-api-gen-plugin</artifactId>
172 <version>${yangtools.version}</version>
179 * JMX generator (target/generated-sources/config)
181 * sal CodeGeneratorImpl (target/generated-sources/sal)
183 * Documentation generator (target/site/models): https://jenkins.opendaylight.org/openflowplugin/job/openflowplugin-merge/ws/openflowplugin/target/site/models/openflow-provider.html[openflow generator]and https://jenkins.opendaylight.org/openflowplugin/job/openflowplugin-merge/ws/openflowplugin/target/site/models/openflow-provider-impl.html[openflow provider impl].
185 ==== Altering generated files
186 Those files were generated under src/main/java in the package as referred in yangs (if they exist, the generator will not overwrite them): +
188 * ConfigurableOpenFlowProviderModuleFactory
190 The *instantiateModule* methods are extended in order to capture and inject the osgi BundleContext into module, so it can be injected into final implementation: *OpenflowPluginProvider* +module.setBundleContext(bundleContext);+ +
192 * ConfigurableOpenFlowProviderModule
194 The *createInstance* method is extended in order to inject osgi BundleContext into the module implementation: +pluginProvider.setContext(bundleContext);+
196 ==== Configuration xml file
198 The configuration file contains: +
200 * Required capabilities
202 ** Modules definitions from openflowjava
204 ** Definitions from openflowplugin
208 ** openflow:switch:connection:provider:impl (listening on port 6633, name=openflow-switch-connection-provider-legacy-impl)
209 ** openflow:switch:connection:provider:impl (listening on port 6653, name=openflow-switch-connection-provider-default-impl)
210 ** openflow:common:config:impl (having 2 services (wrapping those 2 previous modules) and binding-broker-osgi-registry injected)
212 ** openflow-switch-connection-provider-default
213 ** openflow-switch-connection-provider-legacy
217 <required-capabilities>
218 <capability>urn:opendaylight:params:xml:ns:yang:openflow:switch:connection:provider:impl?module=openflow-switch-connection-provider-impl&revision=2014-03-28</capability>
219 <capability>urn:opendaylight:params:xml:ns:yang:openflow:switch:connection:provider?module=openflow-switch-connection-provider&revision=2014-03-28</capability>
220 <capability>urn:opendaylight:params:xml:ns:yang:openflow:common:config:impl?module=openflow-provider-impl&revision=2014-03-26</capability>
221 <capability>urn:opendaylight:params:xml:ns:yang:openflow:common:config?module=openflow-provider&revision=2014-03-26</capability>
222 </required-capabilities>
227 <modules xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
229 <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:openflow:switch:connection:provider:impl">
230 prefix:openflow-switch-connection-provider-impl
232 <name>openflow-switch-connection-provider-default-impl</name>
234 <switch-idle-timeout>15000</switch-idle-timeout>
237 <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:openflow:switch:connection:provider:impl">
238 prefix:openflow-switch-connection-provider-impl
240 <name>openflow-switch-connection-provider-legacy-impl</name>
242 <switch-idle-timeout>15000</switch-idle-timeout>
247 <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:openflow:common:config:impl">
248 prefix:openflow-provider-impl
250 <name>openflow-provider-impl</name>
252 <openflow-switch-connection-provider>
253 <type xmlns:ofSwitch="urn:opendaylight:params:xml:ns:yang:openflow:switch:connection:provider">
254 ofSwitch:openflow-switch-connection-provider
256 <name>openflow-switch-connection-provider-default</name>
257 </openflow-switch-connection-provider>
258 <openflow-switch-connection-provider>
259 <type xmlns:ofSwitch="urn:opendaylight:params:xml:ns:yang:openflow:switch:connection:provider">
260 ofSwitch:openflow-switch-connection-provider
262 <name>openflow-switch-connection-provider-legacy</name>
263 </openflow-switch-connection-provider>
266 <binding-aware-broker>
267 <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">
268 binding:binding-broker-osgi-registry
270 <name>binding-osgi-broker</name>
271 </binding-aware-broker>
275 <services xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
277 <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:openflow:switch:connection:provider">
278 prefix:openflow-switch-connection-provider
281 <name>openflow-switch-connection-provider-default</name>
282 <provider>/modules/module[type='openflow-switch-connection-provider-impl'][name='openflow-switch-connection-provider-default-impl']</provider>
285 <name>openflow-switch-connection-provider-legacy</name>
286 <provider>/modules/module[type='openflow-switch-connection-provider-impl'][name='openflow-switch-connection-provider-legacy-impl']</provider>
291 <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:openflow:common:config">prefix:openflow-provider</type>
293 <name>openflow-provider</name>
294 <provider>/modules/module[type='openflow-provider-impl'][name='openflow-provider-impl']</provider>
304 In order to provide multiple instances of modules from openflowjava, there is an API change. Previously, the OFPlugin got access to the SwitchConnectionProvider exposed by OFJava, and injected the collection of configurations so that for every configuration, a new instance of the TCP listening server was created. Now, those configurations are provided by the configSubsystem, and the configured modules (wrapping the original SwitchConnectionProvider) are injected into the OFPlugin (wrapping SwitchConnectionHandler).
306 ==== Providing config file (IT, local distribution/base, integration/distributions/base)
309 The whole configuration is contained in one file (controller.xml). The entries needed in order to start up and wire the OEPlugin + OFJava are simply added there.
311 *OFPlugin/distribution/base* +
313 The new config file is added (src/main/resources/configuration/initial/42-openflow-protocol-impl.xml), and copied to the config/initial subfolder of the build.
315 *Integration/distributions/build* +
317 In order to push the actual config into the config/initial subfolder of distributions/base in the integration project, a new artifact was created in OFPlugin. The openflowplugin-controller-config contains only the config xml file under src/main/resources. Another change was committed into the integration project. During a build, this config xml is extracted and copied to the final folder in order to be accessible during the controller run.
319 === Message Spy in OF Plugin
321 With the intent to debug, the OpenFlow plugin implements a Message Spy to monitor controller communications.
322 The Message Spy collects and displays message statistics.
324 ==== Message statistics collection +
325 Message statistics are grouped according to message type and checkpoint. The counter assigned to a checkpoint and message class increases by 1 when a message passes through.
327 The following checkpoints count passing messages: +
330 * statistic groups overall in OFPlugin
332 enum STATISTIC_GROUP {
333 /** message from switch, enqueued for processing */
334 FROM_SWITCH_ENQUEUED,
335 /** message from switch translated successfully - source */
336 FROM_SWITCH_TRANSLATE_IN_SUCCESS,
337 /** message from switch translated successfully - target */
338 FROM_SWITCH_TRANSLATE_OUT_SUCCESS,
339 /** message from switch where translation failed - source */
340 FROM_SWITCH_TRANSLATE_SRC_FAILURE,
341 /** message from switch finally published into MD-SAL */
342 FROM_SWITCH_PUBLISHED_SUCCESS,
343 /** message from switch - publishing into MD-SAL failed */
344 FROM_SWITCH_PUBLISHED_FAILURE,
346 /** message from MD-SAL to switch via RPC enqueued */
347 TO_SWITCH_ENQUEUED_SUCCESS,
348 /** message from MD-SAL to switch via RPC NOT enqueued */
349 TO_SWITCH_ENQUEUED_FAILED,
350 /** message from MD-SAL to switch - sent to OFJava successfully */
351 TO_SWITCH_SUBMITTED_SUCCESS,
352 /** message from MD-SAL to switch - sent to OFJava but failed*/
353 TO_SWITCH_SUBMITTED_FAILURE
356 ==== Message statistics display +
357 Access the message statistics by means of logs, osgi, and jmx. +
359 * osgi command (on demand): This method is considered deprecated. +
360 : +osgi> dumpMsgCount+ +
362 * From the controller console where statistics are refreshed every 10 seconds:
363 +Required logback settings: <logger name="org.opendaylight.openflowplugin.openflow.md.queue.MessageSpyCounterImpl" level="DEBUG" />+
365 * As JMX from the jconsole:
366 ** Start the OFplugin with the -jmx parameter.
367 ** Tab MBeans contains org.opendaylight.controller.
368 ** RuntimeBean has a msg-spy-service-impl.
369 ** Operations provides makeMsgStatistics report functionality.
373 DEBUG o.o.o.s.MessageSpyCounterImpl - FROM_SWITCH_ENQUEUED: MSG[PortStatusMessage] -> +0 | 1
374 DEBUG o.o.o.s.MessageSpyCounterImpl - FROM_SWITCH_ENQUEUED: MSG[MultipartReplyMessage] -> +24 | 81
375 DEBUG o.o.o.s.MessageSpyCounterImpl - FROM_SWITCH_ENQUEUED: MSG[PacketInMessage] -> +8 | 111
376 DEBUG o.o.o.s.MessageSpyCounterImpl - FROM_SWITCH_TRANSLATE_IN_SUCCESS: MSG[PortStatusMessage] -> +0 | 1
377 DEBUG o.o.o.s.MessageSpyCounterImpl - FROM_SWITCH_TRANSLATE_IN_SUCCESS: MSG[MultipartReplyMessage] -> +24 | 81
378 DEBUG o.o.o.s.MessageSpyCounterImpl - FROM_SWITCH_TRANSLATE_IN_SUCCESS: MSG[PacketInMessage] -> +8 | 111
379 DEBUG o.o.o.s.MessageSpyCounterImpl - FROM_SWITCH_TRANSLATE_OUT_SUCCESS: MSG[QueueStatisticsUpdate] -> +3 | 7
380 DEBUG o.o.o.s.MessageSpyCounterImpl - FROM_SWITCH_TRANSLATE_OUT_SUCCESS: MSG[NodeUpdated] -> +0 | 3
381 DEBUG o.o.o.s.MessageSpyCounterImpl - FROM_SWITCH_TRANSLATE_OUT_SUCCESS: MSG[NodeConnectorStatisticsUpdate] -> +3 | 7
382 DEBUG o.o.o.s.MessageSpyCounterImpl - FROM_SWITCH_TRANSLATE_OUT_SUCCESS: MSG[GroupDescStatsUpdated] -> +3 | 7
383 DEBUG o.o.o.s.MessageSpyCounterImpl - FROM_SWITCH_TRANSLATE_OUT_SUCCESS: MSG[FlowsStatisticsUpdate] -> +3 | 19
384 DEBUG o.o.o.s.MessageSpyCounterImpl - FROM_SWITCH_TRANSLATE_OUT_SUCCESS: MSG[PacketReceived] -> +8 | 111
385 DEBUG o.o.o.s.MessageSpyCounterImpl - FROM_SWITCH_TRANSLATE_OUT_SUCCESS: MSG[MeterFeaturesUpdated] -> +0 | 3
386 DEBUG o.o.o.s.MessageSpyCounterImpl - FROM_SWITCH_TRANSLATE_OUT_SUCCESS: MSG[GroupStatisticsUpdated] -> +3 | 7
387 DEBUG o.o.o.s.MessageSpyCounterImpl - FROM_SWITCH_TRANSLATE_OUT_SUCCESS: MSG[GroupFeaturesUpdated] -> +0 | 3
388 DEBUG o.o.o.s.MessageSpyCounterImpl - FROM_SWITCH_TRANSLATE_OUT_SUCCESS: MSG[MeterConfigStatsUpdated] -> +3 | 7
389 DEBUG o.o.o.s.MessageSpyCounterImpl - FROM_SWITCH_TRANSLATE_OUT_SUCCESS: MSG[MeterStatisticsUpdated] -> +3 | 7
390 DEBUG o.o.o.s.MessageSpyCounterImpl - FROM_SWITCH_TRANSLATE_OUT_SUCCESS: MSG[NodeConnectorUpdated] -> +0 | 12
391 DEBUG o.o.o.s.MessageSpyCounterImpl - FROM_SWITCH_TRANSLATE_OUT_SUCCESS: MSG[FlowTableStatisticsUpdate] -> +3 | 8
392 DEBUG o.o.o.s.MessageSpyCounterImpl - FROM_SWITCH_TRANSLATE_SRC_FAILURE: no activity detected
393 DEBUG o.o.o.s.MessageSpyCounterImpl - FROM_SWITCH_PUBLISHED_SUCCESS: MSG[QueueStatisticsUpdate] -> +3 | 7
394 DEBUG o.o.o.s.MessageSpyCounterImpl - FROM_SWITCH_PUBLISHED_SUCCESS: MSG[NodeUpdated] -> +0 | 3
395 DEBUG o.o.o.s.MessageSpyCounterImpl - FROM_SWITCH_PUBLISHED_SUCCESS: MSG[NodeConnectorStatisticsUpdate] -> +3 | 7
396 DEBUG o.o.o.s.MessageSpyCounterImpl - FROM_SWITCH_PUBLISHED_SUCCESS: MSG[GroupDescStatsUpdated] -> +3 | 7
397 DEBUG o.o.o.s.MessageSpyCounterImpl - FROM_SWITCH_PUBLISHED_SUCCESS: MSG[FlowsStatisticsUpdate] -> +3 | 19
398 DEBUG o.o.o.s.MessageSpyCounterImpl - FROM_SWITCH_PUBLISHED_SUCCESS: MSG[PacketReceived] -> +8 | 111
399 DEBUG o.o.o.s.MessageSpyCounterImpl - FROM_SWITCH_PUBLISHED_SUCCESS: MSG[MeterFeaturesUpdated] -> +0 | 3
400 DEBUG o.o.o.s.MessageSpyCounterImpl - FROM_SWITCH_PUBLISHED_SUCCESS: MSG[GroupStatisticsUpdated] -> +3 | 7
401 DEBUG o.o.o.s.MessageSpyCounterImpl - FROM_SWITCH_PUBLISHED_SUCCESS: MSG[GroupFeaturesUpdated] -> +0 | 3
402 DEBUG o.o.o.s.MessageSpyCounterImpl - FROM_SWITCH_PUBLISHED_SUCCESS: MSG[MeterConfigStatsUpdated] -> +3 | 7
403 DEBUG o.o.o.s.MessageSpyCounterImpl - FROM_SWITCH_PUBLISHED_SUCCESS: MSG[MeterStatisticsUpdated] -> +3 | 7
404 DEBUG o.o.o.s.MessageSpyCounterImpl - FROM_SWITCH_PUBLISHED_SUCCESS: MSG[NodeConnectorUpdated] -> +0 | 12
405 DEBUG o.o.o.s.MessageSpyCounterImpl - FROM_SWITCH_PUBLISHED_SUCCESS: MSG[FlowTableStatisticsUpdate] -> +3 | 8
406 DEBUG o.o.o.s.MessageSpyCounterImpl - FROM_SWITCH_PUBLISHED_FAILURE: no activity detected
407 DEBUG o.o.o.s.MessageSpyCounterImpl - TO_SWITCH_ENQUEUED_SUCCESS: MSG[AddFlowInput] -> +0 | 12
408 DEBUG o.o.o.s.MessageSpyCounterImpl - TO_SWITCH_ENQUEUED_FAILED: no activity detected
409 DEBUG o.o.o.s.MessageSpyCounterImpl - TO_SWITCH_SUBMITTED_SUCCESS: MSG[AddFlowInput] -> +0 | 12
410 DEBUG o.o.o.s.MessageSpyCounterImpl - TO_SWITCH_SUBMITTED_FAILURE: no activity detected
413 === OpenFlow Plugin:Mininet
414 ==== Mininet on debian wheezy(7), x86_64
419 . Install all requirements.
421 apt-get install build-essential fakeroot
422 apt-get install debhelper autoconf automake libssl-dev pkg-config bzip2 openssl python-all procps python-qt4 python-zopeinterface python-twisted-conch
425 . Install a few helper applications.
427 apt-get -y install screen sudo vim etckeeper mlocate autoconf2.13 libssl-dev graphviz tcpdump gdebi-core
429 ==== Test the Python environment
432 . Install setuptools.
434 wget https://bitbucket.org/pypa/setuptools/raw/bootstrap/ez_setup.py
435 sudo python ez_setup.py
440 wget https://raw.github.com/pypa/pip/master/contrib/get-pip.py
441 sudo python get-pip.py
444 . Post install the python libraries required by the ODL testing script.
446 sudo pip install netaddr
449 ==== Openvswitch 2.0.0
450 . Remove the old packages, as root:
453 apt-get remove openvswitch-common openvswitch-datapath-dkms openvswitch-controller openvswitch-pki openvswitch-switch
456 . Download and unpack OpenV Switch 2.0.0.
458 wget http://openvswitch.org/releases/openvswitch-2.0.0.tar.gz
459 tar zxvf openvswitch-2.0.0.tar.gz
461 *Build and install* +
463 . Install the openvswitch package. Deploy it using the module assistant at: https://wiki.debian.org/ModuleAssistant
466 gdebi openvswitch-datapath-source_2.0.0-1_all.deb
467 module-assistant auto-install openvswitch-datapath
468 gdebi openvswitch-common_2.0.0-1_amd64.deb
469 gdebi openvswitch-switch_2.0.0-1_amd64.deb
470 gdebi openvswitch-pki_2.0.0-1_all.deb
471 gdebi openvswitch-controller_2.0.0-1_amd64.deb
473 *Post installation settings* +
475 service openvswitch-controller stop
476 update-rc.d openvswitch-controller disable
478 *Test installation* +
484 ovs-controller --version
488 . Download and checkout the required version.
490 git clone git://github.com/mininet/mininet
492 git checkout -b 2.1.0 2.1.0
495 . Compile and install mininet.
497 gcc mnexec.c -o mnexec
499 python setup.py install
502 . Test the installation.
509 root@debian:~/mininet# mn --version
511 root@debian:~/mininet# mn --test pingall
513 *** Adding controller
520 *** Configuring hosts
522 *** Starting controller
523 *** Starting 1 switches
525 *** Ping: testing ping reachability
528 *** Results: 0% dropped (2/2 received)
529 *** Stopping 1 switches
533 *** Stopping 1 controllers
536 completed in 0.269 seconds
538 *Post installation additions* +
540 * Modify the source code of the mininet node.py file as described in https://wiki.opendaylight.org/view/Openflow_Protocol_Library:OpenVirtualSwitch#Stage_3[Stage 3].
542 --- /root/mininet/build/lib.linux-x86_64-2.7/mininet/node.py 2013-11-22 03:35:12.000000000 -0800
543 +++ /usr/local/lib/python2.7/dist-packages/mininet-2.1.0-py2.7.egg/mininet/node.py 2013-11-22 06:17:07.350574387 -0800
545 datapath: userspace or kernel mode (kernel|user)"""
546 Switch.__init__( self, name, **params )
547 self.failMode = failMode
548 + protKey = 'protocols'
549 + if self.params and protKey in self.params:
550 + print 'have protcol params!'
551 + self.opts += protKey + '=' + self.params[protKey]
552 self.datapath = datapath
554 @@ -1027,8 +1031,9 @@
555 if self.datapath == 'user':
556 self.cmd( 'ovs-vsctl set bridge', self,'datapath_type=netdev' )
557 int( self.dpid, 16 ) # DPID must be a hex string
558 + print 'OVSswitch opts: ',self.opts
559 self.cmd( 'ovs-vsctl -- set Bridge', self,
560 - 'other_config:datapath-id=' + self.dpid )
561 + self.opts+' other_config:datapath-id=' + self.dpid)
562 self.cmd( 'ovs-vsctl set-fail-mode', self, self.failMode )
563 for intf in self.intfList():
566 *Start and test the modified mininet* +
568 . Start the mn session:
570 sudo mn --topo single,3 --controller 'remote,ip=<your controller IP>' --switch ovsk,protocols=OpenFlow10
573 . Alternatively, use this command:
575 sudo mn --topo single,3 --controller 'remote,ip=<your controller IP>' --switch ovsk,protocols=OpenFlow13
578 . Test the version of the protocol used by switch "s1":
580 ovs-ofctl -O OpenFlow10 show s1
581 ovs-ofctl -O OpenFlow13 show s1
585 REST tests openflowplugin
587 sudo python odl_tests.py --xmls 1,2
589 * For more option informations, use:
591 sudo python odl_tests.py --help
593 === Coding tips for OpenFlow Plugin
594 If you use Eclipse, the following compiler settings might be useful either during coding or while fixing errors.
595 The following errors are noteworthy:
599 * missing case in switch block.
600 * missing break in case.
601 * unused variables/parameters.
602 * annotations checks (@override).
603 * access to non accessible member of enclosing type.
604 * If overriding hashcode or equals, both must be overriden.
606 Also useful are warnings upon missing javadoc comments for public classes, members, and methods.
608 .Configure Compiler Errors and Warnings
609 image::codinghints1.png[height=750]
612 image::codinghints2.png[width=500]
614 === OpenFlow Plugin: Wiring up notifications
616 OpenFlow messages coming from the OpenflowJava plugin into MD-SAL Notification objects must be translated, and then published to the MD-SAL.
618 ==== To create and register a Translator
619 . Create a Translator class.
620 . Register the Translator.
621 . Register the notificationPopListener to handle Notification Objects.
623 ==== Creating a Translator Class
624 An example is available in 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;h=e0944c39bfacad1d396b15087f668d9d1fa1d95d;hb=HEAD[PacketInTranslator.java].
628 public class PacketInTranslator implements IMDMessageTranslator<OfHeader, List<DataObject>> {
631 . Implement the translate function:
633 public class PacketInTranslator implements IMDMessageTranslator<OfHeader, List<DataObject>> {
635 protected static final Logger LOG = LoggerFactory
636 .getLogger(PacketInTranslator.class);
638 public PacketReceived translate(SwitchConnectionDistinguisher cookie,
639 SessionContext sc, OfHeader msg) {
644 . Ensure that the type is the expected one, and cast it:
646 if(msg instanceof PacketInMessage) {
647 PacketInMessage message = (PacketInMessage)msg;
648 List<DataObject> list = new CopyOnWriteArrayList<DataObject>();
651 . Complete the translation and return.
653 PacketReceived pktInEvent = pktInBuilder.build();
654 list.add(pktInEvent);
657 ==== Registeing the Translator Class
658 * Go to https://git.opendaylight.org/gerrit/gitweb?p=openflowplugin.git;a=blob;f=openflowplugin/src/main/java/org/opendaylight/openflowplugin/openflow/md/core/MDController.java;h=d79e18704b05923eee2a2da57d02655e2af6d9c1;hb=HEAD[MDController.java] and in init() add register your Translator:
661 LOG.debug("Initializing!");
662 messageTranslators = new ConcurrentHashMap<>();
663 popListeners = new ConcurrentHashMap<>();
664 //TODO: move registration to factory
665 addMessageTranslator(ErrorMessage.class, OF10, new ErrorTranslator());
666 addMessageTranslator(ErrorMessage.class, OF13, new ErrorTranslator());
667 addMessageTranslator(PacketInMessage.class,OF10, new PacketInTranslator());
668 addMessageTranslator(PacketInMessage.class,OF13, new PacketInTranslator());
670 NOTE: There is a separate registration for each of the OF10 and OF13. Basically, you indicate the type of openflowjava message you wish to translate for, the OF version, and an instance of your Translator.
672 ==== Registering your MD-SAL message for notification to the MD-SAL
673 * In MDController.init() register to have the notificationPopListener handle your MD-SAL Message:
675 addMessagePopListener(PacketReceived.class, new NotificationPopListener<DataObject>());
677 When a message comes from the openflowjava plugin, it will be translated and published to the MD-SAL.
679 === OpenFlow Plugin:Python test scripts
680 ==== Prerequisites for Python test-scripts
681 * Linux based OS (these instructions cover debian 7 - wheezy)
684 * Openvswitch (v 2.0.0)
686 * Controller (supporting openflow 1.3)
688 ==== Installing python tools
689 NOTE: Build python tools with python2.6, not the default python.
691 * wget https://bitbucket.org/pypa/setuptools/raw/bootstrap/ez_setup.py
692 * python2.6 ez_setup.py
693 * wget https://raw.github.com/pypa/pip/master/contrib/get-pip.py
694 * python2.6 get-pip.py
696 See <<_openflow_plugin_mininet>>
698 ==== Installing Wireshark
699 . apt-get install wireshark
700 . Make yourself a standard user again (CTRL^D)
701 . sudo dpkg-reconfigure wireshark-common
702 . sudo usermod -a -G wireshark $USER
705 ==== Adding openflow13 dissector to wireshark
706 . mkdir /home/mininet/.wireshark/plugins/
707 . Copy the file openflow.so to this directory //TODO add attachment.
711 *Install Java JDK and set JAVA_HOME*
713 . apt-get install openjdk-7-jdk
714 . Export JAVA_HOME=/usr/lib/jvm/java-7-openjdk-amd64/jre/bin/java
716 *Download, unzip, and run the integration build* +
718 . Find the latest integration/distribution/base build on nexus.
719 . Download it (using for example, wget <url to artifact.zip>) and unzip it (using for example, unzip <artifact.zip>)
720 . Start the controller:
725 *Clone openflowplugin project* +
727 * git clone https://git.opendaylight.org/gerrit/p/openflowplugin.git
731 * locations: openflowplugin/test-scripts
733 ** xmls (switch configuration input in xml form)
736 *** odl_crud_tests.py
738 *** oper_data_test.py
739 *** sw_restart_test.py
742 The tests are designed for running on Linux based machines with installed ovs and mininet python scripts. All scripts has to be started with same permission as mininet (*sudo*).
743 Otherwise the scripts can not start mininet. All runnable scripts contains a *help* description for input parameters for a quick orientation.
745 Basic parameters for all runnable scripts:
747 * +--help+: dump help
748 * +--mnport+: A controller port listener for the openflow switch communications. The parameter is used for configuration startup of the Mininet. A default value is *6653*.
749 * +--odlhost+: A controller IP address. The parameter is used for configuration startup of the Mininet and for the rest address builders. A default value is *127.0.0.1* (localhost).
750 * +--odlport+: A controller port listener for a http REST communication. The parameter is used for the rest address builders.
752 === ODL Test (odl_crud_tests.py)
754 The test scripts are designed like CRUD (Create Read Update Delete) End-to-End black-box test suite for testing the switch configuration inputs/outputs via RESTconf. (It could work with mininet [opf13] by CPqD,OVS only.)
756 All inputs are read from xml files: +
758 * file prefix f*.xml -> Flow ;
759 * file prefix g*.xml -> Group ;
760 * file prefix m*.xml -> Meter ;
762 NOTE: Only the Groups and the Meters are supported by CPqD.
766 * RESTfull (GET, PUT, POST (create data only), DELETE)
767 * RESTconf POST sal-services
771 . Read input and put in to controller via REST (PUT | POST | POST sal-add).
772 . Get the stored data via REST from config DataStore and compare input vs output (GET).
773 . Get the stored data via REST from operational DataStore and compare input vs output (GET).
774 . Modify the input and the update put in to controller via REST (PUT | POST sal-update).
775 . Delete the input via REST (DELETE | POST sal-remove).
776 . Validate the delete process in config DS and operational DS (GET).
780 * +--odlhost+: odl controller host (default value is 127.0.0.1)
781 * +--odlport+: odl RESTconf listening port (default value is 8080)
782 * +--loglev+: tlogging level definition (default value is DEBUG) debug level contains request/response payload
783 * +--mininet+: OpenVSwitch or CPqD (default OVS)
784 * +--fxmls+:The number specifies a Flow test xml file from xmls directory (pattern: f{nr}.xml) (e.g. 1,3,34). This parameter has no default value. The script is testing all f_.xml files from xmls directory without --fxmls parameter. 0 means no test. The parameter is relevant for (OVS and CPqD)
785 * +--mxmls+:The number specifies a Meter test xml file from xmls directory (pattern: m{nr}.xml) (e.g. 1,3). This parameter has no default value. The script is testing all m_.xml files from xmls directory without --mxmls parameter. 0 means no test. The parameter is relevant for (CPqD only)
786 * +--gmls+:The number specifies a Group test xml file from xmls directory (pattern: g{nr}.xml) (e.g. 1,3). This parameter has no default value. The script is testing all g_.xml files from xmls directory without --gxmls parameter. 0 means no test. The parameter is relevant for (CPqD only)
787 * +--confresp+: (configuration response) - define a delay to the Configruation Data Store (default = 0 sec.) Increase this value is important for a weaker controller machine
788 * +--operresp+: (operation response) - define a delay to the Operation Data Store (defalut = 3 sec.) Increase this value is important for a weaker controller machine or a weaker network
789 * +--coloring+: switcher for enable/disable coloring logged output
791 NOTE: The script has a file and the console logging output handlers (file crud_test.log).
795 python odl_crud_tests.py --mininet 2 --fxmls 1 --gxmls 0 --mxmls 3 --loglev 2
797 cmd means: The script expects ODL Controller RESTconf listener in 127.0.0.1:8080; the script expects Mininet by CPqD (gxmls and mxmls params are not ignored); and the script create the tests for f1.xml, and m3.xml and the script shows only INFO and ERROR logging messages which are colourized.
799 NOTE: The device Errors listener is not supported yet. We recommend that you use a wireshark tool for the investigation of an unexpected behaviour.
801 === Stress Test (stress_test.py)
803 The test simulates multiple connections for the repeatable END-TO-END add flow test scenario. The flow pattern is the same (look at openvswitch.flow_tools.py). The script changes only a flow_id value.
807 * Initialize mininet and thread pool
808 * The incremental add flow's group (in every thread from thread pool)
809 * Check nr. of flows (validate numbers of flows with expected calculated values and make report)
810 * Get all flows from switch directly by command line
811 * Get all flows from configuration DataStore
812 * Get all flows from the operational DataStrore
813 * Incrementally delete the groups of the flow (in every thread from thread pool)
818 * +--threads+: number of threads which should be used for multiple connection simulation in the thread pool. The default value is 50
819 * +--flows+: number of flows which should be used for add connection samples
821 === Operational Data Test (oper_data_test.py)
823 The test checks the operational store of the controller. The Flow addition action and deletion action from the Data Store. When a flow is added via REST, it is added to the config store and then pushed to the switch. When it is successfully pushed to the switch, it is also moved to the operational store. Deletion also happens the same way.
825 You can specify the number of flows added by the parameter:
827 --flows : number of the flows which are add to switch. The default value is 100
829 === Switch restart (sw_restart_test.py)
831 The test is for a flow addition to a switch after the switch has been restarted. After the switch is restarted, it should get the flow configuration from the controller operational datastore. The speed at which the configuration is pushed to the restarted switch may vary. So, you can specify the wait time; and the number of retries by wait time; and the number of retries by:
833 sw_restart_test.py --wait WAIT_TIME (default is 30)
834 sw_restart_test.py --retry NO_RETRIES (default is 1)
836 You can also specify that flows are added by xmls from the /xmls folder. If you do not specify this parameter, the default xml template will be used.
838 sw_restart_test.py --xmls XMLS (default is generic template)
840 === OpenFlow Plugin: Robot framework tests
842 ==== Prerequisites for robot tests
844 * Virtual machine with Mininet for OF1.0 and OF1.3 and with OpenSwitch
845 * Current version of ODL Controller
846 * Python (v 2.6 and higher)
852 There are in three puzzle pieces: +
856 * Robot framework + tests
858 NOTE: Use VMs to run them on the same machine or distribute them.
860 *All-in-one strategy: Advantages and disadvantages*
862 * Easy to transfer whole setup (if running on VM)
863 * No network issues (especially between VMs)
864 * However, there is no simple way to switch or update mininet or ovs
866 *Distributed strategy: Robot + ODL controller on one VM, mininet on another* +
869 * Transfer of the whole set-up involves two VMs
870 * VMs need network access to one another (This can be achieved by the 'internal network' of virtualBox.)
874 There are three options to create a VM:
876 * Follow instructions on this Opendaylight wiki page at:
877 https://wiki.opendaylight.org/view/CrossProject:Integration_Group:Create_System_Test_Environment#Install_Mininet_for_OF1.0_and_OF1.3[Install Mininet for OF1.0 and OF1.3]
878 * Download https://wiki.opendaylight.org/view/CrossProject:Integration_Group:Test_VMs#Links_to_VMs[Preinstalled VMs]
879 or there is also a possibility to create mininet VM from scratch (based on debian distribution)
881 IMPORTANT: In order for robot framework to be able to control mininet through ssh the prompt on mininet VM has to end with ">" character.
886 | Component | Topic | Included in Guide
888 | MD-SAL |Southbound Protocol Plugin | Developer guide
890 | MD-SAL a| Plugin Types:
892 * Southbound Protocol Plugin
893 * Manager-type Application
899 === TLS support for OF Plugin
901 SDN separates the data plane from the control plane of networks. It is imperative that communication between the two planes is secure. +
902 Secure communications between the data plane switches and controllers on the control plane require the authentication of switches and controllers.
903 Authentication ensures that no unsecured switch connects to a controller, and that no unsecured controller manages a switch. When a controller with TLS configured is opened, the OpenFlow port only accepts Transport Layer Security (TLS) communications.
904 Any switch without TLS configured will fail in its connection attempt.
907 Open Secure Sockets Layer (SSL) provides the tools for the public key infrastructure (PKI) management required to establish secure connections between a controller and switches. +
908 Information on `SSL on Open vSwitch and ovs controller’ is available at: +
909 https://github.com/mininet/mininet/wiki/SSL-on-Open-vSwitch-and-ovs-controller +
911 In a lab environment, the private key of the controller resides on the mininet host that also acts as the Certification authority (CA) signing host. In a production environment, the key generation for the controller would be separate from that of the switches; only the public controller key is shared with the switches.
913 NOTE: While in a lab environment, TLS may be configured with the keystore shipped with the controller, the TLS configuration in a production environment must choose a different keystore.
915 *Creating and signing private and public key certificates* +
916 Use ovs pki to create private keys and public certificate files for the switches and the controller. +
919 . On the mininet host, verify whether PKI is initialized: +
920 : +ls /var/lib/openvswitch/pki/controllerca/cacert.pem+ +
921 . If PKI is not initialized, use: +ovs-pki init+ +
922 . To generate the signed certificates, use the request certificates sc-req.pem and ctl-req.pem:
924 $ ls /etc/openvswitch
925 conf.db ctl-cert.pem ctl-privkey.pem ctl-req.pem sc-cert.pem sc-privkey.pem sc-req.pem
929 . To create private keys and public cert files for the switches and the controller, run the ovs-pki:
932 sudo ovs-pki req+sign sc switch
933 sudo ovs-pki req+sign ctl controller
936 . From .pem files, create an intermediate Open SSL PKCS 12 formatted keystore to hold the private key for the controller.
938 sudo openssl pkcs12 -export -in ctl-cert.pem -inkey ctl-privkey.pem \
939 -out ctl.p12 -name odlserver \
940 -CAfile /var/lib/openvswitch/pki/controllerca/cacert.pem -caname root -chain
941 You'll be prompted for a password, use "opendaylight"
942 Enter Export Password:
943 Verifying - Enter Export Password:
946 . Copy the intermediate keystore, which has the private key of the controller, and the switches public key cert file ( ctl.p12 and sc-cert.pem) from the mininet host to any work directory on the controller machine. Import the PKSC 12 format to a Java compatible format that the controller can use:
948 sftp mininet@mininetipaddress
950 sftp get ctl.p12 sc-cert.pem
954 . For use in the steps that follow, find a keytool in a jdk bin directory, and add it to the path:
956 keytool -importkeystore \
957 -deststorepass opendaylight -destkeypass opendaylight -destkeystore ctl.jks \
958 -srckeystore ctl.p12 -srcstoretype PKCS12 -srcstorepass opendaylight \
962 . Store the public key of the switch in a truststore:
964 keytool -importcert -file sc-cert.pem -keystore truststore.jks -storepass opendaylight
965 # when prompted "Trust this certificate? [no]:" enter "yes"
966 # Certificate was added to keystore
969 . Copy the two keystores to the ssl configuration directory:
971 mkdir ODLINSTALL/configuration/ssl
972 cp ctl.jks truststore.jks ODLINSTALL/configuration/ssl
974 === Configuring the ODL OpenFlow plugin
976 * Configure the OF plugin using the following:
978 cd configuration/initial
979 vi configuration/initial/42-openflowplugin.xml
980 # add the <tls> blocks as shown to each of the existing OF-switch-connection-provider modules
982 <!-- default OF-switch-connection-provider (port 6633) -->
984 <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:openflow:switch:connection:provider:impl">
985 prefix:openflow-switch-connection-provider-impl
987 <name>openflow-switch-connection-provider-default-impl</name>
989 <switch-idle-timeout>15000</switch-idle-timeout>
991 <keystore>configuration/ssl/ctl.jks</keystore>
992 <keystore-type>JKS</keystore-type>
993 <keystore-path-type>PATH</keystore-path-type>
994 <keystore-password>opendaylight</keystore-password>
995 <truststore>configuration/ssl/truststore.jks</truststore>
996 <truststore-type>JKS</truststore-type>
997 <truststore-path-type>PATH</truststore-path-type>
998 <truststore-password>opendaylight</truststore-password>
999 <certificate-password>opendaylight</certificate-password>
1003 <!-- default OF-switch-connection-provider (port 6653) -->
1005 <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:openflow:switch:connection:provider:impl">
1006 prefix:openflow-switch-connection-provider-impl
1008 <name>openflow-switch-connection-provider-legacy-impl</name>
1010 <switch-idle-timeout>15000</switch-idle-timeout>
1012 <keystore>configuration/ssl/ctl.jks</keystore>
1013 <keystore-type>JKS</keystore-type>
1014 <keystore-path-type>PATH</keystore-path-type>
1015 <keystore-password>opendaylight</keystore-password>
1016 <truststore>configuration/ssl/truststore.jks</truststore>
1017 <truststore-type>JKS</truststore-type>
1018 <truststore-path-type>PATH</truststore-path-type>
1019 <truststore-password>opendaylight</truststore-password>
1020 <certificate-password>opendaylight</certificate-password>
1025 === Configuring openvswitch SSL +
1027 *To configure openswitch SSL* +
1029 . Set ovs ssl options.
1031 sudo ovs-vsctl set-ssl \
1032 /etc/openvswitch/sc-privkey.pem \
1033 /etc/openvswitch/sc-cert.pem \
1034 /var/lib/openvswitch/pki/controllerca/cacert.pem
1037 . Start a mininet with SSL connections to the ODL controller.
1038 .. Open the `ssl_switch_tests.py’ file
1041 from mininet.net import Mininet
1042 from mininet.node import Controller, RemoteController
1043 from mininet.cli import CLI
1044 from mininet.log import setLogLevel, info
1047 net = Mininet( controller=RemoteController )
1048 net.addController( 'c0' )
1049 h1 = net.addHost( 'h1' )
1050 h2 = net.addHost( 'h2' )
1051 s1 = net.addSwitch( 's1' )
1052 net.addLink( h1, s1 )
1053 net.addLink( h2, s1 )
1056 s1.cmd('ovs-vsctl set-controller s1 ssl:YOURODLCONTROLLERIPADDRESS:6633')
1061 if __name__ == '__main__':
1062 setLogLevel( 'info' )
1066 . Start mininet with TLS:
1068 chmod +x ssl_switch_test.py
1069 sudo ./ssl_switch_test.py
1071 === Configuring a hardware switch with TLS
1073 The configuration example that follows uses a Brocade MLX device. +
1074 *To configure a hardware switch* +
1076 . Set up a tftp server.
1078 telnet@NetIron MLX-4 Router#enable
1079 <enter config password>.
1082 . Copy the sc-cert.pem and sc-privkey.pem files to the tftp sever on the controller:
1084 telnet@NetIron MLX-4 Router(config)#copy tftp flash 10.0.0.1 sc-cert.pem client-certificate
1085 telnet@NetIron MLX-4 Router(config)#copy tftp flash 10.0.0.1 sc-privkey.pem client-private-key
1086 telnet@NetIron MLX-4 Router(config)#openflow controller ip-address 10.0.0.1
1088 NOTE: A tftp server runs on the controller host "10.0.0.1".
1090 ==== Commands for debugging
1091 *Debugging mininet* +
1092 To see connection entries in the ovswitchd log file, use: +
1093 +sudo tail /var/log/openvswitch/ovs-vswitchd.log+ +
1094 *Debugging the ODL controller* +
1095 +./run.sh -Djavax.net.debug=ssl,handshake+ +
1097 === Open Flow Plugin: Support for extensibility
1098 OpenFlow (OF) allows vendor-defined extensions to fields in the flow entries of flow tables. OpenFlow-1.3 specifications describe experimenter items using meter, queue, match, action, multipart, table features, and error message. The OF Plugin supports extensions to the action and match fields of flow entries.
1099 OF Plugin extensibility API is defined in the openflowplugin-extension-api (odl), for example, converter interfaces, and register or lookup keys. OF Plugin extensibility is dependent on the MD-SAL and the OpenFlow Java Library. +
1100 The extensibility functionality uses a two-level conversion between the following: +
1102 * The semantic high level model (MD-SAL) and the protocol-oriented low level model (OFJava)
1103 * The low-level model (OFJava) and the Wire protocol
1105 Vendor actions augment the MD-SAL model. MD-SAL defines the flow model using yang. Vendors can extend the existing MD-SAL models by using the augmentation feature of yang. Augments only add new items to the model. They neither remove nor modify existing models. The OFJava-API contains protocol related constants and interfaces describing how to work with OFJava and generated models (generated from yang files). These models are referred to as OFJava-API models. +
1107 .OF Plugin support for extensibility
1108 image::OFPlugin_ExtensibilitySupportInOFPlugin.png[width=500]
1110 ==== Converters (semantic level)
1111 Converters aid communication between applications and devices by making possible the communication between southbound APIs and their North-bound counterparts. They translate MD-SAL models to OFJava-API models. The default set of converters reside in: openflowplugin/src/main/java/org/opendaylight/openflowplugin/openflow/md/core/sal/convertor
1113 Converters act upon models from and to the MD-SAL. Inputs for *action converter from MD-SAL* are instances of the MD-SAL model: for example, in the case of action, OutputActionCase. The output contains OFJava-API models of Action transferred from applications to devices. Working in reverse, *action converters to MD-SAL* translate OFJava-API models (Action) to MD-SAL models (Action).
1115 After a vendor bundle is activated, converters are registered with the OF plugin so that they can work. Registration is based on the augmentation type and version. Once the converters are registered, the OF Plugin can convert MD-SAL action to OF Java actions.
1117 ==== Approaches to action conversion
1118 The sample that follows shows two approaches to converting action (ActionConvertor.java). The first approach relies on a key field in a generalExtension augmentation. The second approach directly creates the converter lookup key out of the action type.
1120 else if (action instanceof GeneralExtensionGrouping) {
1123 * TODO: EXTENSION PROPOSAL (action, MD-SAL to OFJava)
1124 * - we might need sessionContext as converter input
1128 GeneralExtensionGrouping extensionCaseGrouping = (GeneralExtensionGrouping) action;
1129 Extension extAction = extensionCaseGrouping.getExtension();
1130 ConverterExtensionKey<? extends ExtensionKey> key = new ConverterExtensionKey<>(extensionCaseGrouping.getExtensionKey(), version);
1131 ConvertorToOFJava<Action> convertor =
1132 OFSessionUtil.getExtensionConvertorProvider().getConverter(key);
1133 if (convertor != null) {
1134 ofAction = convertor.convert(extAction);
1137 // try vendor codecs
1138 TypeVersionKey<org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.Action> key =
1139 new TypeVersionKey<>(
1140 (Class<? extends org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.Action>) action.getImplementedInterface(),
1142 ConvertorActionToOFJava<org.opendaylight.yang.gen.v1.urn.opendaylight.action.types.rev131112.action.Action, Action> convertor =
1143 OFSessionUtil.getExtensionConvertorProvider().getConverter(key);
1144 if (convertor != null) {
1145 ofAction = convertor.convert(action);
1149 ==== Encoders and decoders for augment messages (low level)
1151 Augments are encoded using encoders. Vendor bundles register the encoders so that the OpenFlow Java Library can support the vendor actions. Default sets of encoders and decoders reside in /openflow-protocol-impl/src/main/java/org/opendaylight/openflowjava/protocol/impl/serialization and /openflow-protocol-impl/src/main/java/org/opendaylight/openflowjava/protocol/impl/deserialization.
1152 The OF plugin uses encoders to create the binary (wire protocol) form of a message object, and write it to the buffer.
1154 Decoders on the other hand are responsible for the following tasks: +
1156 * Read binary buffer
1157 * Detect the type of message (encoded in the header)
1158 * Create the corresponding objects, and populate them with values from the buffer
1161 Vendor decoders cannot be directly registered if the actual message type is outside the general header, and only vendor-provided logic can take decisions. Then a master decoder, which is also provided be the vendor, is used. The master decoder contains logic to register decoders and to distinguish between vendor actions. The same work-flow persists: the lookup decoder by key containing version, actionClass, vendorActionSubtype. (For example, the experimenter action makes it appear as if all actions from one vendor have the same header, and the subtype of the actual action lies somewhere further in the buffer.)
1163 The OFJava extensions provide the space for registering vendor encoders and master decoders. They also provide the lookup mechanism to pick the right decoder or encoder for work with a message or buffer.
1165 === Overload protection in the OF Plugin
1166 Overload protection in the OpenFlow (OF) Plugin works in the following way: +
1168 . The ConnectionConductor is the source from where all incoming messages are pushed to queues for asynchronous processing. It is the part of the OF Plugin closest to OFJava, and has on*Message methods (listeners to incoming messages). The ConnectionConductorImpl pushes messages to the QueueKeeper. Every ConnectionConductor has a local instance of the QueueKeeper. +
1169 The QueueKeeper has two queues: +
1170 ** Unordered queues (for packetIn messages)
1171 ** Ordered queues (for other messages) +
1172 Both queue types are limited and blocking.
1174 . If a particular queue is full, the messages pushed to it will be dropped. Upon a successful push, the harverster is pinged to be roused from hibernation.
1175 . A QueueZipper wraps the two queues, and provides the poll method. This poll method rotates regularly through the underlying queues. If the currently polled queue is empty, it polls the next queue. (See QueueKeeperFairImpl).
1176 . Each QueueKeeper gets registered by the QueueKeeperHarvester. The Harvester runs upon one thread; iterates through all the registered QueueKeepers; and polls them. The polled message is then queued into the QueueProcessor. +
1177 If all the registered queueKeepers are empty, the harverster hibernates.
1179 . At the QueueProcessor are several threads translating messages from OFJava-API models to MD-SAL models (preserving order). The QueueProcessor uses two threadPools:
1180 ** One threadPool to process the queue items
1181 ** Another threadPool (containing one thread) to publish messages to the MD-SAL +
1183 A queue gets filled for different reasons: +
1185 * The MD-SAL is overloaded.
1186 * A node is flooding, or something has generally slowed down the processing pipeline. +
1187 If the queue in the QueueProcessor is full, it blocks the harvester. If the harvester is blocked, the queues in the QueueKeeper will not be emptied.
1189 NOTE: The current implementation of the feature offers no checking of the memory or CPU load to actively throttle messages.
1191 .Overload protection
1193 image::overloadProtectionBrief.png[width=500]
1195 ==== Effects of overload protection
1197 * When a node floods the controller, it will not block messages from other nodes.
1198 * The processing of messages is fair: 'Floody' node messages are neither prioritized, nor do they infest queues outside the ConnectionConductor.
1199 * Memory is not exhausted on the controller side as messages gets dropped immediately upon an unsuccessful push to the local queue.
1200 * The functionality cannot create back pressure at the netty level. Pressure affects the echo message, and might cause a connection close action on the switch side.