Adding pseudo wire tests

Change-Id: If72e67e7bf1fa81b370c96696196fc575a453557
diff --git a/ofdpa/pw_flows.py b/ofdpa/pw_flows.py
index 42f8476..5713a94 100644
--- a/ofdpa/pw_flows.py
+++ b/ofdpa/pw_flows.py
@@ -199,6 +199,7 @@
                 verify_packet( self, pkt, out_port )
                 verify_no_packet( self, pkt, in_port )
                 verify_no_other_packets( self )
+
                 # Flush all the rules for the next couple
                 delete_all_flows( self.controller )
                 delete_groups( self.controller, Groups )
@@ -474,6 +475,7 @@
                 verify_packet( self, pkt, out_port )
                 verify_no_packet( self, pkt, in_port )
                 verify_no_other_packets( self )
+
                 delete_all_flows( self.controller )
                 delete_groups( self.controller, Groups )
                 delete_groups( self.controller, Groups2 )
@@ -567,6 +569,7 @@
                 verify_packet( self, pkt, out_port )
                 verify_no_packet( self, pkt, in_port )
                 verify_no_other_packets( self )
+
                 delete_all_flows( self.controller )
                 delete_groups( self.controller, Groups )
                 delete_groups( self.controller, Groups2 )
@@ -1156,6 +1159,7 @@
             delete_groups( self.controller, Groups2 )
             delete_all_groups( self.controller )
 
