My Wiki!

ODL dev ima-controller

Copy SDN-TUT plugin-exercise.

  • parent-pom:
    • all features and bundles version
    • all bundles dependencies (already managed by odlparent).
    • feature-pom:
    • all dependent features used in src/features.xml. Versions are declared in parent pom.
    • all dependent bundles
    • plugin bundle-pom:

Karaf - Maven

Updating features-repo snapshot in karaf 3.0

his is an example of a features.xml file that points to jar files in the local file system:

20     <feature name="ima-controller" description="IMA :: OpenDaylight :: Controller" version='${project.version}'>
 21         <feature version="${controller.base.version}">odl-base-all</feature>
 22         <!--
 23         <feature version="${features.adsal-compat.version}">odl-adsal-compatibility</feature>
 24         -->
 25         <feature version="${controller.adsal.version}">odl-adsal-all</feature>
 26         <feature version="${controller.nsf.version}">odl-nsf-all</feature>
 27         <feature version="${controller.restconf.version}">odl-restconf</feature>
 28         <feature version="${controller.mdsal.version}">odl-mdsal-broker</feature>
 29         <feature version="${openflowplugin.version}">odl-openflowplugin-southbound</feature>
 30         <feature version="${openflowplugin.version}">odl-openflow----plugin-nxm-extensions</feature>
 31         <feature version="${openflowplugin.version}">odl-openflowplugin-flow-services</feature>
 32         <feature version="${ovsdb.plugin.version}">odl-ovsdb-plugin</feature>
 33         <bundle>mvn:de.dailab.nemo.ima.controller/ima-controller/${project.version}</bundle>    <---------- copy 1.0.0-SNAPSHOT
 34     </feature>

Karaf Distribution: Exclude features-xml-bundle from dependency list.

Install feature-repo manually from karaf:

  feature:repo-add mvn:de.dailab.nemo.ima.controller/features-ima/1.0.0-SNAPSHOT/xml/features
  

Watch the repo-bundle (is this needed?):

  bundle:watch --start mvn:de.dailab.nemo.ima.controller/features-ima/1.0.0-SNAPSHOT/xml/features
  bundle:watch --start de.dailab.nemo.ima.controller/ima-controller/1.0.0-SNAPSHOT
  bundle:watch --list
  

Make changes to the feature-xml project:

  cd features/ima
  vim src/.../features.xml
  mvn clean install
  

Refresh ima feature repo:

feature:repo-refresh mvn:de.dailab.nemo.ima.controller/features-ima/1.0.0-SNAPSHOT/xml/features
feature:info ima-controller
# the new feature dependencies should be shown

Updating Bundle snapshot in karaf 3.0

Install feature:

  feature:install ima-controller

