Removing unused manuals for Lithium
[docs.git] / manuals / developer-guide / src / main / asciidoc / openflowplugin.adoc
1 == OpenFlow Plugin
2
3 .OpenFlow plugin: Component map
4 [options="header"]
5 |===
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
14 |=== 
15
16 === OpenFlow Plugin: Sequence diagrams
17
18 .Message Lifecycle
19 image::MessageLifecycle.jpg[width=500]
20
21 .Handshake Scenario
22 image::Handshake.png[width=500]
23
24 .Connection Sequence (Handshake) Flow Diagram
25 image::OF1_0_Switch_Handshake_Sequence.png[width=500]
26
27 .Message Order Preservation 
28 image::MessageOrderPreservation.jpg[width=500]
29
30 .Add Flow Sequence 
31 image::Add_flow.png[width=500]
32
33 .Generic Notification Sequence
34 image::Generic_notification.png[width=500]
35
36 === OpenFlow Plugin:Config subsystem
37 ==== Model provided modules by yang
38 *General model (interfaces)* - openflow-plugin-cfg.yang. +
39
40 * The provided module is defined (identity openflow-provider) 
41
42 * The target implementation is assigned (...OpenflowPluginProvider) 
43 ----
44 module openflow-provider {
45    yang-version 1;
46    namespace "urn:opendaylight:params:xml:ns:yang:openflow:common:config";
47    prefix "ofplugin-cfg";
48
49    import config {prefix config; revision-date 2013-04-05; }
50    description
51        "openflow-plugin-custom-config";
52    revision "2014-03-26" {
53        description
54            "Initial revision";
55    }
56    identity openflow-provider{
57        base config:service-type;
58        config:java-class "org.opendaylight.openflowplugin.openflow.md.core.sal.OpenflowPluginProvider";
59    }
60 }
61 ----
62 *Implementation model* - openflow-plugin-cfg-impl.yang + 
63
64 * The implementation of module is defined (+identity openflow-provider-impl+). 
65
66 ** The class name of the generated implementation is defined (ConfigurableOpenFlowProvider). 
67
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.)
71 ----
72 module openflow-provider-impl {
73    yang-version 1;
74    namespace "urn:opendaylight:params:xml:ns:yang:openflow:common:config:impl";
75    prefix "ofplugin-cfg-impl";
76
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;}
81
82
83    description
84        "openflow-plugin-custom-config-impl";
85
86    revision "2014-03-26" {
87        description
88            "Initial revision";
89    }
90
91    identity openflow-provider-impl {
92        base config:module-type;
93        config:provided-service openflow-provider:openflow-provider;
94        config:java-name-prefix ConfigurableOpenFlowProvider;
95    }
96
97    augment "/config:modules/config:module/config:configuration" {
98        case openflow-provider-impl {
99            when "/config:modules/config:module/config:type = 'openflow-provider-impl'";
100
101            container binding-aware-broker {
102                uses config:service-ref {
103                    refine type {
104                        mandatory true;
105                        config:required-identity md-sal-binding:binding-broker-osgi-registry;
106                    }
107                }
108            }
109            list openflow-switch-connection-provider {
110                uses config:service-ref {
111                    refine type {
112                        mandatory true;
113                        config:required-identity openflow-switch-connection-provider:openflow-switch-connection-provider;
114                    }
115                }
116            }
117        }
118    }
119 }
120 ---- 
121 ==== Generating config and sal classes from yangs
122 NOTE: Suitable code generators, needed in pom, are involved.
123
124 ----
125 <build> ...
126   <plugins>
127     <plugin>
128       <groupId>org.opendaylight.yangtools</groupId>
129       <artifactId>yang-maven-plugin</artifactId>
130       <executions>
131         <execution>
132           <goals>
133             <goal>generate-sources</goal>
134           </goals>
135           <configuration>
136             <codeGenerators>
137               <generator>
138                 <codeGeneratorClass>
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>
147               </generator>
148               <generator>
149                 <codeGeneratorClass>
150                   org.opendaylight.yangtools.maven.sal.api.gen.plugin.CodeGeneratorImpl
151                 </codeGeneratorClass>
152                 <outputBaseDir>${project.build.directory}/generated-sources/sal</outputBaseDir>
153               </generator>
154               <generator>
155                 <codeGeneratorClass>org.opendaylight.yangtools.yang.unified.doc.generator.maven.DocumentationGeneratorImpl</codeGeneratorClass>
156                 <outputBaseDir>${project.build.directory}/site/models</outputBaseDir>
157               </generator>
158             </codeGenerators>
159             <inspectDependencies>true</inspectDependencies>
160           </configuration>
161         </execution>
162       </executions>
163       <dependencies>
164         <dependency>
165           <groupId>org.opendaylight.controller</groupId>
166           <artifactId>yang-jmx-generator-plugin</artifactId>
167           <version>0.2.5-SNAPSHOT</version>
168         </dependency>
169         <dependency>
170           <groupId>org.opendaylight.yangtools</groupId>
171           <artifactId>maven-sal-api-gen-plugin</artifactId>
172           <version>${yangtools.version}</version>
173           <type>jar</type>
174         </dependency>
175       </dependencies>
176     </plugin>
177     ...
178 ----
179 * JMX generator (target/generated-sources/config)
180  
181 * sal CodeGeneratorImpl (target/generated-sources/sal)
182  
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].
184
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): +
187
188 * ConfigurableOpenFlowProviderModuleFactory 
189
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);+ +
191
192 * ConfigurableOpenFlowProviderModule 
193
194 The *createInstance* method is extended in order to inject osgi BundleContext into the module implementation: +pluginProvider.setContext(bundleContext);+ 
195  
196 ==== Configuration xml file
197
198 The configuration file contains: +
199
200 * Required capabilities
201   
202 ** Modules definitions from openflowjava 
203
204 **  Definitions from openflowplugin 
205
206 * Modules definition 
207  
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) 
211 * Provided services  
212 ** openflow-switch-connection-provider-default 
213 ** openflow-switch-connection-provider-legacy 
214 ** openflow-provider 
215 ----
216 <snapshot>
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>
223
224  <configuration>
225
226    
227      <modules xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
228        <module>
229          <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:openflow:switch:connection:provider:impl">
230            prefix:openflow-switch-connection-provider-impl
231          </type>
232          <name>openflow-switch-connection-provider-default-impl</name>
233          <port>6633</port>
234          <switch-idle-timeout>15000</switch-idle-timeout>
235        </module>
236        <module>
237          <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:openflow:switch:connection:provider:impl">
238            prefix:openflow-switch-connection-provider-impl
239          </type>
240          <name>openflow-switch-connection-provider-legacy-impl</name>
241          <port>6653</port>
242          <switch-idle-timeout>15000</switch-idle-timeout>
243        </module>
244
245
246        <module>
247          <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:openflow:common:config:impl">
248            prefix:openflow-provider-impl
249          </type>
250          <name>openflow-provider-impl</name>
251          
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
255            </type>
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
261            </type>
262            <name>openflow-switch-connection-provider-legacy</name>
263          </openflow-switch-connection-provider>
264
265
266          <binding-aware-broker>
267            <type xmlns:binding="urn:opendaylight:params:xml:ns:yang:controller:md:sal:binding">
268              binding:binding-broker-osgi-registry
269            </type>
270            <name>binding-osgi-broker</name>
271          </binding-aware-broker>
272        </module>
273      </modules>
274
275      <services xmlns="urn:opendaylight:params:xml:ns:yang:controller:config">
276        <service>
277          <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:openflow:switch:connection:provider">
278            prefix:openflow-switch-connection-provider
279          </type>
280          <instance>
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>
283          </instance>
284          <instance>
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>
287          </instance>
288        </service>
289
290        <service>
291          <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:openflow:common:config">prefix:openflow-provider</type>
292          <instance>
293            <name>openflow-provider</name>
294            <provider>/modules/module[type='openflow-provider-impl'][name='openflow-provider-impl']</provider>
295          </instance>
296        </service>
297      </services>
298    
299
300  </configuration>
301 </snapshot>
302 ----
303 ==== API changes
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). 
305
306 ==== Providing config file (IT, local distribution/base, integration/distributions/base)
307 *openflowplugin-it* 
308
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. 
310
311 *OFPlugin/distribution/base* +
312
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. 
314
315 *Integration/distributions/build* +
316
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. 
318
319 === Message Spy in OF Plugin
320
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.
323
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.
326  
327 The following checkpoints count passing messages: +
328 ----
329 /**
330     * statistic groups overall in OFPlugin
331     */
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,
345        
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
354    }
355 ----
356 ==== Message statistics display +
357 Access the message statistics by means of logs, osgi, and jmx. +
358
359 * osgi command (on demand): This method is considered deprecated. +
360 : +osgi> dumpMsgCount+ +
361
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" />+
364
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.
370
371 *Sample results* +
372 ----
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
411 ----
412
413 === OpenFlow Plugin:Mininet
414 ==== Mininet on debian wheezy(7), x86_64
415 ===== Requirements
416
417 *Openvswitch* +
418
419 . Install all requirements.
420 ----
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
423 ----
424 [start= 2]
425 . Install a few helper applications.
426 ----
427 apt-get -y install screen sudo vim etckeeper mlocate autoconf2.13 libssl-dev graphviz  tcpdump  gdebi-core
428 ----
429 ==== Test the Python environment
430 *Python pip* + 
431
432 . Install setuptools.
433 ----
434 wget https://bitbucket.org/pypa/setuptools/raw/bootstrap/ez_setup.py
435 sudo python ez_setup.py
436 ----
437 [start= 2]
438 . Install pip.
439 ----
440 wget https://raw.github.com/pypa/pip/master/contrib/get-pip.py
441 sudo python get-pip.py
442 ----
443 [start= 3]
444 . Post install the python libraries required by the ODL testing script.
445 ---- 
446 sudo pip install netaddr
447 ----
448 === Installation
449 ==== Openvswitch 2.0.0
450 . Remove the old packages, as root:
451 ---- 
452 sudo -i
453 apt-get remove openvswitch-common openvswitch-datapath-dkms openvswitch-controller openvswitch-pki openvswitch-switch
454 ----
455 [start= 2]
456 . Download and unpack OpenV Switch 2.0.0. 
457 ----
458 wget http://openvswitch.org/releases/openvswitch-2.0.0.tar.gz
459 tar zxvf openvswitch-2.0.0.tar.gz
460 ----
461 *Build and install* +
462
463 . Install the openvswitch package. Deploy it using the module assistant at:  https://wiki.debian.org/ModuleAssistant 
464 ----
465 cd ../
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
472 ----
473 *Post installation settings* +
474 ---- 
475 service openvswitch-controller stop
476 update-rc.d openvswitch-controller disable
477 ----
478 *Test installation* +
479 ---- 
480 ovs-vsctl show
481 ovs-vsctl --version
482 ovs-ofctl --version
483 ovs-dpctl --version
484 ovs-controller --version
485 ----
486 ==== Mininet 2.1.0
487
488 . Download and checkout the required version.
489 ----
490 git clone git://github.com/mininet/mininet
491 cd mininet
492 git checkout -b 2.1.0 2.1.0
493 ----
494 [start=2]
495 . Compile and install mininet.
496 ----
497 gcc mnexec.c -o mnexec
498 mv mnexec /usr/bin/
499 python setup.py install
500 ----
501 [start=3]
502 . Test the installation. 
503 ----
504 mn --version
505 mn --test pingall
506 ----
507 *Expected result* +
508 ---- 
509 root@debian:~/mininet# mn --version
510 2.1.0
511 root@debian:~/mininet# mn --test pingall
512 *** Creating network
513 *** Adding controller
514 *** Adding hosts:
515 h1 h2 
516 *** Adding switches:
517 s1 
518 *** Adding links:
519 (h1, s1) (h2, s1) 
520 *** Configuring hosts
521 h1 h2 
522 *** Starting controller
523 *** Starting 1 switches
524 s1 
525 *** Ping: testing ping reachability
526 h1 -> h2 
527 h2 -> h1 
528 *** Results: 0% dropped (2/2 received)
529 *** Stopping 1 switches
530 s1 ..
531 *** Stopping 2 hosts
532 h1 h2 
533 *** Stopping 1 controllers
534 c0 
535 *** Done
536 completed in 0.269 seconds
537 ----
538 *Post installation additions* +
539
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]. 
541 ----
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
544 @@ -952,6 +952,10 @@
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
553   
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():
564              if not intf.IP():
565 ----
566 *Start and test the modified mininet* +
567
568 . Start the mn session:
569 ---- 
570 sudo mn --topo single,3  --controller 'remote,ip=<your controller IP>' --switch ovsk,protocols=OpenFlow10
571 ----
572 [start=2]
573 . Alternatively, use this command:
574 ---- 
575 sudo mn --topo single,3  --controller 'remote,ip=<your controller IP>' --switch ovsk,protocols=OpenFlow13
576 ----
577 [start= 3]
578 . Test the version of the protocol used by switch "s1": 
579 ----
580 ovs-ofctl -O OpenFlow10 show s1
581 ovs-ofctl -O OpenFlow13 show s1
582 ----
583 === Usage
584
585 REST tests openflowplugin
586 ---- 
587 sudo python odl_tests.py --xmls 1,2
588 ----
589 * For more option informations, use:
590 ---- 
591 sudo python odl_tests.py --help
592 ----
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:
596  
597 * name shadowing. 
598 * null checks. 
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.
605  
606 Also useful are  warnings upon missing javadoc comments for public classes, members, and methods.
607
608 .Configure Compiler Errors and Warnings
609 image::codinghints1.png[height=750]
610
611 .Configure Javadoc
612 image::codinghints2.png[width=500]
613
614 === OpenFlow Plugin: Wiring up notifications
615 ==== Introduction
616 OpenFlow messages coming from the OpenflowJava plugin into MD-SAL Notification objects must be translated, and then published to the MD-SAL.
617
618 ==== To create and register a Translator
619 . Create a Translator class. 
620 . Register the Translator. 
621 . Register the notificationPopListener to handle Notification Objects. 
622
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]. 
625
626 . Create the class.
627 ----
628 public class PacketInTranslator implements IMDMessageTranslator<OfHeader, List<DataObject>> {
629 ----
630 [start=2]
631 . Implement the translate function: 
632 ----
633 public class PacketInTranslator implements IMDMessageTranslator<OfHeader, List<DataObject>> {
634
635     protected static final Logger LOG = LoggerFactory
636             .getLogger(PacketInTranslator.class);
637     @Override
638     public PacketReceived translate(SwitchConnectionDistinguisher cookie,
639             SessionContext sc, OfHeader msg) { 
640             ...
641     }
642 ----
643 [start=2]
644 . Ensure that the type is the expected one, and cast it:
645 ---- 
646         if(msg instanceof PacketInMessage) {
647             PacketInMessage message = (PacketInMessage)msg;
648             List<DataObject> list = new CopyOnWriteArrayList<DataObject>();
649 ----
650 [start=3]
651 . Complete the translation and return.
652 ---- 
653             PacketReceived pktInEvent = pktInBuilder.build();
654             list.add(pktInEvent);
655             return list;
656 ----
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: 
659 ----
660 public void init() {
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());
669 ----
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.
671
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:
674 ---- 
675 addMessagePopListener(PacketReceived.class, new NotificationPopListener<DataObject>());
676 ----
677 When a message comes from the openflowjava plugin, it will be translated and published to the MD-SAL.
678
679 === OpenFlow Plugin:Python test scripts
680 ==== Prerequisites for Python test-scripts
681 * Linux based OS (these instructions cover debian 7 - wheezy) 
682 * Java 1.7+ 
683 * Python (v 2.6) 
684 * Openvswitch (v 2.0.0) 
685 * Mininet (v 2.1.0) 
686 * Controller (supporting openflow 1.3) 
687
688 ==== Installing python tools
689 NOTE: Build python tools with python2.6, not the default python.
690
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 
695
696 See <<_openflow_plugin_mininet>>
697
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 
703 . sudo reboot 
704
705 ==== Adding openflow13 dissector to wireshark 
706 . mkdir /home/mininet/.wireshark/plugins/ 
707 . Copy the file openflow.so to this directory //TODO add attachment. 
708
709 ==== Controller
710
711 *Install Java JDK and set JAVA_HOME* 
712
713 . apt-get install openjdk-7-jdk 
714 . Export JAVA_HOME=/usr/lib/jvm/java-7-openjdk-amd64/jre/bin/java 
715
716 *Download, unzip, and run the integration build* +
717
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: 
721 ----
722 cd opendaylight
723 ./run.sh -of13
724 ----
725 *Clone openflowplugin project* +
726
727 * git clone https://git.opendaylight.org/gerrit/p/openflowplugin.git
728
729 ==== Tests
730
731 * locations: openflowplugin/test-scripts 
732 * content directory  
733 ** xmls (switch configuration input in xml form) 
734 ** openvswitch 
735 ** *runnable files*:  
736 *** odl_crud_tests.py 
737 *** stress_test.py 
738 *** oper_data_test.py
739 *** sw_restart_test.py 
740
741 === General
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. 
744  
745 Basic parameters for all runnable scripts: 
746
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. 
751
752 === ODL Test (odl_crud_tests.py)
753
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.) 
755
756 All inputs are read from xml files: +
757
758 * file prefix f*.xml -> Flow ; 
759 * file prefix g*.xml -> Group ; 
760 * file prefix m*.xml -> Meter ; 
761
762 NOTE: Only the Groups and the Meters are supported by CPqD.
763
764 The test uses: 
765
766 * RESTfull (GET, PUT, POST (create data only), DELETE) 
767 * RESTconf POST sal-services 
768
769 ==== Test life cycle
770  
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). 
777
778 === Parameters
779  
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 
790
791 NOTE: The script has a file and the console logging output handlers (file crud_test.log).
792
793 *cmd example*:
794 ---- 
795 python odl_crud_tests.py --mininet 2 --fxmls 1 --gxmls 0 --mxmls 3 --loglev 2
796 ----
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. 
798
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. 
800
801 === Stress Test (stress_test.py)
802
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.
804
805 The test life cycle: 
806
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) 
814  final report 
815
816 *Parameters*: 
817
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 
820
821 === Operational Data Test (oper_data_test.py)
822
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. 
824
825 You can specify the number of flows added by the parameter:
826 ----
827 --flows : number of the flows which are add to switch. The default value is 100
828 ---- 
829 === Switch restart (sw_restart_test.py)
830
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: 
832 ----
833 sw_restart_test.py --wait WAIT_TIME (default is 30) 
834 sw_restart_test.py --retry NO_RETRIES (default is 1) 
835 ----
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.
837 ---- 
838 sw_restart_test.py --xmls XMLS (default is generic template)
839 ---- 
840 === OpenFlow Plugin: Robot framework tests
841
842 ==== Prerequisites for robot tests
843
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) 
847 * Robot framework 
848 * GIT 
849
850 ==== Installation
851
852 There are in three puzzle pieces: +
853
854 * ODL controller 
855 * Mininet with ovs 
856 * Robot framework + tests 
857
858 NOTE: Use VMs to run them on the same machine or distribute them.
859  
860 *All-in-one strategy: Advantages and disadvantages*
861
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 
865
866 *Distributed strategy: Robot + ODL controller on one VM, mininet on another* +
867
868 * Modularity 
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.) 
871
872 ==== VM with Mininet
873
874 There are three options to create a VM: 
875
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) 
880
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. 
882
883 [options="header"]
884 |===
885
886 | Component | Topic | Included in Guide
887
888 | MD-SAL |Southbound Protocol Plugin | Developer guide
889
890 | MD-SAL a| Plugin Types:
891
892 * Southbound Protocol Plugin
893 * Manager-type Application
894 * Protocol Library
895 * Connector Plugin
896 | User Guide
897 |===
898
899 === TLS support for OF Plugin
900
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. 
905  
906  
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 +
910
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.
912
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.
914
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. +
917
918
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:
923 ----
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
926 system-id.conf
927 ----
928 [start=4]
929 . To create private keys and public cert files for the switches and the controller, run the ovs-pki:
930 ----
931 cd /etc/openvswitch
932 sudo ovs-pki req+sign sc switch
933 sudo ovs-pki req+sign ctl controller
934 ----
935 [start=5]
936 . From .pem files, create an intermediate Open SSL PKCS 12 formatted keystore to hold the private key for the controller.
937 ----
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:
944 ----
945 [start=6]
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:
947 ----
948 sftp mininet@mininetipaddress
949 mininet
950 sftp get ctl.p12 sc-cert.pem
951 quit
952 ----
953 [start=7]
954 . For use in the steps that follow, find a keytool in a jdk bin directory, and add it to the path:
955 ----
956 keytool -importkeystore \
957         -deststorepass opendaylight -destkeypass opendaylight -destkeystore ctl.jks \
958         -srckeystore ctl.p12 -srcstoretype PKCS12 -srcstorepass opendaylight \
959         -alias odlserver
960 ----
961 [start=8]
962 . Store the public key of the switch in a truststore:
963 ----
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
967 ----
968 [start=9]
969 . Copy the two keystores to the ssl configuration directory:
970 ----
971 mkdir ODLINSTALL/configuration/ssl
972 cp ctl.jks truststore.jks ODLINSTALL/configuration/ssl
973 ----
974 === Configuring the ODL OpenFlow plugin
975
976 * Configure the OF plugin using the following:
977 ----
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
981
982         <!-- default OF-switch-connection-provider (port 6633) -->
983         <module>
984           <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:openflow:switch:connection:provider:impl">
985             prefix:openflow-switch-connection-provider-impl
986           </type>
987           <name>openflow-switch-connection-provider-default-impl</name>
988           <port>6633</port>
989           <switch-idle-timeout>15000</switch-idle-timeout>
990           <tls>
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>
1000           </tls>
1001
1002         </module>
1003         <!-- default OF-switch-connection-provider (port 6653) -->
1004         <module>
1005           <type xmlns:prefix="urn:opendaylight:params:xml:ns:yang:openflow:switch:connection:provider:impl">
1006             prefix:openflow-switch-connection-provider-impl
1007           </type>
1008           <name>openflow-switch-connection-provider-legacy-impl</name>
1009           <port>6653</port>
1010           <switch-idle-timeout>15000</switch-idle-timeout>
1011           <tls>
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>
1021           </tls>
1022
1023         </module>
1024 ----
1025 === Configuring openvswitch SSL +
1026
1027 *To configure openswitch SSL* +
1028
1029 . Set ovs ssl options.
1030 ----
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
1035 ----
1036 [start=2]
1037 . Start a mininet with SSL connections to the ODL controller.
1038 ..      Open the  `ssl_switch_tests.py’ file
1039 ----
1040 #!/usr/bin/python
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
1045
1046 def emptyNet():
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 )
1054
1055     net.start()
1056     s1.cmd('ovs-vsctl set-controller s1 ssl:YOURODLCONTROLLERIPADDRESS:6633')
1057
1058     CLI( net )
1059     net.stop()
1060
1061 if __name__ == '__main__':
1062     setLogLevel( 'info' )
1063     emptyNet()
1064 ----
1065 [start=3]
1066 . Start mininet with TLS:
1067 ----
1068 chmod +x ssl_switch_test.py
1069 sudo ./ssl_switch_test.py
1070 ----
1071 === Configuring a hardware switch with TLS
1072
1073 The configuration example that follows uses a Brocade MLX device. +
1074 *To configure a hardware switch* +
1075
1076 . Set up a tftp server.
1077 ----
1078 telnet@NetIron MLX-4 Router#enable
1079 <enter config password>.
1080 ----
1081 [start=2]
1082 . Copy the sc-cert.pem and sc-privkey.pem files to the tftp sever on the controller:
1083 ----
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
1087 ----
1088 NOTE: A tftp server runs on the controller host "10.0.0.1".
1089
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+ +
1096
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: +
1101
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
1104
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. +
1106
1107 .OF Plugin support for extensibility
1108 image::OFPlugin_ExtensibilitySupportInOFPlugin.png[width=500]
1109
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
1112
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).
1114
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.
1116
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.
1119 ----
1120 else if (action instanceof GeneralExtensionGrouping) {
1121                 
1122                 /**
1123                   * TODO: EXTENSION PROPOSAL (action, MD-SAL to OFJava)
1124                  * - we might need sessionContext as converter input
1125                  * 
1126                  */
1127                 
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);
1135                 }
1136             } else {
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(),
1141                                 version);
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);
1146                 }
1147             }
1148 ----
1149 ==== Encoders and decoders for augment messages (low level)
1150
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.
1153
1154 Decoders on the other hand are responsible for the following tasks: +
1155
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
1159
1160 ==== Master decoder
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.)
1162
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.
1164
1165 === Overload protection in the OF Plugin
1166 Overload protection in the OpenFlow (OF) Plugin works in the following way: +
1167
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.
1173 [start=2]
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.
1178 [start=5]
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 +
1182
1183 A queue gets filled for different reasons: +
1184
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.
1188
1189 NOTE: The current implementation of the feature offers no checking of the memory or CPU load to actively throttle messages.
1190
1191 .Overload protection
1192
1193 image::overloadProtectionBrief.png[width=500]
1194
1195 ==== Effects of overload protection
1196
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.