Merge remote-tracking branch 'main/counters'
diff --git a/Detailed_Testing_Methodology.txt b/Detailed_Testing_Methodology.txt
index 7b3c0b2..eda3daa 100644
--- a/Detailed_Testing_Methodology.txt
+++ b/Detailed_Testing_Methodology.txt
@@ -1434,4 +1434,389 @@
 a) Send queue_stats request for port=egress_port and queue_ids=ofp.OFPQ_ALL
 B) send queue_stats request for egress_port and queue_id[0] (i.e first queue configured for egress_port)
 c) Verify reply has tx_errors count .
-d) Repear b , c for the all queue_ids of egress_port
\ No newline at end of file
+d) Repear b , c for the all queue_ids of egress_port
+
+
+
+
+
+****     Flow matches     ****
+
+
+
+1. All Wildcard Match
+
+Test Description: Adding a Flow that matches all the possible fields
+
+Test mode: Automated
+Test Tile: AllWildcardMatch
+POrts: 3 (1 Control Plane 2 Data Plane)
+Initial State: Default (Clear switch state), Connection setup
+Test-Field: Mandatory
+
+
+Test Notes:
+
+a) Insert a flow with wildcard = OFPFW_ALL (wildcard all fields), action output to egress_port
+b) Send packets with different header fields
+c) Verify all packets match the flow and implement the action specified.
+
+
+2. Single Header Field: Ingress Port
+
+Test Description: Match on Ingress Port and Wildcard rest 
+
+Test mode: Automated
+Test Tile: IngressPort
+POrts: 3 (1 Control Plane 2 Data Plane)
+Initial State: Default (Clear switch state), Connection setup
+Test-Field: Mandatory
+
+
+Test Notes: 
+
+a) Insert a flow with match = in_port (say port x), action output to egress_port
+b) Send packet on port x 
+c) Verify packet was recieved on egress_port
+d) Send packet on port y
+e) Verify PacketIn event was triggered on control plane
+
+
+
+3. Single Header Field: Ethernet Src Address
+
+Test Description: Match on Ethernet Source Address and Wildcard rest 
+
+Test mode: Automated
+Test Tile: EthernetSrcAddress
+POrts: 3 (1 Control Plane 2 Data Plane)
+Initial State: Default (Clear switch state), Connection setup
+Test-Field: Mandatory
+
+
+Test Notes: 
+
+a) Insert a flow with match = dl_src (say x) , action output to egress_port
+b) Send packet wth dl_src = x 
+c) Verify packet was recieved on egress_port
+d) Send packet with dl_src = y 
+e) Verify PacketIn event was triggered on the control plane
+
+
+
+4. Single Header Field: Ethernet Dst Address
+
+Test Description: Match on Ethernet Destination Address and Wildcard rest 
+
+Test mode: Automated
+Test Tile: EthernetDstAddress
+POrts: 3 (1 Control Plane 2 Data Plane)
+Initial State: Default (Clear switch state), Connection setup
+Test-Field: Mandatory
+
+
+Test Notes: 
+
+a) Insert a flow with match = dl_dst (say x) , action output to egress_port
+b) Send packet wth dl_dst = x  
+c) Verify packet was recieved on egress_port
+d) Send packet with dl_dst = y 
+e) Verify PacketIn event was triggered on the control plane
+
+
+
+5. Single Header Field: Ethernet Type 
+
+Test Description: Match on Ehternet Type and Wildcard rest 
+
+Test mode: Automated
+Test Tile: EthernetType
+POrts: 3 (1 Control Plane 2 Data Plane)
+Initial State: Default (Clear switch state), Connection setup
+Test-Field: Mandatory
+
+
+Test Notes: 
+
+a) Insert a flow with match = dl_type (say x) , action output to egress_port
+b) Send packet wth dl_type = x   
+c) Verify packet was recieved on egress_port
+d) Send packet with dl_type = y 
+e) Verify PacketIn event was triggered on the control plane
+
+
+
+
+6. Single Header Field: Vlan Id
+
+Test Description: Match on Ingress Port and Wildcard rest 
+
+Test mode: Automated
+Test Tile: VlanId
+POrts: 3 (1 Control Plane 2 Data Plane)
+Initial State: Default (Clear switch state), Connection setup
+Test-Field: Mandatory
+
+
+Test Notes: 
+
+a) Insert a flow with match = dl_vlan (say x) , action output to egress_port
+b) Send a tagged packet with (dl_vlan_enable=True,dl_vlan = x)  
+c) Verify packet was recieved on egress_port
+d) Send another tagged packet with (dl_vlan_enable=True,dl_vlan = y )
+e) Verify PacketIn event was triggered on the control plane
+
+
+
+
+7. Single Header Field: Vlan PCP
+
+Test Description: Match on Vlan ID Priority 
+
+Test mode: Automated
+Test Tile: VlanPcp
+POrts: 3 (1 Control Plane 2 Data Plane)
+Initial State: Default (Clear switch state), Connection setup
+Test-Field: Mandatory
+
+
+Test Notes: 
+
+a) Insert a flow with match = dl_vlan_pcp (say x) , action output to egress_port
+b) Send a tagged packet with (dl_vlan_enable=True, dl_vlan = * , dl_vlan_pcp = x)  
+c) Verify packet was recieved on egress_port
+b) Send a tagged packet with (dl_vlan_enable=True, dl_vlan = * , dl_vlan_pcp = y)  
+e) Verify PacketIn event was triggered on the control plane
+
+
+
+
+
+8. Single Header Field: IP Src Address -------- > (TBD)
+
+Test Description: Match on IP Src Address and Wildcard rest 
+
+Test mode: Automated
+Test Tile: IPSrcAddress
+POrts: 3 (1 Control Plane 2 Data Plane)
+Initial State: Default (Clear switch state), Connection setup
+Test-Field: Mandatory
+
+
+
+
+9. Single Header Field: IP Dst Address -----------> (TBD)
+
+Test Description: Match on IP Dst Address and Wildcard rest 
+
+Test mode: Automated
+Test Tile: IPDstAddress
+POrts: 3 (1 Control Plane 2 Data Plane)
+Initial State: Default (Clear switch state), Connection setup
+Test-Field: Mandatory
+
+
+
+
+
+10. Single Header Field: IP protocol---------------> (TBD)
+
+Test Description: Match on IP Protocol and Wildcard rest 
+
+Test mode: Automated
+Test Tile: IPprotocol
+POrts: 3 (1 Control Plane 2 Data Plane)
+Initial State: Default (Clear switch state), Connection setup
+Test-Field: Mandatory
+
+
+
+
+
+
+11. Single Header Field: IP Tos bits
+
+Test Description: Match on IP Tos bits and Wildcard rest 
+
+Test mode: Automated
+Test Tile: IpTos
+POrts: 3 (1 Control Plane 2 Data Plane)
+Initial State: Default (Clear switch state), Connection setup
+Test-Field: Mandatory
+
+
+Test Notes: 
+
+a) Insert a flow with match = nw_tos (say x) , action output to egress_port
+b) Send a tcp packet with (nw_tos=x)  
+c) Verify packet was recieved on egress_port
+b) Send a tcp packet with (nw_tos = y)
+e) Verify PacketIn event was triggered on the control plane
+
+
+
+12. Single Header Field: Transport Source Port
+
+Test Description: Match on Transport Src Port and Wildcard rest 
+
+Test mode: Automated
+Test Tile: TcpSrcPort
+POrts: 3 (1 Control Plane 2 Data Plane)
+Initial State: Default (Clear switch state), Connection setup
+Test-Field: Mandatory
+
+
+Test Notes: 
+
+a) Insert a flow with match = tp_src (say x) , action output to egress_port
+b) Send a tcp packet with (tp_src=x)  
+c) Verify packet was recieved on egress_port
+b) Send a tcp packet with tp_src= y)
+e) Verify PacketIn event was triggered on the control plane
+
+
+
+13. Single Header Field: Transport Destination Port
+
+Test Description: Match on Transport Dst Port and Wildcard rest 
+
+Test mode: Automated
+Test Tile: TcpDstPort
+POrts: 3 (1 Control Plane 2 Data Plane)
+Initial State: Default (Clear switch state), Connection setup
+Test-Field: Mandatory
+
+
+Test Notes: 
+
+a) Insert a flow with match = tp_dst (say x) , action output to egress_port
+b) Send a tcp packet with (tp_dst=x)  
+c) Verify packet was recieved on egress_port
+b) Send a tcp packet with tp_dst = y)
+e) Verify PacketIn event was triggered on the control plane
+
+
+
+
+14. Multiple Header Fields: L2
+
+
+Test Description: Match on Ethernet Type, Ethernet Source Address, Ethernet Destination Address and Wildcard rest 
+
+Test mode: Automated
+Test Tile: MultipleHeaderFieldL2
+POrts: 3 (1 Control Plane 2 Data Plane)
+Initial State: Default (Clear switch state), Connection setup
+Test-Field: Mandatory
+
+
+Test Notes: 
+
+a) Insert a flow with match = dl_type (say x), dl_src (say y ), dl_dst (say z), action output to egress_port
+b) Send a eth packet with dl_type (say x), dl_src (say y ), dl_dst (say z)
+c) Verify packet was recieved on egress_port
+b) Send a eth packet with dl_type (say w), dl_src (say v ), dl_dst (say f)
+e) Verify PacketIn event was triggered on the control plane
+
+
+
+15. Multiple Header Fields: L3 ------> TBD
+
+
+
+
+16. Multiple Header Fields: L4
+
+Test Description: Match on Tcp Source Port, Tcp Destination Port
+
+Test mode: Automated
+Test Tile: MultipleHeaderFieldL4
+POrts: 3 (1 Control Plane 2 Data Plane)
+Initial State: Default (Clear switch state), Connection setup
+Test-Field: Mandatory
+
+
+Test Notes: 
+
+a) Insert a flow with match = tp_src (say x), tp_dst (say y )
+b) Send a tcp packet with tp_src (say x), tp_dst (say y )	
+c) Verify packet was recieved on egress_port
+b) Send a eth packet with tcp_src (say w), tcp_dst (say v )
+e) Verify PacketIn event was triggered on the control plane
+
+
+
+17. All Header Fields: Exact Match flows
+
+Test Description: Verify exact flow matches are possible 
+
+Test mode: Automated
+Test Tile: ExactMatch
+POrts: 3 (1 Control Plane 2 Data Plane)
+Initial State: Default (Clear switch state), Connection setup
+Test-Field: Mandatory
+
+
+Test Notes: 
+
+a) Insert a flow with exact match, action output to egress_port
+b) Send packet matching the flow  
+c) Verify packet received on egress_port
+d) Send a non-matching packet
+e) Verify PacketIn event gets triggered
+
+
+
+18. Exact Match Highest Priority
+
+Test Description: An exact match flow entry has a highest priority compared to other flow entries 
+
+Test mode: Automated
+Test Tile: ExactMatchHigh
+POrts: 4 (1 Control Plane 3 Data Plane)
+Initial State: Default (Clear switch state), Connection setup
+Test-Field: Mandatory
+
+
+Test Notes: 
+
+a) Insert two overlapping flows:
+	Exact Match (prio = p )   action egress_port
+	Wildacrd All (prio = p+ ) action egress_port2
+b) Send packet matching the flows
+c) Verify packet received on egress_port 
+
+
+
+
+19. Wildcard Match Highest Priority
+
+Test Description: If Wildcard flow entries have priority associated with them.
+		  Higher priority Wildcard flow overrides the lower priroty Wildcard flow  
+
+Test mode: Automated
+Test Tile: WildcardMatchHigh
+POrts: 4 (1 Control Plane 3 Data Plane)
+Initial State: Default (Clear switch state), Connection setup
+Test-Field: Mandatory
+
+
+Test Notes: 
+
+a) Insert two wildcarded flows :
+	Wildcard All Except ingress (prio = p ) , action = egress_port
+	Wildcard All (prio = p+ ) ,action = egress_port2
+b) Send packet matching the flows  
+c) Verify packet is recieved on egress_port2
+
+
+
+20. Fragment TCP Segments ------> TBD 
+
+Test Description: Create flow matching on tcp port number. Verify that fragmented packets always match that flow rule.
+
+Test mode: Automated
+Test Tile: FragTcpSeg
+POrts: 3 (1 Control Plane 2 Data Plane)
+Initial State: Default (Clear switch state), Connection setup
+Test-Field: Mandatory
diff --git a/tests/FuncUtils.py b/tests/FuncUtils.py
index 61f285c..0ef9dc1 100644
--- a/tests/FuncUtils.py
+++ b/tests/FuncUtils.py
@@ -220,6 +220,43 @@
 
         return (Pkt_MatchIngress,match3)
 
