[ONOS-2276] Flow Test Suite
- tests flows with MAC address selectors
- tests flows with IPv4 selectors
- tests flows with vlan selector
Change-Id: I2c38a3449068b220742879b6b952b36e5572b3d3
diff --git a/TestON/tests/FUNCflow/FUNCflow.py b/TestON/tests/FUNCflow/FUNCflow.py
index 89a7e32..0fa77a2 100644
--- a/TestON/tests/FUNCflow/FUNCflow.py
+++ b/TestON/tests/FUNCflow/FUNCflow.py
@@ -27,24 +27,24 @@
main.cellName = main.params[ 'ENV' ][ 'cellName' ]
main.apps = main.params[ 'ENV' ][ 'cellApps' ]
gitBranch = main.params[ 'GIT' ][ 'branch' ]
+ gitPull = main.params[ 'GIT' ][ 'pull' ]
+ main.ONOSport = main.params[ 'CTRL' ][ 'port' ]
main.dependencyPath = main.testOnDirectory + \
main.params[ 'DEPENDENCY' ][ 'path' ]
- main.topology = main.params[ 'DEPENDENCY' ][ 'topology' ]
- main.maxNodes = int( main.params[ 'SCALE' ][ 'max' ] )
- main.ONOSport = main.params[ 'CTRL' ][ 'port' ]
- main.numSwitches = int( main.params[ 'TOPO' ][ 'numSwitches' ] )
- main.numHosts = int( main.params[ 'TOPO' ][ 'numHosts' ] )
- main.numLinks = int( main.params[ 'TOPO' ][ 'numLinks' ] )
wrapperFile1 = main.params[ 'DEPENDENCY' ][ 'wrapper1' ]
wrapperFile2 = main.params[ 'DEPENDENCY' ][ 'wrapper2' ]
+ main.topology = main.params[ 'DEPENDENCY' ][ 'topology' ]
+ main.maxNodes = int( main.params[ 'SCALE' ][ 'max' ] )
main.startUpSleep = int( main.params[ 'SLEEP' ][ 'startup' ] )
- gitPull = main.params[ 'GIT' ][ 'pull' ]
+ main.startMNSleep = int( main.params[ 'SLEEP' ][ 'startMN' ] )
+ main.addFlowSleep = int( main.params[ 'SLEEP' ][ 'addFlow' ] )
+ main.delFlowSleep = int( main.params[ 'SLEEP' ][ 'delFlow' ] )
+ main.swDPID = main.params[ 'TEST' ][ 'swDPID' ]
main.cellData = {} # for creating cell file
main.CLIs = []
main.ONOSip = []
main.ONOSip = main.ONOSbench.getOnosIps()
- print main.ONOSip
# Assigning ONOS cli handles to a list
for i in range( 1, main.maxNodes + 1 ):
@@ -207,49 +207,33 @@
'''
Start Mininet
'''
- main.case( "Setup mininet and assign switches to controllers" )
+ import json
+
+ main.case( "Setup mininet and compare ONOS topology view to Mininet topology" )
+ main.caseExplanation = "Start mininet with custom topology and compare topology " +\
+ "elements between Mininet and ONOS"
+
main.step( "Setup Mininet Topology" )
topology = main.Mininet1.home + '/custom/' + main.topology
- mnCmd = 'mn --custom ' + topology + ' --mac --arp'
- stepResult1 = main.Mininet1.startNet( mnCmd=mnCmd )
+ stepResult = main.Mininet1.startNet( topoFile=topology )
utilities.assert_equals( expect=main.TRUE,
- actual=stepResult1,
+ actual=stepResult,
onpass="Successfully loaded topology",
onfail="Failed to load topology" )
- main.step( "Assign switches to controllers" )
- for i in range( main.numSwitches ):
- stepResult2 = main.Mininet1.assignSwController(
- sw="s" + str( i+1 ),
- ip=main.ONOSip )
- if not stepResult2:
- break
+ main.step( "Assign switch to controller" )
+ stepResult = main.Mininet1.assignSwController( "s1", main.ONOSip[0] )
utilities.assert_equals( expect=main.TRUE,
- actual=stepResult2,
- onpass="Controller assignment successfull",
- onfail="Controller assignment failed" )
+ actual=stepResult,
+ onpass="Successfully assigned switch to controller",
+ onfail="Failed to assign switch to controller" )
- time.sleep(5)
+ time.sleep( main.startMNSleep )
- caseResult = stepResult1 and stepResult2
- if not caseResult:
- main.cleanup()
- main.exit()
-
- def CASE11( self, main ):
- '''
- Compare topology
- '''
- import json
-
- main.case( "Compare ONOS Topology view to Mininet topology" )
- main.caseExplanation = "Compare topology elements between Mininet" +\
- " and ONOS"
-
- main.step( "Gathering topology information" )
- # TODO: add a paramaterized sleep here
+ main.step( "Conmparing MN topology to ONOS topology" )
+ main.log.info( "Gathering topology information" )
devicesResults = main.TRUE
linksResults = main.TRUE
hostsResults = main.TRUE
@@ -263,7 +247,6 @@
mnLinks = main.Mininet1.getLinks()
mnHosts = main.Mininet1.getHosts()
- main.step( "Conmparing MN topology to ONOS topology" )
for controller in range( main.numCtrls ):
controllerStr = str( controller + 1 )
if devices[ controller ] and ports[ controller ] and\
@@ -309,7 +292,6 @@
" hosts don't match Mininet")
-
def CASE66( self, main ):
'''
Testing scapy
@@ -380,75 +362,301 @@
def CASE1000( self, main ):
'''
- Add flows
+ Add flows with MAC selectors and verify the flows
'''
+ import json
+ import time
- main.step("Add flows through rest")
+ main.case( "Verify flow MAC selectors are correctly compiled" )
+ main.caseExplanation = "Install two flows with only MAC selectors " +\
+ "specified, then verify flows are added in ONOS, finally "+\
+ "send a packet that only specifies the MAC src and dst."
- deviceId = main.params['MININET']['deviceId']
- host1_mac = main.params['MININET']['hostMac1']
- host2_mac = main.params['MININET']['hostMac2']
+ main.step( "Add flows with MAC addresses as the only selectors" )
- # Add flows that connects host1 to host 2
- stepResult = main.ONOSrest.addFlow( deviceId=deviceId,
- egressPort=2,
- ingressPort=1,
- ethSrc=host1_mac,
- ethDst=host2_mac)
+ main.log.info( "Creating host components" )
+ main.Mininet1.createHostComponent( "h1" )
+ main.Mininet1.createHostComponent( "h2" )
+ hosts = [main.h1, main.h2]
+ stepResult = main.TRUE
+ for host in hosts:
+ host.startHostCli()
+ host.startScapy()
+ host.updateSelf()
- stepResult = stepResult and main.ONOSrest.addFlow( deviceId=deviceId,
- egressPort=1,
- ingressPort=2,
- ethSrc=host2_mac,
- ethDst=host1_mac)
+ # Add a flow that connects host1 on port1 to host2 on port2
+ # send output on port2
+ # recieve input on port1
+ egress = 2
+ ingress = 1
+
+ # Add flows that sends packets from port1 to port2 with correct
+ # MAC src and dst addresses
+ main.log.info( "Adding flow with MAC selectors" )
+ stepResult = main.ONOSrest.addFlow( deviceId=main.swDPID,
+ egressPort=egress,
+ ingressPort=ingress,
+ ethSrc=main.h1.hostMac,
+ ethDst=main.h2.hostMac,
+ debug=True )
utilities.assert_equals( expect=main.TRUE,
actual=stepResult,
onpass="Successfully added flows",
onfail="Failed add flows" )
- def CASE2000( self, main ):
- '''
- Check flows are ADDED
- '''
- import json
- main.step("Check flows are in the ADDED state")
- main.log.info("Check only the flows added through REST")
+ # Giving ONOS time to add the flows
+ time.sleep( main.addFlowSleep )
+ main.step( "Check flows are in the ADDED state" )
+
+ #TODO: We should check mininet if flows are added as well
+ main.log.info( "Get the flows from ONOS" )
flows = json.loads( main.ONOSrest.flows() )
stepResult = main.TRUE
for f in flows:
if "rest" in f.get("appId"):
- if "ADDED" in f.get("state"):
- stepResult = stepResult and main.ONOSrest.removeFlow( deviceId, flowId )
+ if "ADDED" not in f.get("state"):
+ stepResult = main.FALSE
+ main.log.error( "Flow: %s in state: %s" % (f.get("id"), f.get("state")) )
utilities.assert_equals( expect=main.TRUE,
actual=stepResult,
onpass="All flows are in the ADDED state",
- onfail="All flows are in the ADDED state" )
+ onfail="All flows are NOT in the ADDED state" )
- def CASE3000( self, main ):
+ main.step( "Send a packet to verify the flows are correct" )
+
+ # Specify the src and dst MAC addr
+ main.log.info( "Constructing packet" )
+ main.h1.buildEther( src=main.h1.hostMac, dst=main.h2.hostMac )
+
+ # Filter for packets with the correct host name. Otherwise,
+ # the filter we catch any packet that is sent to host2
+ # NOTE: I believe it doesn't matter which host name it is,
+ # as long as its host1 or host2
+ main.log.info( "Starting filter on host2" )
+ main.h2.startFilter( pktFilter="ether host %s" % main.h1.hostMac)
+
+ main.log.info( "Sending packet to host2" )
+ main.h1.sendPacket()
+
+ main.log.info( "Checking filter for our packet" )
+ stepResult = main.h2.checkFilter()
+ if stepResult:
+ main.log.info( "Packet: %s" % main.h2.readPackets() )
+ else: main.h2.killFilter()
+
+ main.log.info( "Clean up host components" )
+ for host in hosts:
+ host.stopScapy()
+ main.Mininet1.removeHostComponent("h1")
+ main.Mininet1.removeHostComponent("h2")
+
+ utilities.assert_equals( expect=main.TRUE,
+ actual=stepResult,
+ onpass="Successfully sent a packet",
+ onfail="Failed to send a packet" )
+
+ def CASE1100( self, main ):
'''
- Delete flows that were added through REST
+ Add flows with IPv4 selectors and verify the flows
'''
import json
- main.step("Remove flows")
- main.log.info("Remove the flows that were added through rest")
+ import time
+ main.case( "Verify flow IP selectors are correctly compiled" )
+ main.caseExplanation = "Install two flows with only IP selectors " +\
+ "specified, then verify flows are added in ONOS, finally "+\
+ "send a packet that only specifies the IP src and dst."
+
+ main.step( "Add flows with IPv4 addresses as the only selectors" )
+
+ main.log.info( "Creating host components" )
+ main.Mininet1.createHostComponent( "h1" )
+ main.Mininet1.createHostComponent( "h2" )
+ hosts = [main.h1, main.h2]
+ stepResult = main.TRUE
+ for host in hosts:
+ host.startHostCli()
+ host.startScapy()
+ host.updateSelf()
+
+ # Add a flow that connects host1 on port1 to host2 on port2
+ # send output on port2
+ # recieve input on port1
+ egress = 2
+ ingress = 1
+ # IPv4 etherType = 0x800
+ IPv4=2048
+
+ # Add flows that connects host1 to host2
+ main.log.info( "Add flow with port ingress 1 to port egress 2" )
+ stepResult = main.ONOSrest.addFlow( deviceId=main.swDPID,
+ egressPort=egress,
+ ingressPort=ingress,
+ ethType=IPv4,
+ ipSrc=("IPV4_SRC", main.h1.hostIp+"/32"),
+ ipDst=("IPV4_DST", main.h2.hostIp+"/32"),
+ debug=True )
+
+ utilities.assert_equals( expect=main.TRUE,
+ actual=stepResult,
+ onpass="Successfully added flows",
+ onfail="Failed add flows" )
+
+ # Giving ONOS time to add the flow
+ time.sleep( main.addFlowSleep )
+
+ main.step( "Check flow is in the ADDED state" )
+
+ main.log.info( "Get the flows from ONOS" )
flows = json.loads( main.ONOSrest.flows() )
stepResult = main.TRUE
for f in flows:
if "rest" in f.get("appId"):
- flowId = f.get("id")
- deviceId = f.get("deviceId")
- stepResult = stepResult and main.ONOSrest.removeFlow( deviceId, flowId )
+ if "ADDED" not in f.get("state"):
+ stepResult = main.FALSE
+ main.log.error( "Flow: %s in state: %s" % (f.get("id"), f.get("state")) )
utilities.assert_equals( expect=main.TRUE,
actual=stepResult,
- onpass="Successfully removed all rest flows",
- onfail="Failed to remove rest flows" )
+ onpass="All flows are in the ADDED state",
+ onfail="All flows are NOT in the ADDED state" )
+
+ main.step( "Send a packet to verify the flow is correct" )
+
+ main.log.info( "Constructing packet" )
+ # No need for the MAC src dst
+ main.h1.buildEther( dst=main.h2.hostMac )
+ main.h1.buildIP( src=main.h1.hostIp, dst=main.h2.hostIp )
+
+ main.log.info( "Starting filter on host2" )
+ # Defaults to ip
+ main.h2.startFilter()
+
+ main.log.info( "Sending packet to host2" )
+ main.h1.sendPacket()
+
+ main.log.info( "Checking filter for our packet" )
+ stepResult = main.h2.checkFilter()
+ if stepResult:
+ main.log.info( "Packet: %s" % main.h2.readPackets() )
+ else: main.h2.killFilter()
+
+ main.log.info( "Clean up host components" )
+ for host in hosts:
+ host.stopScapy()
+ main.Mininet1.removeHostComponent("h1")
+ main.Mininet1.removeHostComponent("h2")
+
+ utilities.assert_equals( expect=main.TRUE,
+ actual=stepResult,
+ onpass="Successfully sent a packet",
+ onfail="Failed to send a packet" )
+
+ def CASE1200( self, main ):
+ '''
+ Add flow with VLAN selector and verify the flow
+ '''
+ import json
+ import time
+
+ main.case( "Verify VLAN selector is correctly compiled" )
+ main.caseExplanation = "Install one flow with only the VLAN selector " +\
+ "specified, then verify the flow is added in ONOS, and finally "+\
+ "broadcast a packet with the correct VLAN tag."
+
+ # We do this here to utilize the hosts information
+ main.log.info( "Creating host components" )
+ main.Mininet1.createHostComponent( "h3" )
+ main.Mininet1.createHostComponent( "h4" )
+ hosts = [main.h3, main.h4]
+ stepResult = main.TRUE
+ for host in hosts:
+ host.startHostCli()
+ host.startScapy()
+ host.updateSelf()
+
+
+ main.step( "Add a flow with the VLAN tag as the only selector" )
+
+ # Add flows that connects the two vlan hosts h3 and h4
+ # Host 3 is on port 3 and host 4 is on port 4
+ vlan = main.params[ 'TEST' ][ 'vlan' ]
+ egress = 4
+ ingress = 3
+ # VLAN ethType = 0x8100
+ ethType = 33024
+
+ # Add only one flow because we don't need a response
+ main.log.info( "Add flow with port ingress 1 to port egress 2" )
+ stepResult = main.ONOSrest.addFlow( deviceId=main.swDPID,
+ egressPort=egress,
+ ingressPort=ingress,
+ ethType=ethType,
+ vlan=vlan,
+ debug=True )
+
+
+ utilities.assert_equals( expect=main.TRUE,
+ actual=stepResult,
+ onpass="Successfully added flow",
+ onfail="Failed add flows" )
+
+ # Giving ONOS time to add the flows
+ time.sleep( main.addFlowSleep )
+
+ main.step( "Check flows are in the ADDED state" )
+
+ main.log.info( "Get the flows from ONOS" )
+ flows = json.loads( main.ONOSrest.flows() )
+
+ stepResult = main.TRUE
+ for f in flows:
+ if "rest" in f.get("appId"):
+ if "ADDED" not in f.get("state"):
+ stepResult = main.FALSE
+ main.log.error( "Flow: %s in state: %s" % (f.get("id"), f.get("state")) )
+
+ utilities.assert_equals( expect=main.TRUE,
+ actual=stepResult,
+ onpass="All flows are in the ADDED state",
+ onfail="All flows are NOT in the ADDED state" )
+
+ main.step( "Send a packet to verify the flow are correct" )
+
+ # The receiving interface
+ recIface = "{}-eth0.{}".format(main.h4.name, vlan)
+ main.log.info( "Starting filter on host2" )
+ # Filter is setup to catch any packet on the vlan interface with the correct vlan tag
+ main.h4.startFilter( ifaceName=recIface, pktFilter="" )
+
+ # Broadcast the packet on the vlan interface. We only care if the flow forwards
+ # the packet with the correct vlan tag, not if the mac addr is correct
+ BROADCAST = "FF:FF:FF:FF:FF:FF"
+ sendIface = "{}-eth0.{}".format(main.h3.name, vlan)
+ main.log.info( "Broadcasting the packet with a vlan tag" )
+ main.h3.sendPacket( iface=sendIface, packet="Ether(dst='{}')/Dot1Q(vlan={})".format(BROADCAST, vlan))
+
+ main.log.info( "Checking filter for our packet" )
+ stepResult = main.h4.checkFilter()
+ if stepResult:
+ main.log.info( "Packet: %s" % main.h4.readPackets() )
+ else: main.h4.killFilter()
+
+ main.log.info( "Clean up host components" )
+ for host in hosts:
+ host.stopScapy()
+ main.Mininet1.removeHostComponent("h3")
+ main.Mininet1.removeHostComponent("h4")
+
+ utilities.assert_equals( expect=main.TRUE,
+ actual=stepResult,
+ onpass="Successfully sent a packet",
+ onfail="Failed to send a packet" )
def CASE100( self, main ):
'''