[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/drivers/common/api/controller/onosrestdriver.py b/TestON/drivers/common/api/controller/onosrestdriver.py
index 3ff43c7..878e97e 100644
--- a/TestON/drivers/common/api/controller/onosrestdriver.py
+++ b/TestON/drivers/common/api/controller/onosrestdriver.py
@@ -1094,39 +1094,14 @@
             main.cleanup()
             main.exit()
 
-    def addFlow( self,
-                 deviceId,
-                 appId=0,
-                 ingressPort="",
-                 egressPort="",
-                 ethType="",
-                 ethSrc="",
-                 ethDst="",
-                 bandwidth="",
-                 lambdaAlloc=False,
-                 ipProto="",
-                 ipSrc="",
-                 ipDst="",
-                 tcpSrc="",
-                 tcpDst="",
-                 ip="DEFAULT",
-                 port="DEFAULT" ):
+    def sendFlow( self, deviceId, flowJson, ip="DEFAULT", port="DEFAULT", debug=False ):
         """
         Description:
-            Creates a single flow in the specified device
+            Sends a single flow to the specified device. This function exists
+            so you can bypass the addFLow driver and send your own custom flow.
         Required:
-            * deviceId: id of the device
-        Optional:
-            * ingressPort: port ingress device
-            * egressPort: port  of egress device
-            * ethType: specify ethType
-            * ethSrc: specify ethSrc ( i.e. src mac addr )
-            * ethDst: specify ethDst ( i.e. dst mac addr )
-            * ipProto: specify ip protocol
-            * ipSrc: specify ip source address with mask eg. ip#/24
-            * ipDst: specify ip destination address eg. ip#/24
-            * tcpSrc: specify tcp source port
-            * tcpDst: specify tcp destination port
+            * The flow in json
+            * the device id to add the flow to
         Returns:
             Returns main.TRUE for successful requests; Returns main.FALSE
             if error on requests;
@@ -1135,63 +1110,9 @@
             The ip and port option are for the requests input's ip and port
             of the ONOS node
         """
+
         try:
-            flowJson = { "priority":100,
-                           "isPermanent":"true",
-                           "timeout":0,
-                           "deviceId":deviceId,
-                           "treatment":{"instructions":[]},
-                           "selector": {"criteria":[]}}
-            if appId:
-                flowJson[ "appId" ] = appId
-            if egressPort:
-                flowJson[ 'treatment' ][ 'instructions' ].append(
-                                                       { "type":"OUTPUT",
-                                                         "port":egressPort } )
-            if ingressPort:
-                flowJson[ 'selector' ][ 'criteria' ].append(
-                                                       { "type":"IN_PORT",
-                                                         "port":ingressPort } )
-            if ethType == "IPV4":
-                flowJson[ 'selector' ][ 'criteria' ].append( {
-                                                         "type":"ETH_TYPE",
-                                                         "ethType":2048 } )
-            elif ethType:
-                flowJson[ 'selector' ][ 'criteria' ].append( {
-                                                         "type":"ETH_TYPE",
-                                                         "ethType":ethType } )
-            if ethSrc:
-                flowJson[ 'selector' ][ 'criteria' ].append(
-                                                       { "type":"ETH_SRC",
-                                                         "mac":ethSrc } )
-            if ethDst:
-                flowJson[ 'selector' ][ 'criteria' ].append(
-                                                       { "type":"ETH_DST",
-                                                         "mac":ethDst } )
-            if ipSrc:
-                flowJson[ 'selector' ][ 'criteria' ].append(
-                                                       { "type":"IPV4_SRC",
-                                                         "ip":ipSrc } )
-            if ipDst:
-                flowJson[ 'selector' ][ 'criteria' ].append(
-                                                       { "type":"IPV4_DST",
-                                                         "ip":ipDst } )
-            if tcpSrc:
-                flowJson[ 'selector' ][ 'criteria' ].append(
-                                                       { "type":"TCP_SRC",
-                                                         "tcpPort": tcpSrc } )
-            if tcpDst:
-                flowJson[ 'selector' ][ 'criteria' ].append(
-                                                       { "type":"TCP_DST",
-                                                         "tcpPort": tcpDst } )
-            if ipProto:
-                flowJson[ 'selector' ][ 'criteria' ].append(
-                                                       { "type":"IP_PROTO",
-                                                         "protocol": ipProto } )
-            if bandwidth or lambdaAlloc:
-                # TODO: Bandwidth and Lambda will be implemented if needed
-                raise NotImplementedError
-            main.log.debug( "Adding flow: " + self.pprint( flowJson ) )
+            if debug: main.log.debug( "Adding flow: " + self.pprint( flowJson ) )
             output = None
             if ip == "DEFAULT":
                 main.log.warn( "No ip given, reverting to ip from topo file" )
@@ -1225,6 +1146,113 @@
             main.cleanup()
             main.exit()
 
+    def addFlow( self,
+                 deviceId,
+                 appId=0,
+                 ingressPort="",
+                 egressPort="",
+                 ethType="",
+                 ethSrc="",
+                 ethDst="",
+                 vlan="",
+                 ipProto="",
+                 ipSrc=(),
+                 ipDst=(),
+                 tcpSrc="",
+                 tcpDst="",
+                 ip="DEFAULT",
+                 port="DEFAULT",
+                 debug=False ):
+        """
+        Description:
+            Creates a single flow in the specified device
+        Required:
+            * deviceId: id of the device
+        Optional:
+            * ingressPort: port ingress device
+            * egressPort: port  of egress device
+            * ethType: specify ethType
+            * ethSrc: specify ethSrc ( i.e. src mac addr )
+            * ethDst: specify ethDst ( i.e. dst mac addr )
+            * ipProto: specify ip protocol
+            * ipSrc: specify ip source address with mask eg. ip#/24
+                as a tuple (type, ip#)
+            * ipDst: specify ip destination address eg. ip#/24
+                as a tuple (type, ip#)
+            * tcpSrc: specify tcp source port
+            * tcpDst: specify tcp destination port
+        Returns:
+            Returns main.TRUE for successful requests; Returns main.FALSE
+            if error on requests;
+            Returns None for exceptions
+        NOTE:
+            The ip and port option are for the requests input's ip and port
+            of the ONOS node
+        """
+        try:
+            flowJson = { "priority":100,
+                           "isPermanent":"true",
+                           "timeout":0,
+                           "deviceId":deviceId,
+                           "treatment":{"instructions":[]},
+                           "selector": {"criteria":[]}}
+            if appId:
+                flowJson[ "appId" ] = appId
+            if egressPort:
+                flowJson[ 'treatment' ][ 'instructions' ].append( {
+                                                        "type":"OUTPUT",
+                                                        "port":egressPort } )
+            if ingressPort:
+                flowJson[ 'selector' ][ 'criteria' ].append( {
+                                                        "type":"IN_PORT",
+                                                        "port":ingressPort } )
+            if ethType:
+                flowJson[ 'selector' ][ 'criteria' ].append( {
+                                                        "type":"ETH_TYPE",
+                                                        "ethType":ethType } )
+            if ethSrc:
+                flowJson[ 'selector' ][ 'criteria' ].append( {
+                                                        "type":"ETH_SRC",
+                                                        "mac":ethSrc } )
+            if ethDst:
+                flowJson[ 'selector' ][ 'criteria' ].append( {
+                                                        "type":"ETH_DST",
+                                                        "mac":ethDst } )
+            if vlan:
+                flowJson[ 'selector' ][ 'criteria' ].append( {
+                                                        "type":"VLAN_VID",
+                                                        "vlanId":vlan } )
+            if ipSrc:
+                flowJson[ 'selector' ][ 'criteria' ].append( {
+                                                        "type":ipSrc[0],
+                                                        "ip":ipSrc[1] } )
+            if ipDst:
+                flowJson[ 'selector' ][ 'criteria' ].append( {
+                                                        "type":ipDst[0],
+                                                        "ip":ipDst[1] } )
+            if tcpSrc:
+                flowJson[ 'selector' ][ 'criteria' ].append( {
+                                                        "type":"TCP_SRC",
+                                                        "tcpPort": tcpSrc } )
+            if tcpDst:
+                flowJson[ 'selector' ][ 'criteria' ].append( {
+                                                        "type":"TCP_DST",
+                                                        "tcpPort": tcpDst } )
+            if ipProto:
+                flowJson[ 'selector' ][ 'criteria' ].append( {
+                                                        "type":"IP_PROTO",
+                                                        "protocol": ipProto } )
+
+            return self.sendFlow( deviceId=deviceId, flowJson=flowJson, debug=debug )
+
+        except ( AttributeError, TypeError ):
+            main.log.exception( self.name + ": Object not as expected" )
+            return None
+        except Exception:
+            main.log.exception( self.name + ": Uncaught exception!" )
+            main.cleanup()
+            main.exit()
+
     def removeFlow( self, deviceId, flowId,
                        ip="DEFAULT", port="DEFAULT" ):
         """
diff --git a/TestON/drivers/common/cli/emulator/mininetclidriver.py b/TestON/drivers/common/cli/emulator/mininetclidriver.py
index f20589e..ff14fbe 100644
--- a/TestON/drivers/common/cli/emulator/mininetclidriver.py
+++ b/TestON/drivers/common/cli/emulator/mininetclidriver.py
@@ -3124,7 +3124,7 @@
             main.cleanup()
             main.exit()
 
-    def sendPacket( self, packet=None, timeout=1 ):
+    def sendPacket( self, iface=None, packet=None, timeout=1 ):
         """
         Send a packet with either the given scapy packet command, or use the
         packet saved in the variable 'packet'.
@@ -3147,6 +3147,9 @@
                 sendCmd += packet
             else:
                 sendCmd += "packet"
+            if iface:
+                sendCmd += ", iface='{}'".format( iface )
+
             sendCmd += ', timeout=' + str( timeout ) + ')'
             self.handle.sendline( sendCmd )
             self.handle.expect( self.scapyPrompt )
diff --git a/TestON/tests/FUNCflow/Dependency/topo-flow.py b/TestON/tests/FUNCflow/Dependency/topo-flow.py
index 2299d9e..f9d58c1 100755
--- a/TestON/tests/FUNCflow/Dependency/topo-flow.py
+++ b/TestON/tests/FUNCflow/Dependency/topo-flow.py
@@ -14,24 +14,47 @@
 from mininet.util import dumpNodeConnections
 from mininet.node import ( UserSwitch, OVSSwitch, IVSSwitch )
 
+class VLANHost( Host ):
+    def config( self, vlan=100, **params ):
+        r = super( Host, self ).config( **params )
+        intf = self.defaultIntf()
+        self.cmd( 'ifconfig %s inet 0' % intf )
+        self.cmd( 'vconfig add %s %d' % ( intf, vlan ) )
+        self.cmd( 'ifconfig %s.%d inet %s' % ( intf, vlan, params['ip'] ) )
+        newName = '%s.%d' % ( intf, vlan )
+        intf.name = newName
+        self.nameToIntf[ newName ] = intf
+        return r
+
+class IPv6Host( Host ):
+    def config( self, v6Addr='1000:1/64', **params ):
+        r = super( Host, self ).config( **params )
+        intf = self.defaultIntf()
+        self.cmd( 'ifconfig %s inet 0' % intf )
+        self.cmd( 'ip -6 addr add %s dev %s' % ( v6Addr, intf ) )
+        return r
+
 class MyTopo( Topo ):
 
-    def __init__( self ):
+    def __init__( self, **opts ):
         # Initialize topology
-        Topo.__init__( self )
-        # Switch S5 Hosts
-        host1=self.addHost( 'h1', ip='10.1.0.1/24' )
-        host2=self.addHost( 'h2', ip='10.1.0.2/24' )
-        #host3=self.addHost( 'h3', ip='10.1.0.3/24', v6Addr='1000::3/64' )
-        #host4=self.addHost( 'h4', ip='10.1.0.4/24', v6Addr='1000::4/64' )
+        Topo.__init__( self, **opts)
+
+        # IPv4 hosts
+        host1=self.addHost( 'h1', ip='10.0.0.1/24' )
+        host2=self.addHost( 'h2', ip='10.0.0.2/24' )
+
+        # VLAN hosts
+        host3=self.addHost( 'h3', ip='10.0.0.3/24', cls=VLANHost, vlan=10 )
+        host4=self.addHost( 'h4', ip='10.0.0.4/24', cls=VLANHost, vlan=10 )
+
 
         s1 = self.addSwitch( 's1' )
-        #s2 = self.addSwitch( 's2' )
 
         self.addLink(s1, host1)
         self.addLink(s1, host2)
-        #self.addLink(s1, host3)
-        #self.addLink(s1, host4)
+        self.addLink(s1, host3)
+        self.addLink(s1, host4)
 
 
         topos = { 'mytopo': ( lambda: MyTopo() ) }
@@ -39,7 +62,7 @@
 def setupNetwork():
     "Create network"
     topo = MyTopo()
-    network = Mininet(topo=topo, autoSetMacs=True, controller=None)
+    network = Mininet(topo=topo, autoSetMacs=True, autoStaticArp=True, controller=None)
     network.start()
     CLI( network )
     network.stop()
diff --git a/TestON/tests/FUNCflow/FUNCflow.params b/TestON/tests/FUNCflow/FUNCflow.params
index 0aa8e89..7353e69 100755
--- a/TestON/tests/FUNCflow/FUNCflow.params
+++ b/TestON/tests/FUNCflow/FUNCflow.params
@@ -1,16 +1,19 @@
 
 <PARAMS>
     # CASE - Descritpion
+    # 1,2,10,1000,1100,2000,1200,2000,100
     # 1 - Variable initialization and optional pull and build ONOS package
     # 2 - install ONOS
     # 8 - Compare topology
     # 9 - Report logs
-    # 10 - Start mininet and assign switches to controller
+    # 10 - Start mininet and verify topology
     # 66 - Testing Scapy
-    # 1000 - Add flows
-    # 2000 - Verify flows are in the ADDED state
-    # 3000 - Delete flows
-    <testcases>1,2,10,11,1000,2000,[66]*3,3000</testcases>
+    # 1000 - Add flows with MAC selectors
+    # 1100 - Add flows with IPv4 selectors
+    # 1200 - Add flows with vlan selector
+    # 2000 - Delete flows
+
+    <testcases>1,2,10,1000,2,1100,2,1200,100</testcases>
 
     <SCALE>
         <max>1</max>
@@ -23,19 +26,6 @@
         <topology>topo-flow.py</topology>
     </DEPENDENCY>
 
-
-    <TOPO>
-        <numSwitches>1</numSwitches>
-        <numHosts>2</numHosts>
-        <numLinks>0</numLinks>
-    </TOPO>
-
-    <MININET>
-        <deviceId>of:0000000000000001</deviceId>
-        <hostMac1>00:00:00:00:00:01</hostMac1>
-        <hostMac2>00:00:00:00:00:02</hostMac2>
-    </MININET>
-
     <ENV>
         <cellName>productionCell</cellName>
         <cellApps>drivers,openflow</cellApps>
@@ -50,8 +40,19 @@
         <port>6653</port>
     </CTRL>
 
+    <TEST>
+        <vlan>10</vlan>
+        <ip4Type>2048</ip4Type>
+        <ip6Type>34525</ip6Type>
+        <vlanType>33024</vlanType>
+        <swDPID>of:0000000000000001</swDPID>
+    </TEST>
+
     <SLEEP>
         <startup>15</startup>
+        <startMN>5</startMN>
+        <addFlow>10</addFlow>
+        <delFlow>10</delFlow>
     </SLEEP>
 
 </PARAMS>
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 ):
         '''