+def Wildcard_All_Except_Ingress1(self,of_ports,priority=0):
+# Generate Wildcard_All_Except_Ingress_port flow with action output to port egress_port 2 
+        
+
+        #Create a simple tcp packet and generate wildcard all except ingress_port flow.
+        Pkt_MatchIngress = simple_tcp_packet()
+        match3 = parse.packet_to_flow_match(Pkt_MatchIngress)
+        self.assertTrue(match3 is not None, "Could not generate flow match from pkt")
+        match3.wildcards = ofp.OFPFW_ALL-ofp.OFPFW_IN_PORT
+        match3.in_port = of_ports[0]
+
+        msg3 = message.flow_mod()
+        msg3.command = ofp.OFPFC_ADD
+        msg3.match = match3
+        msg3.out_port = of_ports[2] # ignored by flow add,flow modify 
+        msg3.cookie = random.randint(0,9007199254740992)
+        msg3.buffer_id = 0xffffffff
+        msg3.idle_timeout = 0
+        msg3.hard_timeout = 0
+        msg3.buffer_id = 0xffffffff
+       
+        act3 = action.action_output()
+        act3.port = of_ports[2]
+        self.assertTrue(msg3.actions.add(act3), "could not add action")
+
+        if priority != 0 :
+                msg3.priority = priority
+
+        rv = self.controller.message_send(msg3)
+        self.assertTrue(rv != -1, "Error installing flow mod")
+        self.assertEqual(do_barrier(self.controller), 0, "Barrier failed")
+
+        return (Pkt_MatchIngress,match3)
+
+
+
+
 def Match_Vlan_Id(self,of_ports,priority=0):
     #Generate Match_Vlan_Id
 
