def create_vxlan_flood_test_bd(cls, vni, n_ucast_tunnels, port): # Create 10 ucast vxlan tunnels under bd ip_range_start = 10 ip_range_end = ip_range_start + n_ucast_tunnels next_hop_address = cls.pg0.remote_ip4 for dest_ip4 in ip4_range(next_hop_address, ip_range_start, ip_range_end): # add host route so dest_ip4 will not be resolved rip = VppIpRoute( cls, dest_ip4, 32, [VppRoutePath(next_hop_address, INVALID_INDEX)], register=False, ) rip.add_vpp_config() r = VppVxlanTunnel( cls, src=cls.pg0.local_ip4, src_port=port, dst_port=port, dst=dest_ip4, vni=vni, ) r.add_vpp_config() cls.vapi.sw_interface_set_l2_bridge(r.sw_if_index, bd_id=vni)
def setUp(self): super(TestGSO, self).setUp() for i in self.pg_interfaces: i.admin_up() i.config_ip4() i.config_ip6() i.disable_ipv6_ra() i.resolve_arp() i.resolve_ndp() self.single_tunnel_bd = 10 self.vxlan = VppVxlanTunnel(self, src=self.pg0.local_ip4, dst=self.pg0.remote_ip4, vni=self.single_tunnel_bd) self.vxlan2 = VppVxlanTunnel(self, src=self.pg0.local_ip6, dst=self.pg0.remote_ip6, vni=self.single_tunnel_bd) self.ipip4 = VppIpIpTunInterface(self, self.pg0, self.pg0.local_ip4, self.pg0.remote_ip4) self.ipip6 = VppIpIpTunInterface(self, self.pg0, self.pg0.local_ip6, self.pg0.remote_ip6)
def setUp(self): super(TestSpan, self).setUp() self.vxlan = VppVxlanTunnel(self, src=self.pg2.local_ip4, dst=self.pg2.remote_ip4, vni=1111) self.vxlan.add_vpp_config() self.reset_packet_infos()
def test_l2_mode(self): """ VXLAN L2 mode """ t = VppVxlanTunnel(self, src=self.pg0.local_ip4, dst=self.pg0.remote_ip4, vni=1000, is_l3=False) t.add_vpp_config() t.config_ip4() t.admin_up() dstIP = t.local_ip4[:-1] + "2" # Create a packet to send p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) / IP(src=self.pg1.local_ip4, dst=dstIP) / UDP(sport=555, dport=556) / Raw(b'\x00' * 80)) # Expect ARP request rx = self.send_and_expect(self.pg1, [p], self.pg0) for p in rx: self.assertEqual(p[Ether].dst, self.pg0.remote_mac) self.assertEqual(p[Ether].src, self.pg0.local_mac) self.assertEqual(p[ARP].op, 1) self.assertEqual(p[ARP].pdst, dstIP) # Resolve ARP VppNeighbor(self, t.sw_if_index, self.pg1.remote_mac, dstIP).add_vpp_config() # Send packets NUM_PKTS = 128 rx = self.send_and_expect(self.pg1, p * NUM_PKTS, self.pg0) self.assertEqual(NUM_PKTS, len(rx))
def create_vxlan_flood_test_bd(cls, vni, n_ucast_tunnels): # Create 10 ucast vxlan tunnels under bd start = 10 end = start + n_ucast_tunnels for dest_ip6 in cls.ip_range(start, end): # add host route so dest ip will not be resolved rip = VppIpRoute(cls, dest_ip6, 128, [VppRoutePath(cls.pg0.remote_ip6, INVALID_INDEX)], register=False) rip.add_vpp_config() r = VppVxlanTunnel(cls, src=cls.pg0.local_ip6, dst=dest_ip6, vni=vni) r.add_vpp_config() cls.vapi.sw_interface_set_l2_bridge(r.sw_if_index, bd_id=vni)
def setUp(self): super(TestVxlan6, self).setUp() # Create VXLAN VTEP on VPP pg0, and put vxlan_tunnel0 and pg1 # into BD. self.single_tunnel_vni = 0x12345 self.single_tunnel_bd = 1 r = VppVxlanTunnel(self, src=self.pg0.local_ip6, dst=self.pg0.remote_ip6, vni=self.single_tunnel_vni) r.add_vpp_config() self.vapi.sw_interface_set_l2_bridge(rx_sw_if_index=r.sw_if_index, bd_id=self.single_tunnel_bd) self.vapi.sw_interface_set_l2_bridge( rx_sw_if_index=self.pg1.sw_if_index, bd_id=self.single_tunnel_bd) # Setup vni 2 to test multicast flooding self.n_ucast_tunnels = 10 self.mcast_flood_bd = 2 self.create_vxlan_flood_test_bd(self.mcast_flood_bd, self.n_ucast_tunnels) r = VppVxlanTunnel(self, src=self.pg0.local_ip6, dst=self.mcast_ip6, mcast_sw_if_index=1, vni=self.mcast_flood_bd) r.add_vpp_config() self.vapi.sw_interface_set_l2_bridge(rx_sw_if_index=r.sw_if_index, bd_id=self.mcast_flood_bd) self.vapi.sw_interface_set_l2_bridge( rx_sw_if_index=self.pg2.sw_if_index, bd_id=self.mcast_flood_bd) # Setup vni 3 to test unicast flooding self.ucast_flood_bd = 3 self.create_vxlan_flood_test_bd(self.ucast_flood_bd, self.n_ucast_tunnels) self.vapi.sw_interface_set_l2_bridge( rx_sw_if_index=self.pg3.sw_if_index, bd_id=self.ucast_flood_bd)
def createVxLANInterfaces(self, port=4789): # Create VXLAN VTEP on VPP pg0, and put vxlan_tunnel0 and pg1 # into BD. self.dport = port self.single_tunnel_vni = 0x12345 self.single_tunnel_bd = 1 r = VppVxlanTunnel( self, src=self.pg0.local_ip6, dst=self.pg0.remote_ip6, src_port=self.dport, dst_port=self.dport, vni=self.single_tunnel_vni, ) r.add_vpp_config() self.vapi.sw_interface_set_l2_bridge( rx_sw_if_index=r.sw_if_index, bd_id=self.single_tunnel_bd ) self.vapi.sw_interface_set_l2_bridge( rx_sw_if_index=self.pg1.sw_if_index, bd_id=self.single_tunnel_bd ) # Setup vni 2 to test multicast flooding self.n_ucast_tunnels = 10 self.mcast_flood_bd = 2 self.create_vxlan_flood_test_bd( self.mcast_flood_bd, self.n_ucast_tunnels, self.dport ) r = VppVxlanTunnel( self, src=self.pg0.local_ip6, dst=self.mcast_ip6, src_port=self.dport, dst_port=self.dport, mcast_sw_if_index=1, vni=self.mcast_flood_bd, ) r.add_vpp_config() self.vapi.sw_interface_set_l2_bridge( rx_sw_if_index=r.sw_if_index, bd_id=self.mcast_flood_bd ) self.vapi.sw_interface_set_l2_bridge( rx_sw_if_index=self.pg2.sw_if_index, bd_id=self.mcast_flood_bd ) # Setup vni 3 to test unicast flooding self.ucast_flood_bd = 3 self.create_vxlan_flood_test_bd( self.ucast_flood_bd, self.n_ucast_tunnels, self.dport ) self.vapi.sw_interface_set_l2_bridge( rx_sw_if_index=self.pg3.sw_if_index, bd_id=self.ucast_flood_bd ) # Set scapy listen custom port for VxLAN bind_layers(UDP, VXLAN, dport=self.dport)
def test_xconnect(self): """ VXLAN source address not local """ # # test the broken configuration of a VXLAN tunnel whose # source address is not local ot the box. packets sent # through the tunnel should be dropped # t = VppVxlanTunnel(self, src="10.0.0.5", dst=self.pg0.local_ip4, vni=1000) t.add_vpp_config() t.admin_up() self.vapi.sw_interface_set_l2_xconnect(t.sw_if_index, self.pg1.sw_if_index, enable=1) self.vapi.sw_interface_set_l2_xconnect(self.pg1.sw_if_index, t.sw_if_index, enable=1) p = (Ether(src="00:11:22:33:44:55", dst="00:00:00:11:22:33") / IP(src="4.3.2.1", dst="1.2.3.4") / UDP(sport=20000, dport=10000) / Raw(b'\xa5' * 1450)) rx = self.send_and_assert_no_replies(self.pg1, [p])
def setUp(self): super(TestVxlan, self).setUp() # Create VXLAN VTEP on VPP pg0, and put vxlan_tunnel0 and pg1 # into BD. self.single_tunnel_bd = 1 r = VppVxlanTunnel(self, src=self.pg0.local_ip4, dst=self.pg0.remote_ip4, vni=self.single_tunnel_bd) r.add_vpp_config() self.vapi.sw_interface_set_l2_bridge(rx_sw_if_index=r.sw_if_index, bd_id=self.single_tunnel_bd) self.vapi.sw_interface_set_l2_bridge( rx_sw_if_index=self.pg1.sw_if_index, bd_id=self.single_tunnel_bd) # Setup vni 2 to test multicast flooding self.n_ucast_tunnels = 10 self.mcast_flood_bd = 2 self.create_vxlan_flood_test_bd(self.mcast_flood_bd, self.n_ucast_tunnels) r = VppVxlanTunnel(self, src=self.pg0.local_ip4, dst=self.mcast_ip4, mcast_sw_if_index=1, vni=self.mcast_flood_bd) r.add_vpp_config() self.vapi.sw_interface_set_l2_bridge(rx_sw_if_index=r.sw_if_index, bd_id=self.mcast_flood_bd) self.vapi.sw_interface_set_l2_bridge( rx_sw_if_index=self.pg2.sw_if_index, bd_id=self.mcast_flood_bd) # Add and delete mcast tunnels to check stability self.add_shared_mcast_dst_load() self.add_mcast_tunnels_load() self.del_shared_mcast_dst_load() self.del_mcast_tunnels_load() # Setup vni 3 to test unicast flooding self.ucast_flood_bd = 3 self.create_vxlan_flood_test_bd(self.ucast_flood_bd, self.n_ucast_tunnels) self.vapi.sw_interface_set_l2_bridge( rx_sw_if_index=self.pg3.sw_if_index, bd_id=self.ucast_flood_bd)
def add_del_mcast_tunnels_load(cls, is_add): """ add or del tunnels to test vxlan stability """ n_distinct_dst_tunnels = 200 ip_range_start = 10 ip_range_end = ip_range_start + n_distinct_dst_tunnels for dest_ip4 in ip4_range(cls.mcast_ip4, ip_range_start, ip_range_end): vni = bytearray(socket.inet_pton(socket.AF_INET, dest_ip4))[3] r = VppVxlanTunnel(cls, src=cls.pg0.local_ip4, dst=dest_ip4, mcast_sw_if_index=1, vni=vni) if is_add: r.add_vpp_config() else: r.remove_vpp_config()
def add_del_shared_mcast_dst_load(cls, is_add): """ add or del tunnels sharing the same mcast dst to test vxlan ref_count mechanism """ n_shared_dst_tunnels = 20 vni_start = 10000 vni_end = vni_start + n_shared_dst_tunnels for vni in range(vni_start, vni_end): r = VppVxlanTunnel(cls, src=cls.pg0.local_ip4, dst=cls.mcast_ip4, mcast_sw_if_index=1, vni=vni) if is_add: r.add_vpp_config() if r.sw_if_index == 0xffffffff: raise ValueError("bad sw_if_index: ~0") else: r.remove_vpp_config()
class TestGSO(VppTestCase): """ GSO Test Case """ def __init__(self, *args): VppTestCase.__init__(self, *args) @classmethod def setUpClass(self): super(TestGSO, self).setUpClass() res = self.create_pg_interfaces(range(2)) res_gso = self.create_pg_interfaces(range(2, 4), 1, 1460) self.create_pg_interfaces(range(4, 5), 1, 8940) self.pg_interfaces.append(res[0]) self.pg_interfaces.append(res[1]) self.pg_interfaces.append(res_gso[0]) self.pg_interfaces.append(res_gso[1]) @classmethod def tearDownClass(self): super(TestGSO, self).tearDownClass() def setUp(self): super(TestGSO, self).setUp() for i in self.pg_interfaces: i.admin_up() i.config_ip4() i.config_ip6() i.disable_ipv6_ra() i.resolve_arp() i.resolve_ndp() self.single_tunnel_bd = 10 self.vxlan = VppVxlanTunnel(self, src=self.pg0.local_ip4, dst=self.pg0.remote_ip4, vni=self.single_tunnel_bd) self.vxlan2 = VppVxlanTunnel(self, src=self.pg0.local_ip6, dst=self.pg0.remote_ip6, vni=self.single_tunnel_bd) self.ipip4 = VppIpIpTunInterface(self, self.pg0, self.pg0.local_ip4, self.pg0.remote_ip4) self.ipip6 = VppIpIpTunInterface(self, self.pg0, self.pg0.local_ip6, self.pg0.remote_ip6) def tearDown(self): super(TestGSO, self).tearDown() if not self.vpp_dead: for i in self.pg_interfaces: i.unconfig_ip4() i.unconfig_ip6() i.admin_down() def test_gso(self): """ GSO test """ # # Send jumbo frame with gso disabled and DF bit is set # p4 = ( Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4, flags='DF') / TCP(sport=1234, dport=1234) / Raw(b'\xa5' * 65200)) rxs = self.send_and_expect(self.pg0, [p4], self.pg0) for rx in rxs: self.assertEqual(rx[Ether].src, self.pg0.local_mac) self.assertEqual(rx[Ether].dst, self.pg0.remote_mac) self.assertEqual(rx[IP].src, self.pg0.local_ip4) self.assertEqual(rx[IP].dst, self.pg0.remote_ip4) self.assertEqual(rx[ICMP].type, 3) # "dest-unreach" self.assertEqual(rx[ICMP].code, 4) # "fragmentation-needed" # # Send checksum offload frames # p40 = ( Ether(src=self.pg2.remote_mac, dst=self.pg2.local_mac) / IP(src=self.pg2.remote_ip4, dst=self.pg0.remote_ip4, flags='DF') / TCP(sport=1234, dport=1234) / Raw(b'\xa5' * 1460)) rxs = self.send_and_expect(self.pg2, 100 * [p40], self.pg0) for rx in rxs: self.assertEqual(rx[Ether].src, self.pg0.local_mac) self.assertEqual(rx[Ether].dst, self.pg0.remote_mac) self.assertEqual(rx[IP].src, self.pg2.remote_ip4) self.assertEqual(rx[IP].dst, self.pg0.remote_ip4) payload_len = rx[IP].len - 20 - 20 self.assert_ip_checksum_valid(rx) self.assert_tcp_checksum_valid(rx) self.assertEqual(payload_len, len(rx[Raw])) p60 = (Ether(src=self.pg2.remote_mac, dst=self.pg2.local_mac) / IPv6(src=self.pg2.remote_ip6, dst=self.pg0.remote_ip6) / TCP(sport=1234, dport=1234) / Raw(b'\xa5' * 1440)) rxs = self.send_and_expect(self.pg2, 100 * [p60], self.pg0) for rx in rxs: self.assertEqual(rx[Ether].src, self.pg0.local_mac) self.assertEqual(rx[Ether].dst, self.pg0.remote_mac) self.assertEqual(rx[IPv6].src, self.pg2.remote_ip6) self.assertEqual(rx[IPv6].dst, self.pg0.remote_ip6) payload_len = rx[IPv6].plen - 20 self.assert_tcp_checksum_valid(rx) self.assertEqual(payload_len, len(rx[Raw])) # # Send jumbo frame with gso enabled and DF bit is set # input and output interfaces support GSO # self.vapi.feature_gso_enable_disable(self.pg3.sw_if_index) p41 = ( Ether(src=self.pg2.remote_mac, dst=self.pg2.local_mac) / IP(src=self.pg2.remote_ip4, dst=self.pg3.remote_ip4, flags='DF') / TCP(sport=1234, dport=1234) / Raw(b'\xa5' * 65200)) rxs = self.send_and_expect(self.pg2, 100 * [p41], self.pg3, 100) for rx in rxs: self.assertEqual(rx[Ether].src, self.pg3.local_mac) self.assertEqual(rx[Ether].dst, self.pg3.remote_mac) self.assertEqual(rx[IP].src, self.pg2.remote_ip4) self.assertEqual(rx[IP].dst, self.pg3.remote_ip4) self.assertEqual(rx[IP].len, 65240) # 65200 + 20 (IP) + 20 (TCP) self.assertEqual(rx[TCP].sport, 1234) self.assertEqual(rx[TCP].dport, 1234) # # ipv6 # p61 = (Ether(src=self.pg2.remote_mac, dst=self.pg2.local_mac) / IPv6(src=self.pg2.remote_ip6, dst=self.pg3.remote_ip6) / TCP(sport=1234, dport=1234) / Raw(b'\xa5' * 65200)) rxs = self.send_and_expect(self.pg2, 100 * [p61], self.pg3, 100) for rx in rxs: self.assertEqual(rx[Ether].src, self.pg3.local_mac) self.assertEqual(rx[Ether].dst, self.pg3.remote_mac) self.assertEqual(rx[IPv6].src, self.pg2.remote_ip6) self.assertEqual(rx[IPv6].dst, self.pg3.remote_ip6) self.assertEqual(rx[IPv6].plen, 65220) # 65200 + 20 (TCP) self.assertEqual(rx[TCP].sport, 1234) self.assertEqual(rx[TCP].dport, 1234) # # Send jumbo frame with gso enabled only on input interface # and DF bit is set. GSO packet will be chunked into gso_size # data payload # self.vapi.feature_gso_enable_disable(self.pg0.sw_if_index) p42 = ( Ether(src=self.pg2.remote_mac, dst=self.pg2.local_mac) / IP(src=self.pg2.remote_ip4, dst=self.pg0.remote_ip4, flags='DF') / TCP(sport=1234, dport=1234) / Raw(b'\xa5' * 65200)) rxs = self.send_and_expect(self.pg2, 5 * [p42], self.pg0, 225) size = 0 for rx in rxs: self.assertEqual(rx[Ether].src, self.pg0.local_mac) self.assertEqual(rx[Ether].dst, self.pg0.remote_mac) self.assertEqual(rx[IP].src, self.pg2.remote_ip4) self.assertEqual(rx[IP].dst, self.pg0.remote_ip4) payload_len = rx[IP].len - 20 - 20 # len - 20 (IP4) - 20 (TCP) self.assert_ip_checksum_valid(rx) self.assert_tcp_checksum_valid(rx) self.assertEqual(rx[TCP].sport, 1234) self.assertEqual(rx[TCP].dport, 1234) self.assertEqual(payload_len, len(rx[Raw])) size += payload_len self.assertEqual(size, 65200 * 5) # # ipv6 # p62 = (Ether(src=self.pg2.remote_mac, dst=self.pg2.local_mac) / IPv6(src=self.pg2.remote_ip6, dst=self.pg0.remote_ip6) / TCP(sport=1234, dport=1234) / Raw(b'\xa5' * 65200)) rxs = self.send_and_expect(self.pg2, 5 * [p62], self.pg0, 225) size = 0 for rx in rxs: self.assertEqual(rx[Ether].src, self.pg0.local_mac) self.assertEqual(rx[Ether].dst, self.pg0.remote_mac) self.assertEqual(rx[IPv6].src, self.pg2.remote_ip6) self.assertEqual(rx[IPv6].dst, self.pg0.remote_ip6) payload_len = rx[IPv6].plen - 20 self.assert_tcp_checksum_valid(rx) self.assertEqual(rx[TCP].sport, 1234) self.assertEqual(rx[TCP].dport, 1234) self.assertEqual(payload_len, len(rx[Raw])) size += payload_len self.assertEqual(size, 65200 * 5) # # Send jumbo frame with gso enabled only on input interface # and DF bit is unset. GSO packet will be fragmented. # self.vapi.sw_interface_set_mtu(self.pg1.sw_if_index, [576, 0, 0, 0]) self.vapi.feature_gso_enable_disable(self.pg1.sw_if_index) p43 = (Ether(src=self.pg2.remote_mac, dst=self.pg2.local_mac) / IP(src=self.pg2.remote_ip4, dst=self.pg1.remote_ip4) / TCP(sport=1234, dport=1234) / Raw(b'\xa5' * 65200)) rxs = self.send_and_expect(self.pg2, 5 * [p43], self.pg1, 5 * 119) size = 0 for rx in rxs: self.assertEqual(rx[Ether].src, self.pg1.local_mac) self.assertEqual(rx[Ether].dst, self.pg1.remote_mac) self.assertEqual(rx[IP].src, self.pg2.remote_ip4) self.assertEqual(rx[IP].dst, self.pg1.remote_ip4) self.assert_ip_checksum_valid(rx) size += rx[IP].len - 20 size -= 20 * 5 # TCP header self.assertEqual(size, 65200 * 5) # # IPv6 # Send jumbo frame with gso enabled only on input interface. # ICMPv6 Packet Too Big will be sent back to sender. # self.vapi.sw_interface_set_mtu(self.pg1.sw_if_index, [1280, 0, 0, 0]) p63 = (Ether(src=self.pg2.remote_mac, dst=self.pg2.local_mac) / IPv6(src=self.pg2.remote_ip6, dst=self.pg1.remote_ip6) / TCP(sport=1234, dport=1234) / Raw(b'\xa5' * 65200)) rxs = self.send_and_expect(self.pg2, 5 * [p63], self.pg2, 5) for rx in rxs: self.assertEqual(rx[Ether].src, self.pg2.local_mac) self.assertEqual(rx[Ether].dst, self.pg2.remote_mac) self.assertEqual(rx[IPv6].src, self.pg2.local_ip6) self.assertEqual(rx[IPv6].dst, self.pg2.remote_ip6) self.assertEqual(rx[IPv6].plen, 1240) # MTU - IPv6 header self.assertEqual(ipv6nh[rx[IPv6].nh], "ICMPv6") self.assertEqual(rx[ICMPv6PacketTooBig].mtu, 1280) self.assertEqual(rx[IPerror6].src, self.pg2.remote_ip6) self.assertEqual(rx[IPerror6].dst, self.pg1.remote_ip6) self.assertEqual(rx[IPerror6].plen - 20, 65200) # # Send jumbo frame with gso enabled only on input interface with 9K MTU # and DF bit is unset. GSO packet will be fragmented. MSS is 8960. GSO # size will be min(MSS, 2048 - 14 - 20) vlib_buffer_t size # self.vapi.sw_interface_set_mtu(self.pg1.sw_if_index, [9000, 0, 0, 0]) self.vapi.sw_interface_set_mtu(self.pg4.sw_if_index, [9000, 0, 0, 0]) p44 = (Ether(src=self.pg4.remote_mac, dst=self.pg4.local_mac) / IP(src=self.pg4.remote_ip4, dst=self.pg1.remote_ip4) / TCP(sport=1234, dport=1234) / Raw(b'\xa5' * 65200)) rxs = self.send_and_expect(self.pg4, 5 * [p44], self.pg1, 165) size = 0 for rx in rxs: self.assertEqual(rx[Ether].src, self.pg1.local_mac) self.assertEqual(rx[Ether].dst, self.pg1.remote_mac) self.assertEqual(rx[IP].src, self.pg4.remote_ip4) self.assertEqual(rx[IP].dst, self.pg1.remote_ip4) payload_len = rx[IP].len - 20 - 20 # len - 20 (IP4) - 20 (TCP) self.assert_ip_checksum_valid(rx) self.assert_tcp_checksum_valid(rx) self.assertEqual(payload_len, len(rx[Raw])) size += payload_len self.assertEqual(size, 65200 * 5) # # IPv6 # p64 = (Ether(src=self.pg4.remote_mac, dst=self.pg4.local_mac) / IPv6(src=self.pg4.remote_ip6, dst=self.pg1.remote_ip6) / TCP(sport=1234, dport=1234) / Raw(b'\xa5' * 65200)) rxs = self.send_and_expect(self.pg4, 5 * [p64], self.pg1, 170) size = 0 for rx in rxs: self.assertEqual(rx[Ether].src, self.pg1.local_mac) self.assertEqual(rx[Ether].dst, self.pg1.remote_mac) self.assertEqual(rx[IPv6].src, self.pg4.remote_ip6) self.assertEqual(rx[IPv6].dst, self.pg1.remote_ip6) payload_len = rx[IPv6].plen - 20 self.assert_tcp_checksum_valid(rx) self.assertEqual(payload_len, len(rx[Raw])) size += payload_len self.assertEqual(size, 65200 * 5) self.vapi.feature_gso_enable_disable(self.pg0.sw_if_index, enable_disable=0) self.vapi.feature_gso_enable_disable(self.pg1.sw_if_index, enable_disable=0) def test_gso_vxlan(self): """ GSO VXLAN test """ self.logger.info(self.vapi.cli("sh int addr")) # # Send jumbo frame with gso enabled only on input interface and # create VXLAN VTEP on VPP pg0, and put vxlan_tunnel0 and pg2 # into BD. # # # enable ipv4/vxlan # self.vxlan.add_vpp_config() self.vapi.sw_interface_set_l2_bridge( rx_sw_if_index=self.vxlan.sw_if_index, bd_id=self.single_tunnel_bd) self.vapi.sw_interface_set_l2_bridge( rx_sw_if_index=self.pg2.sw_if_index, bd_id=self.single_tunnel_bd) self.vapi.feature_gso_enable_disable(self.pg0.sw_if_index) # # IPv4/IPv4 - VXLAN # p45 = (Ether(src=self.pg2.remote_mac, dst="02:fe:60:1e:a2:79") / IP(src=self.pg2.remote_ip4, dst="172.16.3.3", flags='DF') / TCP(sport=1234, dport=1234) / Raw(b'\xa5' * 65200)) rxs = self.send_and_expect(self.pg2, 5 * [p45], self.pg0, 225) size = 0 for rx in rxs: self.assertEqual(rx[Ether].src, self.pg0.local_mac) self.assertEqual(rx[Ether].dst, self.pg0.remote_mac) self.assertEqual(rx[IP].src, self.pg0.local_ip4) self.assertEqual(rx[IP].dst, self.pg0.remote_ip4) self.assert_ip_checksum_valid(rx) self.assert_udp_checksum_valid(rx) self.assertEqual(rx[VXLAN].vni, 10) inner = rx[VXLAN].payload self.assertEqual(rx[IP].len - 20 - 8 - 8, len(inner)) self.assertEqual(inner[Ether].src, self.pg2.remote_mac) self.assertEqual(inner[Ether].dst, "02:fe:60:1e:a2:79") self.assertEqual(inner[IP].src, self.pg2.remote_ip4) self.assertEqual(inner[IP].dst, "172.16.3.3") self.assert_ip_checksum_valid(inner) self.assert_tcp_checksum_valid(inner) payload_len = inner[IP].len - 20 - 20 self.assertEqual(payload_len, len(inner[Raw])) size += payload_len self.assertEqual(size, 65200 * 5) # # IPv4/IPv6 - VXLAN # p65 = (Ether(src=self.pg2.remote_mac, dst="02:fe:60:1e:a2:79") / IPv6(src=self.pg2.remote_ip6, dst="fd01:3::3") / TCP(sport=1234, dport=1234) / Raw(b'\xa5' * 65200)) rxs = self.send_and_expect(self.pg2, 5 * [p65], self.pg0, 225) size = 0 for rx in rxs: self.assertEqual(rx[Ether].src, self.pg0.local_mac) self.assertEqual(rx[Ether].dst, self.pg0.remote_mac) self.assertEqual(rx[IP].src, self.pg0.local_ip4) self.assertEqual(rx[IP].dst, self.pg0.remote_ip4) self.assert_ip_checksum_valid(rx) self.assert_udp_checksum_valid(rx) self.assertEqual(rx[VXLAN].vni, 10) inner = rx[VXLAN].payload self.assertEqual(rx[IP].len - 20 - 8 - 8, len(inner)) self.assertEqual(inner[Ether].src, self.pg2.remote_mac) self.assertEqual(inner[Ether].dst, "02:fe:60:1e:a2:79") self.assertEqual(inner[IPv6].src, self.pg2.remote_ip6) self.assertEqual(inner[IPv6].dst, "fd01:3::3") self.assert_tcp_checksum_valid(inner) payload_len = inner[IPv6].plen - 20 self.assertEqual(payload_len, len(inner[Raw])) size += payload_len self.assertEqual(size, 65200 * 5) # # disable ipv4/vxlan # self.vxlan.remove_vpp_config() # # enable ipv6/vxlan # self.vxlan2.add_vpp_config() self.vapi.sw_interface_set_l2_bridge( rx_sw_if_index=self.vxlan2.sw_if_index, bd_id=self.single_tunnel_bd) # # IPv6/IPv4 - VXLAN # p46 = (Ether(src=self.pg2.remote_mac, dst="02:fe:60:1e:a2:79") / IP(src=self.pg2.remote_ip4, dst="172.16.3.3", flags='DF') / TCP(sport=1234, dport=1234) / Raw(b'\xa5' * 65200)) rxs = self.send_and_expect(self.pg2, 5 * [p46], self.pg0, 225) size = 0 for rx in rxs: self.assertEqual(rx[Ether].src, self.pg0.local_mac) self.assertEqual(rx[Ether].dst, self.pg0.remote_mac) self.assertEqual(rx[IPv6].src, self.pg0.local_ip6) self.assertEqual(rx[IPv6].dst, self.pg0.remote_ip6) self.assert_udp_checksum_valid(rx) self.assertEqual(rx[VXLAN].vni, 10) inner = rx[VXLAN].payload self.assertEqual(rx[IPv6].plen - 8 - 8, len(inner)) self.assertEqual(inner[Ether].src, self.pg2.remote_mac) self.assertEqual(inner[Ether].dst, "02:fe:60:1e:a2:79") self.assertEqual(inner[IP].src, self.pg2.remote_ip4) self.assertEqual(inner[IP].dst, "172.16.3.3") self.assert_ip_checksum_valid(inner) self.assert_tcp_checksum_valid(inner) payload_len = inner[IP].len - 20 - 20 self.assertEqual(payload_len, len(inner[Raw])) size += payload_len self.assertEqual(size, 65200 * 5) # # IPv6/IPv6 - VXLAN # p66 = (Ether(src=self.pg2.remote_mac, dst="02:fe:60:1e:a2:79") / IPv6(src=self.pg2.remote_ip6, dst="fd01:3::3") / TCP(sport=1234, dport=1234) / Raw(b'\xa5' * 65200)) rxs = self.send_and_expect(self.pg2, 5 * [p66], self.pg0, 225) size = 0 for rx in rxs: self.assertEqual(rx[Ether].src, self.pg0.local_mac) self.assertEqual(rx[Ether].dst, self.pg0.remote_mac) self.assertEqual(rx[IPv6].src, self.pg0.local_ip6) self.assertEqual(rx[IPv6].dst, self.pg0.remote_ip6) self.assert_udp_checksum_valid(rx) self.assertEqual(rx[VXLAN].vni, 10) inner = rx[VXLAN].payload self.assertEqual(rx[IPv6].plen - 8 - 8, len(inner)) self.assertEqual(inner[Ether].src, self.pg2.remote_mac) self.assertEqual(inner[Ether].dst, "02:fe:60:1e:a2:79") self.assertEqual(inner[IPv6].src, self.pg2.remote_ip6) self.assertEqual(inner[IPv6].dst, "fd01:3::3") self.assert_tcp_checksum_valid(inner) payload_len = inner[IPv6].plen - 20 self.assertEqual(payload_len, len(inner[Raw])) size += payload_len self.assertEqual(size, 65200 * 5) # # disable ipv4/vxlan # self.vxlan2.remove_vpp_config() self.vapi.feature_gso_enable_disable(self.pg0.sw_if_index, enable_disable=0) def test_gso_ipip(self): """ GSO IPIP test """ self.logger.info(self.vapi.cli("sh int addr")) # # Send jumbo frame with gso enabled only on input interface and # create IPIP tunnel on VPP pg0. # self.vapi.feature_gso_enable_disable(self.pg0.sw_if_index) # # enable ipip4 # self.ipip4.add_vpp_config() # Set interface up and enable IP on it self.ipip4.admin_up() self.ipip4.set_unnumbered(self.pg0.sw_if_index) # Add IPv4 routes via tunnel interface self.ip4_via_ip4_tunnel = VppIpRoute(self, "172.16.10.0", 24, [ VppRoutePath("0.0.0.0", self.ipip4.sw_if_index, proto=FibPathProto.FIB_PATH_NH_PROTO_IP4) ]) self.ip4_via_ip4_tunnel.add_vpp_config() # # IPv4/IPv4 - IPIP # p47 = (Ether(src=self.pg2.remote_mac, dst="02:fe:60:1e:a2:79") / IP(src=self.pg2.remote_ip4, dst="172.16.10.3", flags='DF') / TCP(sport=1234, dport=1234) / Raw(b'\xa5' * 65200)) rxs = self.send_and_expect(self.pg2, 5 * [p47], self.pg0, 225) size = 0 for rx in rxs: self.assertEqual(rx[Ether].src, self.pg0.local_mac) self.assertEqual(rx[Ether].dst, self.pg0.remote_mac) self.assertEqual(rx[IP].src, self.pg0.local_ip4) self.assertEqual(rx[IP].dst, self.pg0.remote_ip4) self.assert_ip_checksum_valid(rx) self.assertEqual(rx[IP].proto, 4) # ipencap inner = rx[IP].payload self.assertEqual(rx[IP].len - 20, len(inner)) self.assertEqual(inner[IP].src, self.pg2.remote_ip4) self.assertEqual(inner[IP].dst, "172.16.10.3") self.assert_ip_checksum_valid(inner) self.assert_tcp_checksum_valid(inner) payload_len = inner[IP].len - 20 - 20 self.assertEqual(payload_len, len(inner[Raw])) size += payload_len self.assertEqual(size, 65200 * 5) self.ip6_via_ip4_tunnel = VppIpRoute(self, "fd01:10::", 64, [ VppRoutePath("::", self.ipip4.sw_if_index, proto=FibPathProto.FIB_PATH_NH_PROTO_IP6) ]) self.ip6_via_ip4_tunnel.add_vpp_config() # # IPv4/IPv6 - IPIP # p67 = (Ether(src=self.pg2.remote_mac, dst="02:fe:60:1e:a2:79") / IPv6(src=self.pg2.remote_ip6, dst="fd01:10::3") / TCP(sport=1234, dport=1234) / Raw(b'\xa5' * 65200)) rxs = self.send_and_expect(self.pg2, 5 * [p67], self.pg0, 225) size = 0 for rx in rxs: self.assertEqual(rx[Ether].src, self.pg0.local_mac) self.assertEqual(rx[Ether].dst, self.pg0.remote_mac) self.assertEqual(rx[IP].src, self.pg0.local_ip4) self.assertEqual(rx[IP].dst, self.pg0.remote_ip4) self.assert_ip_checksum_valid(rx) self.assertEqual(rx[IP].proto, 41) # ipv6 inner = rx[IP].payload self.assertEqual(rx[IP].len - 20, len(inner)) self.assertEqual(inner[IPv6].src, self.pg2.remote_ip6) self.assertEqual(inner[IPv6].dst, "fd01:10::3") self.assert_tcp_checksum_valid(inner) payload_len = inner[IPv6].plen - 20 self.assertEqual(payload_len, len(inner[Raw])) size += payload_len self.assertEqual(size, 65200 * 5) # # Send jumbo frame with gso enabled only on input interface and # create IPIP tunnel on VPP pg0. Enable gso feature node on ipip # tunnel - IPSec use case # self.vapi.feature_gso_enable_disable(self.pg0.sw_if_index, enable_disable=0) self.vapi.feature_gso_enable_disable(self.ipip4.sw_if_index) rxs = self.send_and_expect(self.pg2, 5 * [p47], self.pg0, 225) size = 0 for rx in rxs: self.assertEqual(rx[Ether].src, self.pg0.local_mac) self.assertEqual(rx[Ether].dst, self.pg0.remote_mac) self.assertEqual(rx[IP].src, self.pg0.local_ip4) self.assertEqual(rx[IP].dst, self.pg0.remote_ip4) self.assert_ip_checksum_valid(rx) self.assertEqual(rx[IP].proto, 4) # ipencap inner = rx[IP].payload self.assertEqual(rx[IP].len - 20, len(inner)) self.assertEqual(inner[IP].src, self.pg2.remote_ip4) self.assertEqual(inner[IP].dst, "172.16.10.3") self.assert_ip_checksum_valid(inner) self.assert_tcp_checksum_valid(inner) payload_len = inner[IP].len - 20 - 20 self.assertEqual(payload_len, len(inner[Raw])) size += payload_len self.assertEqual(size, 65200 * 5) # # disable ipip4 # self.vapi.feature_gso_enable_disable(self.ipip4.sw_if_index, enable_disable=0) self.ip4_via_ip4_tunnel.remove_vpp_config() self.ip6_via_ip4_tunnel.remove_vpp_config() self.ipip4.remove_vpp_config() # # enable ipip6 # self.vapi.feature_gso_enable_disable(self.pg0.sw_if_index) self.ipip6.add_vpp_config() # Set interface up and enable IP on it self.ipip6.admin_up() self.ipip6.set_unnumbered(self.pg0.sw_if_index) # Add IPv4 routes via tunnel interface self.ip4_via_ip6_tunnel = VppIpRoute(self, "172.16.10.0", 24, [ VppRoutePath("0.0.0.0", self.ipip6.sw_if_index, proto=FibPathProto.FIB_PATH_NH_PROTO_IP4) ]) self.ip4_via_ip6_tunnel.add_vpp_config() # # IPv6/IPv4 - IPIP # p48 = (Ether(src=self.pg2.remote_mac, dst="02:fe:60:1e:a2:79") / IP(src=self.pg2.remote_ip4, dst="172.16.10.3", flags='DF') / TCP(sport=1234, dport=1234) / Raw(b'\xa5' * 65200)) rxs = self.send_and_expect(self.pg2, 5 * [p48], self.pg0, 225) size = 0 for rx in rxs: self.assertEqual(rx[Ether].src, self.pg0.local_mac) self.assertEqual(rx[Ether].dst, self.pg0.remote_mac) self.assertEqual(rx[IPv6].src, self.pg0.local_ip6) self.assertEqual(rx[IPv6].dst, self.pg0.remote_ip6) self.assertEqual(ipv6nh[rx[IPv6].nh], "IP") inner = rx[IPv6].payload self.assertEqual(rx[IPv6].plen, len(inner)) self.assertEqual(inner[IP].src, self.pg2.remote_ip4) self.assertEqual(inner[IP].dst, "172.16.10.3") self.assert_ip_checksum_valid(inner) self.assert_tcp_checksum_valid(inner) payload_len = inner[IP].len - 20 - 20 self.assertEqual(payload_len, len(inner[Raw])) size += payload_len self.assertEqual(size, 65200 * 5) self.ip6_via_ip6_tunnel = VppIpRoute(self, "fd01:10::", 64, [ VppRoutePath("::", self.ipip6.sw_if_index, proto=FibPathProto.FIB_PATH_NH_PROTO_IP6) ]) self.ip6_via_ip6_tunnel.add_vpp_config() # # IPv6/IPv6 - IPIP # p68 = (Ether(src=self.pg2.remote_mac, dst="02:fe:60:1e:a2:79") / IPv6(src=self.pg2.remote_ip6, dst="fd01:10::3") / TCP(sport=1234, dport=1234) / Raw(b'\xa5' * 65200)) rxs = self.send_and_expect(self.pg2, 5 * [p68], self.pg0, 225) size = 0 for rx in rxs: self.assertEqual(rx[Ether].src, self.pg0.local_mac) self.assertEqual(rx[Ether].dst, self.pg0.remote_mac) self.assertEqual(rx[IPv6].src, self.pg0.local_ip6) self.assertEqual(rx[IPv6].dst, self.pg0.remote_ip6) self.assertEqual(ipv6nh[rx[IPv6].nh], "IPv6") inner = rx[IPv6].payload self.assertEqual(rx[IPv6].plen, len(inner)) self.assertEqual(inner[IPv6].src, self.pg2.remote_ip6) self.assertEqual(inner[IPv6].dst, "fd01:10::3") self.assert_tcp_checksum_valid(inner) payload_len = inner[IPv6].plen - 20 self.assertEqual(payload_len, len(inner[Raw])) size += payload_len self.assertEqual(size, 65200 * 5) # # disable ipip6 # self.ip4_via_ip6_tunnel.remove_vpp_config() self.ip6_via_ip6_tunnel.remove_vpp_config() self.ipip6.remove_vpp_config() self.vapi.feature_gso_enable_disable(self.pg0.sw_if_index, enable_disable=0)
class TestGSO(VppTestCase): """ GSO Test Case """ def __init__(self, *args): VppTestCase.__init__(self, *args) @classmethod def setUpClass(self): super(TestGSO, self).setUpClass() res = self.create_pg_interfaces(range(2)) res_gso = self.create_pg_interfaces(range(2, 4), 1, 1460) self.create_pg_interfaces(range(4, 5), 1, 8940) self.pg_interfaces.append(res[0]) self.pg_interfaces.append(res[1]) self.pg_interfaces.append(res_gso[0]) self.pg_interfaces.append(res_gso[1]) @classmethod def tearDownClass(self): super(TestGSO, self).tearDownClass() def setUp(self): super(TestGSO, self).setUp() for i in self.pg_interfaces: i.admin_up() i.config_ip4() i.config_ip6() i.disable_ipv6_ra() i.resolve_arp() i.resolve_ndp() self.single_tunnel_bd = 10 self.vxlan = VppVxlanTunnel(self, src=self.pg0.local_ip4, dst=self.pg0.remote_ip4, vni=self.single_tunnel_bd) self.vxlan.add_vpp_config() self.vxlan2 = VppVxlanTunnel(self, src=self.pg0.local_ip6, dst=self.pg0.remote_ip6, vni=self.single_tunnel_bd) self.vxlan2.add_vpp_config() def tearDown(self): super(TestGSO, self).tearDown() if not self.vpp_dead: for i in self.pg_interfaces: i.unconfig_ip4() i.unconfig_ip6() i.admin_down() def test_gso(self): """ GSO test """ # # Send jumbo frame with gso disabled and DF bit is set # p4 = ( Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4, flags='DF') / TCP(sport=1234, dport=1234) / Raw(b'\xa5' * 65200)) rxs = self.send_and_expect(self.pg0, [p4], self.pg0) for rx in rxs: self.assertEqual(rx[Ether].src, self.pg0.local_mac) self.assertEqual(rx[Ether].dst, self.pg0.remote_mac) self.assertEqual(rx[IP].src, self.pg0.local_ip4) self.assertEqual(rx[IP].dst, self.pg0.remote_ip4) self.assertEqual(rx[ICMP].type, 3) # "dest-unreach" self.assertEqual(rx[ICMP].code, 4) # "fragmentation-needed" # # Send jumbo frame with gso enabled and DF bit is set # input and output interfaces support GSO # p41 = ( Ether(src=self.pg2.remote_mac, dst=self.pg2.local_mac) / IP(src=self.pg2.remote_ip4, dst=self.pg3.remote_ip4, flags='DF') / TCP(sport=1234, dport=1234) / Raw(b'\xa5' * 65200)) rxs = self.send_and_expect(self.pg2, [p41], self.pg3) for rx in rxs: self.assertEqual(rx[Ether].src, self.pg3.local_mac) self.assertEqual(rx[Ether].dst, self.pg3.remote_mac) self.assertEqual(rx[IP].src, self.pg2.remote_ip4) self.assertEqual(rx[IP].dst, self.pg3.remote_ip4) self.assertEqual(rx[IP].len, 65240) # 65200 + 20 (IP) + 20 (TCP) self.assertEqual(rx[TCP].sport, 1234) self.assertEqual(rx[TCP].dport, 1234) # # ipv6 # p61 = (Ether(src=self.pg2.remote_mac, dst=self.pg2.local_mac) / IPv6(src=self.pg2.remote_ip6, dst=self.pg3.remote_ip6) / TCP(sport=1234, dport=1234) / Raw(b'\xa5' * 65200)) rxs = self.send_and_expect(self.pg2, [p61], self.pg3) for rx in rxs: self.assertEqual(rx[Ether].src, self.pg3.local_mac) self.assertEqual(rx[Ether].dst, self.pg3.remote_mac) self.assertEqual(rx[IPv6].src, self.pg2.remote_ip6) self.assertEqual(rx[IPv6].dst, self.pg3.remote_ip6) self.assertEqual(rx[IPv6].plen, 65220) # 65200 + 20 (TCP) self.assertEqual(rx[TCP].sport, 1234) self.assertEqual(rx[TCP].dport, 1234) # # Send jumbo frame with gso enabled only on input interface # and DF bit is set. GSO packet will be chunked into gso_size # data payload # self.vapi.feature_gso_enable_disable(self.pg0.sw_if_index) p42 = ( Ether(src=self.pg2.remote_mac, dst=self.pg2.local_mac) / IP(src=self.pg2.remote_ip4, dst=self.pg0.remote_ip4, flags='DF') / TCP(sport=1234, dport=1234) / Raw(b'\xa5' * 65200)) rxs = self.send_and_expect(self.pg2, [p42], self.pg0, 45) size = 0 for rx in rxs: self.assertEqual(rx[Ether].src, self.pg0.local_mac) self.assertEqual(rx[Ether].dst, self.pg0.remote_mac) self.assertEqual(rx[IP].src, self.pg2.remote_ip4) self.assertEqual(rx[IP].dst, self.pg0.remote_ip4) self.assertEqual(rx[TCP].sport, 1234) self.assertEqual(rx[TCP].dport, 1234) size = rxs[44][TCP].seq + rxs[44][IP].len - 20 - 20 self.assertEqual(size, 65200) # # ipv6 # p62 = (Ether(src=self.pg2.remote_mac, dst=self.pg2.local_mac) / IPv6(src=self.pg2.remote_ip6, dst=self.pg0.remote_ip6) / TCP(sport=1234, dport=1234) / Raw(b'\xa5' * 65200)) rxs = self.send_and_expect(self.pg2, [p62], self.pg0, 45) size = 0 for rx in rxs: self.assertEqual(rx[Ether].src, self.pg0.local_mac) self.assertEqual(rx[Ether].dst, self.pg0.remote_mac) self.assertEqual(rx[IPv6].src, self.pg2.remote_ip6) self.assertEqual(rx[IPv6].dst, self.pg0.remote_ip6) self.assertEqual(rx[TCP].sport, 1234) self.assertEqual(rx[TCP].dport, 1234) size = rxs[44][TCP].seq + rxs[44][IPv6].plen - 20 self.assertEqual(size, 65200) # # Send jumbo frame with gso enabled only on input interface # and DF bit is unset. GSO packet will be fragmented. # self.vapi.sw_interface_set_mtu(self.pg1.sw_if_index, [576, 0, 0, 0]) self.vapi.feature_gso_enable_disable(self.pg1.sw_if_index) p43 = (Ether(src=self.pg2.remote_mac, dst=self.pg2.local_mac) / IP(src=self.pg2.remote_ip4, dst=self.pg1.remote_ip4) / TCP(sport=1234, dport=1234) / Raw(b'\xa5' * 65200)) rxs = self.send_and_expect(self.pg2, [p43], self.pg1, 119) size = 0 for rx in rxs: self.assertEqual(rx[Ether].src, self.pg1.local_mac) self.assertEqual(rx[Ether].dst, self.pg1.remote_mac) self.assertEqual(rx[IP].src, self.pg2.remote_ip4) self.assertEqual(rx[IP].dst, self.pg1.remote_ip4) size += rx[IP].len - 20 size -= 20 # TCP header self.assertEqual(size, 65200) # # IPv6 # Send jumbo frame with gso enabled only on input interface. # ICMPv6 Packet Too Big will be sent back to sender. # self.vapi.sw_interface_set_mtu(self.pg1.sw_if_index, [1280, 0, 0, 0]) p63 = (Ether(src=self.pg2.remote_mac, dst=self.pg2.local_mac) / IPv6(src=self.pg2.remote_ip6, dst=self.pg1.remote_ip6) / TCP(sport=1234, dport=1234) / Raw(b'\xa5' * 65200)) rxs = self.send_and_expect(self.pg2, [p63], self.pg2, 1) for rx in rxs: self.assertEqual(rx[Ether].src, self.pg2.local_mac) self.assertEqual(rx[Ether].dst, self.pg2.remote_mac) self.assertEqual(rx[IPv6].src, self.pg2.local_ip6) self.assertEqual(rx[IPv6].dst, self.pg2.remote_ip6) self.assertEqual(rx[IPv6].plen, 1240) # MTU - IPv6 header self.assertEqual(ipv6nh[rx[IPv6].nh], "ICMPv6") self.assertEqual(rx[ICMPv6PacketTooBig].mtu, 1280) self.assertEqual(rx[IPerror6].src, self.pg2.remote_ip6) self.assertEqual(rx[IPerror6].dst, self.pg1.remote_ip6) self.assertEqual(rx[IPerror6].plen - 20, 65200) # # Send jumbo frame with gso enabled only on input interface with 9K MTU # and DF bit is unset. GSO packet will be fragmented. MSS is 8960. GSO # size will be min(MSS, 2048 - 14 - 20) vlib_buffer_t size # self.vapi.sw_interface_set_mtu(self.pg1.sw_if_index, [9000, 0, 0, 0]) self.vapi.sw_interface_set_mtu(self.pg4.sw_if_index, [9000, 0, 0, 0]) p44 = (Ether(src=self.pg4.remote_mac, dst=self.pg4.local_mac) / IP(src=self.pg4.remote_ip4, dst=self.pg1.remote_ip4) / TCP(sport=1234, dport=1234) / Raw(b'\xa5' * 65200)) self.pg1.enable_capture() rxs = self.send_and_expect(self.pg4, [p44], self.pg1, 33) size = 0 for rx in rxs: self.assertEqual(rx[Ether].src, self.pg1.local_mac) self.assertEqual(rx[Ether].dst, self.pg1.remote_mac) self.assertEqual(rx[IP].src, self.pg4.remote_ip4) self.assertEqual(rx[IP].dst, self.pg1.remote_ip4) size = rxs[32][TCP].seq + rxs[32][IP].len - 20 - 20 self.assertEqual(size, 65200) # # IPv6 # p64 = (Ether(src=self.pg4.remote_mac, dst=self.pg4.local_mac) / IPv6(src=self.pg4.remote_ip6, dst=self.pg1.remote_ip6) / TCP(sport=1234, dport=1234) / Raw(b'\xa5' * 65200)) self.pg1.enable_capture() rxs = self.send_and_expect(self.pg4, [p64], self.pg1, 34) size = 0 for rx in rxs: self.assertEqual(rx[Ether].src, self.pg1.local_mac) self.assertEqual(rx[Ether].dst, self.pg1.remote_mac) self.assertEqual(rx[IPv6].src, self.pg4.remote_ip6) self.assertEqual(rx[IPv6].dst, self.pg1.remote_ip6) size = rxs[33][TCP].seq + rxs[33][IPv6].plen - 20 self.assertEqual(size, 65200) def test_gso_vxlan(self): """ GSO VXLAN test """ self.logger.info(self.vapi.cli("sh int addr")) # # Send jumbo frame with gso enabled only on input interface and # create VXLAN VTEP on VPP pg0, and put vxlan_tunnel0 and pg2 # into BD. # self.vapi.sw_interface_set_l2_bridge( rx_sw_if_index=self.vxlan.sw_if_index, bd_id=self.single_tunnel_bd) self.vapi.sw_interface_set_l2_bridge( rx_sw_if_index=self.pg2.sw_if_index, bd_id=self.single_tunnel_bd) self.vapi.feature_gso_enable_disable(self.pg0.sw_if_index) # # IPv4/IPv4 - VXLAN # p45 = (Ether(src=self.pg2.remote_mac, dst="02:fe:60:1e:a2:79") / IP(src=self.pg2.remote_ip4, dst="172.16.3.3", flags='DF') / TCP(sport=1234, dport=1234) / Raw(b'\xa5' * 65200)) self.pg0.enable_capture() rxs = self.send_and_expect(self.pg2, [p45], self.pg0, 45) size = 0 for rx in rxs: self.assertEqual(rx[Ether].src, self.pg0.local_mac) self.assertEqual(rx[Ether].dst, self.pg0.remote_mac) self.assertEqual(rx[IP].src, self.pg0.local_ip4) self.assertEqual(rx[IP].dst, self.pg0.remote_ip4) self.assertEqual(rx[VXLAN].vni, 10) inner = rx[VXLAN].payload self.assertEqual(inner[Ether].src, self.pg2.remote_mac) self.assertEqual(inner[Ether].dst, "02:fe:60:1e:a2:79") self.assertEqual(inner[IP].src, self.pg2.remote_ip4) self.assertEqual(inner[IP].dst, "172.16.3.3") size += inner[IP].len - 20 - 20 self.assertEqual(size, 65200) # # IPv4/IPv6 - VXLAN # p65 = (Ether(src=self.pg2.remote_mac, dst="02:fe:60:1e:a2:79") / IPv6(src=self.pg2.remote_ip6, dst="fd01:3::3") / TCP(sport=1234, dport=1234) / Raw(b'\xa5' * 65200)) self.pg0.enable_capture() rxs = self.send_and_expect(self.pg2, [p65], self.pg0, 45) size = 0 for rx in rxs: self.assertEqual(rx[Ether].src, self.pg0.local_mac) self.assertEqual(rx[Ether].dst, self.pg0.remote_mac) self.assertEqual(rx[IP].src, self.pg0.local_ip4) self.assertEqual(rx[IP].dst, self.pg0.remote_ip4) self.assertEqual(rx[VXLAN].vni, 10) inner = rx[VXLAN].payload self.assertEqual(inner[Ether].src, self.pg2.remote_mac) self.assertEqual(inner[Ether].dst, "02:fe:60:1e:a2:79") self.assertEqual(inner[IPv6].src, self.pg2.remote_ip6) self.assertEqual(inner[IPv6].dst, "fd01:3::3") size += inner[IPv6].plen - 20 self.assertEqual(size, 65200) # # disable ipv4/vxlan # self.vxlan.remove_vpp_config() # # enable ipv6/vxlan # self.vapi.sw_interface_set_l2_bridge( rx_sw_if_index=self.vxlan2.sw_if_index, bd_id=self.single_tunnel_bd) # # IPv6/IPv4 - VXLAN # p46 = (Ether(src=self.pg2.remote_mac, dst="02:fe:60:1e:a2:79") / IP(src=self.pg2.remote_ip4, dst="172.16.3.3", flags='DF') / TCP(sport=1234, dport=1234) / Raw(b'\xa5' * 65200)) self.pg0.enable_capture() rxs = self.send_and_expect(self.pg2, [p46], self.pg0, 45) size = 0 for rx in rxs: self.assertEqual(rx[Ether].src, self.pg0.local_mac) self.assertEqual(rx[Ether].dst, self.pg0.remote_mac) self.assertEqual(rx[IPv6].src, self.pg0.local_ip6) self.assertEqual(rx[IPv6].dst, self.pg0.remote_ip6) self.assertEqual(rx[VXLAN].vni, 10) inner = rx[VXLAN].payload self.assertEqual(inner[Ether].src, self.pg2.remote_mac) self.assertEqual(inner[Ether].dst, "02:fe:60:1e:a2:79") self.assertEqual(inner[IP].src, self.pg2.remote_ip4) self.assertEqual(inner[IP].dst, "172.16.3.3") size += inner[IP].len - 20 - 20 self.assertEqual(size, 65200) # # IPv6/IPv6 - VXLAN # p66 = (Ether(src=self.pg2.remote_mac, dst="02:fe:60:1e:a2:79") / IPv6(src=self.pg2.remote_ip6, dst="fd01:3::3") / TCP(sport=1234, dport=1234) / Raw(b'\xa5' * 65200)) self.pg0.enable_capture() rxs = self.send_and_expect(self.pg2, [p66], self.pg0, 45) size = 0 for rx in rxs: self.assertEqual(rx[Ether].src, self.pg0.local_mac) self.assertEqual(rx[Ether].dst, self.pg0.remote_mac) self.assertEqual(rx[IPv6].src, self.pg0.local_ip6) self.assertEqual(rx[IPv6].dst, self.pg0.remote_ip6) self.assertEqual(rx[VXLAN].vni, 10) inner = rx[VXLAN].payload self.assertEqual(inner[Ether].src, self.pg2.remote_mac) self.assertEqual(inner[Ether].dst, "02:fe:60:1e:a2:79") self.assertEqual(inner[IPv6].src, self.pg2.remote_ip6) self.assertEqual(inner[IPv6].dst, "fd01:3::3") size += inner[IPv6].plen - 20 self.assertEqual(size, 65200)
class TestSpan(VppTestCase): """ SPAN Test Case """ @classmethod def setUpClass(cls): super(TestSpan, cls).setUpClass() # Test variables cls.pkts_per_burst = 257 # Number of packets per burst # create 3 pg interfaces cls.create_pg_interfaces(range(3)) cls.bd_id = 55 cls.sub_if = VppDot1QSubint(cls, cls.pg0, 100) cls.vlan_sub_if = VppDot1QSubint(cls, cls.pg2, 300) cls.vlan_sub_if.set_vtr(L2_VTR_OP.L2_POP_1, tag=300) cls.qinq_sub_if = VppDot1ADSubint(cls, cls.pg2, 33, 400, 500) cls.qinq_sub_if.set_vtr(L2_VTR_OP.L2_POP_2, outer=500, inner=400) # packet flows mapping pg0 -> pg1, pg2 -> pg3, etc. cls.flows = dict() cls.flows[cls.pg0] = [cls.pg1] cls.flows[cls.pg1] = [cls.pg0] # packet sizes cls.pg_if_packet_sizes = [64, 512, 1518] # , 9018] # setup all interfaces for i in cls.pg_interfaces: i.admin_up() i.config_ip4() i.resolve_arp() def setUp(self): super(TestSpan, self).setUp() self.vxlan = VppVxlanTunnel(self, src=self.pg2.local_ip4, dst=self.pg2.remote_ip4, vni=1111) self.vxlan.add_vpp_config() self.reset_packet_infos() def tearDown(self): super(TestSpan, self).tearDown() def show_commands_at_teardown(self): self.logger.info(self.vapi.ppcli("show interface span")) def xconnect(self, a, b, is_add=1): self.vapi.sw_interface_set_l2_xconnect(a, b, enable=is_add) self.vapi.sw_interface_set_l2_xconnect(b, a, enable=is_add) def bridge(self, sw_if_index, is_add=1): self.vapi.sw_interface_set_l2_bridge(rx_sw_if_index=sw_if_index, bd_id=self.bd_id, enable=is_add) def _remove_tag(self, packet, vlan, tag_type): self.assertEqual(packet.type, tag_type) payload = packet.payload self.assertEqual(payload.vlan, vlan) inner_type = payload.type payload = payload.payload packet.remove_payload() packet.add_payload(payload) packet.type = inner_type def remove_tags(self, packet, tags): for t in tags: self._remove_tag(packet, t.vlan, t.dot1) return packet def decap_gre(self, pkt): """ Decapsulate the original payload frame by removing GRE header """ self.assertEqual(pkt[Ether].src, self.pg2.local_mac) self.assertEqual(pkt[Ether].dst, self.pg2.remote_mac) self.assertEqual(pkt[IP].src, self.pg2.local_ip4) self.assertEqual(pkt[IP].dst, self.pg2.remote_ip4) return pkt[GRE].payload def decap_erspan(self, pkt, session): """ Decapsulate the original payload frame by removing ERSPAN header """ self.assertEqual(pkt[Ether].src, self.pg2.local_mac) self.assertEqual(pkt[Ether].dst, self.pg2.remote_mac) self.assertEqual(pkt[IP].src, self.pg2.local_ip4) self.assertEqual(pkt[IP].dst, self.pg2.remote_ip4) self.assertEqual(pkt[ERSPAN].ver, 1) self.assertEqual(pkt[ERSPAN].vlan, 0) self.assertEqual(pkt[ERSPAN].cos, 0) self.assertEqual(pkt[ERSPAN].en, 3) self.assertEqual(pkt[ERSPAN].t, 0) self.assertEqual(pkt[ERSPAN].session_id, session) self.assertEqual(pkt[ERSPAN].reserved, 0) self.assertEqual(pkt[ERSPAN].index, 0) return pkt[ERSPAN].payload def decap_vxlan(self, pkt): """ Decapsulate the original payload frame by removing VXLAN header """ self.assertEqual(pkt[Ether].src, self.pg2.local_mac) self.assertEqual(pkt[Ether].dst, self.pg2.remote_mac) self.assertEqual(pkt[IP].src, self.pg2.local_ip4) self.assertEqual(pkt[IP].dst, self.pg2.remote_ip4) return pkt[VXLAN].payload def create_stream(self, src_if, packet_sizes, do_dot1=False, bcast=False): pkts = [] dst_if = self.flows[src_if][0] dst_mac = src_if.remote_mac if bcast: dst_mac = "ff:ff:ff:ff:ff:ff" for i in range(0, self.pkts_per_burst): payload = "span test" size = packet_sizes[int((i / 2) % len(packet_sizes))] p = (Ether(src=src_if.local_mac, dst=dst_mac) / IP(src=src_if.remote_ip4, dst=dst_if.remote_ip4) / UDP(sport=10000 + src_if.sw_if_index * 1000 + i, dport=1234) / Raw(payload)) if do_dot1: p = self.sub_if.add_dot1_layer(p) self.extend_packet(p, size) pkts.append(p) return pkts def verify_capture(self, cap1, cap2): self.assertEqual( len(cap1), len(cap2), "Different number of sent and mirrored packets :" "%u != %u" % (len(cap1), len(cap2))) pkts1 = [(pkt[Ether] / pkt[IP] / pkt[UDP]) for pkt in cap1] pkts2 = [(pkt[Ether] / pkt[IP] / pkt[UDP]) for pkt in cap2] self.assertEqual(pkts1.sort(), pkts2.sort()) def test_device_span(self): """ SPAN device rx mirror """ # Create bi-directional cross-connects between pg0 and pg1 self.xconnect(self.pg0.sw_if_index, self.pg1.sw_if_index) # Create incoming packet streams for packet-generator interfaces pkts = self.create_stream(self.pg0, self.pg_if_packet_sizes) self.pg0.add_stream(pkts) # Enable SPAN on pg0 (mirrored to pg2) self.vapi.sw_interface_span_enable_disable(self.pg0.sw_if_index, self.pg2.sw_if_index) self.logger.info(self.vapi.ppcli("show interface span")) # Enable packet capturing and start packet sending self.pg_enable_capture(self.pg_interfaces) self.pg_start() # Verify packets outgoing packet streams on mirrored interface (pg2) n_pkts = len(pkts) pg1_pkts = self.pg1.get_capture(n_pkts) pg2_pkts = self.pg2.get_capture(n_pkts) # Disable SPAN on pg0 (mirrored to pg2) self.vapi.sw_interface_span_enable_disable(self.pg0.sw_if_index, self.pg2.sw_if_index, state=0) self.xconnect(self.pg0.sw_if_index, self.pg1.sw_if_index, is_add=0) self.verify_capture(pg1_pkts, pg2_pkts) def test_span_l2_rx(self): """ SPAN l2 rx mirror """ self.sub_if.admin_up() self.bridge(self.pg2.sw_if_index) # Create bi-directional cross-connects between pg0 subif and pg1 self.xconnect(self.sub_if.sw_if_index, self.pg1.sw_if_index) # Create incoming packet streams for packet-generator interfaces pkts = self.create_stream(self.pg0, self.pg_if_packet_sizes, do_dot1=True) self.pg0.add_stream(pkts) # Enable SPAN on pg0 (mirrored to pg2) self.vapi.sw_interface_span_enable_disable(self.sub_if.sw_if_index, self.pg2.sw_if_index, is_l2=1) self.logger.info(self.vapi.ppcli("show interface span")) # Enable packet capturing and start packet sending self.pg_enable_capture(self.pg_interfaces) self.pg_start() # Verify packets outgoing packet streams on mirrored interface (pg2) pg2_expected = len(pkts) pg1_pkts = self.pg1.get_capture(pg2_expected) pg2_pkts = self.pg2.get_capture(pg2_expected) self.bridge(self.pg2.sw_if_index, is_add=0) # Disable SPAN on pg0 (mirrored to pg2) self.vapi.sw_interface_span_enable_disable(self.sub_if.sw_if_index, self.pg2.sw_if_index, state=0, is_l2=1) self.xconnect(self.sub_if.sw_if_index, self.pg1.sw_if_index, is_add=0) self.verify_capture(pg1_pkts, pg2_pkts) def test_span_l2_rx_dst_vxlan(self): """ SPAN l2 rx mirror into vxlan """ self.sub_if.admin_up() self.vapi.sw_interface_set_flags(self.vxlan.sw_if_index, flags=1) self.bridge(self.vxlan.sw_if_index, is_add=1) # Create bi-directional cross-connects between pg0 subif and pg1 self.xconnect(self.sub_if.sw_if_index, self.pg1.sw_if_index) # Create incoming packet streams for packet-generator interfaces pkts = self.create_stream(self.pg0, self.pg_if_packet_sizes, do_dot1=True) self.pg0.add_stream(pkts) # Enable SPAN on pg0 sub if (mirrored to vxlan) self.vapi.sw_interface_span_enable_disable(self.sub_if.sw_if_index, self.vxlan.sw_if_index, is_l2=1) self.logger.info(self.vapi.ppcli("show interface span")) # Enable packet capturing and start packet sending self.pg_enable_capture(self.pg_interfaces) self.pg_start() # Verify packets outgoing packet streams on mirrored interface (pg2) n_pkts = len(pkts) pg1_pkts = self.pg1.get_capture(n_pkts) pg2_pkts = [self.decap_vxlan(p) for p in self.pg2.get_capture(n_pkts)] self.bridge(self.vxlan.sw_if_index, is_add=0) # Disable SPAN on pg0 sub if (mirrored to vxlan) self.vapi.sw_interface_span_enable_disable(self.sub_if.sw_if_index, self.vxlan.sw_if_index, state=0, is_l2=1) self.xconnect(self.sub_if.sw_if_index, self.pg1.sw_if_index, is_add=0) self.verify_capture(pg1_pkts, pg2_pkts) def test_span_l2_rx_dst_gre_erspan(self): """ SPAN l2 rx mirror into gre-erspan """ self.sub_if.admin_up() gre_if = VppGreInterface( self, self.pg2.local_ip4, self.pg2.remote_ip4, session=543, type=(VppEnum.vl_api_gre_tunnel_type_t.GRE_API_TUNNEL_TYPE_ERSPAN)) gre_if.add_vpp_config() gre_if.admin_up() self.bridge(gre_if.sw_if_index) # Create bi-directional cross-connects between pg0 and pg1 self.xconnect(self.sub_if.sw_if_index, self.pg1.sw_if_index, is_add=1) # Create incoming packet streams for packet-generator interfaces pkts = self.create_stream(self.pg0, self.pg_if_packet_sizes, do_dot1=True) self.pg0.add_stream(pkts) # Enable SPAN on pg0 sub if (mirrored to gre-erspan) self.vapi.sw_interface_span_enable_disable(self.sub_if.sw_if_index, gre_if.sw_if_index, is_l2=1) # Enable packet capturing and start packet sending self.pg_enable_capture(self.pg_interfaces) self.pg_start() # Verify packets outgoing packet streams on mirrored interface (pg2) n_pkts = len(pkts) pg1_pkts = self.pg1.get_capture(n_pkts) pg2_pkts = self.pg2.get_capture(n_pkts) def decap(p): return self.decap_erspan(p, session=543) pg2_decaped = [decap(p) for p in pg2_pkts] self.bridge(gre_if.sw_if_index, is_add=0) # Disable SPAN on pg0 sub if self.vapi.sw_interface_span_enable_disable(self.sub_if.sw_if_index, gre_if.sw_if_index, state=0, is_l2=1) gre_if.remove_vpp_config() self.xconnect(self.sub_if.sw_if_index, self.pg1.sw_if_index, is_add=0) self.verify_capture(pg1_pkts, pg2_decaped) def test_span_l2_rx_dst_gre_subif_vtr(self): """ SPAN l2 rx mirror into gre-subif+vtr """ self.sub_if.admin_up() gre_if = VppGreInterface( self, self.pg2.local_ip4, self.pg2.remote_ip4, type=(VppEnum.vl_api_gre_tunnel_type_t.GRE_API_TUNNEL_TYPE_TEB)) gre_if.add_vpp_config() gre_if.admin_up() gre_sub_if = VppDot1QSubint(self, gre_if, 500) gre_sub_if.set_vtr(L2_VTR_OP.L2_POP_1, tag=500) gre_sub_if.admin_up() self.bridge(gre_sub_if.sw_if_index) # Create bi-directional cross-connects between pg0 and pg1 self.xconnect(self.sub_if.sw_if_index, self.pg1.sw_if_index, is_add=1) # Create incoming packet streams for packet-generator interfaces pkts = self.create_stream(self.pg0, self.pg_if_packet_sizes, do_dot1=True) self.pg0.add_stream(pkts) # Enable SPAN on pg0 sub if (mirrored to gre sub if) self.vapi.sw_interface_span_enable_disable(self.sub_if.sw_if_index, gre_sub_if.sw_if_index, is_l2=1) # Enable packet capturing and start packet sending self.pg_enable_capture(self.pg_interfaces) self.pg_start() # Verify packets outgoing packet streams on mirrored interface (pg2) n_pkts = len(pkts) pg1_pkts = self.pg1.get_capture(n_pkts) pg2_pkts = self.pg2.get_capture(n_pkts) def decap(p): return self.remove_tags(self.decap_gre(p), [Tag(dot1=DOT1Q, vlan=500)]) pg2_decaped = [decap(p) for p in pg2_pkts] self.bridge(gre_sub_if.sw_if_index, is_add=0) # Disable SPAN on pg0 sub if self.vapi.sw_interface_span_enable_disable(self.sub_if.sw_if_index, gre_sub_if.sw_if_index, state=0, is_l2=1) gre_if.remove_vpp_config() self.xconnect(self.sub_if.sw_if_index, self.pg1.sw_if_index, is_add=0) self.verify_capture(pg1_pkts, pg2_decaped) def test_span_l2_rx_dst_1q_vtr(self): """ SPAN l2 rx mirror into 1q subif+vtr """ self.sub_if.admin_up() self.vlan_sub_if.admin_up() self.bridge(self.vlan_sub_if.sw_if_index) # Create bi-directional cross-connects between pg0 and pg1 self.xconnect(self.sub_if.sw_if_index, self.pg1.sw_if_index, is_add=1) # Create incoming packet streams for packet-generator interfaces pkts = self.create_stream(self.pg0, self.pg_if_packet_sizes, do_dot1=True) self.pg0.add_stream(pkts) self.vapi.sw_interface_span_enable_disable( self.sub_if.sw_if_index, self.vlan_sub_if.sw_if_index, is_l2=1) # Enable packet capturing and start packet sending self.pg_enable_capture(self.pg_interfaces) self.pg_start() # Verify packets outgoing packet streams on mirrored interface (pg2) n_pkts = len(pkts) pg1_pkts = self.pg1.get_capture(n_pkts) pg2_pkts = self.pg2.get_capture(n_pkts) pg2_untagged = [ self.remove_tags(p, [Tag(dot1=DOT1Q, vlan=300)]) for p in pg2_pkts ] self.bridge(self.vlan_sub_if.sw_if_index, is_add=0) # Disable SPAN on pg0 sub if (mirrored to vxlan) self.vapi.sw_interface_span_enable_disable( self.sub_if.sw_if_index, self.vlan_sub_if.sw_if_index, state=0, is_l2=1) self.xconnect(self.sub_if.sw_if_index, self.pg1.sw_if_index, is_add=0) self.verify_capture(pg1_pkts, pg2_untagged) def test_span_l2_rx_dst_1ad_vtr(self): """ SPAN l2 rx mirror into 1ad subif+vtr """ self.sub_if.admin_up() self.qinq_sub_if.admin_up() self.bridge(self.qinq_sub_if.sw_if_index) # Create bi-directional cross-connects between pg0 and pg1 self.xconnect(self.sub_if.sw_if_index, self.pg1.sw_if_index, is_add=1) # Create incoming packet streams for packet-generator interfaces pkts = self.create_stream(self.pg0, self.pg_if_packet_sizes, do_dot1=True) self.pg0.add_stream(pkts) self.vapi.sw_interface_span_enable_disable( self.sub_if.sw_if_index, self.qinq_sub_if.sw_if_index, is_l2=1) # Enable packet capturing and start packet sending self.pg_enable_capture(self.pg_interfaces) self.pg_start() # Verify packets outgoing packet streams on mirrored interface (pg2) n_pkts = len(pkts) pg1_pkts = self.pg1.get_capture(n_pkts) pg2_pkts = self.pg2.get_capture(n_pkts) pg2_untagged = [ self.remove_tags( p, [Tag(dot1=DOT1AD, vlan=400), Tag(dot1=DOT1Q, vlan=500)]) for p in pg2_pkts ] self.bridge(self.qinq_sub_if.sw_if_index, is_add=0) # Disable SPAN on pg0 sub if (mirrored to vxlan) self.vapi.sw_interface_span_enable_disable( self.sub_if.sw_if_index, self.qinq_sub_if.sw_if_index, state=0, is_l2=1) self.xconnect(self.sub_if.sw_if_index, self.pg1.sw_if_index, is_add=0) self.verify_capture(pg1_pkts, pg2_untagged) def test_l2_tx_span(self): """ SPAN l2 tx mirror """ self.sub_if.admin_up() self.bridge(self.pg2.sw_if_index) # Create bi-directional cross-connects between pg0 and pg1 self.xconnect(self.sub_if.sw_if_index, self.pg1.sw_if_index) # Create incoming packet streams for packet-generator interfaces pkts = self.create_stream(self.pg0, self.pg_if_packet_sizes, do_dot1=True) self.pg0.add_stream(pkts) # Enable SPAN on pg1 (mirrored to pg2) self.vapi.sw_interface_span_enable_disable(self.pg1.sw_if_index, self.pg2.sw_if_index, is_l2=1, state=2) self.logger.info(self.vapi.ppcli("show interface span")) # Enable packet capturing and start packet sending self.pg_enable_capture(self.pg_interfaces) self.pg_start() # Verify packets outgoing packet streams on mirrored interface (pg2) n_pkts = len(pkts) pg1_pkts = self.pg1.get_capture(n_pkts) pg2_pkts = self.pg2.get_capture(n_pkts) self.bridge(self.pg2.sw_if_index, is_add=0) # Disable SPAN on pg0 (mirrored to pg2) self.vapi.sw_interface_span_enable_disable(self.pg1.sw_if_index, self.pg2.sw_if_index, state=0, is_l2=1) self.xconnect(self.sub_if.sw_if_index, self.pg1.sw_if_index, is_add=0) self.verify_capture(pg1_pkts, pg2_pkts) def test_l2_rx_tx_span(self): """ SPAN l2 rx tx mirror """ self.sub_if.admin_up() self.bridge(self.pg2.sw_if_index) # Create bi-directional cross-connects between pg0 and pg1 self.xconnect(self.sub_if.sw_if_index, self.pg1.sw_if_index) # Create incoming packet streams for packet-generator interfaces pg0_pkts = self.create_stream(self.pg0, self.pg_if_packet_sizes, do_dot1=True) self.pg0.add_stream(pg0_pkts) pg1_pkts = self.create_stream(self.pg1, self.pg_if_packet_sizes, do_dot1=False) self.pg1.add_stream(pg1_pkts) # Enable SPAN on pg0 (mirrored to pg2) self.vapi.sw_interface_span_enable_disable(self.sub_if.sw_if_index, self.pg2.sw_if_index, is_l2=1, state=3) self.logger.info(self.vapi.ppcli("show interface span")) # Enable packet capturing and start packet sending self.pg_enable_capture(self.pg_interfaces) self.pg_start() # Verify packets outgoing packet streams on mirrored interface (pg2) pg0_expected = len(pg1_pkts) pg1_expected = len(pg0_pkts) pg2_expected = pg0_expected + pg1_expected pg0_pkts = self.pg0.get_capture(pg0_expected) pg1_pkts = self.pg1.get_capture(pg1_expected) pg2_pkts = self.pg2.get_capture(pg2_expected) self.bridge(self.pg2.sw_if_index, is_add=0) # Disable SPAN on pg0 (mirrored to pg2) self.vapi.sw_interface_span_enable_disable(self.sub_if.sw_if_index, self.pg2.sw_if_index, state=0, is_l2=1) self.xconnect(self.sub_if.sw_if_index, self.pg1.sw_if_index, is_add=0) self.verify_capture(pg0_pkts + pg1_pkts, pg2_pkts) def test_l2_bcast_mirror(self): """ SPAN l2 broadcast mirror """ self.sub_if.admin_up() self.bridge(self.pg2.sw_if_index) # Create bi-directional cross-connects between pg0 and pg1 self.vapi.sw_interface_set_l2_bridge( rx_sw_if_index=self.sub_if.sw_if_index, bd_id=99, enable=1) self.vapi.sw_interface_set_l2_bridge( rx_sw_if_index=self.pg1.sw_if_index, bd_id=99, enable=1) # Create incoming packet streams for packet-generator interfaces pg0_pkts = self.create_stream(self.pg0, self.pg_if_packet_sizes, do_dot1=True, bcast=True) self.pg0.add_stream(pg0_pkts) pg1_pkts = self.create_stream(self.pg1, self.pg_if_packet_sizes, do_dot1=False, bcast=True) self.pg1.add_stream(pg1_pkts) # Enable SPAN on pg0 (mirrored to pg2) self.vapi.sw_interface_span_enable_disable(self.sub_if.sw_if_index, self.pg2.sw_if_index, is_l2=1, state=3) self.logger.info(self.vapi.ppcli("show interface span")) # Enable packet capturing and start packet sending self.pg_enable_capture(self.pg_interfaces) self.pg_start() # Verify packets outgoing packet streams on mirrored interface (pg2) pg0_expected = len(pg1_pkts) pg1_expected = len(pg0_pkts) pg2_expected = pg0_expected + pg1_expected pg0_pkts = self.pg0.get_capture(pg0_expected) pg1_pkts = self.pg1.get_capture(pg1_expected) pg2_pkts = self.pg2.get_capture(pg2_expected) self.bridge(self.pg2.sw_if_index, is_add=0) self.vapi.sw_interface_set_l2_bridge( rx_sw_if_index=self.sub_if.sw_if_index, bd_id=99, enable=0) self.vapi.sw_interface_set_l2_bridge( rx_sw_if_index=self.pg1.sw_if_index, bd_id=99, enable=0) # Disable SPAN on pg0 (mirrored to pg2) self.vapi.sw_interface_span_enable_disable(self.sub_if.sw_if_index, self.pg2.sw_if_index, state=0, is_l2=1) self.verify_capture(pg0_pkts + pg1_pkts, pg2_pkts)