Troubleshooting

    • dependency not declared in bundle, features, etc. Add the to scope compile
  • Bad artifact coordinates mvn:org.opendaylight.controller/features-nsf/${controller.nsf.version}/xml/features,
    • Delete the ${..} from .m2 then recompile
  • feature:install karaf-base-all look for tomcat-security in wrong location:
    • feature-list | grep base
    • feature:repo-list | grep base –> remove duplicate version.
    • cd feature-abc; mvn clean install
    • rm -rf $KARAF/data/*

Karaf: Update Karaf maven version requirement

The generated karaf distribution archetype use maven 3.0.0. This mvn version can not resolve com.google.common.collect.

Use maven > 3.1.1

Could not start bundle mvn:de.dailab.nemo.ima.controller/ima-controller-main/1.0.0-SNAPSHOT in feature(s) ima-controller-1.0.0-   SNAPSHOT: 
The bundle "de.dailab.nemo.ima.controller.ima-controller-main_1.0.0.SNAPSHOT [61]" could not be resolved. 
Reason: Missing Constraint: Import-Package: com.google.common.collect; version="[18.0.0,19.0.0)"

Do a mvn dependecy:tree

+- org.opendaylight.controller:sal-binding-api:jar:1.2.0-SNAPSHOT:compile
  +- com.google.guava:guava:jar:18.0:compile

com.google.common.collect is packaged in guava.jar so check if sal-binding-api is in dependencies list.

Karaf: mvn dependency:tree

Comment out the version of maven-dependency-plugin in the autogenerated karaf-distribution pom. Newer version will be used.

<plugin>
217         <groupId>org.apache.maven.plugins</groupId>
218         <artifactId>maven-dependency-plugin</artifactId>
219         <!--
220         <version>2.6</version>
221         -->
222         <executions>
223           <execution>
224             <id>copy</id>

Bundle could not be resolved

feature:install ima-controller 
Refreshing bundles org.apache.aries.util (13)
Error executing command: Could not start bundle mvn:org.opendaylight.controller/dummy-console/1.3.0-SNAPSHOT in feature(s) odl-base-dummy-console-1.3.0-SNAPSHOT: The bundle "org.opendaylight.controller.dummy-console_1.3.0.SNAPSHOT [101]" could not be resolved. Reason: Missing Constraint: Require-Capability: osgi.ee; filter="(&(osgi.ee=JavaSE)(version=1.7))"

Solution:

dummy-console is in features-adsal. So add it to the features.xml repo and in feature-pom dependencies.

Missing Constraint

https://issues.apache.org/jira/browse/KARAF-3069

Solution: use karaf 3.0.2

In parent.pom: karaf.version 3.0.2

karaf> version

The new maven bundle plugin 2.5.0 creates a new standard OSGi header:
Require-Capability: osgi.ee; filter="(&(osgi.ee=JavaSE)(version=1.6))"

So such bundles can only be resolved if the capability is present. Because of this bug such bundles can not be resolved in karaf by default.

How to reproduce:
Load and unpack karaf 3.0.1
Set "framework=equinox" in etc/config.properties
Start bin/karaf
In the console type "capabilities 0 | grep osgi.ee"
It will show no matching capability.

Problem:
The problem is that we use a variable ${services-${karaf.framework}} which does not exist if the framework is equinox.

Workaround:
Remove the line ${services-${karaf.framework}} and the ", \" in the line above.

Could not find features-base xx in apache (http://repository.apache.org/content/groups/snapshots-group/)

Doing mvn dependency:tree, dependency:lis

Add all feature xml dependencies from features-artifacts to karaf-distribution dependencies.??? not solving problem

Testing

Features:

ima-controller depends on: feature-base, feature-nsf, feature-mdsal, feature-restconf, feature-adsal

  odl-nsf-all and <del>odl-adsal-compatibility</del>
  

Install features in karaf:

  feature:install ima-controller odl-restconf odl-l2switch-switch odl-mdsal-apidocs odl-dlux-all
  

Wireshark

2. on local machine:

# ssh -X root@remotemachine
# wireshark

3. Go to Capture > Options > Interface > Pseudo-Device

Working


feature:repo-add mvn:de.dailab.nemo.ima.controller/features-ima/1.0.0-SNAPSHOT/xml/features
feature:repo-add mvn:de.dailab.nemo.dmm/features-dmm/1.0.0-SNAPSHOT/xml/features

feature:install dmm-switch
feature:install ima-controller odl-mdsal-apidocs odl-dlux-all

bundle:watch de.dailab.nemo.ima.controller/ima-controller/1.0.0-SNAPSHOT

mn --custom topo-2sw-2host.py --topo mytopo --switch ovsk,protocol=OpenFlow13 --controller remote,ip=10.10.11.44,port=6633
sudo mn --switch ovsk,protocol=OpenFlow13 --controller remote,ip=10.10.11.44,port=6633

ovs-ofctl -O OpenFlow13 dump-flows s4

log:set TRACE de.dailab.nemo.ima.controller

If code changes relating to Service loading (SAL) it's better to reinstall bundle:

  feature:uninstall ima-controller
  feature:install ima-controller

See if flow rule applied

   ovs-ofctl -O OpenFlow13 dump-flows s1

show something like this: n_packets show number of packets, for which rule is applied. Here all are dropped!!

[root@mininet fedora]# ovs-ofctl -O OpenFlow13 dump-flows s1
  OFPST_FLOW reply (OF1.3) (xid=0x2):
  cookie=0x0, duration=188.304s, table=0, n_packets=14, n_bytes=644, priority=0 actions=drop
  cookie=0x0, duration=188.141s, table=0, n_packets=0, n_bytes=0, priority=65535,dl_type=0x88cc actions=CONTROLLER:65535

ovs-dpctl dump-flows

  ovs-dpctl show

Show data path in the last 5 second. So start after doing a ping:

ovs-dpctl dump-flows -m
sudo ovs-dpctl dump-flows -m 
skb_priority(0),in_port(s1-eth1),skb_mark(0/0),eth(src=8a:03:93:82:15:2a/00:00:00:00:00:00,dst=ff:ff:ff:ff:ff:ff
/00:00:00:00:00:00),eth_type(0x0806),arp(sip=10.0.0.1/0.0.0.0,tip=10.0.0.3/0.0.0.0,op=1/0,sha=8a:03:93:82:15:2a
/00:00:00:00:00:00,tha=00:00:00:00:00:00/00:00:00:00:00:00), packets:2, bytes:84, used:0.181s, 
actions:userspace(pid=4294962801,slow_path(controller))

.

Restart karaf after installing bundle for the first time. So they are autostarted in good sequence

Empty karaf/data then restart, repo-add, feature:install etc.

ODL Controller Modules

ima-controller project

Dev Resources

Scaffolding

  • generate simple mdsal archetype project
  • cp provider to controller-main
  • generate distribution archetype project
  • move main pom content to commons/parent/pom
  • fix featuers, dependencies…

Feature Dependency

Feature depends on:
  odl-yangtools-common 0.7.0-SNAPSHOT
  odl-yangtools-binding 0.7.0-SNAPSHOT
  odl-l2switch-hosttracker 0.2.0-SNAPSHOT
Feature contains followed bundles:
  mvn:de.dailab.nemo.ima.controller/ima-controller-model/1.0.0-SNAPSHOT
  mvn:de.dailab.nemo.ima.controller/ima-controller-main/1.0.0-SNAPSHOT

Hosttracker depends on AddressTracker depends on Arphandler depends on Loopremover.

https://wiki.opendaylight.org/view/L2_Switch:Helium:Developer_Guide

Arphandler install default flooding rules. Main controller will remove these flows.

How l2switch works

Using mobility.py, disable deleting flows.

Disable flooding:

  vim $karaf/etc/opendaylight/54-arphandler.xml
  

Disable drop rule:

      vim $karaf/etc/opendaylight/58-l2switchmain.xml

Observation

h1 moves from s1 to s2 port 14

  • h1 keeps IP
  • s2 port 2:2 still fwd packets destined to h1 to s1. Flow not updated
  • additional host-tracker for h1 is created on port 14. Timestamp updated.

h1 moves from s2 to s3

  • s2 prot 2:3 fwd to s3 with h1,h3 host-tracker entry.
  • port 2:2 still fwd to s1, old host-tracker entry.

Conclusion:

  • Host-tracker add new nodes, not delete old ones.
  • Flows are not updated.


Arp handler

Listen to arp packet and flood or direct forward arp to ports.

Address Tracker

listen to arp and insert srcMac, ip to the nodeConnectorRef where the arp came from.

Host Tracker

Listen to Topology changes: HostNode.class and Link.class

Listen to Inventory changes: Adresses.class

Remove oldHost, oldLinsk and add newHost, newLinks.

Observation:

  • Topology is updated fast.

MD-SAL database, iid, read, write

Example query for topology model:

"topology": [
            {
                "topology-id": "flow:1",
                "link": [
                    {
                        "link-id": "openflow:3:2",
                        "destination": {
                            "dest-tp": "openflow:2:3",
                            "dest-node": "openflow:2"
                        },
                        "source": {
                            "source-node": "openflow:3",
                            "source-tp": "openflow:3:2"
                        }
                    },
                    {
    // Get all topologies in MD-SAL
    private List<Topology> getAllTopologies() {
         InstanceIdentifier topoIdentifier = 
                 InstanceIdentifier.builder(NetworkTopology.class).toInstance();
         System.out.println("topoIdentifier " + topoIdentifier);
         List<Topology> topos = ((NetworkTopology) this.dataProviderService
                    .readOperationalData(topoIdentifier)).getTopology();    
        return topos;
    }
 
    // Get a particular toplogy in MD-SAL
    private Topology getFlowTopology() {
        TopologyId topoId = new TopologyId("flow:1");
        InstanceIdentifier topoIdentifier = InstanceIdentifier.builder(NetworkTopology.class).child(Topology.class, new TopologyKey(topoId)).toInstance();
        System.out.println("topoIdentifier " + topoIdentifier);
        Topology topology = (Topology) dataProviderService.readOperationalData(topoIdentifier);
        return topology;
    }
 
    // Get all links in MD-SAL
    private List<Link> getAllLinks() {
        Topology flowTopology = getFlowTopology();
        return flowTopology.getLink();
    }

Get all topologies

Create Instance Id form Topology Object to query all data:

  InstanceIdentifier topoIdentifier = InstanceIdentifier.builder(NetworkTopology.class).toInstance();
  

Query Database using the Identifier:

  List<Topology> topos = ((NetworkTopology) this.dataProviderService
                  .readOperationalData(topoIdentifier)).getTopology();
                  

Get a particular toplogy in MD-SAL

We need an ID object:

  TopologyId topoId = new TopologyId("flow:1");

Create InstanceId for the specific flow, using child method:

InstanceIdentifier topoIdentifier = InstanceIdentifier.builder(NetworkTopology.class).child(Topology.class, new TopologyKey(topoId)).toInstance();

Get Topology object from the query:

  Topology topology = (Topology) dataProviderService.readOperationalData(topoIdentifier);

Access Data in the Topology object:

  List<Link> allLinks = topology.getLink();

dmm-switch / ima-controller

Understand startup process

TutorialFlowProgrammer register for OpendaylightInventory (implement OpendaylightInventoryListener).

Start mininet triggers onNodeUpdate callback.

This write 2 LLDP rules to the OVS.

2015-05-07 04:43:07,168 | INFO  | pool-63-thread-1 | TutorialFlowProgrammer           | 407 - de.dailab.nemo.ima.controller.ima-controller - 1.0.0.SNAPSHOT | MD-SAL Node Update: NodeUpdated [_id=Uri [_value=openflow:1], _nodeRef=NodeRef [_value=KeyedInstanceIdentifier{targetType=interface org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node, path=[org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes, org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node[key=NodeKey [_id=Uri [_value=openflow:1]]]]}], augmentation=[FlowCapableNodeUpdated [_ipAddress=IpAddress [_ipv4Address=Ipv4Address [_value=10.10.11.237], _value=[1, 0, ., 1, 0, ., 1, 1, ., 2, 3, 7]], _switchFeatures=SwitchFeatures [_capabilities=[class org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowFeatureCapabilityFlowStats, class org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowFeatureCapabilityPortStats, class org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowFeatureCapabilityQueueStats, class org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowFeatureCapabilityTableStats], _maxBuffers=256, _maxTables=254, augmentation=[]]]]]

WakeupOnNode

2015-05-12 09:41:05,683 | TRACE | lt-dispatcher-17 | WakeupOnNode                     | 389 - de.dailab.nemo.ima.controller.ima-controller - 1.0.0.SNAPSHOT | Data chaged - table: Table{getId=0, augmentations={interface org.opendaylight.yang.gen.v1.urn.opendaylight.flow.table.statistics.rev131215.FlowTableStatisticsData=FlowTableStatisticsData{getFlowTableStatistics=FlowTableStatistics{getActiveFlows=Counter32 [_value=0], getPacketsLookedUp=Counter64 [_value=7106], getPacketsMatched=Counter64 [_value=7058], augmentations={}}}, interface org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.AggregateFlowStatisticsData=AggregateFlowStatisticsData{getAggregateFlowStatistics=AggregateFlowStatistics{getByteCount=Counter64 [_value=0], getFlowCount=Counter32 [_value=0], getPacketCount=Counter64 [_value=0], augmentations={}}}}}
2015-05-12 09:41:05,683 | DEBUG | lt-dispatcher-17 | SwitchHandlerFacadeImpl          | 389 - de.dailab.nemo.ima.controller.ima-controller - 1.0.0.SNAPSHOT | expected table acquired, learning ..
2015-05-12 09:41:05,685 | DEBUG | lt-dispatcher-17 | SwitchHandler                    | 389 - de.dailab.nemo.ima.controller.ima-controller - 1.0.0.SNAPSHOT | expected table acquired, learning ..
2015-05-12 09:41:05,686 | TRACE | lt-dispatcher-14 | WakeupOnNode                     | 389 - de.dailab.nemo.ima.controller.ima-controller - 1.0.0.SNAPSHOT | Data chaged - table: Table{getId=0, augmentations={interface org.opendaylight.yang.gen.v1.urn.opendaylight.flow.table.statistics.rev131215.FlowTableStatisticsData=FlowTableStatisticsData{getFlowTableStatistics=FlowTableStatistics{getActiveFlows=Counter32 [_value=0], getPacketsLookedUp=Counter64 [_value=7106], getPacketsMatched=Counter64 [_value=7058], augmentations={}}}, interface org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.AggregateFlowStatisticsData=AggregateFlowStatisticsData{getAggregateFlowStatistics=AggregateFlowStatistics{getByteCount=Counter64 [_value=0], getFlowCount=Counter32 [_value=0], getPacketCount=Counter64 [_value=0], augmentations={}}}}}
2015-05-12 09:41:05,694 | DEBUG | lt-dispatcher-14 | SwitchHandlerFacadeImpl          | 389 - de.dailab.nemo.ima.controller.ima-controller - 1.0.0.SNAPSHOT | expected table acquired, learning ..
2015-05-12 09:41:05,696 | DEBUG | lt-dispatcher-17 | SwitchHandler                    | 389 - de.dailab.nemo.ima.controller.ima-controller - 1.0.0.SNAPSHOT | writing packetForwardToController flow. 
 Flow Path: KeyedInstanceIdentifier{targetType=interface org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.Table, path=[org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes, org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node[key=NodeKey [_id=Uri [_value=openflow:4]]], org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode, org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.Table[key=TableKey [_id=0]]]}
2015-05-12 09:41:05,999 | TRACE | ult-dispatcher-3 | WakeupOnNode                     | 389 - de.dailab.nemo.ima.controller.ima-controller - 1.0.0.SNAPSHOT | Data chaged - table: Table{getId=0, augmentations={interface org.opendaylight.yang.gen.v1.urn.opendaylight.flow.table.statistics.rev131215.FlowTableStatisticsData=FlowTableStatisticsData{getFlowTableStatistics=FlowTableStatistics{getActiveFlows=Counter32 [_value=0], getPacketsLookedUp=Counter64 [_value=7106], getPacketsMatched=Counter64 [_value=7059], augmentations={}}}, interface org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.AggregateFlowStatisticsData=AggregateFlowStatisticsData{getAggregateFlowStatistics=AggregateFlowStatistics{getByteCount=Counter64 [_value=0], getFlowCount=Counter32 [_value=0], getPacketCount=Counter64 [_value=0], augmentations={}}}}}
2015-05-12 09:41:06,008 | DEBUG | ult-dispatcher-3 | SwitchHandlerFacadeImpl          | 389 - de.dailab.nemo.ima.controller.ima-controller - 1.0.0.SNAPSHOT | expected table acquired, learning ..
2015-05-12 09:41:06,008 | DEBUG | ult-dispatcher-3 | SwitchHandler                    | 389 - de.dailab.nemo.ima.controller.ima-controller - 1.0.0.SNAPSHOT | expected table acquired, learning ..
2015-05-12 09:41:06,008 | DEBUG | ult-dispatcher-3 | SwitchHandler                    | 389 - de.dailab.nemo.ima.controller.ima-controller - 1.0.0.SNAPSHOT | writing packetForwardToController flow. 
 Flow Path: KeyedInstanceIdentifier{targetType=interface org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.Table, path=[org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.Nodes, org.opendaylight.yang.gen.v1.urn.opendaylight.inventory.rev130819.nodes.Node[key=NodeKey [_id=Uri [_value=openflow:3]]], org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.FlowCapableNode, org.opendaylight.yang.gen.v1.urn.opendaylight.flow.inventory.rev130819.tables.Table[key=TableKey [_id=0]]]}
2015-05-12 09:41:06,009 | TRACE | ult-dispatcher-3 | WakeupOnNode                     | 389 - de.dailab.nemo.ima.controller.ima-controller - 1.0.0.SNAPSHOT | Data chaged - table: Table{getId=0, augmentations={interface org.opendaylight.yang.gen.v1.urn.opendaylight.flow.table.statistics.rev131215.FlowTableStatisticsData=FlowTableStatisticsData{getFlowTableStatistics=FlowTableStatistics{getActiveFlows=Counter32 [_value=0], getPacketsLookedUp=Counter64 [_value=7106], getPacketsMatched=Counter64 [_value=7059], augmentations={}}}, interface org.opendaylight.yang.gen.v1.urn.opendaylight.flow.statistics.rev130819.AggregateFlowStatisticsData=AggregateFlowStatisticsData{getAggregateFlowStatistics=AggregateFlowStatistics{getByteCount=Counter64 [_value=0], getFlowCount=Counter32 [_value=0], getPacketCount=Counter64 [_value=0], augmentations={}}}}}
2015-05-12 09:41:06,009 | DEBUG | ult-dispatcher-3 | SwitchHandlerFacadeImpl          | 389 - de.dailab.nemo.ima.controller.ima-controller - 1.0.0.SNAPSHOT | expected table acquired, learning ..
2015-05-12 09:41:11,722 | TRACE | lt-dispatcher-18 | WakeupOnNode    

Write Flow


Navigation