Copy SDN-TUT plugin-exercise.
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
Install feature:
feature:install ima-controller
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.
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>
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.
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.
Doing mvn dependency:tree, dependency:lis
Add all feature xml dependencies from features-artifacts to karaf-distribution dependencies.??? not solving problem
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
2. on local machine:
# ssh -X root@remotemachine # wireshark
3. Go to Capture > Options > Interface > Pseudo-Device
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
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 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.
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.
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
h1 moves from s1 to s2 port 14
h1 moves from s2 to s3
Conclusion:
Listen to arp packet and flood or direct forward arp to ports.
listen to arp and insert srcMac, ip to the nodeConnectorRef where the arp came from.
Listen to Topology changes: HostNode.class and Link.class
Listen to Inventory changes: Adresses.class
Remove oldHost, oldLinsk and add newHost, newLinks.
Observation:
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(); }
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();
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();
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=[]]]]]
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