Added tests for double tagged subscribers.
Change-Id: If90a7d51500bfcbe7a9095ad06e9bf45e8372e8d
diff --git a/ofdpa/flows.py b/ofdpa/flows.py
index 6ca721b..28261d9 100755
--- a/ofdpa/flows.py
+++ b/ofdpa/flows.py
@@ -2508,4 +2508,447 @@
delete_all_flows( self.controller )
delete_all_groups( self.controller )
+class DoubleToUntagged( base_tests.SimpleDataPlane ):
+ """
+ Verify MPLS IP VPN Initiation from /24 rule using ECMP
+ where we receive double tagged packets and output untagged
+ packets.
+
+ Each double tagged packet represents a subscriber where Outer tag is pon
+ and inner tag is the subrscriber tag.
+ """
+
+ def runTest( self ):
+ Groups = Queue.LifoQueue( )
+ try:
+ if len( config[ "port_map" ] ) < 2:
+ logging.info( "Port count less than 2, can't run this case" )
+ return
+
+ input_src_mac = [ 0x00, 0x00, 0x00, 0xcc, 0xcc, 0xcc ]
+ input_src_mac_str = ':'.join( [ '%02X' % x for x in input_src_mac ] )
+
+ input_dst_mac = [ 0x00, 0x00, 0x00, 0x22, 0x22, 0x00 ]
+ input_dst_mac_str = ':'.join( [ '%02X' % x for x in input_dst_mac ] )
+
+ output_dst_mac = [ 0x00, 0x00, 0x00, 0x33, 0x33, 0x00 ]
+ output_dst_mac_str = ':'.join( [ '%02X' % x for x in output_dst_mac ] )
+
+ dip = 0xc0a80001
+ ports = config[ "port_map" ].keys( )
+
+ inner_vlan = 66
+ outer_vlan = 77
+ id = 10
+ mpls_label = 152
+
+ port = ports[0]
+ out_port = ports[1]
+
+ # add l2 interface group
+ l2_gid, l2_msg = add_one_l2_interface_group( self.controller, out_port, inner_vlan, False, True )
+
+ # add MPLS interface group
+ mpls_gid, mpls_msg = add_mpls_intf_group( self.controller, l2_gid, output_dst_mac, input_dst_mac,
+ inner_vlan, id )
+
+ # add MPLS L3 VPN group
+ mpls_label_gid, mpls_label_msg = add_mpls_label_group( self.controller,
+ subtype=OFDPA_MPLS_GROUP_SUBTYPE_L3_VPN_LABEL, index=id, ref_gid=mpls_gid,
+ push_mpls_header=True, set_mpls_label=mpls_label, set_bos=1, set_ttl=32 )
+ ecmp_msg = add_l3_ecmp_group( self.controller, id, [ mpls_label_gid ] )
+
+ do_barrier( self.controller )
+
+ # add vlan flow table
+ add_one_vlan_table_flow( self.controller, port, 1, outer_vlan, vrf=0,
+ flag=VLAN_TABLE_FLAG_ONLY_STACKED )
+
+ add_one_vlan_1_table_flow( self.controller, port, outer_vlan_id=outer_vlan, inner_vlan_id=inner_vlan,
+ flag=VLAN_TABLE_FLAG_ONLY_UNTAG )
+
+ # add termination flow
+ if config["switch_type"] == "qmx":
+ add_termination_flow( self.controller, 0, 0x0800, input_dst_mac, inner_vlan )
+ else:
+ add_termination_flow( self.controller, port, 0x0800, input_dst_mac, inner_vlan )
+
+ # add_unicast_routing_flow(self.controller, 0x0800, dst_ip, 0, mpls_label_gid, vrf=2)
+ add_unicast_routing_flow( self.controller, 0x0800, dip, 0xffffff00, ecmp_msg.group_id,
+ vrf=0 )
+ Groups._put( l2_gid )
+ Groups._put( mpls_gid )
+ Groups._put( mpls_label_gid )
+ Groups._put( ecmp_msg.group_id )
+
+ do_barrier( self.controller )
+
+ ip_src = '192.168.5.5'
+ ip_dst = '192.168.0.5'
+ parsed_pkt = simple_tcp_packet( pktlen=100, dl_vlan_enable=True, vlan_vid=inner_vlan, outer_vlan=outer_vlan,
+ eth_dst=input_dst_mac_str, eth_src=input_src_mac_str, ip_ttl=64, ip_src=ip_src, ip_dst=ip_dst )
+ pkt = str( parsed_pkt )
+
+ # print("Expected %s" % format_packet(pkt))
+
+ self.dataplane.send( port, pkt )
+
+ # build expect packet
+ label = (mpls_label, 0, 1, 32)
+ exp_pkt = mpls_packet( pktlen=96, dl_vlan_enable=False, ip_ttl=63,
+ ip_src=ip_src, ip_dst=ip_dst, eth_dst=output_dst_mac_str, eth_src=input_dst_mac_str,
+ label=[ label ] )
+ pkt = str( exp_pkt )
+ verify_packet( self, pkt, out_port )
+ verify_no_other_packets( self )
+
+ finally:
+ delete_all_flows( self.controller )
+ delete_groups( self.controller, Groups )
+ delete_all_groups( self.controller )
+
+class DoubleToUntaggedMultipleSubscribers( base_tests.SimpleDataPlane ):
+ """
+ Verify MPLS IP VPN Initiation from /24 rule using ECMP
+ where we receive double tagged packets and output untagged
+ packets.
+
+ Each double tagged packet represents a subscriber where Outer tag is pon
+ and inner tag is the subrscriber tag.
+ """
+
+ def runTest( self ):
+ Groups = Queue.LifoQueue( )
+ try:
+ if len( config[ "port_map" ] ) < 2:
+ logging.info( "Port count less than 2, can't run this case" )
+ return
+
+ # each entry represents a subscriber [id, ip in hex, inner_vlan, outer_vlan, ip in dot form]
+ subscriber_info = [ [10, 0xc0a80001, 10, 100, "192.168.0.1"],
+ [20, 0xc0a80002, 10, 101, "192.168.0.2"],
+ [30, 0xc0a80003, 11, 100, "192.168.0.3"],
+ [40, 0xc0a80004, 11, 101, "192.168.0.4"]]
+
+ print("")
+
+ for sub_info in subscriber_info:
+
+ print("Initializing rules for subscriber with id {0}".format(sub_info[0]))
+
+ input_src_mac = [ 0x00, 0x00, 0x00, 0xcc, 0xcc, sub_info[0] ]
+ input_src_mac_str = ':'.join( [ '%02X' % x for x in input_src_mac ] )
+
+ input_dst_mac = [ 0x00, 0x00, 0x00, 0x22, 0x22, 0x00 ]
+ input_dst_mac_str = ':'.join( [ '%02X' % x for x in input_dst_mac ] )
+
+ output_dst_mac = [ 0x00, 0x00, 0x00, 0x33, 0x33, 0x00 ]
+ output_dst_mac_str = ':'.join( [ '%02X' % x for x in output_dst_mac ] )
+
+ dip = sub_info[1]
+ ports = config[ "port_map" ].keys( )
+
+ inner_vlan = sub_info[2]
+ outer_vlan = sub_info[3]
+ id = 10
+ mpls_label = 152
+
+ port = ports[0]
+ out_port = ports[1]
+
+ # add l2 interface group
+ l2_gid, l2_msg = add_one_l2_interface_group( self.controller, out_port, inner_vlan, False, True )
+
+ # add MPLS interface group
+ mpls_gid, mpls_msg = add_mpls_intf_group( self.controller, l2_gid, output_dst_mac, input_dst_mac,
+ inner_vlan, id )
+
+ # add MPLS L3 VPN group
+ mpls_label_gid, mpls_label_msg = add_mpls_label_group( self.controller,
+ subtype=OFDPA_MPLS_GROUP_SUBTYPE_L3_VPN_LABEL, index=id, ref_gid=mpls_gid,
+ push_mpls_header=True, set_mpls_label=mpls_label, set_bos=1, set_ttl=32 )
+ ecmp_msg = add_l3_ecmp_group( self.controller, id, [ mpls_label_gid ] )
+
+ do_barrier( self.controller )
+
+ # add vlan flow table
+ add_one_vlan_table_flow( self.controller, port, 1, outer_vlan, vrf=0,
+ flag=VLAN_TABLE_FLAG_ONLY_STACKED )
+
+ add_one_vlan_1_table_flow( self.controller, port, outer_vlan_id=outer_vlan, inner_vlan_id=inner_vlan,
+ flag=VLAN_TABLE_FLAG_ONLY_UNTAG )
+
+ # add termination flow
+ if config["switch_type"] == "qmx":
+ add_termination_flow( self.controller, 0, 0x0800, input_dst_mac, inner_vlan )
+ else:
+ add_termination_flow( self.controller, port, 0x0800, input_dst_mac, inner_vlan )
+
+ # add_unicast_routing_flow(self.controller, 0x0800, dst_ip, 0, mpls_label_gid, vrf=2)
+ add_unicast_routing_flow( self.controller, 0x0800, dip, 0xffffff00, ecmp_msg.group_id,
+ vrf=0 )
+ Groups._put( l2_gid )
+ Groups._put( mpls_gid )
+ Groups._put( mpls_label_gid )
+ Groups._put( ecmp_msg.group_id )
+
+ do_barrier( self.controller )
+
+ for sub_info in subscriber_info:
+
+ print("Sending packet for subscriber with id {0}".format(sub_info[0]))
+
+ input_src_mac = [ 0x00, 0x00, 0x00, 0xcc, 0xcc, sub_info[0] ]
+ input_src_mac_str = ':'.join( [ '%02X' % x for x in input_src_mac ] )
+
+ input_dst_mac = [ 0x00, 0x00, 0x00, 0x22, 0x22, 0x00 ]
+ input_dst_mac_str = ':'.join( [ '%02X' % x for x in input_dst_mac ] )
+
+ output_dst_mac = [ 0x00, 0x00, 0x00, 0x33, 0x33, 0x00 ]
+ output_dst_mac_str = ':'.join( [ '%02X' % x for x in output_dst_mac ] )
+
+ dip = sub_info[1]
+ ports = config[ "port_map" ].keys( )
+
+ inner_vlan = sub_info[2]
+ outer_vlan = sub_info[3]
+ id = 10
+ mpls_label = 152
+
+ port = ports[0]
+ out_port = ports[1]
+
+ ip_src = sub_info[4]
+ ip_dst = '192.168.0.{}'.format(sub_info[0])
+ parsed_pkt = simple_tcp_packet( pktlen=100, dl_vlan_enable=True, vlan_vid=inner_vlan, outer_vlan=outer_vlan,
+ eth_dst=input_dst_mac_str, eth_src=input_src_mac_str, ip_ttl=64, ip_src=ip_src, ip_dst=ip_dst )
+ pkt = str( parsed_pkt )
+
+ # print("Sent %s" % format_packet(pkt))
+
+ self.dataplane.send( port, pkt )
+
+ # build expect packet
+ label = (mpls_label, 0, 1, 32)
+ exp_pkt = mpls_packet( pktlen=96, dl_vlan_enable=False, ip_ttl=63,
+ ip_src=ip_src, ip_dst=ip_dst, eth_dst=output_dst_mac_str, eth_src=input_dst_mac_str,
+ label=[ label ] )
+ pkt = str( exp_pkt )
+ verify_packet( self, pkt, out_port )
+ verify_no_other_packets( self )
+
+ finally:
+ delete_all_flows( self.controller )
+ delete_groups( self.controller, Groups )
+ delete_all_groups( self.controller )
+
+
+class UntaggedToDouble ( base_tests.SimpleDataPlane ):
+ """
+ Verify google senario where we need to go from
+ an untagged packet to a double tagged packet.
+
+ This is used for a single subscriber.
+ """
+
+ def runTest( self ):
+ Groups = Queue.LifoQueue( )
+ try:
+ if len( config[ "port_map" ] ) < 2:
+ logging.info( "Port count less than 2, can't run this case" )
+ return
+
+ input_src_mac = [ 0x00, 0x00, 0x00, 0xcc, 0xcc, 0xcc ]
+ input_src_mac_str = ':'.join( [ '%02X' % x for x in input_src_mac ] )
+
+ input_dst_mac = [ 0x00, 0x00, 0x00, 0x22, 0x22, 0x00 ]
+ input_dst_mac_str = ':'.join( [ '%02X' % x for x in input_dst_mac ] )
+
+ output_dst_mac = [ 0x00, 0x00, 0x00, 0x33, 0x33, 0x00 ]
+ output_dst_mac_str = ':'.join( [ '%02X' % x for x in output_dst_mac ] )
+
+ dip = 0xc0a80001
+ ports = config[ "port_map" ].keys( )
+
+ inner_vlan = 66
+ outer_vlan = 77
+ id = 10
+ mpls_label = 152
+
+ port = ports[0]
+ out_port = ports[1]
+
+ # add l2 unfiltered interface group
+ l2_gid, l2_msg = add_one_l2_unfiltered_group( self.controller, out_port, True)
+
+ l3_msg = add_l3_unicast_group( self.controller, out_port, vlanid=4094, id=id,
+ src_mac=input_dst_mac, dst_mac=output_dst_mac, gid=l2_gid)
+
+ do_barrier( self.controller )
+
+ # add vlan flow table
+ add_one_vlan_table_flow( self.controller, port, 1, 4094,
+ flag=VLAN_TABLE_FLAG_ONLY_BOTH )
+
+ # add termination flow
+ if config["switch_type"] == "qmx":
+ add_termination_flow( self.controller, 0, 0x0800, input_dst_mac, 4094 )
+ else:
+ add_termination_flow( self.controller, port, 0x0800, input_dst_mac, 4094 )
+
+ add_unicast_routing_flow( self.controller, 0x0800, dip, 0xffffffff, l3_msg.group_id,
+ vrf=0 )
+
+ add_one_egress_vlan_table_flow( self.controller, out_port, 4094 , inner_vlan, outer_vlan)
+
+ Groups._put( l2_gid )
+ Groups._put( l3_msg.group_id )
+
+ do_barrier( self.controller )
+
+ ip_src = '192.168.5.5'
+ ip_dst = '192.168.0.1'
+ parsed_pkt = simple_tcp_packet( pktlen=100, dl_vlan_enable=False,
+ eth_dst=input_dst_mac_str, eth_src=input_src_mac_str, ip_ttl=64, ip_src=ip_src, ip_dst=ip_dst )
+ pkt = str( parsed_pkt )
+
+ # print("Input Packet %s" % format_packet(pkt))
+
+ self.dataplane.send( port, pkt )
+
+ # build expect packet
+ exp_pkt = simple_tcp_packet( pktlen=108, dl_vlan_enable=True, vlan_vid=inner_vlan, outer_vlan=outer_vlan,
+ eth_dst=output_dst_mac_str, eth_src=input_dst_mac_str, ip_ttl=63, ip_src=ip_src, ip_dst=ip_dst )
+ pkt = str( exp_pkt )
+
+ # print("Expected Packet %s" % format_packet(pkt))
+
+ verify_packet( self, pkt, out_port )
+ verify_no_other_packets( self )
+ finally:
+ delete_all_flows( self.controller )
+ delete_groups( self.controller, Groups )
+ delete_all_groups( self.controller )
+
+class UntaggedToDoubleMultipleSubscribers ( base_tests.SimpleDataPlane ):
+ """
+ Verify google senario where we need to go from
+ an untagged packet to a double tagged packet.
+
+ This is used for multiple subscribers.
+
+ However, this solution does not scale, since we assign an internal vlan to each subscriber
+ used in L3 Unicast Group in order to differentiate between them in the Egress Vlan Table.
+ """
+
+ def runTest( self ):
+ Groups = Queue.LifoQueue( )
+ try:
+ if len( config[ "port_map" ] ) < 2:
+ logging.info( "Port count less than 2, can't run this case" )
+ return
+
+ # each entry represents a subscriber [id, ip in hex, inner_vlan, outer_vlan, ip in dot form, internal vlan]
+ subscriber_info = [[1, 0xc0a80001, 10, 100, "192.168.0.1", 4000],
+ [2, 0xc0a80002, 10, 101, "192.168.0.2", 4001],
+ [3, 0xc0a80003, 11, 100, "192.168.0.3", 4002],
+ [4, 0xc0a80004, 11, 101, "192.168.0.4", 4003]]
+
+ print("")
+
+ for sub_info in subscriber_info:
+
+ print("Initializing rules for subscriber with id {0}".format(sub_info[0]))
+
+ input_src_mac = [ 0x00, 0x00, 0x00, 0xcc, 0xcc, sub_info[0] ]
+ input_src_mac_str = ':'.join( [ '%02X' % x for x in input_src_mac ] )
+
+ input_dst_mac = [ 0x00, 0x00, 0x00, 0x22, 0x22, 0x00 ]
+ input_dst_mac_str = ':'.join( [ '%02X' % x for x in input_dst_mac ] )
+
+ output_dst_mac = [ 0x00, 0x00, 0x00, 0x33, 0x33, 0x00 ]
+ output_dst_mac_str = ':'.join( [ '%02X' % x for x in output_dst_mac ] )
+
+ dip = sub_info[1]
+ ports = config[ "port_map" ].keys( )
+
+ inner_vlan = sub_info[2]
+ outer_vlan = sub_info[3]
+ internal_vlan = sub_info[5]
+ id = sub_info[0] + 10
+
+ port = ports[0]
+ out_port = ports[1]
+
+ # add l2 unfiltered interface group
+ l2_gid, l2_msg = add_one_l2_unfiltered_group( self.controller, out_port, True)
+
+ l3_msg = add_l3_unicast_group( self.controller, out_port, vlanid=internal_vlan, id=id,
+ src_mac=input_dst_mac, dst_mac=output_dst_mac, gid=l2_gid)
+
+ do_barrier( self.controller )
+
+ # add vlan flow table
+ add_one_vlan_table_flow( self.controller, port, 1, 4094,
+ flag=VLAN_TABLE_FLAG_ONLY_BOTH )
+
+ # add termination flow
+ if config["switch_type"] == "qmx":
+ add_termination_flow( self.controller, 0, 0x0800, input_dst_mac, 4094 )
+ else:
+ add_termination_flow( self.controller, port, 0x0800, input_dst_mac, 4094 )
+
+ add_unicast_routing_flow( self.controller, 0x0800, dip, 0xffffffff, l3_msg.group_id,
+ vrf=0 )
+
+ add_one_egress_vlan_table_flow( self.controller, out_port, internal_vlan, inner_vlan, outer_vlan)
+
+ Groups._put( l2_gid )
+ Groups._put( l3_msg.group_id )
+ do_barrier( self.controller )
+
+ for sub_info in subscriber_info:
+
+ print("Sending packet for subscriber with id {0}".format(sub_info[0]))
+
+ input_src_mac = [ 0x00, 0x00, 0x00, 0xcc, 0xcc, sub_info[0] ]
+ input_src_mac_str = ':'.join( [ '%02X' % x for x in input_src_mac ] )
+
+ input_dst_mac = [ 0x00, 0x00, 0x00, 0x22, 0x22, 0x00 ]
+ input_dst_mac_str = ':'.join( [ '%02X' % x for x in input_dst_mac ] )
+
+ output_dst_mac = [ 0x00, 0x00, 0x00, 0x33, 0x33, 0x00 ]
+ output_dst_mac_str = ':'.join( [ '%02X' % x for x in output_dst_mac ] )
+
+ dip = sub_info[1]
+ ports = config[ "port_map" ].keys( )
+
+ inner_vlan = sub_info[2]
+ outer_vlan = sub_info[3]
+ internal_vlan = sub_info[5]
+
+ id = sub_info[0] + 10
+ ip_src = '192.168.5.5'
+ ip_dst = '192.168.0.{}'.format(sub_info[0])
+ parsed_pkt = simple_tcp_packet( pktlen=100, dl_vlan_enable=False,
+ eth_dst=input_dst_mac_str, eth_src=input_src_mac_str, ip_ttl=64, ip_src=ip_src, ip_dst=ip_dst )
+ pkt = str( parsed_pkt )
+
+ # print("Input Packet %s" % format_packet(pkt))
+
+ self.dataplane.send( port, pkt )
+
+ # build expect packet
+ exp_pkt = simple_tcp_packet( pktlen=108, dl_vlan_enable=True, vlan_vid=inner_vlan, outer_vlan=outer_vlan,
+ eth_dst=output_dst_mac_str, eth_src=input_dst_mac_str, ip_ttl=63, ip_src=ip_src, ip_dst=ip_dst )
+ pkt = str( exp_pkt )
+
+ # print("Expected Packet %s" % format_packet(pkt))
+
+ verify_packet( self, pkt, out_port )
+ verify_no_other_packets( self )
+ finally:
+ delete_all_flows( self.controller )
+ delete_groups( self.controller, Groups )
+ delete_all_groups( self.controller )