OpenDaylight Controller:MD-SAL:L2 Switch
- 1 Overview
- 2 Switch actions
- 3 Implementation Details
- 4 Assumptions
- 5 Limitation
- 6 How to run L2Switch
- 7 Items for discussion
This is MD-SAL based implementation of a learning switch with optimizations in how packet is forwarded.
When a packet comes in, L2Switch learns about the source's mac address. If it knows about the destination, it teleports the packet to destination. Otherwise, it sends a broadcast message on all external ports in the network.
- Teleporting means that the packet is sent to the destination without flooding.
- Internal ports consist of switch-to-switch ports and switch-to-controller ports. External ports are all the remaining ports, which are potentially connected to hosts.
Teleporting and using only external ports for broadcasting is an optimization over "flooding" which a typical learning switch would do.
Switch only deals with *non lldp* ethernet packets.
|Source Mac||Target Mac||L2 Switch Action||Comments|
|Unknown||Unknown||Learn source, Broadcast packet on all external port minus ingress|
|Unknown||Known||Learn source, Unicast packet to the target||L2 Switch is essentially teleporting the packet to the node where the target is attached. Attachment point is where the target is physically attached.|
|Known||Unknown||Broadcast packet on all external ports minus ingress||L2 Switch doesnt need to learn as it already knows the source. There could be case, however, where a host has moved from one node to another node in the network. In the current implementation, we dont update the attachment point.|
|Known||Known||Unicast the packet to the target, find the shortest path between source and destination and install mac-to-mac flows on all the nodes in that path|
- informs AddressTracker about new Mac-Port pairings.
- informs FlowWriterService about new flows, when the source & destination of a packet are known.
- uses InventoryService to determine external ports and only send packets to those ports when flooding packets in the network.
AddressTracker stores the Mac-Port pairings in the MD-SAL data tree.
InventoryService provides information about the nodes and node connectors in the network.
FlowWriterService adds packet forwarding (mac-to-mac) flows to the MD-SAL data tree.
- uses NetworkGraphDijkstra to determine all the intermediate nodes along a path.
TopologyLinkDataChangeHandler listens to topology updates and informs NetworkGraphDijkstra of these updates.
NetworkGraphDijkstra maintains the network graph and computes the shortest path between each node.
Determining the external ports in the network
Definition of External Ports -- ports that potentially point to a host. All the ports that are NOT connected to another switch or the controller.
To determine external ports:
- Find the list of all node-to-node (switch-to-switch) internal ports. This is done by looking at all the links from the Topology data.
- Find the list of all ports in the network. This is done by looking at the Inventory data.
- The difference between List#1 and List#2 is a list of external ports and switch-to-controller (internal) ports.
- Switch-to-controller ports have special properties and can be easily removed from List#3. This gives us the list of external ports.
Will this ever compute an incorrect list of external ports?
Yes, topology can change at any given time and its possible that by the time we calculated the external ports, one of them became internal!
In such scenario, will will broadcast a packet on this new internal port and that packet will bounce back to controller. Based on this packet, it appears that the host is now connected to the switch that bounced the message, which is incorrect. Our current implementation would just ignore this packet as explained in the section OpenDaylight Controller:MD-SAL:L2 Switch#Why_we_dont_update_attachment_point.
Finding the shortest path between 2 nodes
<TBD> Consult with Amit and add details
Why we do not update attachment point
The L2 Switch maintains mac-port mapping for all mac addresses in the network -- this mapping is a canonical view of the network and not per switch. The port for a mac is the port where the mac is physically connected (not accounting for a repeater or an external switch scenario but it shouldn't matter there too).
In order for the mac-port mapping to remain correct, the controller must not receive duplicate packets from 2 different switches.
Why will receive duplicate packets from 2 different switches cause incorrect mac-port mappings?
It's easiest to explain with an example. Let's say Host is connected to node1 on port1.
Host sends out an ARP request, which the switch sends to the controller (because it doesn't know destination mac). The controller will map this host's mac to node1:port1. This is correct!
The problem occurs when the controller forwards the original host's ARP request to node2 using port1 (so node2:port1 connects controller to node2). If node2 doesn't contain the destination mac, it will pass the ARP request back to controller. This packed has host's mac but the associated ingress would be node2:port1
The question is: Should we update mac-port mapping? and change mac-port association from node1-port1 to node2-port1.
- If no, we correctly operate in the given example since host is not really connected at this port. However, we will not operate correctly when a host genuinely moves to a new location.
- If yes, then there will be cases when our mac-port mapping gets corrupted. We won't be able to optimally find shortest path between 2 hosts and hence not program flows appropriately.
- Assumes that hosts don't move i.e a mac address associated with a port on a node does'nt move to another port.
- Assumes LLDP packets are handled by Openflow Plugin. This switch ignores LLDP packets
- Assumes that for non LLDP packets, L2 Switch is the only forwarder of packet. If not, duplicate packets may be forwarded.
- All nodes in the network are openflow capable controlled by the controller.
- Flow expiration is not handled
- Flow is not updated when host moves (see Assumptions section)
- Flows are not reprogrammed when topology changes
How to run L2Switch
- Setup mininet (how to setup test VMs?)
- Get controller and openflowplugin projects from odl git repo and build them locally(how to?)
- Copy model(l2switch-model-1.1-SNAPSHOT.jar) and impl(l2switch-impl-1.1-SNAPSHOT.jar) jars to plugins directory of openflowplugin distribution (not controller)
$cp controller/opendaylight/md-sal/samples/l2switch/model/target/l2switch-model-1.1-SNAPSHOT.jar openflowplugin/distribution/base/target/distributions-openflowplugin-base-0.0.3-SNAPSHOT-osgipackage/opendaylight/plugins/ $cp controller/opendaylight/md-sal/samples/l2switch/implementation/target/l2switch-impl-1.1-SNAPSHOT.jar openflowplugin/distribution/base/target/distributions-openflowplugin-base-0.0.3-SNAPSHOT-osgipackage/opendaylight/plugins/
- Start opendaylight using openflowplugin distribution
- Stop ARPHandler and SimpleForwardingManager
osgi> ss | grep arp 17 ACTIVE org.opendaylight.controller.arphandler_0.5.2.SNAPSHOT true osgi> ss | grep simple 177 ACTIVE org.opendaylight.controller.samples.simpleforwarding_0.4.2.SNAPSHOT true osgi> stop 17 osgi> stop 177
- Start mininet with a topology of your choice. For eg:
sudo mn --controller=remote,ip=<controller_ip> --topo linear,2 --switch ovsk,protocols=OpenFlow13
- Do pingall in mininet console. This should generate network traffic between hosts. Pings should work.
- All learned map-port mapping by AddressTracker can be accessed at
- All configured flows (by FlowWriterService) can be viewed at
- All operational flows can be viewed at
L2Switch from git with karaf
- Cloning l2switch
git clone https://git.opendaylight.org/gerrit/l2switch
- Build the project
cd l2switch mvn clean install
- Alternatively, one can use parallel build (quicker), but it may fail because of dependencies; however it is possible to run it few times in a row
mvn -T 4 clean install -DskipTests -Dmaven.compile.fork=true
- Karaf distribution should be at
- Now can start
- either with
to get directly to the karaf console
- or in background
In this case, you need to wait a bit and then you can ssh in it:
ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no karaf@localhost -p 8101
Password is: karaf
- Once got to the karaf console, install ui feature:
- Wait a bit, you can see what bundles are loaded which are not, with
- Also possible to grep the output, e.g.
bundle:list | grep -i resolved
- or (to see if web interface bundle is ready):
bundle:list | grep -i dlux
Now your l2switch should be running. You can start mininet as described above for tests. Also, you should get a web interface running at
For Lithium use:
(default login/password are admin/admin)
Items for discussion
- Currently there is no mechanism to allow only 1 packet forwarder in controller. Their can be more than one module forwarding the packets resulting in duplicate packets in network and in some cases even stepping on each other.
- Modeling of ethernet packet based on yang needs to be done.
- Our assumption has been that the deployment would be with an out-of-band controller that connects to all the switches/NEs using a management network (separate than data network). How do we handle in-band controller deployment scenario?
- We had started off building AD-SAL like Hosttracker functionality. AD-SAL hosttracker stores IP for every host and keeps the information current by ARP probing hosts. After consultation with Ed and Colin, we decided to adhere strictly to L2 layer and store only mac-port mapping. Do we need to have a notion of host/device? If so, what would be its definition and what would identify it uniquely?