def sourcenat_test_icmp_echo6_conf(self): sports = [1234, 1235] dports = [6661, 6662] for nbr, remote_host in enumerate(self.pg1.remote_hosts): client_addr = self.pg0.remote_hosts[0].ip6 remote_addr = self.pg1.remote_hosts[nbr].ip6 src_nat_addr = self.pg2.remote_hosts[0].ip6 # ping from pods to outside network p1 = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_hosts[0].mac) / IPv6(src=client_addr, dst=remote_addr) / ICMPv6EchoRequest(id=0xfeed) / Raw()) rxs = self.send_and_expect(self.pg0, p1 * N_PKTS, self.pg1) for rx in rxs: self.assertEqual(rx[IPv6].src, src_nat_addr) self.assert_packet_checksums_valid(rx) received_id = rx[0][ICMPv6EchoRequest].id # ping reply from outside to pods p2 = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_hosts[nbr].mac) / IPv6(src=remote_addr, dst=src_nat_addr) / ICMPv6EchoReply(id=received_id)) rxs = self.send_and_expect(self.pg1, p2 * N_PKTS, self.pg0) for rx in rxs: self.assert_packet_checksums_valid(rx) self.assertEqual(rx[IPv6].src, remote_addr) self.assertEqual(rx[ICMPv6EchoReply].id, 0xfeed)
def test_map_t_echo_reply_ip6_to_ip4(self): """ MAP-T echo reply IPv6 -> IPv4 """ eth = Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) ip = IPv6(src=self.ipv6_cpe_address, dst=self.ipv6_map_address) icmp = ICMPv6EchoReply(id=self.ipv6_udp_or_tcp_map_port) payload = "H" * 10 tx_pkt = eth / ip / icmp / payload self.pg_send(self.pg1, tx_pkt * 1) rx_pkts = self.pg0.get_capture(1) rx_pkt = rx_pkts[0] self.assertEqual(rx_pkt[IP].proto, IP(proto="icmp").proto) self.assertEqual(rx_pkt[ICMP].type, ICMP(type="echo-reply").type) self.assertEqual(rx_pkt[ICMP].code, 0) self.assertEqual(rx_pkt[ICMP].id, self.ipv6_udp_or_tcp_map_port)
def cnat_send_return(self): """This sends the return traffic""" if self.L4PROTO in [TCP, UDP]: l4 = self.L4PROTO(sport=self.expect_dst_port, dport=self.expect_src_port) elif self.L4PROTO in [ICMP] and not self.is_v6: # icmp type 0 if echo reply l4 = self.L4PROTO(id=self.expect_src_port, type=0) elif self.L4PROTO in [ICMP] and self.is_v6: l4 = ICMPv6EchoReply(id=self.expect_src_port) src_mac = self.expected_dst_pg.remote_mac p1 = (Ether(src=src_mac, dst=self.expected_dst_pg.local_mac) / self.IP46(src=self.expect_dst_addr, dst=self.expect_src_addr) / l4 / Raw()) self.return_rxs = self._test.send_and_expect(self.expected_dst_pg, p1 * N_PKTS, self.expected_src_pg) return self
def test_map_t_echo_reply_ip4_to_ip6(self): """ MAP-T echo reply IPv4 -> IPv6 """ eth = Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) ip = IP(src=self.pg0.remote_ip4, dst=self.ipv4_map_address) icmp = ICMP(type="echo-reply", id=self.ipv6_udp_or_tcp_map_port) payload = "H" * 10 tx_pkt = eth / ip / icmp / payload self.pg_send(self.pg0, tx_pkt * 1) rx_pkts = self.pg1.get_capture(1) rx_pkt = rx_pkts[0] self.assertEqual(rx_pkt[IPv6].nh, IPv6(nh="ICMPv6").nh) self.assertEqual(rx_pkt[ICMPv6EchoReply].type, ICMPv6EchoReply(type="Echo Reply").type) self.assertEqual(rx_pkt[ICMPv6EchoReply].code, 0) self.assertEqual(rx_pkt[ICMPv6EchoReply].id, self.ipv6_udp_or_tcp_map_port)
def main(): args = TrafficScriptArg(['src_mac', 'dst_mac', 'src_ip', 'dst_ip']) rxq = RxQueue(args.get_arg('rx_if')) txq = TxQueue(args.get_arg('tx_if')) src_mac = args.get_arg('src_mac') dst_mac = args.get_arg('dst_mac') src_ip = args.get_arg('src_ip') dst_ip = args.get_arg('dst_ip') echo_id = 0xa echo_seq = 0x1 sent_packets = [] # send ICMPv6 neighbor advertisement message pkt_send = (Ether(src=src_mac, dst='ff:ff:ff:ff:ff:ff') / IPv6(src=src_ip, dst='ff02::1:ff00:2') / ICMPv6ND_NA(tgt=src_ip, R=0) / ICMPv6NDOptDstLLAddr(lladdr=src_mac)) sent_packets.append(pkt_send) txq.send(pkt_send) # send ICMPv6 echo request pkt_send = (Ether(src=src_mac, dst=dst_mac) / IPv6(src=src_ip, dst=dst_ip) / ICMPv6EchoRequest(id=echo_id, seq=echo_seq)) sent_packets.append(pkt_send) txq.send(pkt_send) # receive ICMPv6 echo reply while True: ether = rxq.recv(2, sent_packets) if ether is None: raise RuntimeError('ICMPv6 echo reply Rx timeout') if ether.haslayer(ICMPv6ND_NS): # read another packet in the queue if the current one is ICMPv6ND_NS continue else: # otherwise process the current packet break if not ether.haslayer(IPv6): raise RuntimeError( 'Unexpected packet with no IPv6 received {0}'.format( ether.__repr__())) ipv6 = ether[IPv6] if not ipv6.haslayer(ICMPv6EchoReply): raise RuntimeError('Unexpected packet with no ICMPv6 echo reply ' 'received {0}'.format(ipv6.__repr__())) icmpv6 = ipv6[ICMPv6EchoReply] # check identifier and sequence number if icmpv6.id != echo_id or icmpv6.seq != echo_seq: raise RuntimeError('Invalid ICMPv6 echo reply received ID {0} seq {1} ' 'should be ID {2} seq {3}'.format( icmpv6.id, icmpv6.seq, echo_id, echo_seq)) # verify checksum cksum = icmpv6.cksum del icmpv6.cksum tmp = ICMPv6EchoReply(str(icmpv6)) if not checksum_equal(tmp.cksum, cksum): raise RuntimeError('Invalid checksum {0} should be {1}'.format( cksum, tmp.cksum)) sys.exit(0)
def test_static(self): """1:1 NAT66 test""" flags = self.config_flags.NAT_IS_INSIDE self.vapi.nat66_add_del_interface(is_add=1, flags=flags, sw_if_index=self.pg0.sw_if_index) self.vapi.nat66_add_del_interface(is_add=1, sw_if_index=self.pg1.sw_if_index) self.vapi.nat66_add_del_static_mapping( local_ip_address=self.pg0.remote_ip6, external_ip_address=self.nat_addr, is_add=1, ) # in2out pkts = [] p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) / IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) / TCP()) pkts.append(p) p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) / IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) / UDP()) pkts.append(p) p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) / IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) / ICMPv6EchoRequest()) pkts.append(p) p = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) / IPv6(src=self.pg0.remote_ip6, dst=self.pg1.remote_ip6) / GRE() / IP() / TCP()) pkts.append(p) self.pg0.add_stream(pkts) self.pg_enable_capture(self.pg_interfaces) self.pg_start() capture = self.pg1.get_capture(len(pkts)) for packet in capture: try: self.assertEqual(packet[IPv6].src, self.nat_addr) self.assertEqual(packet[IPv6].dst, self.pg1.remote_ip6) self.assert_packet_checksums_valid(packet) except: self.logger.error(ppp("Unexpected or invalid packet:", packet)) raise # out2in pkts = [] p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) / IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr) / TCP()) pkts.append(p) p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) / IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr) / UDP()) pkts.append(p) p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) / IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr) / ICMPv6EchoReply()) pkts.append(p) p = (Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) / IPv6(src=self.pg1.remote_ip6, dst=self.nat_addr) / GRE() / IP() / TCP()) pkts.append(p) self.pg1.add_stream(pkts) self.pg_enable_capture(self.pg_interfaces) self.pg_start() capture = self.pg0.get_capture(len(pkts)) for packet in capture: try: self.assertEqual(packet[IPv6].src, self.pg1.remote_ip6) self.assertEqual(packet[IPv6].dst, self.pg0.remote_ip6) self.assert_packet_checksums_valid(packet) except: self.logger.error(ppp("Unexpected or invalid packet:", packet)) raise sm = self.vapi.nat66_static_mapping_dump() self.assertEqual(len(sm), 1) self.assertEqual(sm[0].total_pkts, 8)
def test_nd_mirror_proxy(self): """ Interface (Mirror) Proxy ND """ # # When VPP has an interface whose address is also applied to a TAP # interface on the host, then VPP's TAP interface will be unnumbered # to the 'real' interface and do proxy ND from the host. # the curious aspect of this setup is that ND requests from the host # will come from the VPP's own address. # addr = self.pg0.remote_ip6 nsma = in6_getnsma(inet_pton(socket.AF_INET6, addr)) d = inet_ntop(socket.AF_INET6, nsma) # Make pg1 un-numbered to pg0 # self.pg1.unconfig_ip6() self.pg1.set_unnumbered(self.pg0.sw_if_index) # # Enable ND proxy on pg1 # self.vapi.ip6nd_proxy_enable_disable(sw_if_index=self.pg1.sw_if_index, is_enable=1) # # Send the ND request with an originating address that # is VPP's own address # nd_req_from_host = ( Ether(src=self.pg1.remote_mac, dst=in6_getnsmac(nsma)) / IPv6(dst=d, src=self.pg0.local_ip6) / ICMPv6ND_NS(tgt=addr) / ICMPv6NDOptSrcLLAddr(lladdr=self.pg1.remote_mac)) rx = self.send_and_expect(self.pg1, [nd_req_from_host], self.pg1) self.assertEqual(rx[0][Ether].src, self.pg1.local_mac) self.assertEqual(rx[0][Ether].dst, self.pg1.remote_mac) self.assertEqual(rx[0][IPv6].src, self.pg0.remote_ip6) self.assertEqual(rx[0][IPv6].dst, self.pg0.local_ip6) self.assertEqual(ipv6nh[rx[0][IPv6].nh], "ICMPv6") self.assertEqual(rx[0][ICMPv6ND_NA].tgt, self.pg0.remote_ip6) self.assertTrue(rx[0].haslayer(ICMPv6NDOptDstLLAddr)) self.assertEqual(rx[0][ICMPv6NDOptDstLLAddr].lladdr, self.pg1.local_mac) # # Send the unicast ND request # unicast_nd_req_from_host = ( Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) / IPv6(dst=self.pg0.remote_ip6, src=self.pg1.remote_ip6_ll) / ICMPv6ND_NS(tgt=self.pg0.remote_ip6) / ICMPv6NDOptSrcLLAddr(lladdr=self.pg1.remote_mac)) rx = self.send_and_expect(self.pg1, [unicast_nd_req_from_host], self.pg0) self.assertEqual(rx[0][Ether].src, self.pg0.local_mac) self.assertEqual(rx[0][Ether].dst, in6_getnsmac(nsma)) self.assertEqual(rx[0][IPv6].src, self.pg0.local_ip6) self.assertEqual(rx[0][IPv6].dst, d) self.assertEqual(ipv6nh[rx[0][IPv6].nh], "ICMPv6") self.assertEqual(rx[0][ICMPv6ND_NS].tgt, self.pg0.remote_ip6) self.assertTrue(rx[0].haslayer(ICMPv6NDOptSrcLLAddr)) self.assertEqual(rx[0][ICMPv6NDOptSrcLLAddr].lladdr, self.pg0.local_mac) # Resolve the NDs on the uplink self.pg0.resolve_ndp() # # Again send the unicast ND request, this time dst address should be # in local cache # rx = self.send_and_expect(self.pg1, [unicast_nd_req_from_host], self.pg1) self.assertEqual(rx[0][Ether].src, self.pg1.local_mac) self.assertEqual(rx[0][Ether].dst, self.pg1.remote_mac) self.assertEqual(rx[0][IPv6].src, self.pg0.remote_ip6) self.assertEqual(in6_ptop(rx[0][IPv6].dst), in6_ptop(self.pg1.remote_ip6_ll)) self.assertEqual(ipv6nh[rx[0][IPv6].nh], "ICMPv6") self.assertEqual(rx[0][ICMPv6ND_NA].tgt, self.pg0.remote_ip6) self.assertTrue(rx[0].haslayer(ICMPv6NDOptDstLLAddr)) self.assertEqual(rx[0][ICMPv6NDOptDstLLAddr].lladdr, self.pg1.local_mac) # # Send the Echo Request from host to remote (of uplink) # id = self.pg1.sw_if_index seq = 0x1 echo_request = ( Ether(dst=self.pg1.local_mac, src=self.pg1.remote_mac) / IPv6(dst=self.pg0.remote_ip6, src=self.pg0.local_ip6) / ICMPv6EchoRequest(seq=seq, id=id)) rx = self.send_and_expect(self.pg1, [echo_request], self.pg0) self.assertEqual(rx[0][Ether].src, self.pg0.local_mac) self.assertEqual(rx[0][Ether].dst, self.pg0.remote_mac) self.assertEqual(rx[0][IPv6].src, self.pg0.local_ip6) self.assertEqual(rx[0][IPv6].dst, self.pg0.remote_ip6) self.assertEqual(ipv6nh[rx[0][IPv6].nh], "ICMPv6") self.assertTrue(rx[0].haslayer(ICMPv6EchoRequest)) self.assertEqual(rx[0][ICMPv6EchoRequest].id, id) self.assertEqual(rx[0][ICMPv6EchoRequest].seq, seq) # # setup a punt redirect so packets from the uplink go to the tap # redirect = VppIpPuntRedirect(self, self.pg0.sw_if_index, self.pg1.sw_if_index, self.pg0.local_ip6) redirect.add_vpp_config() echo_reply = (Ether(dst=self.pg0.remote_mac, src=self.pg0.local_mac) / IPv6(dst=self.pg0.local_ip6, src=self.pg0.remote_ip6) / ICMPv6EchoReply(seq=1, id=id)) rx = self.send_and_expect(self.pg0, [echo_reply], self.pg1) self.assertEqual(rx[0][Ether].src, self.pg1.local_mac) self.assertEqual(rx[0][Ether].dst, self.pg1.remote_mac) self.assertEqual(rx[0][IPv6].src, self.pg0.remote_ip6) self.assertEqual(rx[0][IPv6].dst, self.pg0.local_ip6) self.assertEqual(ipv6nh[rx[0][IPv6].nh], "ICMPv6") self.assertTrue(rx[0].haslayer(ICMPv6EchoReply)) self.assertEqual(rx[0][ICMPv6EchoReply].id, id) self.assertEqual(rx[0][ICMPv6EchoReply].seq, seq) # # cleanup # self.vapi.ip6nd_proxy_enable_disable(sw_if_index=self.pg1.sw_if_index, is_enable=0) redirect.remove_vpp_config()
def ipv6_ping(src_if, dst_if, src_mac, dst_mac, proxy_to_src_mac, proxy_to_dst_mac, src_ip, dst_ip): """Sends ICMPv6 Echo Request, receive it and send a reply. :param src_if: First TG interface on link to DUT. :param dst_if: Second TG interface on link to DUT. :param src_mac: MAC address of first interface. :param dst_mac: MAC address of second interface. :param proxy_to_src_mac: MAC address of first proxy interface on DUT. :param proxy_to_dst_mac: MAC address of second proxy interface on DUT. :param src_ip: IP address of first interface. :param dst_ip: IP address of second interface. :type src_if: str :type dst_if: str :type src_mac: str :type dst_mac: str :type proxy_to_src_mac: str :type proxy_to_dst_mac: str :type src_ip: str :type dst_ip: str :raises RuntimeError: If a received packet is not correct. """ rxq = RxQueue(dst_if) txq = TxQueue(src_if) icmpv6_ping_pkt = (Ether(src=src_mac, dst=proxy_to_src_mac) / IPv6(src=src_ip, dst=dst_ip) / ICMPv6EchoRequest()) txq.send(icmpv6_ping_pkt) ether = None while True: ether = rxq.recv(3) if not ether: continue if ether.haslayer(ICMPv6ND_NS): # read another packet in the queue in case of ICMPv6ND_NS packet continue else: # otherwise process the current packet break if ether is None: raise RuntimeError('ICMPv6 Echo Request timeout.') try: ether[IPv6]["ICMPv6 Echo Request"] except KeyError: raise RuntimeError("Received packet is not an ICMPv6 Echo Request.") print "ICMP Echo: OK." rxq = RxQueue(src_if) txq = TxQueue(dst_if) icmpv6_ping_pkt = (Ether(src=dst_mac, dst=proxy_to_dst_mac) / IPv6(src=dst_ip, dst=src_ip) / ICMPv6EchoReply()) txq.send(icmpv6_ping_pkt) ether = None while True: ether = rxq.recv(3) if not ether: continue if ether.haslayer(ICMPv6ND_NS): # read another packet in the queue in case of ICMPv6ND_NS packet continue else: # otherwise process the current packet break if ether is None: raise RuntimeError('DHCPv6 SOLICIT timeout') try: ether[IPv6]["ICMPv6 Echo Reply"] except KeyError: raise RuntimeError("Received packet is not an ICMPv6 Echo Reply.") print "ICMP Reply: OK."
def ipv6_ping(src_if, dst_if, src_mac, dst_mac, proxy_to_src_mac, proxy_to_dst_mac, src_ip, dst_ip): """Sends ICMPv6 Echo Request, receive it and send a reply. :param src_if: First TG interface on link to DUT. :param dst_if: Second TG interface on link to DUT. :param src_mac: MAC address of first interface. :param dst_mac: MAC address of second interface. :param proxy_to_src_mac: MAC address of first proxy interface on DUT. :param proxy_to_dst_mac: MAC address of second proxy interface on DUT. :param src_ip: IP address of first interface. :param dst_ip: IP address of second interface. :type src_if: str :type dst_if: str :type src_mac: str :type dst_mac: str :type proxy_to_src_mac: str :type proxy_to_dst_mac: str :type src_ip: str :type dst_ip: str :raises RuntimeError: If a received packet is not correct. """ rxq = RxQueue(dst_if) txq = TxQueue(src_if) icmpv6_ping_pkt = \ Ether(src=src_mac, dst=proxy_to_src_mac) / \ IPv6(src=src_ip, dst=dst_ip) / \ ICMPv6EchoRequest() txq.send(icmpv6_ping_pkt) ether = None for _ in range(5): pkt = rxq.recv(3) if pkt is not None: ether = pkt break if ether is None: raise RuntimeError('ICMPv6 Echo Request timeout.') try: ether["IPv6"]["ICMPv6 Echo Request"] except KeyError: raise RuntimeError("Received packet is not an ICMPv6 Echo Request.") print "ICMP Echo: OK." rxq = RxQueue(src_if) txq = TxQueue(dst_if) icmpv6_ping_pkt = \ Ether(src=dst_mac, dst=proxy_to_dst_mac) / \ IPv6(src=dst_ip, dst=src_ip) / \ ICMPv6EchoReply() txq.send(icmpv6_ping_pkt) ether = None for _ in range(5): pkt = rxq.recv(3) if pkt is not None: ether = pkt break if ether is None: raise RuntimeError('DHCPv6 SOLICIT timeout') try: ether["IPv6"]["ICMPv6 Echo Reply"] except KeyError: raise RuntimeError("Received packet is not an ICMPv6 Echo Reply.") print "ICMP Reply: OK."
def main(): # start_size - start size of the ICMPv6 echo data # end_size - end size of the ICMPv6 echo data # step - increment step args = TrafficScriptArg([ 'src_mac', 'dst_mac', 'src_ip', 'dst_ip', 'start_size', 'end_size', 'step' ]) rxq = RxQueue(args.get_arg('rx_if')) txq = TxQueue(args.get_arg('tx_if')) src_mac = args.get_arg('src_mac') dst_mac = args.get_arg('dst_mac') src_ip = args.get_arg('src_ip') dst_ip = args.get_arg('dst_ip') start_size = int(args.get_arg('start_size')) end_size = int(args.get_arg('end_size')) step = int(args.get_arg('step')) echo_id = 0xa # generate some random data buffer data = bytearray(os.urandom(end_size)) # send ICMPv6 neighbor advertisement message sent_packets = [] pkt_send = (Ether(src=src_mac, dst=dst_mac) / IPv6(src=src_ip, dst=dst_ip) / ICMPv6ND_NA(tgt=src_ip, R=0) / ICMPv6NDOptDstLLAddr(lladdr=src_mac)) sent_packets.append(pkt_send) txq.send(pkt_send) # send ICMPv6 echo request with incremented data length and receive ICMPv6 # echo reply for echo_seq in range(start_size, end_size + 1, step): pkt_send = ( Ether(src=src_mac, dst=dst_mac) / IPv6(src=src_ip, dst=dst_ip) / ICMPv6EchoRequest(id=echo_id, seq=echo_seq, data=data[0:echo_seq])) sent_packets.append(pkt_send) txq.send(pkt_send) ether = rxq.recv(ignore=sent_packets) if ether is None: raise RuntimeError( 'ICMPv6 echo reply seq {0} Rx timeout'.format(echo_seq)) if not ether.haslayer(IPv6): raise RuntimeError( 'Unexpected packet with no IPv6 received {0}'.format( ether.__repr__())) ipv6 = ether['IPv6'] if not ipv6.haslayer(ICMPv6EchoReply): raise RuntimeError( 'Unexpected packet with no IPv6 ICMP received {0}'.format( ipv6.__repr__())) icmpv6 = ipv6['ICMPv6 Echo Reply'] if icmpv6.id != echo_id or icmpv6.seq != echo_seq: raise RuntimeError( 'Invalid ICMPv6 echo reply received ID {0} seq {1} should be ' 'ID {2} seq {3}, {0}'.format(icmpv6.id, icmpv6.seq, echo_id, echo_seq)) cksum = icmpv6.cksum del icmpv6.cksum tmp = ICMPv6EchoReply(str(icmpv6)) if not checksum_equal(tmp.cksum, cksum): raise RuntimeError('Invalid checksum {0} should be {1}'.format( cksum, tmp.cksum)) sent_packets.remove(pkt_send) sys.exit(0)
def main(): args = TrafficScriptArg([ 'src_mac', 'dst_mac', 'src_nh_mac', 'dst_nh_mac', 'src_ip', 'dst_ip', 'h_num' ]) src_rxq = RxQueue(args.get_arg('rx_if')) src_txq = TxQueue(args.get_arg('rx_if')) dst_rxq = RxQueue(args.get_arg('tx_if')) dst_txq = TxQueue(args.get_arg('tx_if')) src_mac = args.get_arg('src_mac') dst_mac = args.get_arg('dst_mac') src_nh_mac = args.get_arg('src_nh_mac') dst_nh_mac = args.get_arg('dst_nh_mac') src_ip = args.get_arg('src_ip') dst_ip = args.get_arg('dst_ip') hop_num = int(args.get_arg('h_num')) hop_limit = 64 echo_id = 0xa echo_seq = 0x1 src_sent_packets = [] dst_sent_packets = [] # send ICMPv6 neighbor advertisement message pkt_send = (Ether(src=src_mac, dst='ff:ff:ff:ff:ff:ff') / IPv6(src=src_ip, dst='ff02::1:ff00:2') / ICMPv6ND_NA(tgt=src_ip, R=0) / ICMPv6NDOptDstLLAddr(lladdr=src_mac)) src_sent_packets.append(pkt_send) src_txq.send(pkt_send) pkt_send = (Ether(src=dst_mac, dst='ff:ff:ff:ff:ff:ff') / IPv6(src=dst_ip, dst='ff02::1:ff00:2') / ICMPv6ND_NA(tgt=dst_ip, R=0) / ICMPv6NDOptDstLLAddr(lladdr=dst_mac)) dst_sent_packets.append(pkt_send) dst_txq.send(pkt_send) # send ICMPv6 echo request from first TG interface pkt_send = (Ether(src=src_mac, dst=src_nh_mac) / IPv6(src=src_ip, dst=dst_ip, hlim=hop_limit) / ICMPv6EchoRequest(id=echo_id, seq=echo_seq)) src_sent_packets.append(pkt_send) src_txq.send(pkt_send) # receive ICMPv6 echo request on second TG interface ether = dst_rxq.recv(2, dst_sent_packets) if ether is None: raise RuntimeError('ICMPv6 echo reply Rx timeout') if not ether.haslayer(IPv6): raise RuntimeError( 'Unexpected packet with no IPv6 received {0}'.format( ether.__repr__())) ipv6 = ether['IPv6'] # verify hop limit processing if ipv6.hlim != (hop_limit - hop_num): raise RuntimeError('Invalid hop limit {0} should be {1}'.format( ipv6.hlim, hop_limit - hop_num)) if not ipv6.haslayer(ICMPv6EchoRequest): raise RuntimeError( 'Unexpected packet with no IPv6 ICMP received {0}'.format( ipv6.__repr__())) icmpv6 = ipv6['ICMPv6 Echo Request'] # check identifier and sequence number if icmpv6.id != echo_id or icmpv6.seq != echo_seq: raise RuntimeError( 'Invalid ICMPv6 echo reply received ID {0} seq {1} should be ' \ 'ID {2} seq {3}'.format(icmpv6.id, icmpv6.seq, echo_id, echo_seq)) # verify checksum cksum = icmpv6.cksum del icmpv6.cksum tmp = ICMPv6EchoRequest(str(icmpv6)) if not checksum_equal(tmp.cksum, cksum): raise RuntimeError('Invalid checksum {0} should be {1}'.format( cksum, tmp.cksum)) # send ICMPv6 echo reply from second TG interface pkt_send = (Ether(src=dst_mac, dst=dst_nh_mac) / IPv6(src=dst_ip, dst=src_ip) / ICMPv6EchoReply(id=echo_id, seq=echo_seq)) dst_sent_packets.append(pkt_send) dst_txq.send(pkt_send) # receive ICMPv6 echo reply on first TG interface ether = src_rxq.recv(2, src_sent_packets) if ether is None: raise RuntimeError('ICMPv6 echo reply Rx timeout') if not ether.haslayer(IPv6): raise RuntimeError( 'Unexpected packet with no IPv6 received {0}'.format( ether.__repr__())) ipv6 = ether['IPv6'] # verify hop limit processing if ipv6.hlim != (hop_limit - hop_num): raise RuntimeError('Invalid hop limit {0} should be {1}'.format( ipv6.hlim, hop_limit - hop_num)) if not ipv6.haslayer(ICMPv6EchoReply): raise RuntimeError( 'Unexpected packet with no IPv6 ICMP received {0}'.format( ipv6.__repr__())) icmpv6 = ipv6['ICMPv6 Echo Reply'] # check identifier and sequence number if icmpv6.id != echo_id or icmpv6.seq != echo_seq: raise RuntimeError( 'Invalid ICMPv6 echo reply received ID {0} seq {1} should be ' \ 'ID {2} seq {3}'.format(icmpv6.id, icmpv6.seq, echo_id, echo_seq)) # verify checksum cksum = icmpv6.cksum del icmpv6.cksum tmp = ICMPv6EchoReply(str(icmpv6)) if not checksum_equal(tmp.cksum, cksum): raise RuntimeError('Invalid checksum {0} should be {1}'.format( cksum, tmp.cksum)) sys.exit(0)
def main(): args = TrafficScriptArg([ 'src_mac', 'dst_mac', 'src_nh_mac', 'dst_nh_mac', 'src_ip', 'dst_ip', 'h_num' ], ['is_dst_tg']) src_rxq = RxQueue(args.get_arg('tx_if')) src_txq = TxQueue(args.get_arg('tx_if')) src_mac = args.get_arg('src_mac') dst_mac = args.get_arg('dst_mac') src_nh_mac = args.get_arg('src_nh_mac') dst_nh_mac = args.get_arg('dst_nh_mac') src_ip = args.get_arg('src_ip') dst_ip = args.get_arg('dst_ip') hop_num = int(args.get_arg('h_num')) is_dst_tg = True if args.get_arg('is_dst_tg') in ['True', ''] else False dst_rxq = RxQueue(args.get_arg('rx_if')) if is_dst_tg else None dst_txq = TxQueue(args.get_arg('rx_if')) if is_dst_tg else None hop_limit = 64 echo_id = 0xa echo_seq = 0x1 src_sent_packets = [] dst_sent_packets = [] # send ICMPv6 neighbor advertisement message pkt_send = (Ether(src=src_mac, dst='ff:ff:ff:ff:ff:ff') / IPv6(src=src_ip, dst='ff02::1:ff00:2') / ICMPv6ND_NA(tgt=src_ip, R=0) / ICMPv6NDOptDstLLAddr(lladdr=src_mac)) src_sent_packets.append(pkt_send) src_txq.send(pkt_send) if is_dst_tg: # send ICMPv6 neighbor advertisement message pkt_send = (Ether(src=dst_mac, dst='ff:ff:ff:ff:ff:ff') / IPv6(src=dst_ip, dst='ff02::1:ff00:2') / ICMPv6ND_NA(tgt=dst_ip, R=0) / ICMPv6NDOptDstLLAddr(lladdr=dst_mac)) dst_sent_packets.append(pkt_send) dst_txq.send(pkt_send) # send ICMPv6 echo request from first TG interface pkt_send = (Ether(src=src_mac, dst=src_nh_mac) / IPv6(src=src_ip, dst=dst_ip, hlim=hop_limit) / ICMPv6EchoRequest(id=echo_id, seq=echo_seq)) src_sent_packets.append(pkt_send) src_txq.send(pkt_send) if is_dst_tg: # receive ICMPv6 echo request on second TG interface while True: ether = dst_rxq.recv(2, dst_sent_packets) if ether is None: raise RuntimeError('ICMPv6 echo reply Rx timeout') if ether.haslayer(ICMPv6ND_NS): # read another packet in the queue if the current one is # ICMPv6ND_NS continue else: # otherwise process the current packet break if not ether.haslayer(IPv6): raise RuntimeError( 'Unexpected packet with no IPv6 received: {0}'.format( ether.__repr__())) ipv6 = ether[IPv6] # verify hop limit processing if ipv6.hlim != (hop_limit - hop_num): raise RuntimeError('Invalid hop limit {0} should be {1}'.format( ipv6.hlim, hop_limit - hop_num)) if not ipv6.haslayer(ICMPv6EchoRequest): raise RuntimeError('Unexpected packet with no IPv6 ICMP received ' '{0}'.format(ipv6.__repr__())) icmpv6 = ipv6[ICMPv6EchoRequest] # check identifier and sequence number if icmpv6.id != echo_id or icmpv6.seq != echo_seq: raise RuntimeError('Invalid ICMPv6 echo reply received ID {0} ' 'seq {1} should be ID {2} seq {3}'.format( icmpv6.id, icmpv6.seq, echo_id, echo_seq)) # verify checksum cksum = icmpv6.cksum del icmpv6.cksum tmp = ICMPv6EchoRequest(str(icmpv6)) if not checksum_equal(tmp.cksum, cksum): raise RuntimeError('Invalid checksum {0} should be {1}'.format( cksum, tmp.cksum)) # send ICMPv6 echo reply from second TG interface pkt_send = (Ether(src=dst_mac, dst=dst_nh_mac) / IPv6(src=dst_ip, dst=src_ip, hlim=(ipv6.hlim - 1)) / ICMPv6EchoReply(id=echo_id, seq=echo_seq)) dst_sent_packets.append(pkt_send) dst_txq.send(pkt_send) # receive ICMPv6 echo reply on first TG interface while True: ether = src_rxq.recv(2, src_sent_packets) if ether is None: raise RuntimeError('ICMPv6 echo reply Rx timeout') if ether.haslayer(ICMPv6ND_NS): # read another packet in the queue if the current one is ICMPv6ND_NS continue else: # otherwise process the current packet break if not ether.haslayer(IPv6): raise RuntimeError( 'Unexpected packet with no IPv6 layer received {0}'.format( ether.__repr__())) ipv6 = ether[IPv6] # verify hop limit processing; destination node decrements hlim by one in # outgoing ICMPv6 Echo Reply directions = 2 if is_dst_tg else 1 hop_limit_reply = hop_limit - directions * hop_num - 1 if ipv6.hlim != hop_limit_reply: raise RuntimeError('Invalid hop limit {0} should be {1}'.format( ipv6.hlim, hop_limit_reply)) if not ipv6.haslayer(ICMPv6EchoReply): raise RuntimeError( 'Unexpected packet with no IPv6 ICMP received {0}'.format( ipv6.__repr__())) icmpv6 = ipv6[ICMPv6EchoReply] # check identifier and sequence number if icmpv6.id != echo_id or icmpv6.seq != echo_seq: raise RuntimeError('Invalid ICMPv6 echo reply received ID {0} ' 'seq {1} should be ID {2} seq {3}'.format( icmpv6.id, icmpv6.seq, echo_id, echo_seq)) # verify checksum cksum = icmpv6.cksum del icmpv6.cksum tmp = ICMPv6EchoReply(str(icmpv6)) if not checksum_equal(tmp.cksum, cksum): raise RuntimeError('Invalid checksum {0} should be {1}'.format( cksum, tmp.cksum)) sys.exit(0)