+
 class IntraCO_2_Labels( base_tests.SimpleDataPlane ):
     """
     This is meant to test the PW intermediate transport.
@@ -1463,13 +1467,16 @@
                 return
             ports = config[ "port_map" ].keys( )
             for pair in itertools.product(ports, ports):
+
                 # we generate all possible products
                 in_port     = pair[0]
                 out_port    = pair[1]
                 if out_port == in_port:
                     continue
+
                 # we fill the pipeline for the pw initiation
                 # on the reverse path
+
                 (
                     port_to_mpls_label_2,
                     port_to_mpls_label_1,
@@ -1488,7 +1495,7 @@
                     egress_tag=EGRESS_TAGGED,
                     mpls_labels=1
                     )
-                # we fill the pipeline for the pw termination
+		# we fill the pipeline for the pw termination
                 (
                     port_to_mpls_label_pw,
                     port_to_in_vlan_2,
@@ -1523,12 +1530,13 @@
                 verify_packet( self, pkt, out_port )
                 verify_no_packet( self, pkt, in_port )
                 verify_no_other_packets( self )
-                delete_all_flows( self.controller )
+
+		delete_all_flows( self.controller )
                 delete_groups( self.controller, Groups )
                 delete_groups( self.controller, Groups2 )
                 delete_all_groups( self.controller )
         finally:
-            delete_all_flows( self.controller )
+	    delete_all_flows( self.controller )
             delete_groups( self.controller, Groups )
             delete_groups( self.controller, Groups2 )
             delete_all_groups( self.controller )
@@ -1613,6 +1621,7 @@
                 verify_packet( self, pkt, out_port )
                 verify_no_packet( self, pkt, in_port )
                 verify_no_other_packets( self )
+
                 delete_all_flows( self.controller )
                 delete_groups( self.controller, Groups )
                 delete_groups( self.controller, Groups2 )
@@ -1717,6 +1726,323 @@
             delete_groups( self.controller, Groups2 )
             delete_all_groups( self.controller )
 
+class IntermediateTransport( base_tests.SimpleDataPlane ):
+    """
+    This test is meant to verify that the alternative approach for handling
+    pseudowires in spine switches. Specifically, in the mpls table we install
+    2 rules , the match(SR1, BoS=1) and match(SR2, BoS=0). The match(SR2, BoS=0)
+    should match and the packet should be forwarded through the port and the label
+    for SR2 should be removed.
+    """
+    def runTest( self ):
+        Groups = Queue.LifoQueue( )
+        try:
+            if len( config[ "port_map" ] ) < 1:
+                logging.info( "Port count less than 1, can't run this case" )
+                assert (False)
+                return
+            ports           = config[ "port_map" ].keys( )
+            in_port         = ports[0]
+            out_port        = ports[1]
+            out_vlan        = 4094
+            src_mac         = [ 0x00, 0x00, 0x00, 0x00, 0x11, 0x01 ]
+            src_mac_str     = ':'.join( [ '%02X' % x for x in src_mac ] )
+            dst_mac         = [ 0x00, 0x00, 0x00, 0x11, 0x11, 0x01 ]
+            dst_mac_str     = ':'.join( [ '%02X' % x for x in dst_mac ] )
+            mpls_label      = 100
+            mpls_label_SR1 = 100 + 5
+            mpls_label_SR2 = 100 + 10
+            mpls_label_PW = 100 + 15
+
+            # Add l2 interface group, we have to pop the VLAN;
+            l2_intf_gid, l2_intf_msg = add_one_l2_interface_group(
+                ctrl=self.controller,
+                port=out_port,
+                vlan_id=out_vlan,
+                is_tagged=False,
+                send_barrier=False
+                )
+            Groups._put( l2_intf_gid )
+
+            # add MPLS interface group
+            mpls_intf_gid, mpls_intf_msg = add_mpls_intf_group(
+                ctrl=self.controller,
+                ref_gid=l2_intf_gid,
+                dst_mac=dst_mac,
+                src_mac=src_mac,
+                vid=out_vlan,
+                index=in_port
+                )
+            Groups._put( mpls_intf_gid )
+
+            # Add L3 Unicast  group
+            l3_msg = add_l3_unicast_group(
+                ctrl=self.controller,
+                port=out_port,
+                vlanid=out_vlan,
+                id=in_port,
+                src_mac=src_mac,
+                dst_mac=dst_mac
+                )
+            Groups._put( l3_msg.group_id )
+
+            # Add L3 ecmp group
+            ecmp_msg = add_l3_ecmp_group(
+                ctrl=self.controller,
+                id=in_port,
+                l3_ucast_groups=[ l3_msg.group_id ]
+                )
+            Groups._put( ecmp_msg.group_id )
+
+            # Add MPLS flow with BoS=1
+            add_mpls_flow(
+                ctrl=self.controller,
+                action_group_id=ecmp_msg.group_id,
+                label=mpls_label_SR1
+                )
+
+            # add MPLS flow with BoS=0
+            add_mpls_flow_pw(
+                ctrl=self.controller,
+                action_group_id=mpls_intf_gid,
+                label=mpls_label_SR2,
+                ethertype=0x8847,
+                tunnel_index=1,
+                bos=0
+                )
+
+            # add Termination flow
+            add_termination_flow(
+                ctrl=self.controller,
+                in_port=in_port,
+                eth_type=0x8847,
+                dst_mac=src_mac,
+                vlanid=out_vlan,
+                goto_table=23
+                )
+            # add VLAN flows
+            add_one_vlan_table_flow(
+                ctrl=self.controller,
+                of_port=in_port,
+                vlan_id=out_vlan,
+                flag=VLAN_TABLE_FLAG_ONLY_TAG,
+                )
+            add_one_vlan_table_flow(
+                ctrl=self.controller,
+                of_port=in_port,
+                vlan_id=out_vlan,
+                flag=VLAN_TABLE_FLAG_ONLY_UNTAG
+                )
+            # Packet generation with sleep
+            time.sleep(2)
+            label_SR1 = (mpls_label_SR1, 0, 1, 32)
+            label_SR2 = (mpls_label_SR2, 0, 0, 32)
+            label_2 = (mpls_label_PW, 0, 1, 32)
+
+	    # set to false to test if routing traffic
+	    # comes through
+
+	    pw = True
+            if pw:
+		    parsed_pkt = mpls_packet(
+			pktlen=104,
+			ip_ttl=63,
+			eth_dst=src_mac_str,
+			label=[label_SR2, label_2],
+			encapsulated_ethernet = True
+		    )
+		    pkt = str( parsed_pkt )
+		    self.dataplane.send( in_port, pkt )
+
+
+		    expected_label = (mpls_label_PW, 0, 1, 31)
+		    # we geneate the expected pw packet
+		    parsed_pkt =  mpls_packet(
+			pktlen=100,
+			ip_ttl=63,
+			eth_dst=dst_mac_str,
+			eth_src=src_mac_str,
+			label=[ expected_label ],
+			encapsulated_ethernet = True
+		    )
+
+		    pkt = str( parsed_pkt )
+		    verify_packet( self, pkt, out_port )
+		    verify_no_packet( self, pkt, in_port )
+	    else:
+		    # packet for routing traffic
+		    parsed_pkt_2 = mpls_packet(
+			pktlen=104,
+			ip_ttl=63,
+			eth_dst=src_mac_str,
+			label=[ label_SR1 ]
+		    )
+		    pkt_2 = str(parsed_pkt_2)
+		    self.dataplane.send( in_port, pkt_2 )
+
+		    # we geneate the expected routed packet
+		    parsed_pkt_2 = simple_tcp_packet(
+			pktlen=100,
+			ip_ttl=31,
+			eth_dst=dst_mac_str,
+			eth_src=src_mac_str,
+		    )
+		    pkt_2 = str(parsed_pkt_2)
+
+		    verify_packet( self, pkt_2, out_port)
+		    verify_no_packet( self, pkt_2, in_port )
+
+            verify_no_other_packets( self )
+        finally:
+
+            delete_all_flows( self.controller )
+            delete_groups( self.controller, Groups )
+            delete_all_groups( self.controller )
+
+class PseudowireSpineTerminationBug( base_tests.SimpleDataPlane ):
+    """
+    This is meant to demonstrate a bug observed in the termination of
+    Leaf-Spine pseudowires, where the termination point at the spine
+    is a port connecting to another leaf switch.
+    In this case, there exist two L2 interface groups in the device for the
+    same port :
+
+    L2 interface for routing : POP_VLAN, output to port
+    L2 interface for pseudowire : outpute to port
+
+    The choice of the l2 interface group is associated with the vlan id of the packet.
+    In both cases, packets arrive with untagged vlan and are associated with vlan-id 4094.
+    However, in pw case the outer l2 is popped, and the vlan-id changes (that of the original
+    traffic) which matches the L2 interface group for the pw.
+
+    The bug is that still the group that is chossen is that for routing, which pops the vlan,
+    and thus the pseudowire results with untagged traffic.
+    """
+    def runTest( self ):
+
+        Groups  = Queue.LifoQueue( )
+        Groups2 = Queue.LifoQueue( )
+        try:
+            if len( config[ "port_map" ] ) < 1:
+                logging.info( "Port count less than 1, can't run this case" )
+                assert (False)
+                return
+            ports = config[ "port_map" ].keys( )
+            for pair in itertools.product(ports, ports):
+                # we generate all possible products
+                in_port     = pair[0]
+                out_port    = pair[1]
+                if out_port == in_port:
+                    continue
+                # we fill the pipeline for the pw initiation
+                # on the reverse path
+                (
+                    port_to_mpls_label_2,
+                    port_to_mpls_label_1,
+                    port_to_mpls_label_pw,
+                    port_to_in_vlan_3,
+                    port_to_in_vlan_2,
+                    port_to_in_vlan_1,
+                    port_to_src_mac_str,
+                    port_to_dst_mac_str,
+                    Groups ) = fill_pw_initiation_pipeline(
+                    controller=self.controller,
+                    logging=logging,
+                    in_port=out_port,
+                    out_port=in_port,
+                    ingress_tags=1,
+                    egress_tag=EGRESS_TAGGED,
+                    mpls_labels=1
+                    )
+                # we fill the pipeline for the pw termination
+                (
+                    port_to_mpls_label_pw,
+                    port_to_in_vlan_2,
+                    port_to_in_vlan_1,
+                    port_to_dst_mac_str,
+                    Groups2 ) = fill_pw_termination_pipeline(
+                    controller=self.controller,
+                    logging=logging,
+                    in_port=in_port,
+                    out_port=out_port,
+                    egress_tags=1
+                    )
+
+		print('''\nBefore adding the l2 interface group that pops the vlan we expect to see tagged packets at the output. ''')
+
+                # we generate the pw packet
+                label_pw = (port_to_mpls_label_pw[out_port], 0, 1, 63)
+                cw = (0, 0, 0, 0)
+                parsed_pkt = pw_packet(
+                    pktlen=104,
+                    out_eth_dst=port_to_dst_mac_str[in_port],
+                    label=[label_pw],
+                    cw=cw,
+                    out_dl_vlan_enable=True,
+                    out_vlan_vid=port_to_in_vlan_1[out_port],
+                    )
+                pkt = str( parsed_pkt )
+                self.dataplane.send( in_port, pkt )
+                # we generate the expected tcp packet
+                # with a vlan tag
+                parsed_pkt = simple_tcp_packet(
+                    pktlen=82,
+                    dl_vlan_enable=True,
+                    vlan_vid=port_to_in_vlan_1[out_port]
+                    )
+                pkt = str( parsed_pkt )
+
+                # Assertions
+                verify_packet( self, pkt, out_port )
+                verify_no_packet( self, pkt, in_port )
+                verify_no_other_packets( self )
+
+		print('''After adding the l2 interface group that pops the vlan, packets will come out UNTAGGED and test will fail. Check logs for details.''')
+	        # we create an l2 interface group for routing that
+		# pops the vlan tags
+            	l2_intf_gid, l2_intf_msg = add_one_l2_interface_group(
+                	ctrl=self.controller,
+                	port=out_port,
+                	vlan_id=4094,
+                	is_tagged=False,
+                	send_barrier=False
+                	)
+		Groups._put( l2_intf_gid )
+
+                parsed_pkt = pw_packet(
+                    pktlen=104,
+                    out_eth_dst=port_to_dst_mac_str[in_port],
+                    label=[label_pw],
+                    cw=cw,
+                    out_dl_vlan_enable=True,
+                    out_vlan_vid=port_to_in_vlan_1[out_port],
+                    )
+                pkt = str( parsed_pkt )
+		self.dataplane.send( in_port, pkt )
+
+                parsed_pkt = simple_tcp_packet(
+                    pktlen=82,
+                    dl_vlan_enable=True,
+                    vlan_vid=port_to_in_vlan_1[out_port]
+                    )
+                pkt = str( parsed_pkt )
+
+		# send the packet, test should fail now
+                verify_packet( self, pkt, out_port )
+                verify_no_packet( self, pkt, in_port )
+                verify_no_other_packets( self )
+
+                delete_all_flows( self.controller )
+                delete_groups( self.controller, Groups )
+                delete_groups( self.controller, Groups2 )
+                delete_all_groups( self.controller )
+        finally:
+            delete_all_flows( self.controller )
+            delete_groups( self.controller, Groups )
+            delete_groups( self.controller, Groups2 )
+            delete_all_groups( self.controller )
+
+
 class BoSBug( base_tests.SimpleDataPlane ):
     """
     This test is meant to verify the forwarding of the default traffic
@@ -1819,13 +2145,13 @@
                 )
             # Packet generation with sleep
             time.sleep(2)
-            label = (mpls_label, 0, 1, 32)
+            label = (mpls_label, 0, 0, 32)
             parsed_pkt = mpls_packet(
                 pktlen=104,
                 vlan_vid=out_vlan,
                 ip_ttl=63,
                 eth_dst=src_mac_str,
-                label=[ label]
+                label=[ label ]
             )
             pkt = str( parsed_pkt )
             self.dataplane.send( in_port, pkt )
@@ -1843,6 +2169,17 @@
             verify_no_packet( self, pkt, in_port )
             verify_no_other_packets( self )
         finally:
-            delete_all_flows( self.controller )
-            delete_groups( self.controller, Groups )
-            delete_all_groups( self.controller )
\ No newline at end of file
+	    print("SHOULD CLEAR STATE HERE")
+            # delete_all_flows( self.controller )
+            # delete_groups( self.controller, Groups )
+            # delete_all_groups( self.controller )
+
+class ClearAll( base_tests.SimpleDataPlane ):
+
+    def runTest( self ):
+    	delete_all_flows( self.controller )
+    	delete_all_groups( self.controller )
+
+
+
+