diff --git a/tests/flow_matches.py b/tests/flow_matches.py
new file mode 100644
index 0000000..891bb33
--- /dev/null
+++ b/tests/flow_matches.py
@@ -0,0 +1,633 @@
+"""These tests fall under Conformance Test-Suite (OF-SWITCH-1.0.0 TestCases).
+    Refer Documentation -- Detailed testing methodology 
+    <Some of test-cases are directly taken from oftest> """
+
+"Test Suite 6 --> Flow Matches"
+
+
+import logging
+
+import unittest
+import random
+
+import oftest.controller as controller
+import oftest.cstruct as ofp
+import oftest.message as message
+import oftest.dataplane as dataplane
+import oftest.action as action
+import oftest.parse as parse
+import oftest.base_tests as base_tests
+import time
+
+from oftest.testutils import *
+from time import sleep
+from FuncUtils import *
+
+    
+
+class AllWildcardMatch(base_tests.SimpleDataPlane):
+
+    """Verify for an all wildcarded flow all the injected packets would match that flow"""
+
+    def runTest(self):
+        
+        logging.info("Running All Wildcard Match test")
+
+        of_ports = config["port_map"].keys()
+        of_ports.sort()
+        self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
+
+        #Clear Switch State
+        rc = delete_all_flows(self.controller)
+        self.assertEqual(rc, 0, "Failed to delete all flows")
+
+        logging.info("Inserting an all wildcarded flow and sending packets with various match fields")
+        logging.info("Expecting all sent packets to match")
+
+        #Insert an All Wildcarded flow.
+        Wildcard_All(self,of_ports)
+
+        #check for different  match fields and verify packet implements the action specified in the flow
+        pkt1 = simple_tcp_packet(dl_src="00:01:01:01:01:01");
+        self.dataplane.send(of_ports[0], str(pkt1))
+        egress_port=of_ports[1]
+        no_ports=set(of_ports).difference([egress_port])
+        yes_ports = of_ports[1]
+        receive_pkt_check(self.dataplane,pkt1,[yes_ports],no_ports,self)
+
+        pkt2 = simple_tcp_packet(dl_dst="00:01:01:01:01:01");    
+        self.dataplane.send(of_ports[0], str(pkt2))
+        egress_port=of_ports[1]
+        no_ports=set(of_ports).difference([egress_port])
+        yes_ports = of_ports[1]
+        receive_pkt_check(self.dataplane,pkt2,[yes_ports],no_ports,self)
+        
+        pkt3 = simple_tcp_packet(ip_src="192.168.2.1");
+        self.dataplane.send(of_ports[0], str(pkt3))
+        egress_port=of_ports[1]
+        no_ports=set(of_ports).difference([egress_port])
+        yes_ports = of_ports[1]
+        receive_pkt_check(self.dataplane,pkt3,[yes_ports],no_ports,self)
+
+        pkt4 = simple_tcp_packet(ip_dst="192.168.2.2");
+        self.dataplane.send(of_ports[0], str(pkt4))
+        egress_port=of_ports[1]
+        no_ports=set(of_ports).difference([egress_port])
+        yes_ports = of_ports[1]
+        receive_pkt_check(self.dataplane,pkt4,[yes_ports],no_ports,self)
+
+        pkt5 = simple_tcp_packet(ip_tos=2);
+        self.dataplane.send(of_ports[0], str(pkt5))
+        egress_port=of_ports[1]
+        no_ports=set(of_ports).difference([egress_port])
+        yes_ports = of_ports[1]
+        receive_pkt_check(self.dataplane,pkt5,[yes_ports],no_ports,self)
+
+        pkt6 = simple_tcp_packet(tcp_sport=8080);
+        self.dataplane.send(of_ports[0], str(pkt6))
+        egress_port=of_ports[1]
+        no_ports=set(of_ports).difference([egress_port])
+        yes_ports = of_ports[1]
+        receive_pkt_check(self.dataplane,pkt6,[yes_ports],no_ports,self)
+                  
+        pkt7 = simple_tcp_packet(tcp_dport=8081);
+        self.dataplane.send(of_ports[0], str(pkt7))
+        egress_port=of_ports[1]
+        no_ports=set(of_ports).difference([egress_port])
+        yes_ports = of_ports[1]
+        receive_pkt_check(self.dataplane,pkt7,[yes_ports],no_ports,self)
+
+
+
+class EthernetSrcAddress(base_tests.SimpleDataPlane):
+    
+    """Verify match on single header field -- Ethernet Src Address """
+    
+    def runTest(self):
+
+        logging.info("Running Ethernet Src Address test")
+
+        of_ports = config["port_map"].keys()
+        of_ports.sort()
+        self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
+    
+        #Clear Switch State
+        rc = delete_all_flows(self.controller)
+        self.assertEqual(rc, 0, "Failed to delete all flows")
+
+        logging.info("Inserting a flow with match on Ethernet Source Address ")
+        logging.info("Sending matching and non-matching packets")
+        logging.info("Verifying matching packets implements the action specified in the flow")
+
+        #Insert a Match On Ethernet Src Address flow
+        (pkt,match) = Match_Ethernet_Src_Address(self,of_ports)   
+
+        #Sending packet matching the flow, verify it implements the action
+        self.dataplane.send(of_ports[0], str(pkt))
+
+        #Verify packet implements the action specified in the flow
+        egress_port=of_ports[1]
+        no_ports=set(of_ports).difference([egress_port])
+        yes_ports = of_ports[1]
+        receive_pkt_check(self.dataplane,pkt,[yes_ports],no_ports,self)
+
+        #Sending non matching packet , verify Packetin event gets triggered.
+        pkt2 = simple_tcp_packet(dl_src='00:01:01:01:01:02');
+        self.dataplane.send(of_ports[0], str(pkt2))
+        
+        (response, raw) = self.controller.poll(ofp.OFPT_PACKET_IN,timeout=4)
+        self.assertTrue(response is not None, "PacketIn not received")
+
+class EthernetDstAddress(base_tests.SimpleDataPlane):
+    
+    """Verify match on single Header Field Field -- Ethernet Dst Address """
+
+    def runTest(self):
+
+        logging.info("Running Ethernet Dst Address test")
+
+        of_ports = config["port_map"].keys()
+        of_ports.sort()
+        self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
+        
+        #Clear Switch State
+        rv = delete_all_flows(self.controller)
+        self.assertEqual(rv, 0, "Failed to delete all flows")
+
+        logging.info("Inserting a flow with match on Ethernet Destination Address ")
+        logging.info("Sending matching and non-matching packets")
+        logging.info("Verifying matching packets implements the action specified in the flow")
+        
+        #Insert a Match on Destination Address flow   
+        (pkt,match) = Match_Ethernet_Dst_Address(self,of_ports)
+        
+        #Send Packet matching the flow 
+        self.dataplane.send(of_ports[0], str(pkt))
+
+        #Verify packet implements the action specified in the flow
+        egress_port=of_ports[1]
+        no_ports=set(of_ports).difference([egress_port])
+        yes_ports = of_ports[1]
+        receive_pkt_check(self.dataplane,pkt,[yes_ports],no_ports,self)
+        
+        #Send Non-matching packet
+        pkt2 = simple_tcp_packet(dl_dst='00:01:01:01:01:02');
+        self.dataplane.send(of_ports[0], str(pkt2))
+        
+        #Verify PacketIn event gets triggered
+        (response, raw) = self.controller.poll(ofp.OFPT_PACKET_IN,timeout=4)
+        self.assertTrue(response is not None, "PacketIn not received")
+
+
+class EthernetType(base_tests.SimpleDataPlane):
+    
+    """Verify match on single header field -- Ethernet Type """
+    
+    def runTest(self):
+
+        logging.info("Running Ethernet Type test")
+
+        of_ports = config["port_map"].keys()
+        of_ports.sort()
+        self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
+    
+        #Clear Switch State
+        rc = delete_all_flows(self.controller)
+        self.assertEqual(rc, 0, "Failed to delete all flows")
+
+        logging.info("Inserting a flow with match on Ethernet Type ")
+        logging.info("Sending matching and non-matching packets")
+        logging.info("Verifying matching packets implements the action specified in the flow")
+
+        #Insert a Match on Ethernet Type flow
+        (pkt,match) = Match_Ethernet_Type(self,of_ports)   
+
+        #Sending packet matching the flow 
+        self.dataplane.send(of_ports[0], str(pkt))
+
+        #Verify packet implements the action specified in the flow
+        egress_port=of_ports[1]
+        no_ports=set(of_ports).difference([egress_port])
+        yes_ports = of_ports[1]
+        receive_pkt_check(self.dataplane,pkt,[yes_ports],no_ports,self)
+
+        #Sending non matching packet , 
+        pkt2 = simple_eth_packet(dl_type=0x0806);
+        self.dataplane.send(of_ports[0], str(pkt2))
+        
+        #verify Packetin event gets triggered.
+        (response, raw) = self.controller.poll(ofp.OFPT_PACKET_IN,timeout=4)
+        self.assertTrue(response is not None, "PacketIn not received")
+
+            
+class IngressPort(base_tests.SimpleDataPlane):
+    
+    """Verify match on single Header Field Field -- In_port """
+
+    def runTest(self):
+
+        logging.info("Running Ingress Port test")
+
+        of_ports = config["port_map"].keys()
+        of_ports.sort()
+        self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
+
+        #Clear Switch State
+        rc = delete_all_flows(self.controller)
+        self.assertEqual(rc, 0, "Failed to delete all flows")
+
+        logging.info("Inserting a flow with match on Ingress Port ")
+        logging.info("Sending matching and non-matching packets")
+        logging.info("Verifying matching packets implements the action specified in the flow")
+        
+        #Insert a Match on Ingress Port FLow
+        (pkt,match) = Wildcard_All_Except_Ingress(self,of_ports,priority=0)
+        
+        #Send Packet matching the flow i.e on in_port specified in the flow
+        self.dataplane.send(of_ports[0], str(pkt))
+
+        #Verify packet implements the action specified in the flow
+        egress_port=of_ports[1]
+        no_ports=set(of_ports).difference([egress_port])
+        yes_ports = of_ports[1]
+        receive_pkt_check(self.dataplane,pkt,[yes_ports],no_ports,self)
+
+        #Send Non-Matching Packet 
+        self.dataplane.send(of_ports[1],str(pkt))
+
+        #Verify PacketIn event gets triggered
+        (response, raw) = self.controller.poll(ofp.OFPT_PACKET_IN,timeout=4)
+        self.assertTrue(response is not None, "PacketIn not received")
+
+class VlanId(base_tests.SimpleDataPlane):
+
+    """Verify match on single Header Field Field -- Vlan Id """
+
+    def runTest(self):
+
+        of_ports = config["port_map"].keys()
+        of_ports.sort()
+        self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
+
+        #Clear Switch State
+        rc = delete_all_flows(self.controller)
+        self.assertEqual(rc, 0, "Failed to delete all flows")
+
+        logging.info("Inserting a flow with match on VLAN ID ")
+        logging.info("Sending matching and non-matching packets")
+        logging.info("Verifying matching packets implements the action specified in the flow")
+    
+        #Create a flow with match on Vlan Id
+        (pkt,match) = Match_Vlan_Id(self,of_ports)
+
+        #Send tagged packet matching the flow i.e packet with same vlan id as in flow
+        self.dataplane.send(of_ports[0], str(pkt))
+
+        #Verify packet implements the action specified in the flow
+        egress_port=of_ports[1]
+        no_ports=set(of_ports).difference([egress_port])
+        yes_ports = of_ports[1]
+        receive_pkt_check(self.dataplane,pkt,[yes_ports],no_ports,self)
+        
+        #Send Non-matching packet, i.e packet with different Vlan Id
+        pkt2 = simple_tcp_packet(dl_vlan_enable=True,dl_vlan=4);
+        self.dataplane.send(of_ports[0], str(pkt2))
+        
+        #Verify PacketIn event gets triggered
+        (response, raw) = self.controller.poll(ofp.OFPT_PACKET_IN,timeout=4)
+        self.assertTrue(response is not None, "PacketIn not received")
+
+class VlanPCP(base_tests.SimpleDataPlane):
+
+    """"Verify match on single Header Field Field -- Vlan Priority"""
+
+    def runTest(self):
+
+        logging.info("Running VlanPCP1 test")
+
+        of_ports = config["port_map"].keys()
+        of_ports.sort()
+        self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
+    
+        #Clear Switch State
+        rv = delete_all_flows(self.controller)
+        self.assertEqual(rv, 0, "Failed to delete all flows")
+        
+        logging.info("Inserting a flow with match on VLAN Priority ")
+        logging.info("Sending matching and non-matching packets")
+        logging.info("Verifying matching packets implements the action specified in the flow")
+
+        #Create a flow matching on VLAN Priority
+        (pkt,match) = Match_Vlan_Pcp(self,of_ports)
+
+        #Send tagged Packet matching the flow 
+        self.dataplane.send(of_ports[0], str(pkt))
+
+        #Verify packet implements the action specified in the flow
+        egress_port=of_ports[1]
+        no_ports=set(of_ports).difference([egress_port])
+        yes_ports = of_ports[1]
+        receive_pkt_check(self.dataplane,pkt,[yes_ports],no_ports,self)
+        
+        #Send tagged packet with same vlan_id but different vlan priority
+        pkt2 = simple_tcp_packet(dl_vlan_enable=True,dl_vlan=1,dl_vlan_pcp=20);
+        self.dataplane.send(in_port, str(pkt))
+       
+class MultipleHeaderFieldL2(base_tests.SimpleDataPlane):
+    
+    """Verify match on multiple header field -- Ethernet Type, Ethernet Source Address, Ethernet Destination Address """
+    
+    def runTest(self):
+
+        logging.info("Running Multiple Header Field L2 test")
+
+        of_ports = config["port_map"].keys()
+        of_ports.sort()
+        self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
+    
+        #Clear Switch State
+        rc = delete_all_flows(self.controller)
+        self.assertEqual(rc, 0, "Failed to delete all flows")
+
+        logging.info("Inserting a flow with match on Multiple Header Field L2 ")
+        logging.info("Sending matching and non-matching packets")
+        logging.info("Verifying matching packets implements the action specified in the flow")
+
+        (pkt,match) = Match_Mul_L2(self,of_ports)   
+
+        #Send eth packet matching the dl_type field, verify it implements the action
+        self.dataplane.send(of_ports[0], str(pkt))
+
+        #Verify packet implements the action specified in the flow
+        egress_port=of_ports[1]
+        no_ports=set(of_ports).difference([egress_port])
+        yes_ports = of_ports[1]
+        receive_pkt_check(self.dataplane,pkt,[yes_ports],no_ports,self)
+
+        #Sending non matching packet , verify Packetin event gets triggered.
+        pkt2 = simple_eth_packet(dl_type=0x0806,dl_src='00:01:01:01:01:02',dl_dst='00:01:01:01:01:01');
+        self.dataplane.send(of_ports[0], str(pkt2))
+        
+        (response, raw) = self.controller.poll(ofp.OFPT_PACKET_IN,timeout=4)
+        self.assertTrue(response is not None, "PacketIn not received")
+
+class IpTos(base_tests.SimpleDataPlane):
+
+    """"Verify match on single Header Field Field -- Type of service"""
+
+    def runTest(self):
+
+        logging.info("Running Ip_Tos test")
+
+        of_ports = config["port_map"].keys()
+        of_ports.sort()
+        self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
+    
+        #Clear Switch State
+        rv = delete_all_flows(self.controller)
+        self.assertEqual(rv, 0, "Failed to delete all flows")
+        
+        logging.info("Inserting a flow with match on Ip_Tos ")
+        logging.info("Sending matching and non-matching packets")
+        logging.info("Verifying matching packets implements the action specified in the flow")
+
+        #Create a flow matching on VLAN Priority
+        (pkt,match) = Match_Ip_Tos(self,of_ports)
+
+        #Send Packet matching the flow 
+        self.dataplane.send(of_ports[0], str(pkt))
+
+        #Verify packet implements the action specified in the flow
+        egress_port=of_ports[1]
+        no_ports=set(of_ports).difference([egress_port])
+        yes_ports = of_ports[1]
+        receive_pkt_check(self.dataplane,pkt,[yes_ports],no_ports,self)
+        
+        #Create a non-matching packet , verify packet_in get generated
+        pkt2 = simple_tcp_packet(ip_tos=20);
+        self.dataplane.send(of_ports[0], str(pkt2))
+        (response, raw) = self.controller.poll(ofp.OFPT_PACKET_IN,timeout=4)
+        self.assertTrue(response is not None, "PacketIn not received")
+
+
+class TcpSourcePort(base_tests.SimpleDataPlane):
+    
+    """Verify match on Single header field -- Tcp Source Port,  """
+    
+    def runTest(self):
+
+        logging.info("Running Tcp Source Port test")
+
+        of_ports = config["port_map"].keys()
+        of_ports.sort()
+        self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
+    
+        #Clear Switch State
+        rc = delete_all_flows(self.controller)
+        self.assertEqual(rc, 0, "Failed to delete all flows")
+
+        logging.info("Inserting a flow with match on Tcp Tcp Source Port ")
+        logging.info("Sending matching and non-matching packets")
+        logging.info("Verifying matching packets implements the action specified in the flow")
+
+        (pkt,match) = Match_Tcp_Src(self,of_ports)   
+
+        #Sending packet matching the tcp_sport, verify it implements the action
+        self.dataplane.send(of_ports[0], str(pkt))
+
+        #Verify packet implements the action specified in the flow
+        egress_port=of_ports[1]
+        no_ports=set(of_ports).difference([egress_port])
+        yes_ports = of_ports[1]
+        receive_pkt_check(self.dataplane,pkt,[yes_ports],no_ports,self)
+
+        #Sending non matching packet , verify Packetin event gets triggered.
+        pkt2 = simple_tcp_packet(tcp_sport=540);
+        self.dataplane.send(of_ports[0], str(pkt2))
+        
+        (response, raw) = self.controller.poll(ofp.OFPT_PACKET_IN,timeout=4)
+        self.assertTrue(response is not None, "PacketIn not received")
+
+class TcpDstPort(base_tests.SimpleDataPlane):
+    
+    """Verify match on Single header field -- Tcp Destination Port """
+    
+    def runTest(self):
+
+        logging.info("Running Tcp Destination Port test")
+
+        of_ports = config["port_map"].keys()
+        of_ports.sort()
+        self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
+    
+        #Clear Switch State
+        rc = delete_all_flows(self.controller)
+        self.assertEqual(rc, 0, "Failed to delete all flows")
+
+        logging.info("Inserting a flow with match on Tcp Destination Port ")
+        logging.info("Sending matching and non-matching packets")
+        logging.info("Verifying matching packets implements the action specified in the flow")
+
+        (pkt,match) = Match_Tcp_Dst(self,of_ports)   
+
+        #Sending packet matching the tcp_dport, verify it implements the action
+        self.dataplane.send(of_ports[0], str(pkt))
+
+        #Verify packet implements the action specified in the flow
+        egress_port=of_ports[1]
+        no_ports=set(of_ports).difference([egress_port])
+        yes_ports = of_ports[1]
+        receive_pkt_check(self.dataplane,pkt,[yes_ports],no_ports,self)
+
+        #Sending non matching packet , verify Packetin event gets triggered.
+        pkt2 = simple_tcp_packet(tcp_dport=541);
+        self.dataplane.send(of_ports[0], str(pkt2))
+        
+        (response, raw) = self.controller.poll(ofp.OFPT_PACKET_IN,timeout=10)
+        self.assertTrue(response is not None, "PacketIn not received")
+
+
+class ExactMatch(base_tests.SimpleDataPlane):
+    
+    """Verify match on Single header field -- Exact Match  """
+    
+    def runTest(self):
+
+        logging.info("Running Tcp Exact Match test")
+
+        of_ports = config["port_map"].keys()
+        of_ports.sort()
+        self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
+    
+        #Clear Switch State
+        rc = delete_all_flows(self.controller)
+        self.assertEqual(rc, 0, "Failed to delete all flows")
+
+        logging.info("Inserting a flow with match for Exact Match ")
+        logging.info("Sending matching and non-matching packets")
+        logging.info("Verifying matching packets implements the action specified in the flow")
+
+        (pkt,match) = Exact_Match(self,of_ports)   
+
+        #Sending packet matching all the fields of a tcp_packet, verify it implements the action
+        self.dataplane.send(of_ports[0], str(pkt))
+
+        #Verify packet implements the action specified in the flow
+        egress_port=of_ports[1]
+        no_ports=set(of_ports).difference([egress_port])
+        yes_ports = of_ports[1]
+        receive_pkt_check(self.dataplane,pkt,[yes_ports],no_ports,self)
+
+        #Sending non matching packet , verify Packetin event gets triggered.
+        pkt2 = simple_tcp_packet(tcp_sport=540);
+        self.dataplane.send(of_ports[0], str(pkt2))
+        
+        (response, raw) = self.controller.poll(ofp.OFPT_PACKET_IN,timeout=4)
+        self.assertTrue(response is not None, "PacketIn not received")
+
+
+class MultipleHeaderFieldL4(base_tests.SimpleDataPlane):
+    
+    """Verify match on multiple header field -- Tcp Source Port, Tcp Destination Port  """
+    
+    def runTest(self):
+
+        logging.info("Running Multiple Header Field L4 test")
+
+        of_ports = config["port_map"].keys()
+        of_ports.sort()
+        self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
+    
+        #Clear Switch State
+        rc = delete_all_flows(self.controller)
+        self.assertEqual(rc, 0, "Failed to delete all flows")
+
+        logging.info("Inserting a flow with match on Multiple Header Field L4 ")
+        logging.info("Sending matching and non-matching packets")
+        logging.info("Verifying matching packets implements the action specified in the flow")
+
+        (pkt,match) = Match_Mul_L4(self,of_ports)   
+
+        #Sending packet matching the tcp_sport and tcp_dport field, verify it implements the action
+        self.dataplane.send(of_ports[0], str(pkt))
+
+        #Verify packet implements the action specified in the flow
+        egress_port=of_ports[1]
+        no_ports=set(of_ports).difference([egress_port])
+        yes_ports = of_ports[1]
+        receive_pkt_check(self.dataplane,pkt,[yes_ports],no_ports,self)
+
+        #Sending non matching packet , verify Packetin event gets triggered.
+        pkt2 = simple_tcp_packet(tcp_sport=540,tcp_dport=541);
+        self.dataplane.send(of_ports[0], str(pkt2))
+        
+        (response, raw) = self.controller.poll(ofp.OFPT_PACKET_IN,timeout=4)
+        self.assertTrue(response is not None, "PacketIn not received")
+
+
+
+class ExactMatchHigh(base_tests.SimpleDataPlane):
+    
+    """Verify that Exact Match has highest priority """
+    
+    def runTest(self):
+
+        logging.info("Running Exact Match High Priority test")
+
+        of_ports = config["port_map"].keys()
+        of_ports.sort()
+        self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
+    
+        #Clear Switch State
+        rc = delete_all_flows(self.controller)
+        self.assertEqual(rc, 0, "Failed to delete all flows")
+
+        logging.info("Inserting a flow with Exact Match (low priority)")
+        logging.info("Inserting a overlapping wildcarded flow (higher priority)")
+        logging.info("Sending packets matching both the flows ")
+        logging.info("Verifying matching packets implements the action specified in the exact match flow")
+
+        #Insert two Overlapping Flows : Exact Match and Wildcard All.
+        (pkt,match) = Exact_Match_With_Prio(self,of_ports,priority=10) 
+        (pkt2,match2) = Wildcard_All(self,of_ports,priority=20);  
+        
+        #Sending packet matching the both the flows , verify it implements the action specified in Exact Match Flow
+        self.dataplane.send(of_ports[0], str(pkt2))
+
+        #Verify packet implements the action specified in the flow
+        egress_port=of_ports[2]
+        no_ports=set(of_ports).difference([egress_port])
+        yes_ports = egress_port
+        receive_pkt_check(self.dataplane,pkt,[yes_ports],no_ports,self)
+
+
+class WildcardMatchHigh(base_tests.SimpleDataPlane):
+    
+    """Verify that Wildcard Match with highest priority overrides the low priority WildcardMatch """
+    
+    def runTest(self):
+
+        logging.info("Running Wildcard Match High Priority test")
+
+        of_ports = config["port_map"].keys()
+        of_ports.sort()
+        self.assertTrue(len(of_ports) > 1, "Not enough ports for test")
+    
+        #Clear Switch State
+        rc = delete_all_flows(self.controller)
+        self.assertEqual(rc, 0, "Failed to delete all flows")
+
+        logging.info("Inserting two wildcarded flows with priorities ")
+        logging.info("Sending packets matching the flows")
+        logging.info("Verifying matching packets implements the action specified in the flow with higher priority")
+
+        (pkt,match) = Wildcard_All(self,of_ports,priority=20) 
+        (pkt1,match1) =  Wildcard_All_Except_Ingress1(self,of_ports,priority=10)  
+
+        #Sending packet matching both the flows , verify it implements the action specified by Higher Priority flow
+        self.dataplane.send(of_ports[0], str(pkt1))
+
+        egress_port=of_ports[1]
+        no_ports=set(of_ports).difference([egress_port])
+        yes_ports = of_ports[1]
+        receive_pkt_check(self.dataplane,pkt,[yes_ports],no_ports,self)
\ No newline at end of file