def test_map_e(self): """ MAP-E """ # # Add a route to the MAP-BR # map_br_pfx = "2001::" map_br_pfx_len = 64 map_route = VppIpRoute(self, map_br_pfx, map_br_pfx_len, [ VppRoutePath(self.pg1.remote_ip6, self.pg1.sw_if_index, proto=DpoProto.DPO_PROTO_IP6) ], is_ip6=1) map_route.add_vpp_config() # # Add a domain that maps from pg0 to pg1 # map_dst = '2001::/64' map_src = '3000::1/128' client_pfx = '192.168.0.0/16' self.vapi.map_add_domain(map_dst, client_pfx, map_src) # Enable MAP on interface. self.vapi.map_if_enable_disable(is_enable=1, sw_if_index=self.pg0.sw_if_index, is_translation=0) # Ensure MAP doesn't steal all packets! v4 = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) / IP(src=self.pg0.remote_ip4, dst=self.pg0.remote_ip4) / UDP(sport=20000, dport=10000) / Raw('\xa5' * 100)) rx = self.send_and_expect(self.pg0, v4 * 1, self.pg0) v4_reply = v4[1] v4_reply.ttl -= 1 for p in rx: self.validate(p[1], v4_reply) # # Fire in a v4 packet that will be encapped to the BR # v4 = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) / IP(src=self.pg0.remote_ip4, dst='192.168.1.1') / UDP(sport=20000, dport=10000) / Raw('\xa5' * 100)) self.send_and_assert_encapped(v4, "3000::1", "2001::c0a8:0:0") # Enable MAP on interface. self.vapi.map_if_enable_disable(is_enable=1, sw_if_index=self.pg1.sw_if_index, is_translation=0) # Ensure MAP doesn't steal all packets v6 = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) / IPv6(src=self.pg1.remote_ip6, dst=self.pg1.remote_ip6) / UDP(sport=20000, dport=10000) / Raw('\xa5' * 100)) rx = self.send_and_expect(self.pg1, v6 * 1, self.pg1) v6_reply = v6[1] v6_reply.hlim -= 1 for p in rx: self.validate(p[1], v6_reply) # # Fire in a V6 encapped packet. # expect a decapped packet on the inside ip4 link # p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) / IPv6(dst='3000::1', src="2001::1") / IP(dst=self.pg0.remote_ip4, src='192.168.1.1') / UDP(sport=20000, dport=10000) / Raw('\xa5' * 100)) self.pg1.add_stream(p) self.pg_enable_capture(self.pg_interfaces) self.pg_start() rx = self.pg0.get_capture(1) rx = rx[0] self.assertFalse(rx.haslayer(IPv6)) self.assertEqual(rx[IP].src, p[IP].src) self.assertEqual(rx[IP].dst, p[IP].dst) # # Pre-resolve. No API for this!! # self.vapi.ppcli("map params pre-resolve ip6-nh 4001::1") self.send_and_assert_no_replies(self.pg0, v4, "resolved via default route") # # Add a route to 4001::1. Expect the encapped traffic to be # sent via that routes next-hop # pre_res_route = VppIpRoute( self, "4001::1", 128, [ VppRoutePath(self.pg1.remote_hosts[2].ip6, self.pg1.sw_if_index, proto=DpoProto.DPO_PROTO_IP6) ], is_ip6=1) pre_res_route.add_vpp_config() self.send_and_assert_encapped(v4, "3000::1", "2001::c0a8:0:0", dmac=self.pg1.remote_hosts[2].mac) # # change the route to the pre-solved next-hop # pre_res_route.modify([ VppRoutePath(self.pg1.remote_hosts[3].ip6, self.pg1.sw_if_index, proto=DpoProto.DPO_PROTO_IP6) ]) pre_res_route.add_vpp_config() self.send_and_assert_encapped(v4, "3000::1", "2001::c0a8:0:0", dmac=self.pg1.remote_hosts[3].mac) # # cleanup. The test infra's object registry will ensure # the route is really gone and thus that the unresolve worked. # pre_res_route.remove_vpp_config() self.vapi.ppcli("map params pre-resolve del ip6-nh 4001::1")
def create_ip(self, src_ip=None, dst_ip=None, tran_l_proto="UDP", pkt_len=None, src_port=None, dst_port=None, cnt=100, inter=0.01): # If src_ip is named in machines, use that, and its mac addr # Else if src_ip written in octet format, use it and random addr # Else randomly select from machnes given along with mac #-------------------------------------- # SRC IP, MAC, PORT #-------------------------------------- if src_ip == None: # Select key at random machine_name = random.choice(list(machines.keys())) src = machines[machine_name]['ip'] # Select random mac src_mac = self.rand_mac() elif src_ip in machines: src = machines[src_ip]['ip'] src_mac = machines[src_ip]['mac'] if src_port == None: src_port = machines[src_ip]['port'] else: # Custom IP src = src_ip # Random mac src_mac = self.rand_mac() if src_port == None: src_port = self.random_port() else: src_port = int(src_port) print(src, src_mac, src_port) #-------------------------------------- # DST IP, MAC, PORT #-------------------------------------- if dst_ip == None: # Select key at random machine_name = random.choice(list(machines.keys())) dst = machines[machine_name]['ip'] # Select random mac dst_mac = self.rand_mac() elif dst_ip in machines: dst = machines[dst_ip]['ip'] dst_mac = machines[dst_ip]['mac'] if dst_port == None: dst_port = machines[dst_ip]['port'] else: # Custom IP dst = dst_ip # Random mac dst_mac = self.rand_mac() if dst_port == None: dst_port = self.random_port() else: dst_port = int(dst_port) print(dst, dst_mac, dst_port) #-------------------------------------- # LENGTH, Protocol #-------------------------------------- if pkt_len is None: pkt_len = random.randint(1, PKT_MAX_LEN) load = os.urandom(int(pkt_len)) #-------------------------------------- # Packet gerneration #-------------------------------------- pkt = None if tran_l_proto == "UDP": pkt = Ether(dst=dst_mac, src=src_mac, type=ETHER_TYPES['IPv4'])/\ IP(dst=dst, src=src,)/\ UDP(dport=dst_port, sport=src_port)/\ Raw(load=load) #print(len(load)) pkt.show2() else: # TCP pkt = Ether(dst=dst_mac, src=src_mac, type=ETHER_TYPES['IPv4'])/\ IP(dst=dst, src=src,)/\ TCP(dport=dst_port, sport=src_port)/\ Raw(load=load) #print(len(load)) pkt.show2() return pkt
def test_fif6(self): """ Fragments in fragments (6o6) """ # TODO this should be ideally in setUpClass, but then we hit a bug # with VppIpRoute incorrectly reporting it's present when it's not # so we need to manually remove the vpp config, thus we cannot have # it shared for multiple test cases self.tun_ip6 = "1002::1" self.gre6 = VppGre6Interface(self, self.src_if.local_ip6, self.tun_ip6) self.gre6.add_vpp_config() self.gre6.admin_up() self.gre6.config_ip6() self.vapi.ip_reassembly_enable_disable( sw_if_index=self.gre6.sw_if_index, enable_ip6=True) self.route6 = VppIpRoute(self, self.tun_ip6, 128, [ VppRoutePath(self.src_if.remote_ip6, self.src_if.sw_if_index, proto=DpoProto.DPO_PROTO_IP6) ], is_ip6=1) self.route6.add_vpp_config() self.reset_packet_infos() for i in range(test_packet_count): info = self.create_packet_info(self.src_if, self.dst_if) payload = self.info_to_payload(info) # Ethernet header here is only for size calculation, thus it # doesn't matter how it's initialized. This is to ensure that # reassembled packet is not > 9000 bytes, so that it's not dropped p = (Ether() / IPv6(src=self.src_if.remote_ip6, dst=self.dst_if.remote_ip6) / UDP(sport=1234, dport=5678) / Raw(payload)) size = self.packet_sizes[(i // 2) % len(self.packet_sizes)] self.extend_packet(p, size, self.padding) info.data = p[IPv6] # use only IPv6 part, without ethernet header fragments = [ x for _, i in six.iteritems(self._packet_infos) for x in fragment_rfc8200(i.data, i.index, 400) ] encapped_fragments = \ [Ether(dst=self.src_if.local_mac, src=self.src_if.remote_mac) / IPv6(src=self.tun_ip6, dst=self.src_if.local_ip6) / GRE() / p for p in fragments] fragmented_encapped_fragments = \ [x for p in encapped_fragments for x in ( fragment_rfc8200( p, 2 * len(self._packet_infos) + p[IPv6ExtHdrFragment].id, 200) if IPv6ExtHdrFragment in p else [p] ) ] self.src_if.add_stream(fragmented_encapped_fragments) self.pg_enable_capture(self.pg_interfaces) self.pg_start() self.src_if.assert_nothing_captured() packets = self.dst_if.get_capture(len(self._packet_infos)) self.verify_capture(packets, IPv6) # TODO remove gre vpp config by hand until VppIpRoute gets fixed # so that it's query_vpp_config() works as it should self.gre6.remove_vpp_config()
def test_bier_tail_o_udp(self): """BIER Tail over UDP""" # # Add a BIER table for sub-domain 0, set 0, and BSL 256 # bti = VppBierTableID(1, 0, BIERLength.BIER_LEN_256) bt = VppBierTable(self, bti, MPLS_LABEL_INVALID) bt.add_vpp_config() # # disposition table # bdt = VppBierDispTable(self, 8) bdt.add_vpp_config() # # BIER route in table that's for-us # bier_route_1 = VppBierRoute( self, bti, 1, [VppRoutePath("0.0.0.0", 0xffffffff, nh_table_id=8)]) bier_route_1.add_vpp_config() # # An entry in the disposition table # bier_de_1 = VppBierDispEntry(self, bdt.id, 99, BIER_HDR_PAYLOAD.BIER_HDR_PROTO_IPV4, DpoProto.DPO_PROTO_BIER, "0.0.0.0", 0, rpf_id=8192) bier_de_1.add_vpp_config() # # A multicast route to forward post BIER disposition # route_eg_232_1_1_1 = VppIpMRoute( self, "0.0.0.0", "232.1.1.1", 32, MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE, paths=[ VppMRoutePath(self.pg1.sw_if_index, MRouteItfFlags.MFIB_ITF_FLAG_FORWARD) ]) route_eg_232_1_1_1.add_vpp_config() route_eg_232_1_1_1.update_rpf_id(8192) # # A packet with all bits set gets spat out to BP:1 # p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) / IP(src=self.pg0.remote_ip4, dst=self.pg0.local_ip4) / UDP(sport=333, dport=8138) / BIFT(sd=1, set=0, bsl=2, ttl=255) / BIER(length=BIERLength.BIER_LEN_256, BitString=chr(255) * 32, BFRID=99) / IP(src="1.1.1.1", dst="232.1.1.1") / UDP(sport=1234, dport=1234) / Raw()) rx = self.send_and_expect(self.pg0, [p], self.pg1)
async def run_test(dut): tb = TB(dut) await tb.init() tb.log.info("test UDP RX packet") payload = bytes([x % 256 for x in range(256)]) eth = Ether(src='5a:51:52:53:54:55', dst='02:00:00:00:00:00') ip = IP(src='192.168.1.100', dst='192.168.1.128') udp = UDP(sport=5678, dport=1234) test_pkt = eth / ip / udp / payload test_frame = XgmiiFrame.from_payload(test_pkt.build()) await tb.qsfp_0_0_source.send(test_frame) tb.log.info("receive ARP request") rx_frame = await tb.qsfp_0_0_sink.recv() rx_pkt = Ether(bytes(rx_frame.get_payload())) tb.log.info("RX packet: %s", repr(rx_pkt)) assert rx_pkt.dst == 'ff:ff:ff:ff:ff:ff' assert rx_pkt.src == test_pkt.dst assert rx_pkt[ARP].hwtype == 1 assert rx_pkt[ARP].ptype == 0x0800 assert rx_pkt[ARP].hwlen == 6 assert rx_pkt[ARP].plen == 4 assert rx_pkt[ARP].op == 1 assert rx_pkt[ARP].hwsrc == test_pkt.dst assert rx_pkt[ARP].psrc == test_pkt[IP].dst assert rx_pkt[ARP].hwdst == '00:00:00:00:00:00' assert rx_pkt[ARP].pdst == test_pkt[IP].src tb.log.info("send ARP response") eth = Ether(src=test_pkt.src, dst=test_pkt.dst) arp = ARP(hwtype=1, ptype=0x0800, hwlen=6, plen=4, op=2, hwsrc=test_pkt.src, psrc=test_pkt[IP].src, hwdst=test_pkt.dst, pdst=test_pkt[IP].dst) resp_pkt = eth / arp resp_frame = XgmiiFrame.from_payload(resp_pkt.build()) await tb.qsfp_0_0_source.send(resp_frame) tb.log.info("receive UDP packet") rx_frame = await tb.qsfp_0_0_sink.recv() rx_pkt = Ether(bytes(rx_frame.get_payload())) tb.log.info("RX packet: %s", repr(rx_pkt)) assert rx_pkt.dst == test_pkt.src assert rx_pkt.src == test_pkt.dst assert rx_pkt[IP].dst == test_pkt[IP].src assert rx_pkt[IP].src == test_pkt[IP].dst assert rx_pkt[UDP].dport == test_pkt[UDP].sport assert rx_pkt[UDP].sport == test_pkt[UDP].dport assert rx_pkt[UDP].payload == test_pkt[UDP].payload await RisingEdge(dut.clk) await RisingEdge(dut.clk)
def test_bier_head(self): """BIER head""" # # Add a BIER table for sub-domain 0, set 0, and BSL 256 # bti = VppBierTableID(0, 0, BIERLength.BIER_LEN_256) bt = VppBierTable(self, bti, 77) bt.add_vpp_config() # # 2 bit positions via two next hops # nh1 = "10.0.0.1" nh2 = "10.0.0.2" ip_route_1 = VppIpRoute(self, nh1, 32, [ VppRoutePath( self.pg1.remote_ip4, self.pg1.sw_if_index, labels=[2001]) ]) ip_route_2 = VppIpRoute(self, nh2, 32, [ VppRoutePath( self.pg1.remote_ip4, self.pg1.sw_if_index, labels=[2002]) ]) ip_route_1.add_vpp_config() ip_route_2.add_vpp_config() bier_route_1 = VppBierRoute( self, bti, 1, [VppRoutePath(nh1, 0xffffffff, labels=[101])]) bier_route_2 = VppBierRoute( self, bti, 2, [VppRoutePath(nh2, 0xffffffff, labels=[102])]) bier_route_1.add_vpp_config() bier_route_2.add_vpp_config() # # An imposition object with both bit-positions set # bi = VppBierImp(self, bti, 333, chr(0x3) * 32) bi.add_vpp_config() # # Add a multicast route that will forward into the BIER doamin # route_ing_232_1_1_1 = VppIpMRoute( self, "0.0.0.0", "232.1.1.1", 32, MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE, paths=[ VppMRoutePath(self.pg0.sw_if_index, MRouteItfFlags.MFIB_ITF_FLAG_ACCEPT), VppMRoutePath(0xffffffff, MRouteItfFlags.MFIB_ITF_FLAG_FORWARD, proto=DpoProto.DPO_PROTO_BIER, bier_imp=bi.bi_index) ]) route_ing_232_1_1_1.add_vpp_config() # # inject an IP packet. We expect it to be BIER encapped and # replicated. # p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) / IP(src="1.1.1.1", dst="232.1.1.1") / UDP(sport=1234, dport=1234)) self.pg0.add_stream([p]) self.pg_enable_capture(self.pg_interfaces) self.pg_start() rx = self.pg1.get_capture(2) # # Encap Stack is; eth, MPLS, MPLS, BIER # igp_mpls = rx[0][MPLS] self.assertEqual(igp_mpls.label, 2001) self.assertEqual(igp_mpls.ttl, 64) self.assertEqual(igp_mpls.s, 0) bier_mpls = igp_mpls[MPLS].payload self.assertEqual(bier_mpls.label, 101) self.assertEqual(bier_mpls.ttl, 64) self.assertEqual(bier_mpls.s, 1) self.assertEqual(rx[0][BIER].length, 2) igp_mpls = rx[1][MPLS] self.assertEqual(igp_mpls.label, 2002) self.assertEqual(igp_mpls.ttl, 64) self.assertEqual(igp_mpls.s, 0) bier_mpls = igp_mpls[MPLS].payload self.assertEqual(bier_mpls.label, 102) self.assertEqual(bier_mpls.ttl, 64) self.assertEqual(bier_mpls.s, 1) self.assertEqual(rx[0][BIER].length, 2)
def bier_e2e(self, hdr_len_id, n_bytes, max_bp): """ BIER end-to-end""" # # Add a BIER table for sub-domain 0, set 0, and BSL 256 # bti = VppBierTableID(0, 0, hdr_len_id) bt = VppBierTable(self, bti, 77) bt.add_vpp_config() lowest = ['\0'] * (n_bytes) lowest[-1] = chr(1) highest = ['\0'] * (n_bytes) highest[0] = chr(128) # # Impostion Sets bit strings # bi_low = VppBierImp(self, bti, 333, lowest) bi_low.add_vpp_config() bi_high = VppBierImp(self, bti, 334, highest) bi_high.add_vpp_config() # # Add a multicast route that will forward into the BIER doamin # route_ing_232_1_1_1 = VppIpMRoute( self, "0.0.0.0", "232.1.1.1", 32, MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE, paths=[ VppMRoutePath(self.pg0.sw_if_index, MRouteItfFlags.MFIB_ITF_FLAG_ACCEPT), VppMRoutePath(0xffffffff, MRouteItfFlags.MFIB_ITF_FLAG_FORWARD, proto=DpoProto.DPO_PROTO_BIER, bier_imp=bi_low.bi_index) ]) route_ing_232_1_1_1.add_vpp_config() route_ing_232_1_1_2 = VppIpMRoute( self, "0.0.0.0", "232.1.1.2", 32, MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE, paths=[ VppMRoutePath(self.pg0.sw_if_index, MRouteItfFlags.MFIB_ITF_FLAG_ACCEPT), VppMRoutePath(0xffffffff, MRouteItfFlags.MFIB_ITF_FLAG_FORWARD, proto=DpoProto.DPO_PROTO_BIER, bier_imp=bi_high.bi_index) ]) route_ing_232_1_1_2.add_vpp_config() # # disposition table 8 # bdt = VppBierDispTable(self, 8) bdt.add_vpp_config() # # BIER routes in table that are for-us, resolving through # disp table 8. # bier_route_1 = VppBierRoute( self, bti, 1, [VppRoutePath("0.0.0.0", 0xffffffff, nh_table_id=8)]) bier_route_1.add_vpp_config() bier_route_max = VppBierRoute( self, bti, max_bp, [VppRoutePath("0.0.0.0", 0xffffffff, nh_table_id=8)]) bier_route_max.add_vpp_config() # # An entry in the disposition table for sender 333 # lookup in VRF 10 # bier_de_1 = VppBierDispEntry(self, bdt.id, 333, BIER_HDR_PAYLOAD.BIER_HDR_PROTO_IPV4, DpoProto.DPO_PROTO_BIER, "0.0.0.0", 10, rpf_id=8192) bier_de_1.add_vpp_config() bier_de_1 = VppBierDispEntry(self, bdt.id, 334, BIER_HDR_PAYLOAD.BIER_HDR_PROTO_IPV4, DpoProto.DPO_PROTO_BIER, "0.0.0.0", 10, rpf_id=8193) bier_de_1.add_vpp_config() # # Add a multicast routes that will forward the traffic # post-disposition # route_eg_232_1_1_1 = VppIpMRoute( self, "0.0.0.0", "232.1.1.1", 32, MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE, table_id=10, paths=[ VppMRoutePath(self.pg1.sw_if_index, MRouteItfFlags.MFIB_ITF_FLAG_FORWARD) ]) route_eg_232_1_1_1.add_vpp_config() route_eg_232_1_1_1.update_rpf_id(8192) route_eg_232_1_1_2 = VppIpMRoute( self, "0.0.0.0", "232.1.1.2", 32, MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE, table_id=10, paths=[ VppMRoutePath(self.pg1.sw_if_index, MRouteItfFlags.MFIB_ITF_FLAG_FORWARD) ]) route_eg_232_1_1_2.add_vpp_config() route_eg_232_1_1_2.update_rpf_id(8193) # # inject a packet in VRF-0. We expect it to be BIER encapped, # replicated, then hit the disposition and be forwarded # out of VRF 10, i.e. on pg1 # p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) / IP(src="1.1.1.1", dst="232.1.1.1") / UDP(sport=1234, dport=1234) / Raw(chr(5) * 32)) rx = self.send_and_expect(self.pg0, p * 65, self.pg1) self.assertEqual(rx[0][IP].src, "1.1.1.1") self.assertEqual(rx[0][IP].dst, "232.1.1.1") p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) / IP(src="1.1.1.1", dst="232.1.1.2") / UDP(sport=1234, dport=1234) / Raw(chr(5) * 512)) rx = self.send_and_expect(self.pg0, p * 65, self.pg1) self.assertEqual(rx[0][IP].src, "1.1.1.1") self.assertEqual(rx[0][IP].dst, "232.1.1.2")
def test_wg_peer_init(self): """ Handoff """ wg_output_node_name = '/err/wg-output-tun/' wg_input_node_name = '/err/wg-input/' port = 12353 # Create interfaces wg0 = VppWgInterface(self, self.pg1.local_ip4, port).add_vpp_config() wg0.admin_up() wg0.config_ip4() peer_1 = VppWgPeer(self, wg0, self.pg1.remote_ip4, port + 1, ["10.11.2.0/24", "10.11.3.0/24"]).add_vpp_config() self.assertEqual(len(self.vapi.wireguard_peers_dump()), 1) # send a valid handsake init for which we expect a response p = peer_1.mk_handshake(self.pg1) rx = self.send_and_expect(self.pg1, [p], self.pg1) peer_1.consume_response(rx[0]) # send a data packet from the peer through the tunnel # this completes the handshake and pins the peer to worker 0 p = (IP(src="10.11.3.1", dst=self.pg0.remote_ip4, ttl=20) / UDP(sport=222, dport=223) / Raw()) d = peer_1.encrypt_transport(p) p = (peer_1.mk_tunnel_header(self.pg1) / (Wireguard(message_type=4, reserved_zero=0) / WireguardTransport(receiver_index=peer_1.sender, counter=0, encrypted_encapsulated_packet=d))) rxs = self.send_and_expect(self.pg1, [p], self.pg0, worker=0) for rx in rxs: self.assertEqual(rx[IP].dst, self.pg0.remote_ip4) self.assertEqual(rx[IP].ttl, 19) # send a packets that are routed into the tunnel # and pins the peer tp worker 1 pe = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) / IP(src=self.pg0.remote_ip4, dst="10.11.3.2") / UDP(sport=555, dport=556) / Raw(b'\x00' * 80)) rxs = self.send_and_expect(self.pg0, pe * 255, self.pg1, worker=1) peer_1.validate_encapped(rxs, pe) # send packets into the tunnel, from the other worker p = [(peer_1.mk_tunnel_header(self.pg1) / Wireguard(message_type=4, reserved_zero=0) / WireguardTransport( receiver_index=peer_1.sender, counter=ii + 1, encrypted_encapsulated_packet=peer_1.encrypt_transport( (IP(src="10.11.3.1", dst=self.pg0.remote_ip4, ttl=20) / UDP(sport=222, dport=223) / Raw())))) for ii in range(255)] rxs = self.send_and_expect(self.pg1, p, self.pg0, worker=1) for rx in rxs: self.assertEqual(rx[IP].dst, self.pg0.remote_ip4) self.assertEqual(rx[IP].ttl, 19) # send a packets that are routed into the tunnel # from owrker 0 rxs = self.send_and_expect(self.pg0, pe * 255, self.pg1, worker=0) peer_1.validate_encapped(rxs, pe) peer_1.remove_vpp_config() wg0.remove_vpp_config()
for block in scanner: if firstBlock and isinstance(block, EnhancedPacket): firstBlock = False timestampOrigin = block.timestamp if isinstance(block, EnhancedPacket): packetId += 1 if packetId < start_id: continue if packetId > end_id: break decoded = Ether(block.packet_data) _pl1 = decoded.payload _pl2 = _pl1.payload if isinstance(_pl1, IP) and isinstance(_pl2, TCP) and _pl1.src == src_ip and _pl1.dst == dst_ip: # Skip this packet if it was sent before currentSeq = _pl2.seq if currentSeq in seqHistory: if enabled_debug: print("Skipped a redundant packet.") continue else: seqHistory.append(currentSeq) currentPacketTimestamp = block.timestamp - timestampOrigin
def mk_tunnel_header(self, tx_itf): return (Ether(dst=tx_itf.local_mac, src=tx_itf.remote_mac) / IP(src=self.endpoint, dst=self.itf.src) / UDP(sport=self.port, dport=self.itf.port))
def test_wg_peer_init(self): """ Send handshake init """ wg_output_node_name = '/err/wg-output-tun/' wg_input_node_name = '/err/wg-input/' port = 12333 # Create interfaces wg0 = VppWgInterface(self, self.pg1.local_ip4, port).add_vpp_config() wg0.admin_up() wg0.config_ip4() peer_1 = VppWgPeer(self, wg0, self.pg1.remote_ip4, port + 1, ["10.11.2.0/24", "10.11.3.0/24"]).add_vpp_config() self.assertEqual(len(self.vapi.wireguard_peers_dump()), 1) # route a packet into the wg interface # use the allowed-ip prefix # this is dropped because the peer is not initiated p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) / IP(src=self.pg0.remote_ip4, dst="10.11.3.2") / UDP(sport=555, dport=556) / Raw()) self.send_and_assert_no_replies(self.pg0, [p]) kp_error = wg_output_node_name + "Keypair error" self.assertEqual(1, self.statistics.get_err_counter(kp_error)) # send a handsake from the peer with an invalid MAC p = peer_1.mk_handshake(self.pg1) p[WireguardInitiation].mac1 = b'foobar' self.send_and_assert_no_replies(self.pg1, [p]) self.assertEqual( 1, self.statistics.get_err_counter(wg_input_node_name + "Invalid MAC handshake")) # send a handsake from the peer but signed by the wrong key. p = peer_1.mk_handshake(self.pg1, X25519PrivateKey.generate().public_key()) self.send_and_assert_no_replies(self.pg1, [p]) self.assertEqual( 1, self.statistics.get_err_counter(wg_input_node_name + "Peer error")) # send a valid handsake init for which we expect a response p = peer_1.mk_handshake(self.pg1) rx = self.send_and_expect(self.pg1, [p], self.pg1) peer_1.consume_response(rx[0]) # route a packet into the wg interface # this is dropped because the peer is still not initiated p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) / IP(src=self.pg0.remote_ip4, dst="10.11.3.2") / UDP(sport=555, dport=556) / Raw()) self.send_and_assert_no_replies(self.pg0, [p]) self.assertEqual(2, self.statistics.get_err_counter(kp_error)) # send a data packet from the peer through the tunnel # this completes the handshake p = (IP(src="10.11.3.1", dst=self.pg0.remote_ip4, ttl=20) / UDP(sport=222, dport=223) / Raw()) d = peer_1.encrypt_transport(p) p = (peer_1.mk_tunnel_header(self.pg1) / (Wireguard(message_type=4, reserved_zero=0) / WireguardTransport(receiver_index=peer_1.sender, counter=0, encrypted_encapsulated_packet=d))) rxs = self.send_and_expect(self.pg1, [p], self.pg0) for rx in rxs: self.assertEqual(rx[IP].dst, self.pg0.remote_ip4) self.assertEqual(rx[IP].ttl, 19) # send a packets that are routed into the tunnel p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) / IP(src=self.pg0.remote_ip4, dst="10.11.3.2") / UDP(sport=555, dport=556) / Raw(b'\x00' * 80)) rxs = self.send_and_expect(self.pg0, p * 255, self.pg1) for rx in rxs: rx = IP(peer_1.decrypt_transport(rx)) # chech the oringial packet is present self.assertEqual(rx[IP].dst, p[IP].dst) self.assertEqual(rx[IP].ttl, p[IP].ttl - 1) # send packets into the tunnel, expect to receive them on # the other side p = [(peer_1.mk_tunnel_header(self.pg1) / Wireguard(message_type=4, reserved_zero=0) / WireguardTransport( receiver_index=peer_1.sender, counter=ii + 1, encrypted_encapsulated_packet=peer_1.encrypt_transport( (IP(src="10.11.3.1", dst=self.pg0.remote_ip4, ttl=20) / UDP(sport=222, dport=223) / Raw())))) for ii in range(255)] rxs = self.send_and_expect(self.pg1, p, self.pg0) for rx in rxs: self.assertEqual(rx[IP].dst, self.pg0.remote_ip4) self.assertEqual(rx[IP].ttl, 19) peer_1.remove_vpp_config() wg0.remove_vpp_config()
async def run_test(dut, payload_lengths=None, payload_data=None, idle_inserter=None, backpressure_inserter=None): tb = TB(dut) await tb.reset() tb.set_idle_generator(idle_inserter) tb.set_backpressure_generator(backpressure_inserter) test_pkts = [] test_frames = [] ip_id = 1 for payload in [payload_data(x) for x in payload_lengths()]: eth = Ether(src='5A:51:52:53:54:55', dst='DA:D1:D2:D3:D4:D5') ip = IP(src='192.168.1.100', dst='192.168.1.101', id=ip_id) udp = UDP(sport=1234, dport=4321) test_pkt = eth / ip / udp / payload ip_id = (ip_id + 1) & 0xffff # don't compute checksum test_pkts.append(test_pkt.copy()) test_frame = AxiStreamFrame(test_pkt.build()) test_frames.append(test_frame) await tb.source.send(test_frame) await tb.cmd_source.send( CsumCmdTransaction(csum_enable=0, csum_start=34, csum_offset=40, csum_init=0)) # inline partial checksum test_pkts.append(test_pkt.copy()) pkt = test_pkt.copy() partial_csum = scapy.utils.checksum(bytes(pkt[UDP])) pkt[UDP].chksum = partial_csum test_frame = AxiStreamFrame(pkt.build()) test_frames.append(test_frame) await tb.source.send(test_frame) await tb.cmd_source.send( CsumCmdTransaction(csum_enable=1, csum_start=34, csum_offset=40, csum_init=0)) # partial checksum in command test_pkts.append(test_pkt.copy()) pkt = test_pkt.copy() partial_csum = scapy.utils.checksum(bytes(pkt[UDP])) pkt[UDP].chksum = 0 test_frame = AxiStreamFrame(pkt.build()) test_frames.append(test_frame) await tb.source.send(test_frame) await tb.cmd_source.send( CsumCmdTransaction(csum_enable=1, csum_start=34, csum_offset=40, csum_init=partial_csum)) for test_pkt, test_frame in zip(test_pkts, test_frames): rx_frame = await tb.sink.recv() rx_pkt = Ether(bytes(rx_frame)) tb.log.info("RX packet: %s", repr(rx_pkt)) check_pkt = Ether(test_pkt.build()) tb.log.info("RX packet UDP checksum: 0x%04x (expected 0x%04x)", rx_pkt[UDP].chksum, check_pkt[UDP].chksum) assert check_pkt == rx_pkt assert tb.sink.empty() await RisingEdge(dut.clk) await RisingEdge(dut.clk)
async def run_test_offsets(dut, payload_lengths=None, payload_data=None, idle_inserter=None, backpressure_inserter=None): tb = TB(dut) await tb.reset() tb.set_idle_generator(idle_inserter) tb.set_backpressure_generator(backpressure_inserter) test_pkts = [] test_frames = [] check_frames = [] ip_id = 1 for payload in [payload_data(x) for x in payload_lengths()]: eth = Ether(src='5A:51:52:53:54:55', dst='DA:D1:D2:D3:D4:D5') test_pkt = eth / payload ip_id = (ip_id + 1) & 0xffff for start in range(0, min(len(payload) + 14, 32)): offset = 0 test_pkts.append(test_pkt.copy()) test_frame = AxiStreamFrame(test_pkt.build()) test_frames.append(test_frame) await tb.source.send(test_frame) await tb.cmd_source.send( CsumCmdTransaction(csum_enable=1, csum_start=start, csum_offset=offset, csum_init=0)) csum = scapy.utils.checksum(bytes(test_pkt)[start:]) check_frame = bytearray(test_frame.tdata) struct.pack_into('>H', check_frame, offset, csum) check_frames.append(check_frame) for offset in range(0, min(len(payload) + 14, 32) - 1): start = 0 test_pkts.append(test_pkt.copy()) test_frame = AxiStreamFrame(test_pkt.build()) test_frames.append(test_frame) await tb.source.send(test_frame) await tb.cmd_source.send( CsumCmdTransaction(csum_enable=1, csum_start=start, csum_offset=offset, csum_init=0)) csum = scapy.utils.checksum(bytes(test_pkt)[start:]) check_frame = bytearray(test_frame.tdata) struct.pack_into('>H', check_frame, offset, csum) check_frames.append(check_frame) for test_pkt, test_frame, check_frame in zip(test_pkts, test_frames, check_frames): rx_frame = await tb.sink.recv() rx_pkt = Ether(bytes(rx_frame)) tb.log.info("RX packet: %s", repr(rx_pkt)) assert rx_frame.tdata == check_frame assert tb.sink.empty() await RisingEdge(dut.clk) await RisingEdge(dut.clk)
def get_mac(target): arp_broadcast = Ether(dst="ff:ff:ff:ff:ff:ff") / ARP(op=ARP.who_has, pdst=target) answered = srp(arp_broadcast, timeout=2, verbose=False)[0] # Return the MAC address of the target machine that responded to our ARP broadcast return answered[0][1].hwsrc
async def run_test_nic(dut): tb = TB(dut) await tb.init() tb.log.info("Init driver") await tb.driver.init_dev(tb.dev.functions[0].pcie_id) await tb.driver.interfaces[0].open() # await driver.interfaces[1].open() # enable queues tb.log.info("Enable queues") await tb.rc.mem_write_dword( tb.driver.interfaces[0].ports[0].hw_addr + mqnic.MQNIC_PORT_REG_SCHED_ENABLE, 0x00000001) for k in range(tb.driver.interfaces[0].tx_queue_count): await tb.rc.mem_write_dword( tb.driver.interfaces[0].ports[0].schedulers[0].hw_addr + 4 * k, 0x00000003) # wait for all writes to complete await tb.rc.mem_read(tb.driver.hw_addr, 4) tb.log.info("Init complete") tb.log.info("Send and receive single packet") data = bytearray([x % 256 for x in range(1024)]) await tb.driver.interfaces[0].start_xmit(data, 0) pkt = await tb.sfp_1_sink.recv() tb.log.info("Packet: %s", pkt) await tb.sfp_1_source.send(pkt) pkt = await tb.driver.interfaces[0].recv() tb.log.info("Packet: %s", pkt) assert pkt.rx_checksum == ~scapy.utils.checksum(bytes( pkt.data[14:])) & 0xffff # await tb.driver.interfaces[1].start_xmit(data, 0) # pkt = await tb.sfp_2_sink.recv() # tb.log.info("Packet: %s", pkt) # await tb.sfp_2_source.send(pkt) # pkt = await tb.driver.interfaces[1].recv() # tb.log.info("Packet: %s", pkt) # assert pkt.rx_checksum == ~scapy.utils.checksum(bytes(pkt.data[14:])) & 0xffff tb.log.info("RX and TX checksum tests") payload = bytes([x % 256 for x in range(256)]) eth = Ether(src='5A:51:52:53:54:55', dst='DA:D1:D2:D3:D4:D5') ip = IP(src='192.168.1.100', dst='192.168.1.101') udp = UDP(sport=1, dport=2) test_pkt = eth / ip / udp / payload test_pkt2 = test_pkt.copy() test_pkt2[UDP].chksum = scapy.utils.checksum(bytes(test_pkt2[UDP])) await tb.driver.interfaces[0].start_xmit(test_pkt2.build(), 0, 34, 6) pkt = await tb.sfp_1_sink.recv() tb.log.info("Packet: %s", pkt) await tb.sfp_1_source.send(pkt) pkt = await tb.driver.interfaces[0].recv() tb.log.info("Packet: %s", pkt) assert pkt.rx_checksum == ~scapy.utils.checksum(bytes( pkt.data[14:])) & 0xffff assert Ether(pkt.data).build() == test_pkt.build() tb.log.info("Multiple small packets") count = 64 pkts = [ bytearray([(x + k) % 256 for x in range(60)]) for k in range(count) ] tb.loopback_enable = True for p in pkts: await tb.driver.interfaces[0].start_xmit(p, 0) for k in range(count): pkt = await tb.driver.interfaces[0].recv() tb.log.info("Packet: %s", pkt) assert pkt.data == pkts[k] assert pkt.rx_checksum == ~scapy.utils.checksum(bytes( pkt.data[14:])) & 0xffff tb.loopback_enable = False tb.log.info("Multiple large packets") count = 64 pkts = [ bytearray([(x + k) % 256 for x in range(1514)]) for k in range(count) ] tb.loopback_enable = True for p in pkts: await tb.driver.interfaces[0].start_xmit(p, 0) for k in range(count): pkt = await tb.driver.interfaces[0].recv() tb.log.info("Packet: %s", pkt) assert pkt.data == pkts[k] assert pkt.rx_checksum == ~scapy.utils.checksum(bytes( pkt.data[14:])) & 0xffff tb.loopback_enable = False await RisingEdge(dut.clk_250mhz) await RisingEdge(dut.clk_250mhz)
def gen_pkts6(self, p, sw_intf, src, dst, count=1, payload_size=54): return [Ether(src=sw_intf.remote_mac, dst=sw_intf.local_mac) / IPv6(src=src, dst=dst) / UDP(sport=4444, dport=4444) / Raw(b'X' * payload_size) for i in range(count)]
def test_pipe(self): """ Pipes """ pipes = [VppPipe(self), VppPipe(self, 10)] for p in pipes: p.add_vpp_config() p.admin_up() # # L2 cross-connect pipe0 east with pg0 and west with pg1 # self.vapi.sw_interface_set_l2_xconnect(self.pg0.sw_if_index, pipes[0].east, enable=1) self.vapi.sw_interface_set_l2_xconnect(pipes[0].east, self.pg0.sw_if_index, enable=1) self.vapi.sw_interface_set_l2_xconnect(self.pg1.sw_if_index, pipes[0].west, enable=1) self.vapi.sw_interface_set_l2_xconnect(pipes[0].west, self.pg1.sw_if_index, enable=1) # test bi-directional L2 flow pg0<->pg1 p = (Ether(src=self.pg0.remote_mac, dst=self.pg1.remote_mac) / IP(src="1.1.1.1", dst="1.1.1.2") / UDP(sport=1234, dport=1234) / Raw(b'\xa5' * 100)) self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg1) self.send_and_expect(self.pg1, p * NUM_PKTS, self.pg0) # # Attach ACL to ensure features are run on the pipe # rule_1 = ({ 'is_permit': 0, 'is_ipv6': 0, 'proto': 17, 'srcport_or_icmptype_first': 1234, 'srcport_or_icmptype_last': 1234, 'src_ip_prefix_len': 32, 'src_ip_addr': inet_pton(AF_INET, "1.1.1.1"), 'dstport_or_icmpcode_first': 1234, 'dstport_or_icmpcode_last': 1234, 'dst_ip_prefix_len': 32, 'dst_ip_addr': inet_pton(AF_INET, "1.1.1.2") }) acl = self.vapi.acl_add_replace(acl_index=4294967295, r=[rule_1]) # Apply the ACL on the pipe on output self.vapi.acl_interface_set_acl_list(pipes[0].east, 0, [acl.acl_index]) self.send_and_assert_no_replies(self.pg0, p * NUM_PKTS) self.send_and_expect(self.pg1, p * NUM_PKTS, self.pg0) # remove from output and apply on input self.vapi.acl_interface_set_acl_list(pipes[0].east, 0, []) self.vapi.acl_interface_set_acl_list(pipes[0].west, 1, [acl.acl_index]) self.send_and_assert_no_replies(self.pg0, p * NUM_PKTS) self.send_and_expect(self.pg1, p * NUM_PKTS, self.pg0) self.vapi.acl_interface_set_acl_list(pipes[0].west, 0, []) self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg1) self.send_and_expect(self.pg1, p * NUM_PKTS, self.pg0) # # L3 routes in two separate tables so a pipe can be used to L3 # x-connect # tables = [] tables.append(VppIpTable(self, 1)) tables.append(VppIpTable(self, 2)) for t in tables: t.add_vpp_config() self.pg2.set_table_ip4(1) self.pg2.config_ip4() self.pg2.resolve_arp() self.pg3.set_table_ip4(2) self.pg3.config_ip4() self.pg3.resolve_arp() routes = [] routes.append( VppIpRoute( self, "1.1.1.1", 32, [VppRoutePath(self.pg3.remote_ip4, self.pg3.sw_if_index)], table_id=2)) routes.append( VppIpRoute(self, "1.1.1.1", 32, [VppRoutePath("0.0.0.0", pipes[1].east)], table_id=1)) routes.append( VppIpRoute(self, "1.1.1.2", 32, [VppRoutePath("0.0.0.0", pipes[1].west)], table_id=2)) routes.append( VppIpRoute( self, "1.1.1.2", 32, [VppRoutePath(self.pg2.remote_ip4, self.pg2.sw_if_index)], table_id=1)) for r in routes: r.add_vpp_config() p_east = (Ether(src=self.pg2.remote_mac, dst=self.pg2.local_mac) / IP(src="1.1.1.2", dst="1.1.1.1") / UDP(sport=1234, dport=1234) / Raw(b'\xa5' * 100)) # bind the pipe ends to the correct tables self.vapi.sw_interface_set_table(pipes[1].west, 0, 2) self.vapi.sw_interface_set_table(pipes[1].east, 0, 1) # IP is not enabled on the pipes at this point self.send_and_assert_no_replies(self.pg2, p_east * NUM_PKTS) # IP enable the Pipes by making them unnumbered pipes[0].set_unnumbered(self.pg2.sw_if_index) pipes[1].set_unnumbered(self.pg3.sw_if_index) self.send_and_expect(self.pg2, p_east * NUM_PKTS, self.pg3) # and the return path p_west = (Ether(src=self.pg3.remote_mac, dst=self.pg3.local_mac) / IP(src="1.1.1.1", dst="1.1.1.2") / UDP(sport=1234, dport=1234) / Raw(b'\xa5' * 100)) self.send_and_expect(self.pg3, p_west * NUM_PKTS, self.pg2) # # Use ACLs to test features run on the Pipes # self.vapi.acl_interface_set_acl_list(pipes[1].east, 0, [acl.acl_index]) self.send_and_assert_no_replies(self.pg2, p_east * NUM_PKTS) self.send_and_expect(self.pg3, p_west * NUM_PKTS, self.pg2) # remove from output and apply on input self.vapi.acl_interface_set_acl_list(pipes[1].east, 0, []) self.vapi.acl_interface_set_acl_list(pipes[1].west, 1, [acl.acl_index]) self.send_and_assert_no_replies(self.pg2, p_east * NUM_PKTS) self.send_and_expect(self.pg3, p_west * NUM_PKTS, self.pg2) self.vapi.acl_interface_set_acl_list(pipes[1].west, 0, []) self.send_and_expect(self.pg2, p_east * NUM_PKTS, self.pg3) self.send_and_expect(self.pg3, p_west * NUM_PKTS, self.pg2) # cleanup (so the tables delete) self.pg2.unconfig_ip4() self.pg2.set_table_ip4(0) self.pg3.unconfig_ip4() self.pg3.set_table_ip4(0) self.vapi.sw_interface_set_table(pipes[1].west, 0, 0) self.vapi.sw_interface_set_table(pipes[1].east, 0, 0)
def test_bier_load_balance(self): """BIER load-balance""" # # Add a BIER table for sub-domain 0, set 0, and BSL 256 # bti = VppBierTableID(0, 0, BIERLength.BIER_LEN_64) bt = VppBierTable(self, bti, 77) bt.add_vpp_config() # # packets with varying entropy # pkts = [] for ii in range(257): pkts.append( (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) / MPLS(label=77, ttl=255) / BIER(length=BIERLength.BIER_LEN_64, entropy=ii, BitString=scapy.compat.chb(255) * 16) / IPv6(src=self.pg0.remote_ip6, dst=self.pg0.remote_ip6) / UDP(sport=1234, dport=1234) / Raw())) # # 4 next hops # nhs = [{ 'ip': "10.0.0.1", 'label': 201 }, { 'ip': "10.0.0.2", 'label': 202 }, { 'ip': "10.0.0.3", 'label': 203 }, { 'ip': "10.0.0.4", 'label': 204 }] for nh in nhs: ipr = VppIpRoute(self, nh['ip'], 32, [ VppRoutePath(self.pg1.remote_ip4, self.pg1.sw_if_index, labels=[VppMplsLabel(nh['label'])]) ]) ipr.add_vpp_config() bier_route = VppBierRoute(self, bti, 1, [ VppRoutePath(nhs[0]['ip'], 0xffffffff, labels=[VppMplsLabel(101)]), VppRoutePath(nhs[1]['ip'], 0xffffffff, labels=[VppMplsLabel(101)]) ]) bier_route.add_vpp_config() rx = self.send_and_expect(self.pg0, pkts, self.pg1) # # we should have recieved a packet from each neighbor # for nh in nhs[:2]: self.assertTrue(sum(p[MPLS].label == nh['label'] for p in rx)) # # add the other paths # bier_route.update_paths([ VppRoutePath(nhs[0]['ip'], 0xffffffff, labels=[VppMplsLabel(101)]), VppRoutePath(nhs[1]['ip'], 0xffffffff, labels=[VppMplsLabel(101)]), VppRoutePath(nhs[2]['ip'], 0xffffffff, labels=[VppMplsLabel(101)]), VppRoutePath(nhs[3]['ip'], 0xffffffff, labels=[VppMplsLabel(101)]) ]) rx = self.send_and_expect(self.pg0, pkts, self.pg1) for nh in nhs: self.assertTrue(sum(p[MPLS].label == nh['label'] for p in rx)) # # remove first two paths # bier_route.remove_path( VppRoutePath(nhs[0]['ip'], 0xffffffff, labels=[VppMplsLabel(101)])) bier_route.remove_path( VppRoutePath(nhs[1]['ip'], 0xffffffff, labels=[VppMplsLabel(101)])) rx = self.send_and_expect(self.pg0, pkts, self.pg1) for nh in nhs[2:]: self.assertTrue(sum(p[MPLS].label == nh['label'] for p in rx)) # # remove the last of the paths, deleteing the entry # bier_route.remove_all_paths() self.send_and_assert_no_replies(self.pg0, pkts)
def test_bier_tail(self): """BIER Tail""" # # Add a BIER table for sub-domain 0, set 0, and BSL 256 # bti = VppBierTableID(0, 0, BIERLength.BIER_LEN_256) bt = VppBierTable(self, bti, 77) bt.add_vpp_config() # # disposition table # bdt = VppBierDispTable(self, 8) bdt.add_vpp_config() # # BIER route in table that's for-us # bier_route_1 = VppBierRoute( self, bti, 1, [VppRoutePath("0.0.0.0", 0xffffffff, nh_table_id=8)]) bier_route_1.add_vpp_config() # # An entry in the disposition table # bier_de_1 = VppBierDispEntry(self, bdt.id, 99, BIER_HDR_PAYLOAD.BIER_HDR_PROTO_IPV4, DpoProto.DPO_PROTO_BIER, "0.0.0.0", 0, rpf_id=8192) bier_de_1.add_vpp_config() # # A multicast route to forward post BIER disposition # route_eg_232_1_1_1 = VppIpMRoute( self, "0.0.0.0", "232.1.1.1", 32, MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE, paths=[ VppMRoutePath(self.pg1.sw_if_index, MRouteItfFlags.MFIB_ITF_FLAG_FORWARD) ]) route_eg_232_1_1_1.add_vpp_config() route_eg_232_1_1_1.update_rpf_id(8192) # # A packet with all bits set gets spat out to BP:1 # p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) / MPLS(label=77, ttl=255) / BIER(length=BIERLength.BIER_LEN_256, BitString=chr(255) * 32, BFRID=99) / IP(src="1.1.1.1", dst="232.1.1.1") / UDP(sport=1234, dport=1234) / Raw()) self.send_and_expect(self.pg0, [p], self.pg1) # # A packet that does not match the Disposition entry gets dropped # p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) / MPLS(label=77, ttl=255) / BIER(length=BIERLength.BIER_LEN_256, BitString=chr(255) * 32, BFRID=77) / IP(src="1.1.1.1", dst="232.1.1.1") / UDP(sport=1234, dport=1234) / Raw()) self.send_and_assert_no_replies(self.pg0, p * 2, "no matching disposition entry") # # Add the default route to the disposition table # bier_de_2 = VppBierDispEntry(self, bdt.id, 0, BIER_HDR_PAYLOAD.BIER_HDR_PROTO_IPV4, DpoProto.DPO_PROTO_BIER, "0.0.0.0", 0, rpf_id=8192) bier_de_2.add_vpp_config() # # now the previous packet is forwarded # self.send_and_expect(self.pg0, [p], self.pg1)
def eth_head(eth_type): EthHead = Ether(type=eth_type) return EthHead pass
def test_bier_head_o_udp(self): """BIER head over UDP""" # # Add a BIER table for sub-domain 1, set 0, and BSL 256 # bti = VppBierTableID(1, 0, BIERLength.BIER_LEN_256) bt = VppBierTable(self, bti, 77) bt.add_vpp_config() # # 1 bit positions via 1 next hops # nh1 = "10.0.0.1" ip_route = VppIpRoute(self, nh1, 32, [ VppRoutePath( self.pg1.remote_ip4, self.pg1.sw_if_index, labels=[2001]) ]) ip_route.add_vpp_config() udp_encap = VppUdpEncap(self, 4, self.pg0.local_ip4, nh1, 330, 8138) udp_encap.add_vpp_config() bier_route = VppBierRoute(self, bti, 1, [ VppRoutePath("0.0.0.0", 0xFFFFFFFF, is_udp_encap=1, next_hop_id=4) ]) bier_route.add_vpp_config() # # An 2 imposition objects with all bit-positions set # only use the second, but creating 2 tests with a non-zero # value index in the route add # bi = VppBierImp(self, bti, 333, chr(0xff) * 32) bi.add_vpp_config() bi2 = VppBierImp(self, bti, 334, chr(0xff) * 32) bi2.add_vpp_config() # # Add a multicast route that will forward into the BIER doamin # route_ing_232_1_1_1 = VppIpMRoute( self, "0.0.0.0", "232.1.1.1", 32, MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE, paths=[ VppMRoutePath(self.pg0.sw_if_index, MRouteItfFlags.MFIB_ITF_FLAG_ACCEPT), VppMRoutePath(0xffffffff, MRouteItfFlags.MFIB_ITF_FLAG_FORWARD, proto=DpoProto.DPO_PROTO_BIER, bier_imp=bi2.bi_index) ]) route_ing_232_1_1_1.add_vpp_config() # # inject a packet an IP. We expect it to be BIER and UDP encapped, # p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) / IP(src="1.1.1.1", dst="232.1.1.1") / UDP(sport=1234, dport=1234)) self.pg0.add_stream([p]) self.pg_enable_capture(self.pg_interfaces) self.pg_start() rx = self.pg1.get_capture(1) # # Encap Stack is, eth, IP, UDP, BIFT, BIER # self.assertEqual(rx[0][IP].src, self.pg0.local_ip4) self.assertEqual(rx[0][IP].dst, nh1) self.assertEqual(rx[0][UDP].sport, 330) self.assertEqual(rx[0][UDP].dport, 8138) self.assertEqual(rx[0][BIFT].bsl, 2) self.assertEqual(rx[0][BIFT].sd, 1) self.assertEqual(rx[0][BIFT].set, 0) self.assertEqual(rx[0][BIFT].ttl, 64) self.assertEqual(rx[0][BIER].length, 2)
def verify(): """ Retrieves rows pertaining to the given keys from the Table instance represented by big_table. Silly things may happen if other_silly_variable is not None. Args: None Returns: if first lacpdu switch pass, receive lacpdu.actor.syn=true print pass1 if the second lacpdu switch pass,receive lacp.actor.state=0x3d print PASS2 return 2 else not a successful switch process return 3 Raises: Scapy_Exception: An error occurred accessing scapy. """ a=Ether(dst='01:80:c2:00:00:02', src='00:1B:21:6A:C2:6F', type=0x8809)/LACP(\ Actor_system='00:1B:21:6A:C2:6F', \ Actor_key=1, \ Actor_port_priority=1, \ Actor_port=1, \ Actor_state=0x45, \ Partner_system='00:00:00:00:00:00', \ Partner_state=0x02, CollectorMaxDelay=5000) sendp(a, iface='xgbe0', count=1) #send a LACPDU with actor information and without partner information,then recv a LACPDU reply show switch syn ans, unans = srp(a, iface='xgbe0', timeout=60) for s, r in ans: if r.haslayer(LACP): r.show() partner_system_priority = r.sprintf('%LACP.Actor_system_priority%') partner_system = r.sprintf('%LACP.Actor_system%') partner_key = r.sprintf('%LACP.Actor_key%') partner_port_priority = r.sprintf('%LACP.Actor_port_priority%') partner_port = r.sprintf('%LACP.Actor_port%') partner_state_lacpdu = r.sprintf('%LACP.Actor_state%') if partner_state_lacpdu == 'LACP_Activity+Aggregation+Synchronization': print "PASS1" b=Ether(dst='01:80:c2:00:00:02', src='00:1B:21:6A:C2:6F', type=0x8809)/LACP(\ Actor_system='00:1B:21:6A:C2:6F', \ Actor_key=1, \ Actor_port_priority=1, \ Actor_port=1, Actor_state=0x0d, \ Partner_system=partner_system, \ Partner_system_priority=int(partner_system_priority), \ Partner_key=int(partner_key), \ Partner_port_priority=int(partner_port_priority), \ Partner_port=int(partner_port), \ Partner_state=0x0d, CollectorMaxDelay=5000) ans1, unans1 = srp(b, iface='xgbe0') for s1, r1 in ans1: if r1.haslayer(LACP): r1.show() partner_state1_lacpdu = r1.sprintf( '%LACP.Actor_state%') print type(partner_state1_lacpdu) if partner_state1_lacpdu == 'LACP_Activity\ +Aggregation+Synchronization+Collecting+Distributing': print "PASS2" exit(2) else: print "switch is not lacpactive" exit(3) else: print "recv is not LACPDU" exit(3) else: print "switch is not Synchronization" exit(3) else: exit(3)
def bier_midpoint(self, hdr_len_id, n_bytes, max_bp): """BIER midpoint""" # # Add a BIER table for sub-domain 0, set 0, and BSL 256 # bti = VppBierTableID(0, 0, hdr_len_id) bt = VppBierTable(self, bti, 77) bt.add_vpp_config() # # A packet with no bits set gets dropped # p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) / MPLS(label=77, ttl=255) / BIER(length=hdr_len_id) / IPv6(src=self.pg0.remote_ip6, dst=self.pg0.remote_ip6) / UDP(sport=1234, dport=1234) / Raw()) pkts = [p] self.send_and_assert_no_replies(self.pg0, pkts, "Empty Bit-String") # # Add a BIER route for each bit-position in the table via a different # next-hop. Testing whether the BIER walk and replicate forwarding # function works for all bit posisitons. # nh_routes = [] bier_routes = [] for i in range(1, max_bp + 1): nh = "10.0.%d.%d" % (i / 255, i % 255) nh_routes.append( VppIpRoute(self, nh, 32, [ VppRoutePath(self.pg1.remote_ip4, self.pg1.sw_if_index, labels=[2000 + i]) ])) nh_routes[-1].add_vpp_config() bier_routes.append( VppBierRoute(self, bti, i, [VppRoutePath(nh, 0xffffffff, labels=[100 + i])])) bier_routes[-1].add_vpp_config() # # A packet with all bits set gets replicated once for each bit # pkt_sizes = [64, 1400] for pkt_size in pkt_sizes: p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) / MPLS(label=77, ttl=255) / BIER(length=hdr_len_id, BitString=chr(255) * n_bytes) / IPv6(src=self.pg0.remote_ip6, dst=self.pg0.remote_ip6) / UDP(sport=1234, dport=1234) / Raw(chr(5) * pkt_size)) pkts = p self.pg0.add_stream(pkts) self.pg_enable_capture(self.pg_interfaces) self.pg_start() rx = self.pg1.get_capture(max_bp) for rxp in rx: # # The packets are not required to be sent in bit-position order # when we setup the routes above we used the bit-position to # construct the out-label. so use that here to determine the BP # olabel = rxp[MPLS] bp = olabel.label - 2000 blabel = olabel[MPLS].payload self.assertEqual(blabel.label, 100 + bp) self.assertEqual(blabel.ttl, 254) bier_hdr = blabel[MPLS].payload self.assertEqual(bier_hdr.id, 5) self.assertEqual(bier_hdr.version, 0) self.assertEqual(bier_hdr.length, hdr_len_id) self.assertEqual(bier_hdr.entropy, 0) self.assertEqual(bier_hdr.OAM, 0) self.assertEqual(bier_hdr.RSV, 0) self.assertEqual(bier_hdr.DSCP, 0) self.assertEqual(bier_hdr.Proto, 5) # The bit-string should consist only of the BP given by i. byte_array = ['\0'] * (n_bytes) byte_val = chr(1 << (bp - 1) % 8) byte_pos = n_bytes - (((bp - 1) / 8) + 1) byte_array[byte_pos] = byte_val bitstring = ''.join(byte_array) self.assertEqual(len(bitstring), len(bier_hdr.BitString)) self.assertEqual(bitstring, bier_hdr.BitString) # # cleanup. not strictly necessary, but it's much quicker this way # becuase the bier_fib_dump and ip_fib_dump will be empty when the # auto-cleanup kicks in # for br in bier_routes: br.remove_vpp_config() for nhr in nh_routes: nhr.remove_vpp_config()
def gen_pkts(self, sw_intf, src, dst, count=1): return [Ether(src=sw_intf.remote_mac, dst=sw_intf.local_mac) / IP(src=src, dst=dst) / ICMP() / self.payload for i in range(count)]
def main(): """Send ICMP echo request and wait for ICMP echo reply. It ignores all other packets.""" args = TrafficScriptArg( [u"dst_mac", u"src_mac", u"dst_ip", u"src_ip", u"timeout"]) dst_mac = args.get_arg(u"dst_mac") src_mac = args.get_arg(u"src_mac") dst_ip = args.get_arg(u"dst_ip") src_ip = args.get_arg(u"src_ip") tx_if = args.get_arg(u"tx_if") rx_if = args.get_arg(u"rx_if") timeout = int(args.get_arg(u"timeout")) wait_step = 1 rxq = RxQueue(rx_if) txq = TxQueue(tx_if) sent_packets = [] # Create empty ip ICMP packet if valid_ipv4(src_ip) and valid_ipv4(dst_ip): ip_layer = IP icmp_req = ICMP icmp_resp = ICMP icmp_type = 0 # echo-reply elif valid_ipv6(src_ip) and valid_ipv6(dst_ip): ip_layer = IP icmp_req = ICMPv6EchoRequest icmp_resp = ICMPv6EchoReply icmp_type = 0 # Echo Reply else: raise ValueError(u"IP not in correct format") icmp_request = (Ether(src=src_mac, dst=dst_mac) / ip_layer(src=src_ip, dst=dst_ip) / icmp_req()) # Send created packet on the interface icmp_request /= Raw() sent_packets.append(icmp_request) txq.send(icmp_request) for _ in range(1000): while True: icmp_reply = rxq.recv(wait_step, ignore=sent_packets) if icmp_reply is None: timeout -= wait_step if timeout < 0: raise RuntimeError(u"ICMP echo Rx timeout") elif icmp_reply.haslayer(ICMPv6ND_NS): # read another packet in the queue in case of ICMPv6ND_NS packet continue else: # otherwise process the current packet break if icmp_reply[ip_layer][icmp_resp].type == icmp_type: if icmp_reply[ip_layer].src == dst_ip and \ icmp_reply[ip_layer].dst == src_ip: break else: raise RuntimeError(u"Max packet count limit reached") print(u"ICMP echo reply received.") sys.exit(0)
def gen_pkts6(self, sw_intf, src, dst, count=1): return [Ether(src=sw_intf.remote_mac, dst=sw_intf.local_mac) / IPv6(src=src, dst=dst) / ICMPv6EchoRequest(id=0, seq=1, data=self.payload) for i in range(count)]
def test_fif4(self): """ Fragments in fragments (4o4) """ # TODO this should be ideally in setUpClass, but then we hit a bug # with VppIpRoute incorrectly reporting it's present when it's not # so we need to manually remove the vpp config, thus we cannot have # it shared for multiple test cases self.tun_ip4 = "1.1.1.2" self.gre4 = VppGreInterface(self, self.src_if.local_ip4, self.tun_ip4) self.gre4.add_vpp_config() self.gre4.admin_up() self.gre4.config_ip4() self.vapi.ip_reassembly_enable_disable( sw_if_index=self.gre4.sw_if_index, enable_ip4=True) self.route4 = VppIpRoute( self, self.tun_ip4, 32, [VppRoutePath(self.src_if.remote_ip4, self.src_if.sw_if_index)]) self.route4.add_vpp_config() self.reset_packet_infos() for i in range(test_packet_count): info = self.create_packet_info(self.src_if, self.dst_if) payload = self.info_to_payload(info) # Ethernet header here is only for size calculation, thus it # doesn't matter how it's initialized. This is to ensure that # reassembled packet is not > 9000 bytes, so that it's not dropped p = (Ether() / IP( id=i, src=self.src_if.remote_ip4, dst=self.dst_if.remote_ip4) / UDP(sport=1234, dport=5678) / Raw(payload)) size = self.packet_sizes[(i // 2) % len(self.packet_sizes)] self.extend_packet(p, size, self.padding) info.data = p[IP] # use only IP part, without ethernet header fragments = [ x for _, p in six.iteritems(self._packet_infos) for x in fragment_rfc791(p.data, 400) ] encapped_fragments = \ [Ether(dst=self.src_if.local_mac, src=self.src_if.remote_mac) / IP(src=self.tun_ip4, dst=self.src_if.local_ip4) / GRE() / p for p in fragments] fragmented_encapped_fragments = \ [x for p in encapped_fragments for x in fragment_rfc791(p, 200)] self.src_if.add_stream(fragmented_encapped_fragments) self.pg_enable_capture(self.pg_interfaces) self.pg_start() self.src_if.assert_nothing_captured() packets = self.dst_if.get_capture(len(self._packet_infos)) self.verify_capture(packets, IP) # TODO remove gre vpp config by hand until VppIpRoute gets fixed # so that it's query_vpp_config() works as it should self.gre4.remove_vpp_config() self.logger.debug(self.vapi.ppcli("show interface"))
def test_tra_anti_replay(self, count=1): """ ipsec v4 transport anti-reply test """ p = self.params[socket.AF_INET] # fire in a packet with seq number 1 pkt = (Ether(src=self.tra_if.remote_mac, dst=self.tra_if.local_mac) / p.scapy_tra_sa.encrypt(IP(src=self.tra_if.remote_ip4, dst=self.tra_if.local_ip4) / ICMP(), seq_num=1)) recv_pkts = self.send_and_expect(self.tra_if, [pkt], self.tra_if) # now move the window over to 235 pkt = (Ether(src=self.tra_if.remote_mac, dst=self.tra_if.local_mac) / p.scapy_tra_sa.encrypt(IP(src=self.tra_if.remote_ip4, dst=self.tra_if.local_ip4) / ICMP(), seq_num=235)) recv_pkts = self.send_and_expect(self.tra_if, [pkt], self.tra_if) # the window size is 64 packets # in window are still accepted pkt = (Ether(src=self.tra_if.remote_mac, dst=self.tra_if.local_mac) / p.scapy_tra_sa.encrypt(IP(src=self.tra_if.remote_ip4, dst=self.tra_if.local_ip4) / ICMP(), seq_num=172)) recv_pkts = self.send_and_expect(self.tra_if, [pkt], self.tra_if) # out of window are dropped pkt = (Ether(src=self.tra_if.remote_mac, dst=self.tra_if.local_mac) / p.scapy_tra_sa.encrypt(IP(src=self.tra_if.remote_ip4, dst=self.tra_if.local_ip4) / ICMP(), seq_num=17)) self.send_and_assert_no_replies(self.tra_if, pkt * 17) self.assert_packet_counter_equal( '/err/%s/SA replayed packet' % self.tra4_decrypt_node_name, 17) # a packet that does not decrypt does not move the window forward bogus_sa = SecurityAssociation(self.encryption_type, p.vpp_tra_spi) pkt = (Ether(src=self.tra_if.remote_mac, dst=self.tra_if.local_mac) / bogus_sa.encrypt(IP(src=self.tra_if.remote_ip4, dst=self.tra_if.local_ip4) / ICMP(), seq_num=350)) self.send_and_assert_no_replies(self.tra_if, pkt * 17) self.assert_packet_counter_equal( '/err/%s/Integrity check failed' % self.tra4_decrypt_node_name, 17) # which we can determine since this packet is still in the window pkt = (Ether(src=self.tra_if.remote_mac, dst=self.tra_if.local_mac) / p.scapy_tra_sa.encrypt(IP(src=self.tra_if.remote_ip4, dst=self.tra_if.local_ip4) / ICMP(), seq_num=234)) self.send_and_expect(self.tra_if, [pkt], self.tra_if) # move the security-associations seq number on to the last we used p.scapy_tra_sa.seq_num = 351 p.vpp_tra_sa.seq_num = 351
def format_packet_information(packet_data): decoded = Ether(packet_data) return format_scapy_packet(decoded)
def test_map_t(self): """ MAP-T """ # # Add a domain that maps from pg0 to pg1 # map_dst = '2001:db8::/32' map_src = '1234:5678:90ab:cdef::/64' ip4_pfx = '192.168.0.0/24' self.vapi.map_add_domain(map_dst, ip4_pfx, map_src, 16, 6, 4, mtu=1500) # Enable MAP-T on interfaces. self.vapi.map_if_enable_disable(is_enable=1, sw_if_index=self.pg0.sw_if_index, is_translation=1) self.vapi.map_if_enable_disable(is_enable=1, sw_if_index=self.pg1.sw_if_index, is_translation=1) # Ensure MAP doesn't steal all packets! v4 = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) / IP(src=self.pg0.remote_ip4, dst=self.pg0.remote_ip4) / UDP(sport=20000, dport=10000) / Raw('\xa5' * 100)) rx = self.send_and_expect(self.pg0, v4 * 1, self.pg0) v4_reply = v4[1] v4_reply.ttl -= 1 for p in rx: self.validate(p[1], v4_reply) # Ensure MAP doesn't steal all packets v6 = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) / IPv6(src=self.pg1.remote_ip6, dst=self.pg1.remote_ip6) / UDP(sport=20000, dport=10000) / Raw('\xa5' * 100)) rx = self.send_and_expect(self.pg1, v6 * 1, self.pg1) v6_reply = v6[1] v6_reply.hlim -= 1 for p in rx: self.validate(p[1], v6_reply) map_route = VppIpRoute(self, "2001:db8::", 32, [ VppRoutePath(self.pg1.remote_ip6, self.pg1.sw_if_index, proto=DpoProto.DPO_PROTO_IP6) ], is_ip6=1) map_route.add_vpp_config() # # Send a v4 packet that will be translated # p_ether = Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) p_ip4 = IP(src=self.pg0.remote_ip4, dst='192.168.0.1') payload = TCP(sport=0xabcd, dport=0xabcd) p4 = (p_ether / p_ip4 / payload) p6_translated = (IPv6(src="1234:5678:90ab:cdef:ac:1001:200:0", dst="2001:db8:1f0::c0a8:1:f") / payload) p6_translated.hlim -= 1 rx = self.send_and_expect(self.pg0, p4 * 1, self.pg1) for p in rx: self.validate(p[1], p6_translated) # Send back an IPv6 packet that will be "untranslated" p_ether6 = Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) p_ip6 = IPv6(src='2001:db8:1f0::c0a8:1:f', dst='1234:5678:90ab:cdef:ac:1001:200:0') p6 = (p_ether6 / p_ip6 / payload) p4_translated = (IP(src='192.168.0.1', dst=self.pg0.remote_ip4) / payload) p4_translated.id = 0 p4_translated.ttl -= 1 rx = self.send_and_expect(self.pg1, p6 * 1, self.pg0) for p in rx: self.validate(p[1], p4_translated) # IPv4 TTL ip4_ttl_expired = IP(src=self.pg0.remote_ip4, dst='192.168.0.1', ttl=0) p4 = (p_ether / ip4_ttl_expired / payload) icmp4_reply = ( IP(id=0, ttl=254, src=self.pg0.local_ip4, dst=self.pg0.remote_ip4) / ICMP(type='time-exceeded', code='ttl-zero-during-transit') / IP(src=self.pg0.remote_ip4, dst='192.168.0.1', ttl=0) / payload) rx = self.send_and_expect(self.pg0, p4 * 1, self.pg0) for p in rx: self.validate(p[1], icmp4_reply) ''' This one is broken, cause it would require hairpinning... # IPv4 TTL TTL1 ip4_ttl_expired = IP(src=self.pg0.remote_ip4, dst='192.168.0.1', ttl=1) p4 = (p_ether / ip4_ttl_expired / payload) icmp4_reply = IP(id=0, ttl=254, src=self.pg0.local_ip4, dst=self.pg0.remote_ip4) / \ ICMP(type='time-exceeded', code='ttl-zero-during-transit' ) / \ IP(src=self.pg0.remote_ip4, dst='192.168.0.1', ttl=0) / payload rx = self.send_and_expect(self.pg0, p4*1, self.pg0) for p in rx: self.validate(p[1], icmp4_reply) ''' # IPv6 Hop limit ip6_hlim_expired = IPv6(hlim=0, src='2001:db8:1ab::c0a8:1:ab', dst='1234:5678:90ab:cdef:ac:1001:200:0') p6 = (p_ether6 / ip6_hlim_expired / payload) icmp6_reply = (IPv6( hlim=255, src=self.pg1.local_ip6, dst="2001:db8:1ab::c0a8:1:ab") / ICMPv6TimeExceeded(code=0) / IPv6(src="2001:db8:1ab::c0a8:1:ab", dst='1234:5678:90ab:cdef:ac:1001:200:0', hlim=0) / payload) rx = self.send_and_expect(self.pg1, p6 * 1, self.pg1) for p in rx: self.validate(p[1], icmp6_reply) # IPv4 Well-known port p_ip4 = IP(src=self.pg0.remote_ip4, dst='192.168.0.1') payload = UDP(sport=200, dport=200) p4 = (p_ether / p_ip4 / payload) self.send_and_assert_no_replies(self.pg0, p4 * 1) # IPv6 Well-known port payload = UDP(sport=200, dport=200) p6 = (p_ether6 / p_ip6 / payload) self.send_and_assert_no_replies(self.pg1, p6 * 1) # Packet fragmentation payload = UDP(sport=40000, dport=4000) / self.payload(1453) p4 = (p_ether / p_ip4 / payload) self.pg_enable_capture() self.pg0.add_stream(p4) self.pg_start() rx = self.pg1.get_capture(2) for p in rx: pass # TODO: Manual validation # self.validate(p[1], icmp4_reply) # Packet fragmentation send fragments payload = UDP(sport=40000, dport=4000) / self.payload(1453) p4 = (p_ether / p_ip4 / payload) frags = fragment(p4, fragsize=1000) self.pg_enable_capture() self.pg0.add_stream(frags) self.pg_start() rx = self.pg1.get_capture(2) for p in rx: pass # p.show2() # reass_pkt = reassemble(rx) # p4_reply.ttl -= 1 # p4_reply.id = 256 # self.validate(reass_pkt, p4_reply) # TCP MSS clamping self.vapi.map_param_set_tcp(1300) # # Send a v4 TCP SYN packet that will be translated and MSS clamped # p_ether = Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) p_ip4 = IP(src=self.pg0.remote_ip4, dst='192.168.0.1') payload = TCP(sport=0xabcd, dport=0xabcd, flags="S", options=[('MSS', 1460)]) p4 = (p_ether / p_ip4 / payload) p6_translated = (IPv6(src="1234:5678:90ab:cdef:ac:1001:200:0", dst="2001:db8:1f0::c0a8:1:f") / payload) p6_translated.hlim -= 1 p6_translated[TCP].options = [('MSS', 1300)] rx = self.send_and_expect(self.pg0, p4 * 1, self.pg1) for p in rx: self.validate(p[1], p6_translated) # Send back an IPv6 packet that will be "untranslated" p_ether6 = Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) p_ip6 = IPv6(src='2001:db8:1f0::c0a8:1:f', dst='1234:5678:90ab:cdef:ac:1001:200:0') p6 = (p_ether6 / p_ip6 / payload) p4_translated = (IP(src='192.168.0.1', dst=self.pg0.remote_ip4) / payload) p4_translated.id = 0 p4_translated.ttl -= 1 p4_translated[TCP].options = [('MSS', 1300)] rx = self.send_and_expect(self.pg1, p6 * 1, self.pg0) for p in rx: self.validate(p[1], p4_translated)