def create_stream_labelled_ip4(self, src_if, mpls_labels, mpls_ttl=255, ping=0, ip_itf=None): pkts = [] for i in range(0, 257): info = self.create_packet_info(src_if.sw_if_index, src_if.sw_if_index) payload = self.info_to_payload(info) p = Ether(dst=src_if.local_mac, src=src_if.remote_mac) for ii in range(len(mpls_labels)): if ii == len(mpls_labels) - 1: p = p / MPLS(label=mpls_labels[ii], ttl=mpls_ttl, s=1) else: p = p / MPLS(label=mpls_labels[ii], ttl=mpls_ttl, s=0) if not ping: p = (p / IP(src=src_if.local_ip4, dst=src_if.remote_ip4) / UDP(sport=1234, dport=1234) / Raw(payload)) else: p = (p / IP(src=ip_itf.remote_ip4, dst=ip_itf.local_ip4) / ICMP()) info.data = p.copy() pkts.append(p) return pkts
def verify_ip_precedence_ip_precedence(packets, exclude_src_ip=None): """Verify that all packets have mapped IP precedence value to EXP Args: packets ('obj'): Packets to analyze exclude_src_ip ('str'): Source ip to exclude Returns: True / False Raises: None """ try: from scapy.all import load_contrib from scapy.contrib.mpls import MPLS except ImportError: raise ImportError( 'scapy is not installed, please install it by running: ' 'pip install scapy') from None log.info( "Verifying that all the packets have mapped IP precedence value to EXP" ) if exclude_src_ip: log.info( "Exclude packets with source ip {ip}".format(ip=exclude_src_ip)) load_contrib("mpls") not_matched = False no_check = True for pkt in packets: if pkt.haslayer("Raw"): mpls_pkt = MPLS(pkt["Raw"]) if mpls_pkt.haslayer("IP") and ( exclude_src_ip is None or mpls_pkt["IP"].src != exclude_src_ip): no_check = False log.info("Analyzing the following packet:" "\n-------------------------------\n{}".format( mpls_pkt.show(dump=True))) tos = "{0:08b}".format(mpls_pkt["IP"].tos) cos = "{0:03b}".format(mpls_pkt["MPLS"].cos) if tos[0:3] != cos: not_matched = True log.info( "MPLS EXP 'COS' value didn't match the IP Precedence 'TOS'" ) else: log.info( "MPLS EXP 'COS' value matched the IP Precedence 'TOS'") if no_check: log.info("Didn't find any 'IPv4' protocol packets to " "analyze out of the {} packets".format(len(packets))) if not_matched: return False return True
def send_packet(et_src, et_dst, content_name, chunk_num, ip_src, ip_proto=150, mpls_ttl=10): ether = Ether(src=et_src, dst=et_dst) label = hashlib.sha256() label.update(content_name.encode()) name_bytes = label.digest() mpls_label = name_bytes[0]*4096 + name_bytes[1]*16 + (name_bytes[2]>>4)#first 20 bits mpls = MPLS(label=mpls_label, ttl=mpls_ttl) # name = ndn.Name(ndn.Name.Component(content_name)) # name.appendSegment(chunk_num) # interest = ndn.Interest(name) # interest.setInterestLifetimeMilliseconds(INTEREST_LIFETIME) # data=interest.wireEncode().buf().tobytes() #creating Interest packet data=encode_in_2bytes(content_name) data = data + encode_in_2bytes(str(chunk_num)) ip = IP(src=ip_src, proto=ip_proto) packet = ether / mpls / ip / data.decode() packet.show() sendp(packet)
def send_packet(self, req_id, et_src, et_dst, content_name, chunk_num, flow_num, ip_src): # req_id, et_src, et_dst, content_name, chunk_num, flow_num, ip_src = args[0], args[1],args[2],args[3],args[4],args[5],args[6] ip_proto = 150 mpls_ttl = 10 ether = Ether(src=et_src, dst=et_dst) label = hashlib.sha256() label.update(content_name.encode()) name_bytes = label.digest() mpls_label = name_bytes[0] * 4096 + name_bytes[1] * 16 + ( name_bytes[2] >> 4) #first 20 bits # print('content name ' ,content_name, 'mpls label:', mpls_label) mpls = MPLS(label=mpls_label, ttl=mpls_ttl) #creating Interest packet data = self.encode_in_2bytes(content_name) data = data + self.encode_in_2bytes(str(chunk_num)) data = data + (req_id).encode('utf-8') ip = IP(src=ip_src, proto=ip_proto) packet = ether / mpls / ip / data.decode() self.recieved_data[content_name][flow_num][chunk_num][0].start() self.slog_delay_int.save(content_name, chunk_num, str(req_id)) # print("sending packet " + str(flow_num) + "...") sendp(packet, verbose=False)
def test_bier_tail(self): """BIER Tail""" # # Add a BIER table for sub-domain 0, set 0, and BSL 256 # bti = VppBierTableID(0, 0, BIERLength.BIER_LEN_256) bt = VppBierTable(self, bti, 77) bt.add_vpp_config() # # disposition table # bdt = VppBierDispTable(self, 8) bdt.add_vpp_config() # # BIER route in table that's for-us # bier_route_1 = VppBierRoute(self, bti, 1, "0.0.0.0", 0, disp_table=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, "0.0.0.0", 0, rpf_id=8192) bier_de_1.add_vpp_config() # # A multicast route to forward post BIER disposition # route_eg_232_1_1_1 = VppIpMRoute( self, "0.0.0.0", "232.1.1.1", 32, MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE, paths=[ VppMRoutePath(self.pg1.sw_if_index, MRouteItfFlags.MFIB_ITF_FLAG_FORWARD) ]) route_eg_232_1_1_1.add_vpp_config() route_eg_232_1_1_1.update_rpf_id(8192) # # A packet with all bits set gets spat out to BP:1 # p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) / MPLS(label=77, ttl=255) / BIER(length=BIERLength.BIER_LEN_256, 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)
def runTest(self): self.setup_int() dport = 5060 # int_type=hop-by-hop int_shim = INT_L45_HEAD(int_type=1, length=4) # ins_cnt: 5 = switch id + ports + q occupancy + ig port + eg port) # max_hop_count: 3 # total_hop_count: 0 # instruction_mask_0003: 0xd = switch id (0), ports (1), q occupancy (3) # instruction_mask_0407: 0xc = ig timestamp (4), eg timestamp (5) int_header = "\x00\x05\x03\x00\xdc\x00\x00\x00" # IP proto (UDP), UDP dport (4096) int_tail = INT_L45_TAIL(next_proto=17, proto_param=dport) payload = "\xab" * 128 inner_udp = UDP(sport=5061, dport=dport, chksum=0) # IP tos is 0x04 to enable INT pkt = Ether(src=self.DMAC_2, dst=self.SWITCH_MAC_2) / \ IP(tos=0x04, src=self.S1U_ENB_IPV4, dst=self.END_POINT_IPV4) / \ inner_udp / \ int_shim / int_header / int_tail / \ payload exp_int_shim = INT_L45_HEAD(int_type=1, length=9) # total_hop_count: 1 exp_int_header = "\x00\x05\x03\x01\xdc\x00\x00\x00" # switch id: 1 exp_int_metadata = "\x00\x00\x00\x01" # ig port: port2, eg port: port2 exp_int_metadata += stringify(self.port2, 2) + stringify(self.port1, 2) # q id: 0, q occupancy: ? exp_int_metadata += "\x00\x00\x00\x00" # ig timestamp: ? # eg timestamp: ? exp_int_metadata += "\x00\x00\x00\x00" * 2 exp_int = exp_int_shim / exp_int_header / exp_int_metadata / int_tail exp_pkt = Ether(src=self.SWITCH_MAC_1, dst=self.DMAC_1) / \ MPLS(label=self.mpls_label, cos=0, s=1, ttl=64) / \ IP(tos=0, id=0x1513, flags=0, frag=0, src=self.S1U_SGW_IPV4, dst=self.S1U_ENB_IPV4) / \ UDP(sport=2152, dport=2152, chksum=0) / \ make_gtp(20 + len(inner_udp) + len(exp_int) + len(payload), 1) / \ IP(tos=0x04, src=self.S1U_ENB_IPV4, dst=self.END_POINT_IPV4, ttl=64) / \ inner_udp / \ exp_int / \ payload # We mask off the timestamps as well as the queue occupancy exp_pkt = Mask(exp_pkt) offset_metadata = 14 + 4 + 20 + 8 + 8 + 20 + 8 + 4 + 8 exp_pkt.set_do_not_care((offset_metadata + 9) * 8, 11 * 8) testutils.send_packet(self, self.port2, str(pkt)) testutils.verify_packet(self, exp_pkt, self.port1)
def create_stream_labelled_ip6(self, src_if, mpls_label, mpls_ttl): pkts = [] for i in range(0, 257): info = self.create_packet_info(src_if.sw_if_index, src_if.sw_if_index) payload = self.info_to_payload(info) p = (Ether(dst=src_if.local_mac, src=src_if.remote_mac) / MPLS(label=mpls_label, ttl=mpls_ttl) / IPv6(src=src_if.remote_ip6, dst=src_if.remote_ip6) / UDP(sport=1234, dport=1234) / Raw(payload)) info.data = p.copy() pkts.append(p) return pkts
def send_register_packet(self, content_name): ether = Ether(src=self.SH_IN_ETH, dst=self.CONTROLLER_ETH) mpls = MPLS(label=content_name, ttl=10) ip = IP(src=self.SH_IN_IP, proto=152) data = "register" packet = ether / mpls / ip / data #packet.show() sendp(packet, verbose=False)
def get_ntp_packet(packets, ip_address_source, ip_address_destination): """ Find ntp packet with src ip and dest ip in pcap file Args: packets (`obj`): pcap object ip_address_source (`str`): source ip ip_address_destination (`str`): destination ip Returns: pkt (`obj`): verified ntp packet """ try: from scapy.contrib.mpls import MPLS except ImportError: raise ImportError( 'scapy is not installed, please install it by running: ' 'pip install scapy') from None for pkt in packets: if pkt.haslayer("Raw"): mpls_pkt = MPLS(pkt["Raw"]) if (mpls_pkt.haslayer("IP") and mpls_pkt.haslayer("NTPHeader") and mpls_pkt["IP"].src == ip_address_source and mpls_pkt["IP"].dst == ip_address_destination): log.info("Found NTP packet:\n{pkt}".format(pkt=mpls_pkt.show( dump=True))) return pkt elif (pkt.haslayer("IP") and pkt.haslayer("NTPHeader") and pkt["IP"].src == ip_address_source and pkt["IP"].dst == ip_address_destination): log.info( "Found NTP packet:\n{pkt}".format(pkt=pkt.show(dump=True))) return pkt return None
def send_mpls(self): mpls_eth = Ether(src=self.src_mac, dst=self.dst_mac, type=0x8847) mpls_lables = MPLS(label=16, s=0, ttl=255) / MPLS( label=18, s=0, ttl=255) / MPLS(label=18, s=0, ttl=255) / MPLS( label=16, s=1, ttl=255) mpls_ip = IP(src=self.src_ip, dst=self.dst_ip) mpls_icmp = ICMP(type="echo-request") mpls_raw = Raw(load=self.raw_msg) mpls_frame = mpls_eth / mpls_lables / mpls_ip / mpls_icmp / mpls_raw send_mpls_log = mpls_frame.sprintf("Packets send from mac: " "%Ether.src%, ip: %IP.src% to mac: " "%Ether.dst%, ip: %IP.dst% with the" " following raw message: " "%Raw.load%") try: logger.info("Send MPLS traffic from the {iface} interface with " "the following details: \n{packet_details}".format( iface=self.iface, packet_details=send_mpls_log)) sendp(mpls_frame, iface=self.iface, count=self.count) except Exception as e: logger.info("The MPLS traffic send failed due" " to: {}".format(e.message)) return
def runTest(self): inner_udp = UDP(sport=5061, dport=5060) / ("\xab" * 128) pkt = Ether(src=self.DMAC_2, dst=self.SWITCH_MAC_2) / \ IP(src=self.S1U_ENB_IPV4, dst=self.END_POINT_IPV4) / \ inner_udp exp_pkt = Ether(src=self.SWITCH_MAC_1, dst=self.DMAC_1) / \ MPLS(label=self.mpls_label, cos=0, s=1, ttl=64) / \ IP(tos=0, id=0x1513, flags=0, frag=0, src=self.S1U_SGW_IPV4, dst=self.S1U_ENB_IPV4) / \ UDP(sport=2152, dport=2152, chksum=0) / \ make_gtp(20 + len(inner_udp), 1) / \ IP(src=self.S1U_ENB_IPV4, dst=self.END_POINT_IPV4, ttl=64) / \ inner_udp testutils.send_packet(self, self.port2, str(pkt)) testutils.verify_packet(self, exp_pkt, self.port1)
def test_mpls_disabled(self): """ MPLS Disabled """ tx = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) / MPLS(label=32, ttl=64) / IPv6(src="2001::1", dst=self.pg0.remote_ip6) / UDP(sport=1234, dport=1234) / Raw('\xa5' * 100)) # # A simple MPLS xconnect - eos label in label out # route_32_eos = VppMplsRoute(self, 32, 1, [VppRoutePath(self.pg0.remote_ip4, self.pg0.sw_if_index, labels=[33])]) route_32_eos.add_vpp_config() # # PG1 does not forward IP traffic # self.send_and_assert_no_replies(self.pg1, tx, "MPLS disabled") # # MPLS enable PG1 # self.pg1.enable_mpls() # # Now we get packets through # self.pg1.add_stream(tx) self.pg_enable_capture(self.pg_interfaces) self.pg_start() rx = self.pg0.get_capture(1) # # Disable PG1 # self.pg1.disable_mpls() # # PG1 does not forward IP traffic # self.send_and_assert_no_replies(self.pg1, tx, "IPv6 disabled") self.send_and_assert_no_replies(self.pg1, tx, "IPv6 disabled")
def bier_midpoint(self, hdr_len_id, n_bytes, max_bp): """BIER midpoint""" # # Add a BIER table for sub-domain 0, set 0, and BSL 256 # bti = VppBierTableID(0, 0, hdr_len_id) bt = VppBierTable(self, bti, 77) bt.add_vpp_config() # # A packet with no bits set gets dropped # p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) / MPLS(label=77, ttl=255) / BIER(length=hdr_len_id) / IPv6(src=self.pg0.remote_ip6, dst=self.pg0.remote_ip6) / UDP(sport=1234, dport=1234) / Raw()) pkts = [p] self.send_and_assert_no_replies(self.pg0, pkts, "Empty Bit-String") # # Add a BIER route for each bit-position in the table via a different # next-hop. Testing whether the BIER walk and replicate forwarding # function works for all bit posisitons. # nh_routes = [] bier_routes = [] for i in range(1, max_bp + 1): nh = "10.0.%d.%d" % (i / 255, i % 255) nh_routes.append( VppIpRoute(self, nh, 32, [ VppRoutePath(self.pg1.remote_ip4, self.pg1.sw_if_index, labels=[VppMplsLabel(2000 + i)]) ])) nh_routes[-1].add_vpp_config() bier_routes.append( VppBierRoute(self, bti, i, [ VppRoutePath( nh, 0xffffffff, labels=[VppMplsLabel(100 + i)]) ])) bier_routes[-1].add_vpp_config() # # A packet with all bits set gets replicated once for each bit # pkt_sizes = [64, 1400] for pkt_size in pkt_sizes: p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) / MPLS(label=77, ttl=255) / BIER(length=hdr_len_id, BitString=scapy.compat.chb(255) * n_bytes) / IPv6(src=self.pg0.remote_ip6, dst=self.pg0.remote_ip6) / UDP(sport=1234, dport=1234) / Raw(scapy.compat.chb(5) * pkt_size)) pkts = p self.pg0.add_stream(pkts) self.pg_enable_capture(self.pg_interfaces) self.pg_start() rx = self.pg1.get_capture(max_bp) for rxp in rx: # # The packets are not required to be sent in bit-position order # when we setup the routes above we used the bit-position to # construct the out-label. so use that here to determine the BP # olabel = rxp[MPLS] bp = olabel.label - 2000 blabel = olabel[MPLS].payload self.assertEqual(blabel.label, 100 + bp) self.assertEqual(blabel.ttl, 254) bier_hdr = blabel[MPLS].payload self.assertEqual(bier_hdr.id, 5) self.assertEqual(bier_hdr.version, 0) self.assertEqual(bier_hdr.length, hdr_len_id) self.assertEqual(bier_hdr.entropy, 0) self.assertEqual(bier_hdr.OAM, 0) self.assertEqual(bier_hdr.RSV, 0) self.assertEqual(bier_hdr.DSCP, 0) self.assertEqual(bier_hdr.Proto, 5) # The bit-string should consist only of the BP given by i. byte_array = [b'\0'] * (n_bytes) byte_val = scapy.compat.chb(1 << (bp - 1) % 8) byte_pos = n_bytes - (((bp - 1) // 8) + 1) byte_array[byte_pos] = byte_val bitstring = ''.join([scapy.compat.chb(x) for x in byte_array]) self.assertEqual(len(bitstring), len(bier_hdr.BitString)) self.assertEqual(bitstring, bier_hdr.BitString) # # cleanup. not strictly necessary, but it's much quicker this way # because the bier_fib_dump and ip_fib_dump will be empty when the # auto-cleanup kicks in # for br in bier_routes: br.remove_vpp_config() for nhr in nh_routes: nhr.remove_vpp_config()
def test_bier_tail(self): """BIER Tail""" # # Add a BIER table for sub-domain 0, set 0, and BSL 256 # bti = VppBierTableID(0, 0, BIERLength.BIER_LEN_256) bt = VppBierTable(self, bti, 77) bt.add_vpp_config() # # disposition table # bdt = VppBierDispTable(self, 8) bdt.add_vpp_config() # # BIER route in table that's for-us # bier_route_1 = VppBierRoute(self, bti, 1, [ VppRoutePath("0.0.0.0", 0xffffffff, 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_ENTRY_FLAG_NONE, paths=[ VppMRoutePath(self.pg1.sw_if_index, MRouteItfFlags.MFIB_ITF_FLAG_FORWARD) ]) route_eg_232_1_1_1.add_vpp_config() route_eg_232_1_1_1.update_rpf_id(8192) # # A packet with all bits set gets spat out to BP:1 # p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) / MPLS(label=77, ttl=255) / BIER(length=BIERLength.BIER_LEN_256, BitString=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_ENTRY_FLAG_NONE, paths=[ VppMRoutePath(0xffffffff, MRouteItfFlags.MFIB_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_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_load_balance(self): """BIER load-balance""" # # Add a BIER table for sub-domain 0, set 0, and BSL 256 # bti = VppBierTableID(0, 0, BIERLength.BIER_LEN_64) bt = VppBierTable(self, bti, 77) bt.add_vpp_config() # # packets with varying entropy # pkts = [] for ii in range(257): pkts.append( (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) / MPLS(label=77, ttl=255) / BIER(length=BIERLength.BIER_LEN_64, entropy=ii, BitString=scapy.compat.chb(255) * 16) / IPv6(src=self.pg0.remote_ip6, dst=self.pg0.remote_ip6) / UDP(sport=1234, dport=1234) / Raw())) # # 4 next hops # nhs = [{ 'ip': "10.0.0.1", 'label': 201 }, { 'ip': "10.0.0.2", 'label': 202 }, { 'ip': "10.0.0.3", 'label': 203 }, { 'ip': "10.0.0.4", 'label': 204 }] for nh in nhs: ipr = VppIpRoute(self, nh['ip'], 32, [ VppRoutePath(self.pg1.remote_ip4, self.pg1.sw_if_index, labels=[VppMplsLabel(nh['label'])]) ]) ipr.add_vpp_config() bier_route = VppBierRoute(self, bti, 1, [ VppRoutePath(nhs[0]['ip'], 0xffffffff, labels=[VppMplsLabel(101)]), VppRoutePath(nhs[1]['ip'], 0xffffffff, labels=[VppMplsLabel(101)]) ]) bier_route.add_vpp_config() rx = self.send_and_expect(self.pg0, pkts, self.pg1) # # we should have recieved a packet from each neighbor # for nh in nhs[:2]: self.assertTrue(sum(p[MPLS].label == nh['label'] for p in rx)) # # add the other paths # bier_route.update_paths([ VppRoutePath(nhs[0]['ip'], 0xffffffff, labels=[VppMplsLabel(101)]), VppRoutePath(nhs[1]['ip'], 0xffffffff, labels=[VppMplsLabel(101)]), VppRoutePath(nhs[2]['ip'], 0xffffffff, labels=[VppMplsLabel(101)]), VppRoutePath(nhs[3]['ip'], 0xffffffff, labels=[VppMplsLabel(101)]) ]) rx = self.send_and_expect(self.pg0, pkts, self.pg1) for nh in nhs: self.assertTrue(sum(p[MPLS].label == nh['label'] for p in rx)) # # remove first two paths # bier_route.remove_path( VppRoutePath(nhs[0]['ip'], 0xffffffff, labels=[VppMplsLabel(101)])) bier_route.remove_path( VppRoutePath(nhs[1]['ip'], 0xffffffff, labels=[VppMplsLabel(101)])) rx = self.send_and_expect(self.pg0, pkts, self.pg1) for nh in nhs[2:]: self.assertTrue(sum(p[MPLS].label == nh['label'] for p in rx)) # # remove the last of the paths, deleteing the entry # bier_route.remove_all_paths() self.send_and_assert_no_replies(self.pg0, pkts)
RTT = 0.08 # Tuning parameter for flowlet division in seconds PROBE_FREQ = 50 # in milliseconds REQ_FREQ = 0.5 ALPHA = bebaproto.EWMA_PARAM_0750 # alpha parameter for the ewma filter UPPER_PORTS = [1, 2] DOWN_PORTS = [3] LEAVES = [1, 2, 3] HOSTS_NUMBER = 1 MAC_ADDRS = ["00:00:00:00:00:01", "00:00:00:00:00:02", "00:00:00:00:00:03"] # Probe packet generated with scapy pkt = Ether(src="10:00:00:00:00:01", dst="20:00:00:00:00:02") / MPLS( ttl=64) / IP(ttl=64, dst='10.0.0.1', src='2.2.2.2') pkt_raw = bytearray(str(pkt)) LOG.info("Generated probe is " + str(pkt).encode("HEX")) class OpenStateEvolution(app_manager.RyuApp): def __init__(self, *args, **kwargs): super(OpenStateEvolution, self).__init__(*args, **kwargs) self.datapaths = [] self.output_files = ["leaf1.txt", "leaf2.txt", "leaf3.txt"] self.monitor_thread = hub.spawn(self._monitor) self.time = 0 def add_flow(self, datapath, table_id, priority, match, actions): if len(actions) > 0: inst = [
def test_bier_midpoint(self): """BIER midpoint""" # # 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() # # A packet with no bits set gets dropped # p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) / MPLS(label=77, ttl=255) / BIER(length=BIERLength.BIER_LEN_256, BitString=chr(0)*64) / IPv6(src=self.pg0.remote_ip6, dst=self.pg0.remote_ip6) / UDP(sport=1234, dport=1234) / Raw()) pkts = [p] self.send_and_assert_no_replies(self.pg0, pkts, "Empty Bit-String") # # Add a BIER route for each bit-position in the table via a different # next-hop. Testing whether the BIER walk and replicate forwarding # function works for all bit posisitons. # nh_routes = [] bier_routes = [] for i in range(1, 256): nh = "10.0.%d.%d" % (i / 255, i % 255) nh_routes.append(VppIpRoute(self, nh, 32, [VppRoutePath(self.pg1.remote_ip4, self.pg1.sw_if_index, labels=[2000+i])])) nh_routes[-1].add_vpp_config() bier_routes.append(VppBierRoute(self, bti, i, [VppRoutePath(nh, 0xffffffff, labels=[100+i])])) bier_routes[-1].add_vpp_config() # # A packet with all bits set gets 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) / IPv6(src=self.pg0.remote_ip6, dst=self.pg0.remote_ip6) / UDP(sport=1234, dport=1234) / Raw()) pkts = [p] self.pg0.add_stream(pkts) self.pg_enable_capture(self.pg_interfaces) self.pg_start() rx = self.pg1.get_capture(255) for rxp in rx: # # The packets are not required to be sent in bit-position order # when we setup the routes above we used the bit-position to # construct the out-label. so use that here to determine the BP # olabel = rxp[MPLS] bp = olabel.label - 2000 blabel = olabel[MPLS].payload self.assertEqual(blabel.label, 100+bp) self.assertEqual(blabel.ttl, 254) bier_hdr = blabel[MPLS].payload self.assertEqual(bier_hdr.id, 5) self.assertEqual(bier_hdr.version, 0) self.assertEqual(bier_hdr.length, BIERLength.BIER_LEN_256) self.assertEqual(bier_hdr.entropy, 0) self.assertEqual(bier_hdr.OAM, 0) self.assertEqual(bier_hdr.RSV, 0) self.assertEqual(bier_hdr.DSCP, 0) self.assertEqual(bier_hdr.Proto, 5) # The bit-string should consist only of the BP given by i. i = 0 bitstring = "" bpi = bp - 1 while (i < bpi/8): bitstring = chr(0) + bitstring i += 1 bitstring = chr(1 << bpi % 8) + bitstring while len(bitstring) < 32: bitstring = chr(0) + bitstring self.assertEqual(len(bitstring), len(bier_hdr.BitString)) self.assertEqual(bitstring, bier_hdr.BitString)
def craft_pkt(_types, _dicts): pkt = None for i in range(len(_types)): _type = _types[i] _dict = _dicts[i] logging.debug("type: {}, dict: {}".format(_type, _dict)) if _type == "Ether": if 'smac' not in _dict.keys() or \ 'dmac' not in _dict.keys(): raise Exception('Ether: smac and/or dmac not found') else: if pkt: pkt = pkt / Ether(src=_dict['smac'], dst=_dict['dmac']) else: pkt = Ether(src=_dict['smac'], dst=_dict['dmac']) elif _type == "Dot1Q": if 'vlan' not in _dict.keys(): raise Exception('Dot1Q: vlan not found') else: pkt = pkt / Dot1Q(vlan=int(_dict['vlan'])) elif _type == "IP": if 'sip' not in _dict.keys() or \ 'dip' not in _dict.keys(): raise Exception('IP: sip and/or dip not found') else: pkt = pkt / IP(src=_dict['sip'], dst=_dict['dip'], id=0) if 'flags' in _dict.keys(): pkt.getlayer('IP').flags = _dict['flags'] if 'ttl' in _dict.keys(): pkt.getlayer('IP').ttl = _dict['ttl'] elif _type == "UDP": if 'sport' not in _dict.keys() or \ 'dport' not in _dict.keys(): raise Exception('UDP: sport and/or dport not found') else: pkt = pkt / UDP(sport=int(_dict['sport']), dport=int(_dict['dport'])) elif _type == "TCP": if 'sport' not in _dict.keys() or \ 'dport' not in _dict.keys(): raise Exception('TCP: sport and/or dport not found') elif 'flags' in _dict.keys(): pkt = pkt / TCP(sport=int(_dict['sport']), dport=int(_dict['dport']), flags=_dict['flags']) else: pkt = pkt / TCP(sport=int(_dict['sport']), dport=int(_dict['dport'])) elif _type == "ICMP": if 'icmp_type' not in _dict.keys() or \ 'icmp_code' not in _dict.keys(): raise Exception('ICMP: icmp_type and/or icmp_code not found') else: pkt = pkt / ICMP(type=int(_dict['icmp_type']), code=int(_dict['icmp_code'])) elif _type == "MPLS": if 'label' not in _dict.keys() or \ 's' not in _dict.keys(): raise Exception('MPLS: label and/or s not found') else: pkt = pkt / MPLS(label=int(_dict['label']), s=int(_dict['s'])) elif _type == "GENEVE": if 'vni' not in _dict.keys() or \ 'options' not in _dict.keys(): raise Exception('GENEVE: vni and/or options not found') else: pkt = pkt / GENEVE(vni=int(_dict['vni']), options=_dict['options']) return pkt
def analyze_udp_in_mpls_packets( packets, ip_address, ttl, packet_count, destination_port ): """ Analyze passed packets Args: packets('str'): Packets to analyze ip_address ('str'): Destination IP address ttl (`int`): Time to live packet_count (`int`): Packet count to check during packet analysis destination_port (`int`): Destination port start "traceroute" Returns: pkt count Raises: None """ try: from scapy.all import load_contrib, UDP from scapy.contrib.mpls import MPLS except ImportError: raise ImportError('scapy is not installed, please install it by running: ' 'pip install scapy') from None count = 0 for pkt in packets: # Analyze MPLS packets if pkt.type == 34887: load_contrib("mpls") mpls_pkt = MPLS(pkt["Raw"]) if ( mpls_pkt.haslayer("IP") and mpls_pkt["IP"].dst == ip_address and mpls_pkt["IP"].ttl == ttl and mpls_pkt.haslayer("UDP") ): # Catch the start of source and destination ports if count == 0: sport_count = mpls_pkt["UDP"].sport dport_count = destination_port log.info( "Found a packet that meets the requirement:\nDestination:\t{" "ip_pkt_dst}\nDestination Port:\t{dst_port}\nSource:\t\t{" "ip_pkt_src}\nSource Port:\t{src_port}\nUDP Packet:\t{" "mpls_pkt}\n".format( ip_pkt_dst=mpls_pkt["IP"].dst, dst_port=dport_count, ip_pkt_src=mpls_pkt["IP"].src, src_port=sport_count, mpls_pkt="True" if mpls_pkt["UDP"] else "False", ) ) count += 1 continue # Verify source and destination ports are incrementing if mpls_pkt["UDP"].sport != sport_count + 1: log.info( "Source port didn't increment to " "{source_port} as expected; instead it is {sp}".format( source_port=sport_count + 1, destination_port=dport_count + 1, sp=mpls_pkt["UDP"].sport, ) ) return None, 0 elif mpls_pkt["UDP"].dport != dport_count + 1: log.info( "destination port didn't increment to " "{destination_port} as expected; instead " "it is {dp}".format( source_port=sport_count + 1, destination_port=dport_count + 1, dp=mpls_pkt["UDP"].dport, ) ) return None, 0 else: count += 1 sport_count += 1 dport_count += 1 log.info( 'Found a packet that "meets" the requirement:\nDestination:\t{' "ip_pkt_dst}\nDestination Port:\t{dst_port}\nSource:\t\t{" "ip_pkt_src}\nSource Port:\t{src_port}\nUDP Packet:\t{" "mpls_pkt}\n".format( ip_pkt_dst=mpls_pkt["IP"].dst, dst_port=dport_count, ip_pkt_src=mpls_pkt["IP"].src, src_port=sport_count, mpls_pkt="True" if mpls_pkt["UDP"] else "False", ) ) if count == packet_count: return pkt, count return None, count
from ryu.controller import ofp_event from ryu.controller.handler import CONFIG_DISPATCHER, MAIN_DISPATCHER from ryu.controller.handler import set_ev_cls import ryu.ofproto.ofproto_v1_3 as ofproto import ryu.ofproto.ofproto_v1_3_parser as ofparser import ryu.ofproto.beba_v1_0 as bebaproto import ryu.ofproto.beba_v1_0_parser as bebaparser from ryu.lib import hub from scapy.contrib.mpls import MPLS from scapy.layers.l2 import Ether from scapy.layers.inet import IP, UDP LOG = logging.getLogger('app.openstate.evolution') # Probe packet generated with scapy pkt = Ether(src="00:00:00:00:00:00", dst="00:00:00:00:00:00") / MPLS( ttl=64) / IP(src="0.0.0.0", dst="0.0.0.0") / UDP() pkt_raw = bytearray(str(pkt)) LOG.info("Generated probe is " + str(pkt).encode("HEX")) class OpenStateEvolution(app_manager.RyuApp): def __init__(self, *args, **kwargs): super(OpenStateEvolution, self).__init__(*args, **kwargs) def add_flow(self, datapath, table_id, priority, match, actions): if len(actions) > 0: inst = [ ofparser.OFPInstructionActions(ofproto.OFPIT_APPLY_ACTIONS, actions) ] else:
def test_udp_encap(self): """UDP Encap test""" # # construct a UDP encap object through each of the peers # v4 through the first two peers, v6 through the second. # The last encap is v4 and is used to check the codepath # where 2 different udp encap objects are processed at the # same time # udp_encap_0 = VppUdpEncap(self, self.pg0.local_ip4, self.pg0.remote_ip4, 330, 440) udp_encap_1 = VppUdpEncap(self, self.pg1.local_ip4, self.pg1.remote_ip4, 331, 441, table_id=1) udp_encap_2 = VppUdpEncap(self, self.pg2.local_ip6, self.pg2.remote_ip6, 332, 442, table_id=2) udp_encap_3 = VppUdpEncap(self, self.pg3.local_ip6, self.pg3.remote_ip6, 333, 443, table_id=3) udp_encap_4 = VppUdpEncap(self, self.pg0.local_ip4, self.pg0.remote_ip4, 334, 444) udp_encap_0.add_vpp_config() udp_encap_1.add_vpp_config() udp_encap_2.add_vpp_config() udp_encap_3.add_vpp_config() udp_encap_4.add_vpp_config() self.logger.info(self.vapi.cli("sh udp encap")) self.assertTrue(find_udp_encap(self, udp_encap_2)) self.assertTrue(find_udp_encap(self, udp_encap_3)) self.assertTrue(find_udp_encap(self, udp_encap_0)) self.assertTrue(find_udp_encap(self, udp_encap_1)) self.assertTrue(find_udp_encap(self, udp_encap_4)) # # Routes via each UDP encap object - all combinations of v4 and v6. # route_4o4 = VppIpRoute( self, "1.1.0.1", 24, [ VppRoutePath( "0.0.0.0", 0xFFFFFFFF, type=FibPathType.FIB_PATH_TYPE_UDP_ENCAP, next_hop_id=udp_encap_0.id, proto=FibPathProto.FIB_PATH_NH_PROTO_IP4, ) ], table_id=1, ) # specific route to match encap4, to test encap of 2 packets using 2 # different encap route_4o4_2 = VppIpRoute( self, "1.1.0.2", 32, [ VppRoutePath( "0.0.0.0", 0xFFFFFFFF, type=FibPathType.FIB_PATH_TYPE_UDP_ENCAP, next_hop_id=udp_encap_4.id, proto=FibPathProto.FIB_PATH_NH_PROTO_IP4, ) ], table_id=1, ) route_4o6 = VppIpRoute( self, "1.1.2.1", 32, [ VppRoutePath( "0.0.0.0", 0xFFFFFFFF, type=FibPathType.FIB_PATH_TYPE_UDP_ENCAP, next_hop_id=udp_encap_2.id, proto=FibPathProto.FIB_PATH_NH_PROTO_IP4, ) ], ) route_6o4 = VppIpRoute( self, "2001::1", 128, [ VppRoutePath( "0.0.0.0", 0xFFFFFFFF, type=FibPathType.FIB_PATH_TYPE_UDP_ENCAP, next_hop_id=udp_encap_1.id, proto=FibPathProto.FIB_PATH_NH_PROTO_IP6, ) ], ) route_6o6 = VppIpRoute( self, "2001::3", 128, [ VppRoutePath( "0.0.0.0", 0xFFFFFFFF, type=FibPathType.FIB_PATH_TYPE_UDP_ENCAP, next_hop_id=udp_encap_3.id, proto=FibPathProto.FIB_PATH_NH_PROTO_IP6, ) ], ) route_4o6.add_vpp_config() route_6o6.add_vpp_config() route_6o4.add_vpp_config() route_4o4.add_vpp_config() route_4o4_2.add_vpp_config() # # 4o4 encap # we add a single packet matching the last encap at the beginning of # the packet vector so that we encap 2 packets with different udp # encap object at the same time # p_4o4 = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) / IP(src="2.2.2.2", dst="1.1.0.1") / UDP(sport=1234, dport=1234) / Raw(b"\xa5" * 100)) p_4o4_2 = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) / IP(src="2.2.2.2", dst="1.1.0.2") / UDP(sport=1234, dport=1234) / Raw(b"\xa5" * 100)) rx = self.send_and_expect(self.pg1, p_4o4_2 * 1 + p_4o4 * (NUM_PKTS - 1), self.pg0) # checking encap4 magic packet p = rx.pop(0) self.validate_outer4(p, udp_encap_4) p = IP(p["UDP"].payload.load) self.validate_inner4(p, p_4o4_2) self.assertEqual(udp_encap_4.get_stats()["packets"], 1) # checking remaining packets for encap0 for p in rx: self.validate_outer4(p, udp_encap_0) p = IP(p["UDP"].payload.load) self.validate_inner4(p, p_4o4) self.assertEqual(udp_encap_0.get_stats()["packets"], NUM_PKTS - 1) # # 4o6 encap # p_4o6 = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) / IP(src="2.2.2.2", dst="1.1.2.1") / UDP(sport=1234, dport=1234) / Raw(b"\xa5" * 100)) rx = self.send_and_expect(self.pg0, p_4o6 * NUM_PKTS, self.pg2) for p in rx: self.validate_outer6(p, udp_encap_2) p = IP(p["UDP"].payload.load) self.validate_inner4(p, p_4o6) self.assertEqual(udp_encap_2.get_stats()["packets"], NUM_PKTS) # # 6o4 encap # p_6o4 = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) / IPv6(src="2001::100", dst="2001::1") / UDP(sport=1234, dport=1234) / Raw(b"\xa5" * 100)) rx = self.send_and_expect(self.pg0, p_6o4 * NUM_PKTS, self.pg1) for p in rx: self.validate_outer4(p, udp_encap_1) p = IPv6(p["UDP"].payload.load) self.validate_inner6(p, p_6o4) self.assertEqual(udp_encap_1.get_stats()["packets"], NUM_PKTS) # # 6o6 encap # p_6o6 = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) / IPv6(src="2001::100", dst="2001::3") / UDP(sport=1234, dport=1234) / Raw(b"\xa5" * 100)) rx = self.send_and_expect(self.pg0, p_6o6 * NUM_PKTS, self.pg3) for p in rx: self.validate_outer6(p, udp_encap_3) p = IPv6(p["UDP"].payload.load) self.validate_inner6(p, p_6o6) self.assertEqual(udp_encap_3.get_stats()["packets"], NUM_PKTS) # # A route with an output label # the TTL of the inner packet is decremented on LSP ingress # route_4oMPLSo4 = VppIpRoute( self, "1.1.2.22", 32, [ VppRoutePath( "0.0.0.0", 0xFFFFFFFF, type=FibPathType.FIB_PATH_TYPE_UDP_ENCAP, next_hop_id=1, labels=[VppMplsLabel(66)], ) ], ) route_4oMPLSo4.add_vpp_config() p_4omo4 = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) / IP(src="2.2.2.2", dst="1.1.2.22") / UDP(sport=1234, dport=1234) / Raw(b"\xa5" * 100)) rx = self.send_and_expect(self.pg0, p_4omo4 * NUM_PKTS, self.pg1) for p in rx: self.validate_outer4(p, udp_encap_1) p = MPLS(p["UDP"].payload.load) self.validate_inner4(p, p_4omo4, ttl=63) self.assertEqual(udp_encap_1.get_stats()["packets"], 2 * NUM_PKTS)
def test_udp_encap(self): """ UDP Encap test """ # # construct a UDP encap object through each of the peers # v4 through the first two peears, v6 through the second. # udp_encap_0 = VppUdpEncap(self, self.pg0.local_ip4, self.pg0.remote_ip4, 330, 440) udp_encap_1 = VppUdpEncap(self, self.pg1.local_ip4, self.pg1.remote_ip4, 331, 441, table_id=1) udp_encap_2 = VppUdpEncap(self, self.pg2.local_ip6, self.pg2.remote_ip6, 332, 442, table_id=2) udp_encap_3 = VppUdpEncap(self, self.pg3.local_ip6, self.pg3.remote_ip6, 333, 443, table_id=3) udp_encap_0.add_vpp_config() udp_encap_1.add_vpp_config() udp_encap_2.add_vpp_config() udp_encap_3.add_vpp_config() self.logger.info(self.vapi.cli("sh udp encap")) self.assertTrue(find_udp_encap(self, udp_encap_2)) self.assertTrue(find_udp_encap(self, udp_encap_3)) self.assertTrue(find_udp_encap(self, udp_encap_0)) self.assertTrue(find_udp_encap(self, udp_encap_1)) # # Routes via each UDP encap object - all combinations of v4 and v6. # route_4o4 = VppIpRoute(self, "1.1.0.1", 32, [ VppRoutePath("0.0.0.0", 0xFFFFFFFF, is_udp_encap=1, next_hop_id=udp_encap_0.id) ]) route_4o6 = VppIpRoute(self, "1.1.2.1", 32, [ VppRoutePath("0.0.0.0", 0xFFFFFFFF, is_udp_encap=1, next_hop_id=udp_encap_2.id) ]) route_6o4 = VppIpRoute(self, "2001::1", 128, [ VppRoutePath("0.0.0.0", 0xFFFFFFFF, is_udp_encap=1, next_hop_id=udp_encap_1.id) ], is_ip6=1) route_6o6 = VppIpRoute(self, "2001::3", 128, [ VppRoutePath("0.0.0.0", 0xFFFFFFFF, is_udp_encap=1, next_hop_id=udp_encap_3.id) ], is_ip6=1) route_4o4.add_vpp_config() route_4o6.add_vpp_config() route_6o6.add_vpp_config() route_6o4.add_vpp_config() # # 4o4 encap # p_4o4 = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) / IP(src="2.2.2.2", dst="1.1.0.1") / UDP(sport=1234, dport=1234) / Raw('\xa5' * 100)) rx = self.send_and_expect(self.pg0, p_4o4 * 65, self.pg0) for p in rx: self.validate_outer4(p, udp_encap_0) p = IP(p["UDP"].payload.load) self.validate_inner4(p, p_4o4) self.assertEqual(udp_encap_0.get_stats()['packets'], 65) # # 4o6 encap # p_4o6 = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) / IP(src="2.2.2.2", dst="1.1.2.1") / UDP(sport=1234, dport=1234) / Raw('\xa5' * 100)) rx = self.send_and_expect(self.pg0, p_4o6 * 65, self.pg2) for p in rx: self.validate_outer6(p, udp_encap_2) p = IP(p["UDP"].payload.load) self.validate_inner4(p, p_4o6) self.assertEqual(udp_encap_2.get_stats()['packets'], 65) # # 6o4 encap # p_6o4 = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) / IPv6(src="2001::100", dst="2001::1") / UDP(sport=1234, dport=1234) / Raw('\xa5' * 100)) rx = self.send_and_expect(self.pg0, p_6o4 * 65, self.pg1) for p in rx: self.validate_outer4(p, udp_encap_1) p = IPv6(p["UDP"].payload.load) self.validate_inner6(p, p_6o4) self.assertEqual(udp_encap_1.get_stats()['packets'], 65) # # 6o6 encap # p_6o6 = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) / IPv6(src="2001::100", dst="2001::3") / UDP(sport=1234, dport=1234) / Raw('\xa5' * 100)) rx = self.send_and_expect(self.pg0, p_6o6 * 65, self.pg3) for p in rx: self.validate_outer6(p, udp_encap_3) p = IPv6(p["UDP"].payload.load) self.validate_inner6(p, p_6o6) self.assertEqual(udp_encap_3.get_stats()['packets'], 65) # # A route with an output label # the TTL of the inner packet is decremented on LSP ingress # route_4oMPLSo4 = VppIpRoute(self, "1.1.2.22", 32, [ VppRoutePath("0.0.0.0", 0xFFFFFFFF, is_udp_encap=1, next_hop_id=1, labels=[VppMplsLabel(66)]) ]) route_4oMPLSo4.add_vpp_config() p_4omo4 = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) / IP(src="2.2.2.2", dst="1.1.2.22") / UDP(sport=1234, dport=1234) / Raw('\xa5' * 100)) rx = self.send_and_expect(self.pg0, p_4omo4 * 65, self.pg1) for p in rx: self.validate_outer4(p, udp_encap_1) p = MPLS(p["UDP"].payload.load) self.validate_inner4(p, p_4omo4, ttl=63) self.assertEqual(udp_encap_1.get_stats()['packets'], 130)
def test_mpls(self): """ MPLS over ip{6,4} test """ tbl = VppMplsTable(self, 0) tbl.add_vpp_config() self.p_ether = Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) self.p_payload = UDP(sport=1234, dport=1234) / Raw(b'X' * 100) f = FibPathProto # IPv4 transport tun4 = VppIpIpTunInterface(self, self.pg1, self.pg1.local_ip4, self.pg1.remote_ip4).add_vpp_config() tun4.admin_up() tun4.config_ip4() tun4.enable_mpls() # IPv6 transport tun6 = VppIpIpTunInterface(self, self.pg1, self.pg1.local_ip6, self.pg1.remote_ip6).add_vpp_config() tun6.admin_up() tun6.config_ip6() tun6.enable_mpls() # ip routes into the tunnels with output labels r4 = VppIpRoute(self, "1.1.1.1", 32, [ VppRoutePath( tun4.remote_ip4, tun4.sw_if_index, labels=[VppMplsLabel(44)]) ]).add_vpp_config() r6 = VppIpRoute(self, "1::1", 128, [ VppRoutePath( tun6.remote_ip6, tun6.sw_if_index, labels=[VppMplsLabel(66)]) ]).add_vpp_config() # deag MPLS routes from the tunnel r4 = VppMplsRoute( self, 44, 1, [VppRoutePath(self.pg0.remote_ip4, self.pg0.sw_if_index) ]).add_vpp_config() r6 = VppMplsRoute( self, 66, 1, [VppRoutePath(self.pg0.remote_ip6, self.pg0.sw_if_index)], eos_proto=f.FIB_PATH_NH_PROTO_IP6).add_vpp_config() # # Tunnel Encap # p4 = (self.p_ether / IP(src="2.2.2.2", dst="1.1.1.1") / self.p_payload) rxs = self.send_and_expect(self.pg0, p4 * N_PACKETS, self.pg1) for rx in rxs: self.assertEqual(rx[IP].src, self.pg1.local_ip4) self.assertEqual(rx[IP].dst, self.pg1.remote_ip4) self.assertEqual(rx[MPLS].label, 44) inner = rx[MPLS].payload self.assertEqual(inner.src, "2.2.2.2") self.assertEqual(inner.dst, "1.1.1.1") p6 = (self.p_ether / IPv6(src="2::2", dst="1::1") / self.p_payload) rxs = self.send_and_expect(self.pg0, p6 * N_PACKETS, self.pg1) for rx in rxs: self.assertEqual(rx[IPv6].src, self.pg1.local_ip6) self.assertEqual(rx[IPv6].dst, self.pg1.remote_ip6) self.assertEqual(rx[MPLS].label, 66) inner = rx[MPLS].payload self.assertEqual(inner.src, "2::2") self.assertEqual(inner.dst, "1::1") # # Tunnel Decap # p4 = (self.p_ether / IP(src=self.pg1.remote_ip4, dst=self.pg1.local_ip4) / MPLS(label=44, ttl=4) / IP(src="1.1.1.1", dst="2.2.2.2") / self.p_payload) rxs = self.send_and_expect(self.pg1, p4 * N_PACKETS, self.pg0) for rx in rxs: self.assertEqual(rx[IP].src, "1.1.1.1") self.assertEqual(rx[IP].dst, "2.2.2.2") p6 = (self.p_ether / IPv6(src=self.pg1.remote_ip6, dst=self.pg1.local_ip6) / MPLS(label=66, ttl=4) / IPv6(src="1::1", dst="2::2") / self.p_payload) rxs = self.send_and_expect(self.pg1, p6 * N_PACKETS, self.pg0) for rx in rxs: self.assertEqual(rx[IPv6].src, "1::1") self.assertEqual(rx[IPv6].dst, "2::2") tun4.disable_mpls() tun6.disable_mpls()
def test_udp_decap(self): """ UDP Decap test """ # # construct a UDP decap object for each type of protocol # # IPv4 udp_api_proto = VppEnum.vl_api_udp_decap_next_proto_t next_proto = udp_api_proto.UDP_API_DECAP_PROTO_IP4 udp_decap_0 = VppUdpDecap(self, 1, 220, next_proto) # IPv6 next_proto = udp_api_proto.UDP_API_DECAP_PROTO_IP6 udp_decap_1 = VppUdpDecap(self, 0, 221, next_proto) # MPLS next_proto = udp_api_proto.UDP_API_DECAP_PROTO_MPLS udp_decap_2 = VppUdpDecap(self, 1, 222, next_proto) udp_decap_0.add_vpp_config() udp_decap_1.add_vpp_config() udp_decap_2.add_vpp_config() # # Routes via the corresponding pg after the UDP decap # route_4 = VppIpRoute(self, "1.1.1.1", 32, [VppRoutePath("0.0.0.0", self.pg0.sw_if_index)], table_id=0) route_6 = VppIpRoute(self, "2001::1", 128, [VppRoutePath("::", self.pg1.sw_if_index)], table_id=1) route_mo4 = VppIpRoute(self, "3.3.3.3", 32, [VppRoutePath("0.0.0.0", self.pg2.sw_if_index)], table_id=2) route_4.add_vpp_config() route_6.add_vpp_config() route_mo4.add_vpp_config() # # Adding neighbors to route the packets # n_4 = VppNeighbor(self, self.pg0.sw_if_index, "00:11:22:33:44:55", "1.1.1.1") n_6 = VppNeighbor(self, self.pg1.sw_if_index, "11:22:33:44:55:66", "2001::1") n_mo4 = VppNeighbor(self, self.pg2.sw_if_index, "22:33:44:55:66:77", "3.3.3.3") n_4.add_vpp_config() n_6.add_vpp_config() n_mo4.add_vpp_config() # # MPLS decapsulation config # mpls_table = VppMplsTable(self, 0) mpls_table.add_vpp_config() mpls_route = VppMplsRoute(self, 77, 1, [ VppRoutePath("0.0.0.0", 0xFFFFFFFF, nh_table_id=2, proto=FibPathProto.FIB_PATH_NH_PROTO_IP4) ]) mpls_route.add_vpp_config() # # UDP over ipv4 decap # p_4 = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) / IP(src=self.pg0.remote_ip4, dst=self.pg0.local_ip4) / UDP(sport=1111, dport=220) / IP(src="2.2.2.2", dst="1.1.1.1") / UDP(sport=1234, dport=4321) / Raw(b'\xa5' * 100)) rx = self.send_and_expect(self.pg0, p_4 * NUM_PKTS, self.pg0) p_4 = IP(p_4["UDP"].payload) for p in rx: p = IP(p["Ether"].payload) self.validate_inner4(p, p_4, ttl=63) # # UDP over ipv6 decap # p_6 = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) / IPv6(src=self.pg1.remote_ip6, dst=self.pg1.local_ip6) / UDP(sport=2222, dport=221) / IPv6(src="2001::100", dst="2001::1") / UDP(sport=1234, dport=4321) / Raw(b'\xa5' * 100)) rx = self.send_and_expect(self.pg1, p_6 * NUM_PKTS, self.pg1) p_6 = IPv6(p_6["UDP"].payload) p = IPv6(rx[0]["Ether"].payload) for p in rx: p = IPv6(p["Ether"].payload) self.validate_inner6(p, p_6, hlim=63) # # UDP over mpls decap # p_mo4 = (Ether(src=self.pg2.remote_mac, dst=self.pg2.local_mac) / IP(src=self.pg2.remote_ip4, dst=self.pg2.local_ip4) / UDP(sport=3333, dport=222) / MPLS(label=77, ttl=1) / IP(src="4.4.4.4", dst="3.3.3.3") / UDP(sport=1234, dport=4321) / Raw(b'\xa5' * 100)) self.pg2.enable_mpls() rx = self.send_and_expect(self.pg2, p_mo4 * NUM_PKTS, self.pg2) self.pg2.disable_mpls() p_mo4 = IP(MPLS(p_mo4["UDP"].payload).payload) for p in rx: p = IP(p["Ether"].payload) self.validate_inner4(p, p_mo4, ttl=63)
def forge_packet(self, packet, **kwargs): return MPLS(**kwargs) / packet
def pkt_add_mpls(pkt, label, ttl, cos=0, s=1): return Ether(src=pkt[Ether].src, dst=pkt[Ether].dst) / \ MPLS(label=label, cos=cos, s=s, ttl=ttl) / \ pkt[Ether].payload
def test_ip_load_balance(self): """ IP Load-Balancing """ # # An array of packets that differ only in the destination port # port_ip_pkts = [] port_mpls_pkts = [] # # An array of packets that differ only in the source address # src_ip_pkts = [] src_mpls_pkts = [] for ii in range(65): port_ip_hdr = (IP(dst="10.0.0.1", src="20.0.0.1") / UDP(sport=1234, dport=1234 + ii) / Raw('\xa5' * 100)) port_ip_pkts.append( (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) / port_ip_hdr)) port_mpls_pkts.append( (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) / MPLS(label=66, ttl=2) / port_ip_hdr)) src_ip_hdr = (IP(dst="10.0.0.1", src="20.0.0.%d" % ii) / UDP(sport=1234, dport=1234) / Raw('\xa5' * 100)) src_ip_pkts.append( (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) / src_ip_hdr)) src_mpls_pkts.append( (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) / MPLS(label=66, ttl=2) / src_ip_hdr)) route_10_0_0_1 = VppIpRoute(self, "10.0.0.1", 32, [ VppRoutePath(self.pg1.remote_ip4, self.pg1.sw_if_index), VppRoutePath(self.pg2.remote_ip4, self.pg2.sw_if_index) ]) route_10_0_0_1.add_vpp_config() binding = VppMplsIpBind(self, 66, "10.0.0.1", 32) binding.add_vpp_config() # # inject the packet on pg0 - expect load-balancing across the 2 paths # - since the default hash config is to use IP src,dst and port # src,dst # We are not going to ensure equal amounts of packets across each link, # since the hash algorithm is statistical and therefore this can never # be guaranteed. But wuth 64 different packets we do expect some # balancing. So instead just ensure there is traffic on each link. # self.send_and_expect_load_balancing(self.pg0, port_ip_pkts, [self.pg1, self.pg2]) self.send_and_expect_load_balancing(self.pg0, src_ip_pkts, [self.pg1, self.pg2]) self.send_and_expect_load_balancing(self.pg0, port_mpls_pkts, [self.pg1, self.pg2]) self.send_and_expect_load_balancing(self.pg0, src_mpls_pkts, [self.pg1, self.pg2]) # # change the flow hash config so it's only IP src,dst # - now only the stream with differing source address will # load-balance # self.vapi.set_ip_flow_hash(0, src=1, dst=1, sport=0, dport=0) self.send_and_expect_load_balancing(self.pg0, src_ip_pkts, [self.pg1, self.pg2]) self.send_and_expect_load_balancing(self.pg0, src_mpls_pkts, [self.pg1, self.pg2]) self.send_and_expect_one_itf(self.pg0, port_ip_pkts, self.pg2) # # change the flow hash config back to defaults # self.vapi.set_ip_flow_hash(0, src=1, dst=1, sport=1, dport=1) # # Recursive prefixes # - testing that 2 stages of load-balancing occurs and there is no # polarisation (i.e. only 2 of 4 paths are used) # port_pkts = [] src_pkts = [] for ii in range(257): port_pkts.append( (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) / IP(dst="1.1.1.1", src="20.0.0.1") / UDP(sport=1234, dport=1234 + ii) / Raw('\xa5' * 100))) src_pkts.append( (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) / IP(dst="1.1.1.1", src="20.0.0.%d" % ii) / UDP(sport=1234, dport=1234) / Raw('\xa5' * 100))) route_10_0_0_2 = VppIpRoute(self, "10.0.0.2", 32, [ VppRoutePath(self.pg3.remote_ip4, self.pg3.sw_if_index), VppRoutePath(self.pg4.remote_ip4, self.pg4.sw_if_index) ]) route_10_0_0_2.add_vpp_config() route_1_1_1_1 = VppIpRoute(self, "1.1.1.1", 32, [ VppRoutePath("10.0.0.2", 0xffffffff), VppRoutePath("10.0.0.1", 0xffffffff) ]) route_1_1_1_1.add_vpp_config() # # inject the packet on pg0 - expect load-balancing across all 4 paths # self.vapi.cli("clear trace") self.send_and_expect_load_balancing( self.pg0, port_pkts, [self.pg1, self.pg2, self.pg3, self.pg4]) self.send_and_expect_load_balancing( self.pg0, src_pkts, [self.pg1, self.pg2, self.pg3, self.pg4]) # # Recursive prefixes # - testing that 2 stages of load-balancing, no choices # port_pkts = [] for ii in range(257): port_pkts.append( (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) / IP(dst="1.1.1.2", src="20.0.0.2") / UDP(sport=1234, dport=1234 + ii) / Raw('\xa5' * 100))) route_10_0_0_3 = VppIpRoute( self, "10.0.0.3", 32, [VppRoutePath(self.pg3.remote_ip4, self.pg3.sw_if_index)]) route_10_0_0_3.add_vpp_config() route_1_1_1_2 = VppIpRoute(self, "1.1.1.2", 32, [VppRoutePath("10.0.0.3", 0xffffffff)]) route_1_1_1_2.add_vpp_config() # # inject the packet on pg0 - expect load-balancing across all 4 paths # self.vapi.cli("clear trace") self.send_and_expect_one_itf(self.pg0, port_pkts, self.pg3)
for p in range(0, len(pkt), 8): chunk = bytes(pkt)[p:p+8] print(', '.join('0x{:02X}'.format(b) for b in chunk), end=",\n") ############################################################################### # begin golden/main.cc ############################################################################### payload = 'abcdefghijlkmnopqrstuvwzxyabcdefghijlkmnopqrstuvwzxy' spkt = Ether(dst='00:01:02:03:04:05', src='00:C1:C2:C3:C4:C5') / \ Dot1Q(vlan=100) / \ IP(dst='10.10.1.1', src='11.11.1.1') / \ TCP(sport=0x1234, dport=0x5678) / payload urpkt = Ether(dst='00:12:34:56:78:90', src='00:AA:BB:CC:DD:EE') / \ IP(dst='12.12.1.1', src='100.101.102.103', id=0, ttl=64) / \ UDP(sport=0xE4E7, dport=6635, chksum=0) / MPLS(label=200, s=1) / \ IP(dst='10.10.1.1', src='11.11.1.1') / \ TCP(sport=0x1234, dport=0x5678) / payload grpkt = Ether(dst='00:12:34:56:78:90', src='00:AA:BB:CC:DD:EE') / \ IP(dst='12.12.1.1', src='100.101.102.103', id=0, ttl=64) / \ GRE(proto=0x8847) / MPLS(label=200, s=1) / \ IP(dst='10.10.1.1', src='11.11.1.1') / \ TCP(sport=0x1234, dport=0x5678) / payload dump_pkt(spkt) dump_pkt(urpkt) payload = 'abcdefghijlkmnopqrstuvwzxyabcdefghijlkmnopqrstuvwzxy' spkt = Ether(dst='00:AA:BB:CC:DD:EE', src='00:12:34:56:78:90') / \ IP(dst='100.101.102.103', src='12.12.1.1', id=0, ttl=64) / \ UDP(sport=0xC0D, dport=6635) / MPLS(label=0x12345, s=1) / \ IP(dst='11.11.1.1', src='10.10.1.1') / \
def test_qos_mpls(self): """ QoS Mark/Record MPLS """ # # 255 QoS for all input values # from_ext = 7 from_ip = 6 from_mpls = 5 from_vlan = 4 output = [scapy.compat.chb(from_ext)] * 256 os1 = b''.join(output) output = [scapy.compat.chb(from_vlan)] * 256 os2 = b''.join(output) output = [scapy.compat.chb(from_mpls)] * 256 os3 = b''.join(output) output = [scapy.compat.chb(from_ip)] * 256 os4 = b''.join(output) rows = [{'outputs': os1}, {'outputs': os2}, {'outputs': os3}, {'outputs': os4}] self.vapi.qos_egress_map_update(1, rows) # # a route with 1 MPLS label # route_10_0_0_1 = VppIpRoute(self, "10.0.0.1", 32, [VppRoutePath(self.pg1.remote_ip4, self.pg1.sw_if_index, labels=[32])]) route_10_0_0_1.add_vpp_config() # # a route with 3 MPLS labels # route_10_0_0_3 = VppIpRoute(self, "10.0.0.3", 32, [VppRoutePath(self.pg1.remote_ip4, self.pg1.sw_if_index, labels=[63, 33, 34])]) route_10_0_0_3.add_vpp_config() # # enable IP QoS recording on the input Pg0 and MPLS egress marking # on Pg1 # self.vapi.qos_record_enable_disable(self.pg0.sw_if_index, self.QOS_SOURCE.QOS_API_SOURCE_IP, 1) self.vapi.qos_mark_enable_disable(self.pg1.sw_if_index, self.QOS_SOURCE.QOS_API_SOURCE_MPLS, 1, 1) # # packet that will get one label added and 3 labels added resp. # p_1 = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) / IP(src=self.pg0.remote_ip4, dst="10.0.0.1", tos=1) / UDP(sport=1234, dport=1234) / Raw(scapy.compat.chb(100) * NUM_PKTS)) p_3 = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) / IP(src=self.pg0.remote_ip4, dst="10.0.0.3", tos=1) / UDP(sport=1234, dport=1234) / Raw(scapy.compat.chb(100) * NUM_PKTS)) rx = self.send_and_expect(self.pg0, p_1 * NUM_PKTS, self.pg1) # # only 3 bits of ToS value in MPLS make sure tos is correct # and the label and EOS bit have not been corrupted # for p in rx: self.assertEqual(p[MPLS].cos, from_ip) self.assertEqual(p[MPLS].label, 32) self.assertEqual(p[MPLS].s, 1) rx = self.send_and_expect(self.pg0, p_3 * NUM_PKTS, self.pg1) for p in rx: self.assertEqual(p[MPLS].cos, from_ip) self.assertEqual(p[MPLS].label, 63) self.assertEqual(p[MPLS].s, 0) h = p[MPLS].payload self.assertEqual(h[MPLS].cos, from_ip) self.assertEqual(h[MPLS].label, 33) self.assertEqual(h[MPLS].s, 0) h = h[MPLS].payload self.assertEqual(h[MPLS].cos, from_ip) self.assertEqual(h[MPLS].label, 34) self.assertEqual(h[MPLS].s, 1) # # enable MPLS QoS recording on the input Pg0 and IP egress marking # on Pg1 # self.vapi.qos_record_enable_disable( self.pg0.sw_if_index, self.QOS_SOURCE.QOS_API_SOURCE_MPLS, 1) self.vapi.qos_mark_enable_disable(self.pg1.sw_if_index, self.QOS_SOURCE.QOS_API_SOURCE_IP, 1, 1) # # MPLS x-connect - COS according to pg1 map # route_32_eos = VppMplsRoute(self, 32, 1, [VppRoutePath(self.pg1.remote_ip4, self.pg1.sw_if_index, labels=[VppMplsLabel(33)])]) route_32_eos.add_vpp_config() p_m1 = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) / MPLS(label=32, cos=3, ttl=2) / IP(src=self.pg0.remote_ip4, dst="10.0.0.1", tos=1) / UDP(sport=1234, dport=1234) / Raw(scapy.compat.chb(100) * NUM_PKTS)) rx = self.send_and_expect(self.pg0, p_m1 * NUM_PKTS, self.pg1) for p in rx: self.assertEqual(p[MPLS].cos, from_mpls) self.assertEqual(p[MPLS].label, 33) self.assertEqual(p[MPLS].s, 1) # # MPLS deag - COS is copied from MPLS to IP # route_33_eos = VppMplsRoute(self, 33, 1, [VppRoutePath("0.0.0.0", 0xffffffff, nh_table_id=0)]) route_33_eos.add_vpp_config() route_10_0_0_4 = VppIpRoute(self, "10.0.0.4", 32, [VppRoutePath(self.pg1.remote_ip4, self.pg1.sw_if_index)]) route_10_0_0_4.add_vpp_config() p_m2 = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) / MPLS(label=33, ttl=2, cos=3) / IP(src=self.pg0.remote_ip4, dst="10.0.0.4", tos=1) / UDP(sport=1234, dport=1234) / Raw(scapy.compat.chb(100) * NUM_PKTS)) rx = self.send_and_expect(self.pg0, p_m2 * NUM_PKTS, self.pg1) for p in rx: self.assertEqual(p[IP].tos, from_mpls) # # cleanup # self.vapi.qos_record_enable_disable(self.pg0.sw_if_index, self.QOS_SOURCE.QOS_API_SOURCE_IP, 0) self.vapi.qos_mark_enable_disable(self.pg1.sw_if_index, self.QOS_SOURCE.QOS_API_SOURCE_MPLS, 1, 0) self.vapi.qos_record_enable_disable( self.pg0.sw_if_index, self.QOS_SOURCE.QOS_API_SOURCE_MPLS, 0) self.vapi.qos_mark_enable_disable(self.pg1.sw_if_index, self.QOS_SOURCE.QOS_API_SOURCE_IP, 1, 0) self.vapi.qos_egress_map_delete(1)
THRESHOLD = 50 CORE_PORTS = [1, 2] HOST_PORT = 3 addrs = ['10.0.0.1', '10.0.0.2', '10.0.0.3', '10.0.0.4'] REQ_FREQ = 0.5 server_dict = {2: '10.0.0.1', 4: '10.0.0.3', 6: '10.0.0.2', 8: '10.0.0.4'} MAX_32 = pow(2, 32) - 1 pkts = [] # Probe packet generated with scapy for i in [1, 2, 3, 4]: pkt = Ether(src="10:00:00:00:00:01", dst="20:00:00:00:00:02") / MPLS( ttl=64) / IP(ttl=64, dst='10.0.0.' + str(i), src='2.2.2.2') / UDP() pkts.append(bytearray(str(pkt))) class DDosDistributedDetection(app_manager.RyuApp): def __init__(self, *args, **kwargs): super(DDosDistributedDetection, self).__init__(*args, **kwargs) self.datapaths = [] self.output_files = ["state1.txt", "state2.txt"] self.monitor_thread = hub.spawn(self._monitor) def add_flow(self, datapath, table_id, priority, match, actions): if len(actions) > 0: inst = [ ofparser.OFPInstructionActions(ofproto.OFPIT_APPLY_ACTIONS, actions)