def run(self):
        instance = ByteBlower.InstanceGet()
        assert isinstance(instance, ByteBlower)

        # Connect to the server
        self.server = instance.ServerAdd(self.server_address)

        # create and configure the port.
        self.port = self.server.PortCreate(self.server_interface)

        # configure the MAC address on the port
        port_layer2_config = self.port.Layer2EthIISet()
        port_layer2_config.MacSet(self.port_mac_address)

        # configure the IP addressing on the port
        port_layer3_config = self.port.Layer3IPv6Set()
        if (type(self.port_ip_address) is str
                and self.port_ip_address.lower() == 'dhcp'):
            # DHCP is configured on the DHCP protocol
            dhcp_protocol = port_layer3_config.ProtocolDhcpGet()
            dhcp_protocol.Perform()
        elif (type(self.port_ip_address) is str
              and self.port_ip_address.lower() == 'slaac'):
            # wait for stateless autoconfiguration to complete
            port_layer3_config.StatelessAutoconfiguration()
        else:
            # Static addressing
            address = self.port_ip_address[0]
            prefixlength = self.port_ip_address[1]
            ip = "{}/{}".format(address, prefixlength)
            port_layer3_config.IpManualAdd(ip)

        print("Created port", self.port.DescriptionGet())

        # Connect to the meetingpoint
        self.meetingpoint = instance.MeetingPointAdd(self.meetingpoint_address)

        # If no WirelessEndpoint UUID was given, search an available one.
        if self.wireless_endpoint_uuid is None:
            self.wireless_endpoint_uuid = self.select_wireless_endpoint_uuid()

        # Get the WirelessEndpoint device
        self.wireless_endpoint = self.meetingpoint.DeviceGet(
            self.wireless_endpoint_uuid)
        print("Using wireless endpoint",
              self.wireless_endpoint.DescriptionGet())

        # Now we have the correct information to start configuring the flow.

        # The ByteBlower port will transmit frames to the wireless endpoint,
        # This means we need to create a 'stream' on the ByteBlower port
        #  and a Trigger on the WirelessEndpoint

        stream = self.port.TxStreamAdd()
        stream.InterFrameGapSet(self.interframe_gap_nanoseconds)
        stream.NumberOfFramesSet(self.number_of_frames)

        # a stream needs to send some data, so lets create a frame
        # For the frame, we need:
        # - The source MAC address (MAC address of the ByteBlower port
        #   in our case)
        # - The destination MAC address.  This can be the MAC address of the
        #   WirelessEndpoint, a router, ... This will resolved later on.
        # - The source IP address (The IP address of the ByteBlower port)
        # - The destination IP address (The IP address of the WirelessEndpoint)
        # - The source and destination UDP ports (we configured this on top of
        #   this script)
        # - a payload to transmit.

        port_mac = self.port.Layer2EthIIGet().MacGet()
        port_layer3_config = self.port.Layer3IPv6Get()

        ipv6_addresses = port_layer3_config.IpLinkLocalGet()
        if self.port_ip_address == "dhcp":
            ipv6_addresses = port_layer3_config.IpDhcpGet()
        elif self.port_ip_address == "slaac":
            ipv6_addresses = port_layer3_config.IpStatelessGet()
        elif isinstance(self.port_ip_address, list):
            ipv6_addresses = port_layer3_config.IpManualGet()

        port_ipv6 = None
        for ipv6_address in ipv6_addresses:
            port_ipv6 = ipv6_address.split("/")[0]

        # destination MAC must be resolved, since we do not know whether the WE
        # is available on the local LAN
        destination_mac = None
        wireless_endpoint_ipv6 = None
        all_we_addresses = self.select_wireless_endpoint_addresses()
        for address in all_we_addresses:
            wireless_endpoint_ipv6 = address.split('/')[0]
            try:
                destination_mac = port_layer3_config.Resolve(
                    wireless_endpoint_ipv6)
                break
            except:
                pass

        payload = 'a' * (self.frame_size - 42)

        from scapy.layers.inet6 import UDP, IPv6, Ether
        from scapy.all import Raw
        udp_payload = Raw(payload.encode('ascii', 'strict'))
        udp_header = UDP(dport=self.udp_dstport, sport=self.udp_srcport)
        ip_header = IPv6(src=port_ipv6, dst=wireless_endpoint_ipv6)
        eth_header = Ether(src=port_mac, dst=destination_mac)
        scapy_frame = eth_header / ip_header / udp_header / udp_payload

        frame_content = bytearray(bytes(scapy_frame))

        # The ByteBlower API expects an 'str' as input for the
        # frame.BytesSet() method, we need to convert the bytearray
        hexbytes = ''.join((format(b, "02x") for b in frame_content))

        frame = stream.FrameAdd()
        frame.BytesSet(hexbytes)

        # The trigger on the WirelessEndpoint counts received frames
        # We need
        # - the source UDP port
        # - the destination UDP port
        # - the originating IP address
        # - the duration of the session.  This can be calculated from the
        #   stream settings as
        #   interframegap (nanoseconds/frame) * number of frames (frames)
        #   some fixed rollout can be added too
        trigger = self.wireless_endpoint.RxTriggerBasicAdd()

        # Add 2 seconds of rollout, so frames in transit can be counted too
        duration_ns = self.interframe_gap_nanoseconds * self.number_of_frames
        duration_ns += 2000000000

        trigger.DurationSet(duration_ns)
        trigger.FilterUdpSourcePortSet(self.udp_srcport)
        trigger.FilterUdpDestinationPortSet(self.udp_dstport)
        trigger.FilterSourceAddressSet(port_ipv6)

        # Now all configuration is made
        print(stream.DescriptionGet())
        print(trigger.DescriptionGet())

        # Make sure we are the only users for the wireless endpoint
        self.wireless_endpoint.Lock(True)

        # Upload the configuration to the wireless endpoint
        self.wireless_endpoint.Prepare()

        from time import sleep

        # POSIX timestamp in nanoseconds when the wireless endpoint will start
        starttime_posix = self.wireless_endpoint.Start()
        # Current POSIX timestamp on the meetingpoint
        current_time_posix = self.meetingpoint.TimestampGet()

        time_to_wait_ns = starttime_posix - current_time_posix
        # Wait 200 ms longer, to make sure the wireless endpoint has started.
        time_to_wait_ns += 200000000

        print("Waiting for", time_to_wait_ns / 1000000000.0,
              "to start the port")
        sleep(time_to_wait_ns / 1000000000.0)

        print("Port will transmit for", duration_ns / 1000000000.0, "seconds")
        self.port.Start()

        print("Waiting for the test to finish")
        sleep(duration_ns / 1000000000.0)

        # get the results from the wireless endpoint
        self.wireless_endpoint.ResultGet()

        self.wireless_endpoint.Lock(False)

        tx_result = stream.ResultGet()
        tx_result.Refresh()
        rx_result = trigger.ResultGet()
        rx_result.Refresh()

        print("Transmitted", tx_result.PacketCountGet(), "packets")
        print("Received   ", rx_result.PacketCountGet(), "packets")

        return {
            'tx': tx_result.PacketCountGet(),
            'rx': rx_result.PacketCountGet()
        }
示例#2
0
    def test_ipip6(self):
        """ ip{v4,v6} over ip6 test """

        # that's annoying
        self.destroy_tunnel()

        self.pg1.generate_remote_hosts(5)
        self.pg1.configure_ipv6_neighbors()
        e = VppEnum.vl_api_tunnel_encap_decap_flags_t
        d = VppEnum.vl_api_ip_dscp_t
        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)

        # create a TOS byte by shifting a DSCP code point 2 bits. those 2 bits
        # are for the ECN.
        dscp = d.IP_API_DSCP_AF31 << 2
        ecn = 3
        dscp_ecn = d.IP_API_DSCP_AF31 << 2 | ecn

        # IPv4 transport that copies the DCSP from the payload
        tun_dscp = VppIpIpTunInterface(
            self,
            self.pg0,
            self.pg0.local_ip6,
            self.pg1.remote_hosts[0].ip6,
            flags=e.TUNNEL_API_ENCAP_DECAP_FLAG_ENCAP_COPY_DSCP)
        tun_dscp.add_vpp_config()
        # IPv4 transport that copies the DCSP and ECN from the payload
        tun_dscp_ecn = VppIpIpTunInterface(
            self,
            self.pg0,
            self.pg0.local_ip6,
            self.pg1.remote_hosts[1].ip6,
            flags=(e.TUNNEL_API_ENCAP_DECAP_FLAG_ENCAP_COPY_DSCP
                   | e.TUNNEL_API_ENCAP_DECAP_FLAG_ENCAP_COPY_ECN))
        tun_dscp_ecn.add_vpp_config()
        # IPv4 transport that copies the ECN from the payload and sets the
        # DF bit on encap. copies the ECN on decap
        tun_ecn = VppIpIpTunInterface(
            self,
            self.pg0,
            self.pg0.local_ip6,
            self.pg1.remote_hosts[2].ip6,
            flags=(e.TUNNEL_API_ENCAP_DECAP_FLAG_ENCAP_COPY_ECN
                   | e.TUNNEL_API_ENCAP_DECAP_FLAG_ENCAP_SET_DF
                   | e.TUNNEL_API_ENCAP_DECAP_FLAG_DECAP_COPY_ECN))
        tun_ecn.add_vpp_config()
        # IPv4 transport that sets a fixed DSCP in the encap and copies
        # the DF bit
        tun = VppIpIpTunInterface(
            self,
            self.pg0,
            self.pg0.local_ip6,
            self.pg1.remote_hosts[3].ip6,
            dscp=d.IP_API_DSCP_AF11,
            flags=e.TUNNEL_API_ENCAP_DECAP_FLAG_ENCAP_COPY_DF)
        tun.add_vpp_config()

        # array of all the tunnels
        tuns = [tun_dscp, tun_dscp_ecn, tun_ecn, tun]

        # addresses for prefixes routed via each tunnel
        a4s = ["" for i in range(len(tuns))]
        a6s = ["" for i in range(len(tuns))]

        # IP headers for inner packets with each combination of DSCp/ECN tested
        p_ip6s = [
            IPv6(src="1::1", dst="DEAD::1", nh='UDP', tc=dscp),
            IPv6(src="1::1", dst="DEAD::1", nh='UDP', tc=dscp_ecn),
            IPv6(src="1::1", dst="DEAD::1", nh='UDP', tc=ecn),
            IPv6(src="1::1", dst="DEAD::1", nh='UDP', tc=0xff)
        ]
        p_ip4s = [
            IP(src="1.2.3.4", dst="130.67.0.1", tos=dscp, flags='DF'),
            IP(src="1.2.3.4", dst="130.67.0.1", tos=dscp_ecn),
            IP(src="1.2.3.4", dst="130.67.0.1", tos=ecn),
            IP(src="1.2.3.4", dst="130.67.0.1", tos=0xff)
        ]

        # Configure each tunnel
        for i, t in enumerate(tuns):
            # Set interface up and enable IP on it
            self.vapi.sw_interface_set_flags(t.sw_if_index, 1)
            self.vapi.sw_interface_set_unnumbered(
                sw_if_index=self.pg0.sw_if_index,
                unnumbered_sw_if_index=t.sw_if_index)

            # prefix for route / destination address for packets
            a4s[i] = "130.67.%d.0" % i
            a6s[i] = "dead:%d::" % i

            # Add IPv4 and IPv6 routes via tunnel interface
            ip4_via_tunnel = VppIpRoute(self, a4s[i], 24, [
                VppRoutePath("0.0.0.0",
                             t.sw_if_index,
                             proto=FibPathProto.FIB_PATH_NH_PROTO_IP4)
            ])
            ip4_via_tunnel.add_vpp_config()

            ip6_via_tunnel = VppIpRoute(self, a6s[i], 64, [
                VppRoutePath("::",
                             t.sw_if_index,
                             proto=FibPathProto.FIB_PATH_NH_PROTO_IP6)
            ])
            ip6_via_tunnel.add_vpp_config()

        #
        # Encapsulation
        #

        # tun_dscp copies only the dscp
        # expected TC values are thus only the DCSP value is present from the
        # inner
        exp_tcs = [dscp, dscp, 0, 0xfc]
        p_ip6_encaps = [
            IPv6(src=self.pg0.local_ip6, dst=tun_dscp.dst, tc=tc)
            for tc in exp_tcs
        ]

        # IPv4 in to IPv4 tunnel
        self.verify_ip4ip6_encaps(a4s[0], p_ip4s, p_ip6_encaps)
        # IPv6 in to IPv4 tunnel
        self.verify_ip6ip6_encaps(a6s[0], p_ip6s, p_ip6_encaps)

        # tun_dscp_ecn copies the dscp and the ecn
        exp_tcs = [dscp, dscp_ecn, ecn, 0xff]
        p_ip6_encaps = [
            IPv6(src=self.pg0.local_ip6, dst=tun_dscp_ecn.dst, tc=tc)
            for tc in exp_tcs
        ]

        self.verify_ip4ip6_encaps(a4s[1], p_ip4s, p_ip6_encaps)
        self.verify_ip6ip6_encaps(a6s[1], p_ip6s, p_ip6_encaps)

        # tun_ecn copies only the ecn and always sets DF
        exp_tcs = [0, ecn, ecn, ecn]
        p_ip6_encaps = [
            IPv6(src=self.pg0.local_ip6, dst=tun_ecn.dst, tc=tc)
            for tc in exp_tcs
        ]

        self.verify_ip4ip6_encaps(a4s[2], p_ip4s, p_ip6_encaps)
        self.verify_ip6ip6_encaps(a6s[2], p_ip6s, p_ip6_encaps)

        # tun sets a fixed dscp
        fixed_dscp = tun.dscp << 2
        p_ip6_encaps = [
            IPv6(src=self.pg0.local_ip6, dst=tun.dst, tc=fixed_dscp)
            for i in range(len(p_ip4s))
        ]

        self.verify_ip4ip6_encaps(a4s[3], p_ip4s, p_ip6_encaps)
        self.verify_ip6ip6_encaps(a6s[3], p_ip6s, p_ip6_encaps)

        #
        # Decapsulation
        #
        n_packets_decapped = self.statistics.get_err_counter(
            '/err/ipip6-input/packets decapsulated')

        self.p_ether = Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)

        # IPv6 tunnel to IPv4
        tcs = [0, dscp, dscp_ecn, ecn]

        # one overlay packet and all combinations of its encap
        p_ip4 = IP(src="1.2.3.4", dst=self.pg0.remote_ip4)
        p_ip6_encaps = [
            IPv6(src=tun.dst, dst=self.pg0.local_ip6, tc=tc) for tc in tcs
        ]

        # for each encap tun will produce the same inner packet because it does
        # not copy up fields from the payload
        for p_ip6_encap in p_ip6_encaps:
            p6 = (self.p_ether / p_ip6_encap / p_ip4 / self.p_payload)
            p4_reply = (p_ip4 / self.p_payload)
            p4_reply.ttl -= 1
            rx = self.send_and_expect(self.pg1, p6 * N_PACKETS, self.pg0)
            n_packets_decapped += N_PACKETS
            for p in rx:
                self.validate(p[1], p4_reply)
                self.assert_packet_checksums_valid(p)

        err = self.statistics.get_err_counter(
            '/err/ipip6-input/packets decapsulated')
        self.assertEqual(err, n_packets_decapped)

        # tun_ecn copies the ECN bits from the encap to the inner
        p_ip6_encaps = [
            IPv6(src=tun_ecn.dst, dst=self.pg0.local_ip6, tc=tc) for tc in tcs
        ]
        p_ip4_replys = [p_ip4.copy() for i in range(len(p_ip6_encaps))]
        p_ip4_replys[2].tos = ecn
        p_ip4_replys[3].tos = ecn
        for i, p_ip6_encap in enumerate(p_ip6_encaps):
            p6 = (self.p_ether / p_ip6_encap / p_ip4 / self.p_payload)
            p4_reply = (p_ip4_replys[i] / self.p_payload)
            p4_reply.ttl -= 1
            rx = self.send_and_expect(self.pg1, p6 * N_PACKETS, self.pg0)
            n_packets_decapped += N_PACKETS
            for p in rx:
                self.validate(p[1], p4_reply)
                self.assert_packet_checksums_valid(p)

        err = self.statistics.get_err_counter(
            '/err/ipip6-input/packets decapsulated')
        self.assertEqual(err, n_packets_decapped)

        # IPv6 tunnel to IPv6
        # for each encap tun will produce the same inner packet because it does
        # not copy up fields from the payload
        p_ip6_encaps = [
            IPv6(src=tun.dst, dst=self.pg0.local_ip6, tc=tc) for tc in tcs
        ]
        p_ip6 = IPv6(src="1:2:3::4", dst=self.pg0.remote_ip6)
        for p_ip6_encap in p_ip6_encaps:
            p6 = (self.p_ether / p_ip6_encap / p_ip6 / self.p_payload)
            p6_reply = (p_ip6 / self.p_payload)
            p6_reply.hlim = 63
            rx = self.send_and_expect(self.pg1, p6 * N_PACKETS, self.pg0)
            n_packets_decapped += N_PACKETS
            for p in rx:
                self.validate(p[1], p6_reply)
                self.assert_packet_checksums_valid(p)

        err = self.statistics.get_err_counter(
            '/err/ipip6-input/packets decapsulated')
        self.assertEqual(err, n_packets_decapped)

        # IPv6 tunnel to IPv6
        # tun_ecn copies the ECN bits from the encap to the inner
        p_ip6_encaps = [
            IPv6(src=tun_ecn.dst, dst=self.pg0.local_ip6, tc=tc) for tc in tcs
        ]
        p_ip6 = IPv6(src="1:2:3::4", dst=self.pg0.remote_ip6)
        p_ip6_replys = [p_ip6.copy() for i in range(len(p_ip6_encaps))]
        p_ip6_replys[2].tc = ecn
        p_ip6_replys[3].tc = ecn
        for i, p_ip6_encap in enumerate(p_ip6_encaps):
            p6 = (self.p_ether / p_ip6_encap / p_ip6 / self.p_payload)
            p6_reply = (p_ip6_replys[i] / self.p_payload)
            p6_reply.hlim = 63
            rx = self.send_and_expect(self.pg1, p6 * N_PACKETS, self.pg0)
            n_packets_decapped += N_PACKETS
            for p in rx:
                self.validate(p[1], p6_reply)
                self.assert_packet_checksums_valid(p)

        err = self.statistics.get_err_counter(
            '/err/ipip6-input/packets decapsulated')
        self.assertEqual(err, n_packets_decapped)
示例#3
0
    def test_dhcp_ia_na_send_solicit_receive_advertise(self):
        """ Verify DHCPv6 IA NA Solicit packet and Advertise event """

        self.vapi.dhcp6_clients_enable_disable(enable=1)

        self.pg_enable_capture(self.pg_interfaces)
        self.pg_start()
        address = {
            'address': '1:2:3::5',
            'preferred_time': 60,
            'valid_time': 120
        }
        self.vapi.dhcp6_send_client_message(
            server_index=0xffffffff,
            mrc=1,
            msg_type=VppEnum.vl_api_dhcpv6_msg_type_t.DHCPV6_MSG_API_SOLICIT,
            sw_if_index=self.pg0.sw_if_index,
            T1=20,
            T2=40,
            addresses=[address],
            n_addresses=len([address]))
        rx_list = self.pg0.get_capture(1)
        self.assertEqual(len(rx_list), 1)
        packet = rx_list[0]

        self.assertEqual(packet.haslayer(IPv6), 1)
        self.assertEqual(packet[IPv6].haslayer(DHCP6_Solicit), 1)

        client_duid = packet[DHCP6OptClientId].duid
        trid = packet[DHCP6_Solicit].trid

        dst = ip6_normalize(packet[IPv6].dst)
        dst2 = ip6_normalize("ff02::1:2")
        self.assert_equal(dst, dst2)
        src = ip6_normalize(packet[IPv6].src)
        src2 = ip6_normalize(self.pg0.local_ip6_ll)
        self.assert_equal(src, src2)
        ia_na = packet[DHCP6OptIA_NA]
        self.assert_equal(ia_na.T1, 20)
        self.assert_equal(ia_na.T2, 40)
        self.assert_equal(len(ia_na.ianaopts), 1)
        address = ia_na.ianaopts[0]
        self.assert_equal(address.addr, '1:2:3::5')
        self.assert_equal(address.preflft, 60)
        self.assert_equal(address.validlft, 120)

        self.vapi.want_dhcp6_reply_events(enable_disable=1, pid=os.getpid())

        try:
            ia_na_opts = DHCP6OptIAAddress(addr='7:8::2',
                                           preflft=60,
                                           validlft=120)
            p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
                 IPv6(src=util.mk_ll_addr(self.pg0.remote_mac),
                      dst=self.pg0.local_ip6_ll) / UDP(sport=547, dport=546) /
                 DHCP6_Advertise(trid=trid) /
                 DHCP6OptServerId(duid=self.server_duid) /
                 DHCP6OptClientId(duid=client_duid) / DHCP6OptPref(prefval=7) /
                 DHCP6OptStatusCode(statuscode=1) /
                 DHCP6OptIA_NA(iaid=1, T1=20, T2=40, ianaopts=ia_na_opts))
            self.pg0.add_stream([p])
            self.pg_start()

            ev = self.vapi.wait_for_event(1, "dhcp6_reply_event")

            self.assert_equal(ev.preference, 7)
            self.assert_equal(ev.status_code, 1)
            self.assert_equal(ev.T1, 20)
            self.assert_equal(ev.T2, 40)

            reported_address = ev.addresses[0]
            address = ia_na_opts.getfieldval("addr")
            self.assert_equal(str(reported_address.address), address)
            self.assert_equal(reported_address.preferred_time,
                              ia_na_opts.getfieldval("preflft"))
            self.assert_equal(reported_address.valid_time,
                              ia_na_opts.getfieldval("validlft"))

        finally:
            self.vapi.want_dhcp6_reply_events(enable_disable=0)
        self.vapi.dhcp6_clients_enable_disable(enable=0)
示例#4
0
    def test_ipip4(self):
        """ ip{v4,v6} over ip4 test """

        self.pg1.generate_remote_hosts(5)
        self.pg1.configure_ipv4_neighbors()
        e = VppEnum.vl_api_tunnel_encap_decap_flags_t
        d = VppEnum.vl_api_ip_dscp_t
        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)

        # create a TOS byte by shifting a DSCP code point 2 bits. those 2 bits
        # are for the ECN.
        dscp = d.IP_API_DSCP_AF31 << 2
        ecn = 3
        dscp_ecn = d.IP_API_DSCP_AF31 << 2 | ecn

        # IPv4 transport that copies the DCSP from the payload
        tun_dscp = VppIpIpTunInterface(
            self,
            self.pg0,
            self.pg0.local_ip4,
            self.pg1.remote_hosts[0].ip4,
            flags=e.TUNNEL_API_ENCAP_DECAP_FLAG_ENCAP_COPY_DSCP)
        tun_dscp.add_vpp_config()
        # IPv4 transport that copies the DCSP and ECN from the payload
        tun_dscp_ecn = VppIpIpTunInterface(
            self,
            self.pg0,
            self.pg0.local_ip4,
            self.pg1.remote_hosts[1].ip4,
            flags=(e.TUNNEL_API_ENCAP_DECAP_FLAG_ENCAP_COPY_DSCP
                   | e.TUNNEL_API_ENCAP_DECAP_FLAG_ENCAP_COPY_ECN))
        tun_dscp_ecn.add_vpp_config()
        # IPv4 transport that copies the ECN from the payload and sets the
        # DF bit on encap. copies the ECN on decap
        tun_ecn = VppIpIpTunInterface(
            self,
            self.pg0,
            self.pg0.local_ip4,
            self.pg1.remote_hosts[2].ip4,
            flags=(e.TUNNEL_API_ENCAP_DECAP_FLAG_ENCAP_COPY_ECN
                   | e.TUNNEL_API_ENCAP_DECAP_FLAG_ENCAP_SET_DF
                   | e.TUNNEL_API_ENCAP_DECAP_FLAG_DECAP_COPY_ECN))
        tun_ecn.add_vpp_config()
        # IPv4 transport that sets a fixed DSCP in the encap and copies
        # the DF bit
        tun = VppIpIpTunInterface(
            self,
            self.pg0,
            self.pg0.local_ip4,
            self.pg1.remote_hosts[3].ip4,
            dscp=d.IP_API_DSCP_AF11,
            flags=e.TUNNEL_API_ENCAP_DECAP_FLAG_ENCAP_COPY_DF)
        tun.add_vpp_config()

        # array of all the tunnels
        tuns = [tun_dscp, tun_dscp_ecn, tun_ecn, tun]

        # addresses for prefixes routed via each tunnel
        a4s = ["" for i in range(len(tuns))]
        a6s = ["" for i in range(len(tuns))]

        # IP headers with each combination of DSCp/ECN tested
        p_ip6s = [
            IPv6(src="1::1", dst="DEAD::1", nh='UDP', tc=dscp),
            IPv6(src="1::1", dst="DEAD::1", nh='UDP', tc=dscp_ecn),
            IPv6(src="1::1", dst="DEAD::1", nh='UDP', tc=ecn),
            IPv6(src="1::1", dst="DEAD::1", nh='UDP', tc=0xff)
        ]
        p_ip4s = [
            IP(src="1.2.3.4", dst="130.67.0.1", tos=dscp, flags='DF'),
            IP(src="1.2.3.4", dst="130.67.0.1", tos=dscp_ecn),
            IP(src="1.2.3.4", dst="130.67.0.1", tos=ecn),
            IP(src="1.2.3.4", dst="130.67.0.1", tos=0xff)
        ]

        # Configure each tunnel
        for i, t in enumerate(tuns):
            # Set interface up and enable IP on it
            self.vapi.sw_interface_set_flags(t.sw_if_index, 1)
            self.vapi.sw_interface_set_unnumbered(
                sw_if_index=self.pg0.sw_if_index,
                unnumbered_sw_if_index=t.sw_if_index)

            # prefix for route / destination address for packets
            a4s[i] = "130.67.%d.0" % i
            a6s[i] = "dead:%d::" % i

            # Add IPv4 and IPv6 routes via tunnel interface
            ip4_via_tunnel = VppIpRoute(self, a4s[i], 24, [
                VppRoutePath("0.0.0.0",
                             t.sw_if_index,
                             proto=FibPathProto.FIB_PATH_NH_PROTO_IP4)
            ])
            ip4_via_tunnel.add_vpp_config()

            ip6_via_tunnel = VppIpRoute(self, a6s[i], 64, [
                VppRoutePath("::",
                             t.sw_if_index,
                             proto=FibPathProto.FIB_PATH_NH_PROTO_IP6)
            ])
            ip6_via_tunnel.add_vpp_config()

        #
        # Encapsulation
        #

        # tun_dscp copies only the dscp
        # expected TC values are thus only the DCSP value is present from the
        # inner
        exp_tcs = [dscp, dscp, 0, 0xfc]
        p_ip44_encaps = [
            IP(src=self.pg0.local_ip4, dst=tun_dscp.dst, tos=tc)
            for tc in exp_tcs
        ]
        p_ip64_encaps = [
            IP(src=self.pg0.local_ip4,
               dst=tun_dscp.dst,
               proto='ipv6',
               id=0,
               tos=tc) for tc in exp_tcs
        ]

        # IPv4 in to IPv4 tunnel
        self.verify_ip4ip4_encaps(a4s[0], p_ip4s, p_ip44_encaps)
        # IPv6 in to IPv4 tunnel
        self.verify_ip6ip4_encaps(a6s[0], p_ip6s, p_ip64_encaps)

        # tun_dscp_ecn copies the dscp and the ecn
        exp_tcs = [dscp, dscp_ecn, ecn, 0xff]
        p_ip44_encaps = [
            IP(src=self.pg0.local_ip4, dst=tun_dscp_ecn.dst, tos=tc)
            for tc in exp_tcs
        ]
        p_ip64_encaps = [
            IP(src=self.pg0.local_ip4,
               dst=tun_dscp_ecn.dst,
               proto='ipv6',
               id=0,
               tos=tc) for tc in exp_tcs
        ]

        self.verify_ip4ip4_encaps(a4s[1], p_ip4s, p_ip44_encaps)
        self.verify_ip6ip4_encaps(a6s[1], p_ip6s, p_ip64_encaps)

        # tun_ecn copies only the ecn and always sets DF
        exp_tcs = [0, ecn, ecn, ecn]
        p_ip44_encaps = [
            IP(src=self.pg0.local_ip4, dst=tun_ecn.dst, flags='DF', tos=tc)
            for tc in exp_tcs
        ]
        p_ip64_encaps = [
            IP(src=self.pg0.local_ip4,
               dst=tun_ecn.dst,
               flags='DF',
               proto='ipv6',
               id=0,
               tos=tc) for tc in exp_tcs
        ]

        self.verify_ip4ip4_encaps(a4s[2], p_ip4s, p_ip44_encaps)
        self.verify_ip6ip4_encaps(a6s[2], p_ip6s, p_ip64_encaps)

        # tun sets a fixed dscp and copies DF
        fixed_dscp = tun.dscp << 2
        flags = ['DF', 0, 0, 0]
        p_ip44_encaps = [
            IP(src=self.pg0.local_ip4, dst=tun.dst, flags=f, tos=fixed_dscp)
            for f in flags
        ]
        p_ip64_encaps = [
            IP(src=self.pg0.local_ip4,
               dst=tun.dst,
               proto='ipv6',
               id=0,
               tos=fixed_dscp) for i in range(len(p_ip4s))
        ]

        self.verify_ip4ip4_encaps(a4s[3], p_ip4s, p_ip44_encaps)
        self.verify_ip6ip4_encaps(a6s[3], p_ip6s, p_ip64_encaps)

        #
        # Decapsulation
        #
        n_packets_decapped = 0
        self.p_ether = Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)

        # IPv4 tunnel to IPv4
        tcs = [0, dscp, dscp_ecn, ecn]

        # one overlay packet and all combinations of its encap
        p_ip4 = IP(src="1.2.3.4", dst=self.pg0.remote_ip4)
        p_ip4_encaps = [
            IP(src=tun.dst, dst=self.pg0.local_ip4, tos=tc) for tc in tcs
        ]

        # for each encap tun will produce the same inner packet because it does
        # not copy up fields from the payload
        for p_ip4_encap in p_ip4_encaps:
            p4 = (self.p_ether / p_ip4_encap / p_ip4 / self.p_payload)
            p4_reply = (p_ip4 / self.p_payload)
            p4_reply.ttl -= 1
            rx = self.send_and_expect(self.pg1, p4 * N_PACKETS, self.pg0)
            n_packets_decapped += N_PACKETS
            for p in rx:
                self.validate(p[1], p4_reply)
                self.assert_packet_checksums_valid(p)

        err = self.statistics.get_err_counter(
            '/err/ipip4-input/packets decapsulated')
        self.assertEqual(err, n_packets_decapped)

        # tun_ecn copies the ECN bits from the encap to the inner
        p_ip4_encaps = [
            IP(src=tun_ecn.dst, dst=self.pg0.local_ip4, tos=tc) for tc in tcs
        ]
        p_ip4_replys = [p_ip4.copy() for i in range(len(p_ip4_encaps))]
        p_ip4_replys[2].tos = ecn
        p_ip4_replys[3].tos = ecn
        for i, p_ip4_encap in enumerate(p_ip4_encaps):
            p4 = (self.p_ether / p_ip4_encap / p_ip4 / self.p_payload)
            p4_reply = (p_ip4_replys[i] / self.p_payload)
            p4_reply.ttl -= 1
            rx = self.send_and_expect(self.pg1, p4 * N_PACKETS, self.pg0)
            n_packets_decapped += N_PACKETS
            for p in rx:
                self.validate(p[1], p4_reply)
                self.assert_packet_checksums_valid(p)

        err = self.statistics.get_err_counter(
            '/err/ipip4-input/packets decapsulated')
        self.assertEqual(err, n_packets_decapped)

        # IPv4 tunnel to IPv6
        # for each encap tun will produce the same inner packet because it does
        # not copy up fields from the payload
        p_ip4_encaps = [
            IP(src=tun.dst, dst=self.pg0.local_ip4, tos=tc) for tc in tcs
        ]
        p_ip6 = IPv6(src="1:2:3::4", dst=self.pg0.remote_ip6)
        for p_ip4_encap in p_ip4_encaps:
            p6 = (self.p_ether / p_ip4_encap / p_ip6 / self.p_payload)
            p6_reply = (p_ip6 / self.p_payload)
            p6_reply.hlim = 63
            rx = self.send_and_expect(self.pg1, p6 * N_PACKETS, self.pg0)
            n_packets_decapped += N_PACKETS
            for p in rx:
                self.validate(p[1], p6_reply)
                self.assert_packet_checksums_valid(p)

        err = self.statistics.get_err_counter(
            '/err/ipip4-input/packets decapsulated')
        self.assertEqual(err, n_packets_decapped)

        # IPv4 tunnel to IPv6
        # tun_ecn copies the ECN bits from the encap to the inner
        p_ip4_encaps = [
            IP(src=tun_ecn.dst, dst=self.pg0.local_ip4, tos=tc) for tc in tcs
        ]
        p_ip6 = IPv6(src="1:2:3::4", dst=self.pg0.remote_ip6)
        p_ip6_replys = [p_ip6.copy() for i in range(len(p_ip4_encaps))]
        p_ip6_replys[2].tc = ecn
        p_ip6_replys[3].tc = ecn
        for i, p_ip4_encap in enumerate(p_ip4_encaps):
            p6 = (self.p_ether / p_ip4_encap / p_ip6 / self.p_payload)
            p6_reply = (p_ip6_replys[i] / self.p_payload)
            p6_reply.hlim = 63
            rx = self.send_and_expect(self.pg1, p6 * N_PACKETS, self.pg0)
            n_packets_decapped += N_PACKETS
            for p in rx:
                self.validate(p[1], p6_reply)
                self.assert_packet_checksums_valid(p)

        err = self.statistics.get_err_counter(
            '/err/ipip4-input/packets decapsulated')
        self.assertEqual(err, n_packets_decapped)

        #
        # Fragmentation / Reassembly and Re-fragmentation
        #
        rv = self.vapi.ip_reassembly_enable_disable(
            sw_if_index=self.pg1.sw_if_index, enable_ip4=1)

        self.vapi.ip_reassembly_set(timeout_ms=1000,
                                    max_reassemblies=1000,
                                    max_reassembly_length=1000,
                                    expire_walk_interval_ms=10000,
                                    is_ip6=0)

        # Send lots of fragments, verify reassembled packet
        frags, p4_reply = self.generate_ip4_frags(3131, 1400)
        f = []
        for i in range(0, 1000):
            f.extend(frags)
        self.pg1.add_stream(f)
        self.pg_enable_capture()
        self.pg_start()
        rx = self.pg0.get_capture(1000)
        n_packets_decapped += 1000

        for p in rx:
            self.validate(p[1], p4_reply)

        err = self.statistics.get_err_counter(
            '/err/ipip4-input/packets decapsulated')
        self.assertEqual(err, n_packets_decapped)

        f = []
        r = []
        for i in range(1, 90):
            frags, p4_reply = self.generate_ip4_frags(i * 100, 1000)
            f.extend(frags)
            r.extend(p4_reply)
        self.pg_enable_capture()
        self.pg1.add_stream(f)
        self.pg_start()
        rx = self.pg0.get_capture(89)
        i = 0
        for p in rx:
            self.validate(p[1], r[i])
            i += 1

        # Now try with re-fragmentation
        #
        # Send fragments to tunnel head-end, for the tunnel head end
        # to reassemble and then refragment
        #
        self.vapi.sw_interface_set_mtu(self.pg0.sw_if_index, [576, 0, 0, 0])
        frags, p4_reply = self.generate_ip4_frags(3123, 1200)
        self.pg_enable_capture()
        self.pg1.add_stream(frags)
        self.pg_start()
        rx = self.pg0.get_capture(6)
        reass_pkt = reassemble4(rx)
        p4_reply.id = 256
        self.validate(reass_pkt, p4_reply)

        self.vapi.sw_interface_set_mtu(self.pg0.sw_if_index, [1600, 0, 0, 0])
        frags, p4_reply = self.generate_ip4_frags(3123, 1200)
        self.pg_enable_capture()
        self.pg1.add_stream(frags)
        self.pg_start()
        rx = self.pg0.get_capture(2)
        reass_pkt = reassemble4(rx)
        p4_reply.id = 512
        self.validate(reass_pkt, p4_reply)

        # send large packets through the tunnel, expect them to be fragmented
        self.vapi.sw_interface_set_mtu(tun_dscp.sw_if_index, [600, 0, 0, 0])

        p4 = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
              IP(src="1.2.3.4", dst="130.67.0.1", tos=42) /
              UDP(sport=1234, dport=1234) / Raw(b'Q' * 1000))
        rx = self.send_and_expect(self.pg0, p4 * 15, self.pg1, 30)
        inners = []
        for p in rx:
            inners.append(p[IP].payload)
        reass_pkt = reassemble4(inners)
        for p in reass_pkt:
            self.assert_packet_checksums_valid(p)
            self.assertEqual(p[IP].ttl, 63)
示例#5
0
    def test_mipip4(self):
        """ p2mp IPv4 tunnel Tests """

        for itf in self.pg_interfaces:
            #
            # one underlay nh for each overlay/tunnel peer
            #
            itf.generate_remote_hosts(4)
            itf.configure_ipv4_neighbors()

            #
            # Create an p2mo IPIP tunnel.
            #  - set it admin up
            #  - assign an IP Addres
            #  - Add a route via the tunnel
            #
            ipip_if = VppIpIpTunInterface(
                self,
                itf,
                itf.local_ip4,
                "0.0.0.0",
                mode=(VppEnum.vl_api_tunnel_mode_t.TUNNEL_API_MODE_MP))
            ipip_if.add_vpp_config()
            ipip_if.admin_up()
            ipip_if.config_ip4()
            ipip_if.generate_remote_hosts(4)

            self.logger.info(self.vapi.cli("sh adj"))
            self.logger.info(self.vapi.cli("sh ip fib"))

            #
            # ensure we don't match to the tunnel if the source address
            # is all zeros
            #
            # tx = self.create_tunnel_stream_4o4(self.pg0,
            #                                    "0.0.0.0",
            #                                    itf.local_ip4,
            #                                    self.pg0.local_ip4,
            #                                    self.pg0.remote_ip4)
            # self.send_and_assert_no_replies(self.pg0, tx)

            #
            # for-each peer
            #
            for ii in range(1, 4):
                route_addr = "4.4.4.%d" % ii

                #
                # route traffic via the peer
                #
                route_via_tun = VppIpRoute(self, route_addr, 32, [
                    VppRoutePath(ipip_if._remote_hosts[ii].ip4,
                                 ipip_if.sw_if_index)
                ])
                route_via_tun.add_vpp_config()

                #
                # Add a TEIB entry resolves the peer
                #
                teib = VppTeib(self, ipip_if, ipip_if._remote_hosts[ii].ip4,
                               itf._remote_hosts[ii].ip4)
                teib.add_vpp_config()
                self.logger.info(
                    self.vapi.cli("sh adj nbr ipip0 %s" %
                                  ipip_if._remote_hosts[ii].ip4))

                #
                # Send a packet stream that is routed into the tunnel
                #  - packets are IPIP encapped
                #
                inner = (IP(dst=route_addr, src="5.5.5.5") /
                         UDP(sport=1234, dport=1234) / Raw(b'0x44' * 100))
                tx_e = [
                    (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
                     inner) for x in range(63)
                ]

                rxs = self.send_and_expect(self.pg0, tx_e, itf)

                for rx in rxs:
                    self.assertEqual(rx[IP].src, itf.local_ip4)
                    self.assertEqual(rx[IP].dst, itf._remote_hosts[ii].ip4)

                tx_i = [
                    (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
                     IP(src=itf._remote_hosts[ii].ip4, dst=itf.local_ip4) /
                     IP(src=self.pg0.local_ip4, dst=self.pg0.remote_ip4) /
                     UDP(sport=1234, dport=1234) / Raw(b'0x44' * 100))
                    for x in range(63)
                ]

                self.logger.info(self.vapi.cli("sh ipip tunnel-hash"))
                rx = self.send_and_expect(self.pg0, tx_i, self.pg0)

                #
                # delete and re-add the TEIB
                #
                teib.remove_vpp_config()
                self.send_and_assert_no_replies(self.pg0, tx_e)
                self.send_and_assert_no_replies(self.pg0, tx_i)

                teib.add_vpp_config()
                rx = self.send_and_expect(self.pg0, tx_e, itf)
                for rx in rxs:
                    self.assertEqual(rx[IP].src, itf.local_ip4)
                    self.assertEqual(rx[IP].dst, itf._remote_hosts[ii].ip4)
                rx = self.send_and_expect(self.pg0, tx_i, self.pg0)

            ipip_if.admin_down()
            ipip_if.unconfig_ip4()
示例#6
0
文件: test_ip6.py 项目: vamsiDT/vpp
    def test_ip_disabled(self):
        """ IP Disabled """

        #
        # An (S,G).
        # one accepting interface, pg0, 2 forwarding interfaces
        #
        route_ff_01 = VppIpMRoute(
            self,
            "::",
            "ffef::1",
            128,
            MRouteEntryFlags.MFIB_ENTRY_FLAG_NONE, [
                VppMRoutePath(self.pg1.sw_if_index,
                              MRouteItfFlags.MFIB_ITF_FLAG_ACCEPT),
                VppMRoutePath(self.pg0.sw_if_index,
                              MRouteItfFlags.MFIB_ITF_FLAG_FORWARD)
            ],
            is_ip6=1)
        route_ff_01.add_vpp_config()

        pu = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
              IPv6(src="2001::1", dst=self.pg0.remote_ip6) /
              UDP(sport=1234, dport=1234) / Raw('\xa5' * 100))
        pm = (Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac) /
              IPv6(src="2001::1", dst="ffef::1") /
              UDP(sport=1234, dport=1234) / Raw('\xa5' * 100))

        #
        # PG1 does not forward IP traffic
        #
        self.send_and_assert_no_replies(self.pg1, pu, "IPv6 disabled")
        self.send_and_assert_no_replies(self.pg1, pm, "IPv6 disabled")

        #
        # IP enable PG1
        #
        self.pg1.config_ip6()

        #
        # Now we get packets through
        #
        self.pg1.add_stream(pu)
        self.pg_enable_capture(self.pg_interfaces)
        self.pg_start()
        rx = self.pg0.get_capture(1)

        self.pg1.add_stream(pm)
        self.pg_enable_capture(self.pg_interfaces)
        self.pg_start()
        rx = self.pg0.get_capture(1)

        #
        # Disable PG1
        #
        self.pg1.unconfig_ip6()

        #
        # PG1 does not forward IP traffic
        #
        self.send_and_assert_no_replies(self.pg1, pu, "IPv6 disabled")
        self.send_and_assert_no_replies(self.pg1, pm, "IPv6 disabled")
示例#7
0
    def test_frag(self):
        """ ip{v4,v6} over ip6 test frag """

        p_ether = Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)
        p_ip6 = IPv6(src="1::1", dst="DEAD::1", tc=42, nh='UDP')
        p_ip4 = IP(src="1.2.3.4", dst=self.pg0.remote_ip4)
        p_payload = UDP(sport=1234, dport=1234)

        #
        # Fragmentation / Reassembly and Re-fragmentation
        #
        rv = self.vapi.ip_reassembly_enable_disable(
            sw_if_index=self.pg1.sw_if_index, enable_ip6=1)

        self.vapi.ip_reassembly_set(timeout_ms=1000,
                                    max_reassemblies=1000,
                                    max_reassembly_length=1000,
                                    expire_walk_interval_ms=10000,
                                    is_ip6=1)

        # Send lots of fragments, verify reassembled packet
        before_cnt = self.statistics.get_err_counter(
            '/err/ipip6-input/packets decapsulated')
        frags, p6_reply = self.generate_ip6_frags(3131, 1400)
        f = []
        for i in range(0, 1000):
            f.extend(frags)
        self.pg1.add_stream(f)
        self.pg_enable_capture()
        self.pg_start()
        rx = self.pg0.get_capture(1000)

        for p in rx:
            self.validate(p[1], p6_reply)

        cnt = self.statistics.get_err_counter(
            '/err/ipip6-input/packets decapsulated')
        self.assertEqual(cnt, before_cnt + 1000)

        f = []
        r = []
        # TODO: Check out why reassembly of atomic fragments don't work
        for i in range(10, 90):
            frags, p6_reply = self.generate_ip6_frags(i * 100, 1000)
            f.extend(frags)
            r.extend(p6_reply)
        self.pg_enable_capture()
        self.pg1.add_stream(f)
        self.pg_start()
        rx = self.pg0.get_capture(80)
        i = 0
        for p in rx:
            self.validate(p[1], r[i])
            i += 1

        # Simple fragmentation
        p_ether = Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
        self.vapi.sw_interface_set_mtu(self.pg1.sw_if_index, [1280, 0, 0, 0])

        # IPv6 in to IPv6 tunnel
        p_payload = UDP(sport=1234, dport=1234) / self.payload(1300)

        p6 = (p_ether / p_ip6 / p_payload)
        p6_reply = (
            IPv6(src=self.pg0.local_ip6, dst=self.pg1.remote_ip6, hlim=63) /
            p_ip6 / p_payload)
        p6_reply[1].hlim -= 1
        self.pg_enable_capture()
        self.pg0.add_stream(p6)
        self.pg_start()
        rx = self.pg1.get_capture(2)

        # Scapy defragment doesn't deal well with multiple layers
        # of same type / Ethernet header first
        f = [p[1] for p in rx]
        reass_pkt = defragment6(f)
        self.validate(reass_pkt, p6_reply)

        # Now try with re-fragmentation
        #
        # Send large fragments to tunnel head-end, for the tunnel head end
        # to reassemble and then refragment out the tunnel again.
        # Hair-pinning
        #
        self.vapi.sw_interface_set_mtu(self.pg1.sw_if_index, [1280, 0, 0, 0])
        frags, p6_reply = self.generate_ip6_hairpin_frags(8000, 1200)
        self.pg_enable_capture()
        self.pg1.add_stream(frags)
        self.pg_start()
        rx = self.pg1.get_capture(7)
        f = [p[1] for p in rx]
        reass_pkt = defragment6(f)
        p6_reply.id = 256
        self.validate(reass_pkt, p6_reply)
示例#8
0
    def test_ipip4(self):
        """ ip{v4,v6} over ip4 test """
        p_ether = Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
        p_ip6 = IPv6(src="1::1", dst="DEAD::1", nh='UDP', tc=42)
        p_ip4 = IP(src="1.2.3.4", dst="130.67.0.1", tos=42)
        p_payload = UDP(sport=1234, dport=1234)

        # IPv4 transport
        rv = self.vapi.ipip_add_tunnel(src_address=self.pg0.local_ip4n,
                                       dst_address=self.pg1.remote_ip4n,
                                       is_ipv6=0,
                                       tc_tos=0xFF)
        sw_if_index = rv.sw_if_index

        # Set interface up and enable IP on it
        self.vapi.sw_interface_set_flags(sw_if_index, 1)
        self.vapi.sw_interface_set_unnumbered(
            ip_sw_if_index=self.pg0.sw_if_index, sw_if_index=sw_if_index)

        # Add IPv4 and IPv6 routes via tunnel interface
        ip4_via_tunnel = VppIpRoute(
            self,
            "130.67.0.0",
            16, [
                VppRoutePath(
                    "0.0.0.0", sw_if_index, proto=DpoProto.DPO_PROTO_IP4)
            ],
            is_ip6=0)
        ip4_via_tunnel.add_vpp_config()

        ip6_via_tunnel = VppIpRoute(
            self,
            "dead::",
            16,
            [VppRoutePath("::", sw_if_index, proto=DpoProto.DPO_PROTO_IP6)],
            is_ip6=1)
        ip6_via_tunnel.add_vpp_config()

        # IPv6 in to IPv4 tunnel
        p6 = (p_ether / p_ip6 / p_payload)
        p_inner_ip6 = p_ip6
        p_inner_ip6.hlim -= 1
        p6_reply = (IP(src=self.pg0.local_ip4,
                       dst=self.pg1.remote_ip4,
                       proto='ipv6',
                       id=0,
                       tos=42) / p_inner_ip6 / p_payload)
        p6_reply.ttl -= 1
        rx = self.send_and_expect(self.pg0, p6 * 10, self.pg1)
        for p in rx:
            self.validate(p[1], p6_reply)

        # IPv4 in to IPv4 tunnel
        p4 = (p_ether / p_ip4 / p_payload)
        p_ip4_inner = p_ip4
        p_ip4_inner.ttl -= 1
        p4_reply = (
            IP(src=self.pg0.local_ip4, dst=self.pg1.remote_ip4, tos=42) /
            p_ip4_inner / p_payload)
        p4_reply.ttl -= 1
        p4_reply.id = 0
        rx = self.send_and_expect(self.pg0, p4 * 10, self.pg1)
        for p in rx:
            self.validate(p[1], p4_reply)

        # Decapsulation
        p_ether = Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)

        # IPv4 tunnel to IPv4
        p_ip4 = IP(src="1.2.3.4", dst=self.pg0.remote_ip4)
        p4 = (p_ether / IP(src=self.pg1.remote_ip4, dst=self.pg0.local_ip4) /
              p_ip4 / p_payload)
        p4_reply = (p_ip4 / p_payload)
        p4_reply.ttl -= 1
        rx = self.send_and_expect(self.pg1, p4 * 10, self.pg0)
        for p in rx:
            self.validate(p[1], p4_reply)

        # IPv4 tunnel to IPv6
        p_ip6 = IPv6(src="1:2:3::4", dst=self.pg0.remote_ip6)
        p6 = (p_ether / IP(src=self.pg1.remote_ip4, dst=self.pg0.local_ip4) /
              p_ip6 / p_payload)
        p6_reply = (p_ip6 / p_payload)
        p6_reply.hlim = 63
        rx = self.send_and_expect(self.pg1, p6 * 10, self.pg0)
        for p in rx:
            self.validate(p[1], p6_reply)
示例#9
0
    def test_dhcp_pd_send_solicit_receive_advertise(self):
        """ Verify DHCPv6 PD Solicit packet and Advertise envent """

        self.vapi.dhcp6_clients_enable_disable()

        self.pg_enable_capture(self.pg_interfaces)
        self.pg_start()
        prefix_bin = '\00\01\00\02\00\03' + '\00' * 10
        prefix = {'prefix': prefix_bin,
                  'prefix_length': 50,
                  'preferred_time': 60,
                  'valid_time': 120}
        self.vapi.dhcp6_pd_send_client_message(1, self.pg0.sw_if_index,
                                               T1=20, T2=40, prefixes=[prefix])
        rx_list = self.pg0.get_capture(1)
        self.assertEqual(len(rx_list), 1)
        packet = rx_list[0]

        self.assertTrue(packet.haslayer(IPv6))
        self.assertTrue(packet[IPv6].haslayer(DHCP6_Solicit))

        client_duid = packet[DHCP6OptClientId].duid
        trid = packet[DHCP6_Solicit].trid

        dst = ip6_normalize(packet[IPv6].dst)
        dst2 = ip6_normalize("ff02::1:2")
        self.assert_equal(dst, dst2)
        src = ip6_normalize(packet[IPv6].src)
        src2 = ip6_normalize(self.pg0.local_ip6_ll)
        self.assert_equal(src, src2)
        ia_pd = packet[DHCP6OptIA_PD]
        self.assert_equal(ia_pd.T1, 20)
        self.assert_equal(ia_pd.T2, 40)
        self.assert_equal(len(ia_pd.iapdopt), 1)
        prefix = ia_pd.iapdopt[0]
        self.assert_equal(prefix.prefix, '1:2:3::')
        self.assert_equal(prefix.plen, 50)
        self.assert_equal(prefix.preflft, 60)
        self.assert_equal(prefix.validlft, 120)

        self.vapi.want_dhcp6_pd_reply_events()

        try:
            ia_pd_opts = DHCP6OptIAPrefix(prefix='7:8::', plen=56, preflft=60,
                                          validlft=120)
            p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
                 IPv6(src=mk_ll_addr(self.pg0.remote_mac),
                      dst=self.pg0.local_ip6_ll) /
                 UDP(sport=547, dport=546) /
                 DHCP6_Advertise(trid=trid) /
                 DHCP6OptServerId(duid=self.server_duid) /
                 DHCP6OptClientId(duid=client_duid) /
                 DHCP6OptPref(prefval=7) /
                 DHCP6OptStatusCode(statuscode=1) /
                 DHCP6OptIA_PD(iaid=1, T1=20, T2=40, iapdopt=ia_pd_opts)
                 )
            self.pg0.add_stream([p])
            self.pg_start()

            ev = self.vapi.wait_for_event(1, "dhcp6_pd_reply_event")

            self.assert_equal(ev.preference, 7)
            self.assert_equal(ev.status_code, 1)
            self.assert_equal(ev.T1, 20)
            self.assert_equal(ev.T2, 40)

            reported_prefix = ev.prefixes[0]
            prefix = inet_pton(AF_INET6, ia_pd_opts.getfieldval("prefix"))
            self.assert_equal(reported_prefix.prefix, prefix)
            self.assert_equal(reported_prefix.prefix_length,
                              ia_pd_opts.getfieldval("plen"))
            self.assert_equal(reported_prefix.preferred_time,
                              ia_pd_opts.getfieldval("preflft"))
            self.assert_equal(reported_prefix.valid_time,
                              ia_pd_opts.getfieldval("validlft"))

        finally:
            self.vapi.want_dhcp6_pd_reply_events(enable_disable=0)
示例#10
0
def main():  # pylint: disable=too-many-statements, too-many-locals
    """Main function of the script file."""
    args = TrafficScriptArg(['tx_dst_mac', 'tx_src_mac',
                             'tx_src_ipv6', 'tx_dst_ipv6',
                             'tx_src_udp_port', 'rx_dst_mac', 'rx_src_mac',
                             'rx_src_ipv4', 'rx_dst_ipv4'])
    rx_if = args.get_arg('rx_if')
    tx_if = args.get_arg('tx_if')
    tx_dst_mac = args.get_arg('tx_dst_mac')
    tx_src_mac = args.get_arg('tx_src_mac')
    tx_src_ipv6 = args.get_arg('tx_src_ipv6')
    tx_dst_ipv6 = args.get_arg('tx_dst_ipv6')
    tx_src_udp_port = int(args.get_arg('tx_src_udp_port'))
    tx_dst_udp_port = 20000
    rx_dst_mac = args.get_arg('rx_dst_mac')
    rx_src_mac = args.get_arg('rx_src_mac')
    rx_src_ipv4 = args.get_arg('rx_src_ipv4')
    rx_dst_ipv4 = args.get_arg('rx_dst_ipv4')

    rxq = RxQueue(rx_if)
    txq = TxQueue(tx_if)
    sent_packets = []

    # Create empty UDP datagram in IPv6

    udp = (Ether(dst=tx_dst_mac, src=tx_src_mac) /
           IPv6(src=tx_src_ipv6, dst=tx_dst_ipv6) /
           UDP(sport=tx_src_udp_port, dport=tx_dst_udp_port) /
           'udp_payload')

    txq.send(udp)
    sent_packets.append(udp)

    for _ in range(5):
        pkt = rxq.recv(2)
        if _is_udp_in_ipv4(pkt):
            ether = pkt
            break
    else:
        raise RuntimeError("UDP in IPv4 Rx error.")

    # check ethernet
    if ether.dst != rx_dst_mac:
        raise RuntimeError("Destination MAC error {} != {}.".
                           format(ether.dst, rx_dst_mac))
    print "Destination MAC: OK."

    if ether.src != rx_src_mac:
        raise RuntimeError("Source MAC error {} != {}.".
                           format(ether.src, rx_src_mac))
    print "Source MAC: OK."

    ipv4 = ether.payload

    # check ipv4
    if ip_address(unicode(ipv4.dst)) != ip_address(unicode(rx_dst_ipv4)):
        raise RuntimeError("Destination IPv4 error {} != {}.".
                           format(ipv4.dst, rx_dst_ipv4))
    print "Destination IPv4: OK."

    if ip_address(unicode(ipv4.src)) != ip_address(unicode(rx_src_ipv4)):
        raise RuntimeError("Source IPv4 error {} != {}.".
                           format(ipv4.src, rx_src_ipv4))
    print "Source IPv4: OK."

    udp = ipv4.payload

    # check udp
    if udp.dport != tx_dst_udp_port:
        raise RuntimeError("UDP dport error {} != {}.".
                           format(udp.dport, tx_dst_udp_port))
    print "UDP dport: OK."

    if udp.sport != tx_src_udp_port:
        raise RuntimeError("UDP sport error {} != {}.".
                           format(udp.sport, tx_src_udp_port))
    print "UDP sport: OK."

    if not _check_udp_checksum(ipv4):
        raise RuntimeError("UDP checksum error.")
    print "UDP checksum OK."

    sys.exit(0)
示例#11
0
    def test_ipip4(self):
        """ ip{v4,v6} over ip4 test """
        p_ether = Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
        p_ip6 = IPv6(src="1::1", dst="DEAD::1", nh='UDP', tc=42)
        p_ip4 = IP(src="1.2.3.4", dst="130.67.0.1", tos=42)
        p_payload = UDP(sport=1234, dport=1234)

        # IPv4 transport
        rv = ipip_add_tunnel(self,
                             self.pg0.local_ip4,
                             self.pg1.remote_ip4,
                             tc_tos=0xFF)
        sw_if_index = rv.sw_if_index

        # Set interface up and enable IP on it
        self.vapi.sw_interface_set_flags(sw_if_index, 1)
        self.vapi.sw_interface_set_unnumbered(
            sw_if_index=self.pg0.sw_if_index,
            unnumbered_sw_if_index=sw_if_index)

        # Add IPv4 and IPv6 routes via tunnel interface
        ip4_via_tunnel = VppIpRoute(
            self,
            "130.67.0.0",
            16, [
                VppRoutePath(
                    "0.0.0.0", sw_if_index, proto=DpoProto.DPO_PROTO_IP4)
            ],
            is_ip6=0)
        ip4_via_tunnel.add_vpp_config()

        ip6_via_tunnel = VppIpRoute(
            self,
            "dead::",
            16,
            [VppRoutePath("::", sw_if_index, proto=DpoProto.DPO_PROTO_IP6)],
            is_ip6=1)
        ip6_via_tunnel.add_vpp_config()

        # IPv6 in to IPv4 tunnel
        p6 = (p_ether / p_ip6 / p_payload)
        p_inner_ip6 = p_ip6
        p_inner_ip6.hlim -= 1
        p6_reply = (IP(src=self.pg0.local_ip4,
                       dst=self.pg1.remote_ip4,
                       proto='ipv6',
                       id=0,
                       tos=42) / p_inner_ip6 / p_payload)
        p6_reply.ttl -= 1
        rx = self.send_and_expect(self.pg0, p6 * 10, self.pg1)
        for p in rx:
            self.validate(p[1], p6_reply)

        # IPv4 in to IPv4 tunnel
        p4 = (p_ether / p_ip4 / p_payload)
        p_ip4_inner = p_ip4
        p_ip4_inner.ttl -= 1
        p4_reply = (
            IP(src=self.pg0.local_ip4, dst=self.pg1.remote_ip4, tos=42) /
            p_ip4_inner / p_payload)
        p4_reply.ttl -= 1
        p4_reply.id = 0
        rx = self.send_and_expect(self.pg0, p4 * 10, self.pg1)
        for p in rx:
            self.validate(p[1], p4_reply)

        # Decapsulation
        p_ether = Ether(src=self.pg1.remote_mac, dst=self.pg1.local_mac)

        # IPv4 tunnel to IPv4
        p_ip4 = IP(src="1.2.3.4", dst=self.pg0.remote_ip4)
        p4 = (p_ether / IP(src=self.pg1.remote_ip4, dst=self.pg0.local_ip4) /
              p_ip4 / p_payload)
        p4_reply = (p_ip4 / p_payload)
        p4_reply.ttl -= 1
        rx = self.send_and_expect(self.pg1, p4 * 10, self.pg0)
        for p in rx:
            self.validate(p[1], p4_reply)

        err = self.statistics.get_err_counter(
            '/err/ipip4-input/packets decapsulated')
        self.assertEqual(err, 10)

        # IPv4 tunnel to IPv6
        p_ip6 = IPv6(src="1:2:3::4", dst=self.pg0.remote_ip6)
        p6 = (p_ether / IP(src=self.pg1.remote_ip4, dst=self.pg0.local_ip4) /
              p_ip6 / p_payload)
        p6_reply = (p_ip6 / p_payload)
        p6_reply.hlim = 63
        rx = self.send_and_expect(self.pg1, p6 * 10, self.pg0)
        for p in rx:
            self.validate(p[1], p6_reply)

        err = self.statistics.get_err_counter(
            '/err/ipip4-input/packets decapsulated')
        self.assertEqual(err, 20)

        #
        # Fragmentation / Reassembly and Re-fragmentation
        #
        rv = self.vapi.ip_reassembly_enable_disable(
            sw_if_index=self.pg1.sw_if_index, enable_ip4=1)

        self.vapi.ip_reassembly_set(timeout_ms=1000,
                                    max_reassemblies=1000,
                                    max_reassembly_length=1000,
                                    expire_walk_interval_ms=10000,
                                    is_ip6=0)

        # Send lots of fragments, verify reassembled packet
        frags, p4_reply = self.generate_ip4_frags(3131, 1400)
        f = []
        for i in range(0, 1000):
            f.extend(frags)
        self.pg1.add_stream(f)
        self.pg_enable_capture()
        self.pg_start()
        rx = self.pg0.get_capture(1000)

        for p in rx:
            self.validate(p[1], p4_reply)

        err = self.statistics.get_err_counter(
            '/err/ipip4-input/packets decapsulated')
        self.assertEqual(err, 1020)

        f = []
        r = []
        for i in range(1, 90):
            frags, p4_reply = self.generate_ip4_frags(i * 100, 1000)
            f.extend(frags)
            r.extend(p4_reply)
        self.pg_enable_capture()
        self.pg1.add_stream(f)
        self.pg_start()
        rx = self.pg0.get_capture(89)
        i = 0
        for p in rx:
            self.validate(p[1], r[i])
            i += 1

        # Now try with re-fragmentation
        #
        # Send fragments to tunnel head-end, for the tunnel head end
        # to reassemble and then refragment
        #
        self.vapi.sw_interface_set_mtu(self.pg0.sw_if_index, [576, 0, 0, 0])
        frags, p4_reply = self.generate_ip4_frags(3123, 1200)
        self.pg_enable_capture()
        self.pg1.add_stream(frags)
        self.pg_start()
        rx = self.pg0.get_capture(6)
        reass_pkt = reassemble4(rx)
        p4_reply.ttl -= 1
        p4_reply.id = 256
        self.validate(reass_pkt, p4_reply)

        self.vapi.sw_interface_set_mtu(self.pg0.sw_if_index, [1600, 0, 0, 0])
        frags, p4_reply = self.generate_ip4_frags(3123, 1200)
        self.pg_enable_capture()
        self.pg1.add_stream(frags)
        self.pg_start()
        rx = self.pg0.get_capture(2)
        reass_pkt = reassemble4(rx)
        p4_reply.ttl -= 1
        p4_reply.id = 512
        self.validate(reass_pkt, p4_reply)
示例#12
0
文件: test_ipip.py 项目: zzqcn/vpp
    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()
示例#13
0
def dhcpv6_solicit(tx_if, rx_if, dhcp_multicast_ip, link_local_ip, proxy_ip,
                   server_ip, server_mac, client_duid, client_mac):
    """Send and check DHCPv6 SOLICIT proxy packet.

    :param tx_if: Client interface.
    :param rx_if: DHCPv6 server interface.
    :param dhcp_multicast_ip: Servers and relay agents multicast address.
    :param link_local_ip: Client link-local address.
    :param proxy_ip: IP address of DHCPv6 proxy server.
    :param server_ip: IP address of DHCPv6 server.
    :param server_mac: MAC address of DHCPv6 server.
    :param client_duid: Client DHCP Unique Identifier.
    :param client_mac: Client MAC address.
    :type tx_if: str
    :type rx_if: str
    :type dhcp_multicast_ip: str
    :type link_local_ip: str
    :type proxy_ip: str
    :type server_ip: str
    :type server_mac: str
    :type client_duid: str
    :type client_mac: str
    :return interface_id: ID of proxy interface.
    :rtype interface_id: str
    """

    rxq = RxQueue(rx_if)
    txq = TxQueue(tx_if)

    sent_packets = []

    dhcp6_solicit_pkt = Ether(src=client_mac, dst="33:33:00:01:00:02") / \
                        IPv6(src=link_local_ip, dst=dhcp_multicast_ip) / \
                        UDP(sport=UDP_SERVICES.dhcpv6_client,
                            dport=UDP_SERVICES.dhcpv6_server) / \
                        DHCP6_Solicit() / \
                        DHCP6OptClientId(duid=client_duid)

    sent_packets.append(dhcp6_solicit_pkt)
    txq.send(dhcp6_solicit_pkt)

    ether = rxq.recv(2)

    if ether is None:
        raise RuntimeError('DHCPv6 SOLICIT timeout')

    if ether.dst != server_mac:
        raise RuntimeError("Destination MAC address error: {} != {}".format(
            ether.dst, server_mac))
    print "Destination MAC address: OK."

    if ether['IPv6'].src != proxy_ip:
        raise RuntimeError("Source IP address error: {} != {}".format(
            ether['IPv6'].src, proxy_ip))
    print "Source IP address: OK."

    if ether['IPv6'].dst != server_ip:
        raise RuntimeError("Destination IP address error: {} != {}".format(
            ether['IPv6'].dst, server_ip))
    print "Destination IP address: OK."

    msgtype = _get_dhcpv6_msgtype(
        ether['IPv6']['UDP']
        ['DHCPv6 Relay Forward Message (Relay Agent/Server Message)'].msgtype)
    if msgtype != 'RELAY-FORW':
        raise RuntimeError(
            "Message type error: {} != RELAY-FORW".format(msgtype))
    print "Message type: OK."

    linkaddr = ether['IPv6']['UDP']\
        ['DHCPv6 Relay Forward Message (Relay Agent/Server Message)'].linkaddr
    if linkaddr != proxy_ip:
        raise RuntimeError("Proxy IP address error: {} != {}".format(
            linkaddr, proxy_ip))
    print "Proxy IP address: OK."

    try:
        interface_id =  ether['IPv6']['UDP']\
            ['DHCPv6 Relay Forward Message (Relay Agent/Server Message)']\
            ['Unknown DHCPv6 OPtion']['DHCP6 Interface-Id Option'].ifaceid
    except Exception:
        raise RuntimeError("DHCP6 Interface-Id error!")

    return interface_id
示例#14
0
文件: test_ip6.py 项目: vamsiDT/vpp
    def test_nd_proxy(self):
        """ IPv6 Proxy ND """

        #
        # Generate some hosts in the subnet that we are proxying
        #
        self.pg0.generate_remote_hosts(8)

        nsma = in6_getnsma(inet_pton(AF_INET6, self.pg0.local_ip6))
        d = inet_ntop(AF_INET6, nsma)

        #
        # Send an NS for one of those remote hosts on one of the proxy links
        # expect no response since it's from an address that is not
        # on the link that has the prefix configured
        #
        ns_pg1 = (Ether(dst=in6_getnsmac(nsma), src=self.pg1.remote_mac) /
                  IPv6(dst=d, src=self.pg0._remote_hosts[2].ip6) /
                  ICMPv6ND_NS(tgt=self.pg0.local_ip6) /
                  ICMPv6NDOptSrcLLAddr(lladdr=self.pg0._remote_hosts[2].mac))

        self.send_and_assert_no_replies(self.pg1, ns_pg1, "Off link NS")

        #
        # Add proxy support for the host
        #
        self.vapi.ip6_nd_proxy(
            inet_pton(AF_INET6, self.pg0._remote_hosts[2].ip6),
            self.pg1.sw_if_index)

        #
        # try that NS again. this time we expect an NA back
        #
        self.pg1.add_stream(ns_pg1)
        self.pg_enable_capture(self.pg_interfaces)
        self.pg_start()
        rx = self.pg1.get_capture(1)

        self.validate_na(self.pg1,
                         rx[0],
                         dst_ip=self.pg0._remote_hosts[2].ip6,
                         tgt_ip=self.pg0.local_ip6)

        #
        # ... and that we have an entry in the ND cache
        #
        self.assertTrue(
            find_nbr(self,
                     self.pg1.sw_if_index,
                     self.pg0._remote_hosts[2].ip6,
                     inet=AF_INET6))

        #
        # ... and we can route traffic to it
        #
        t = (Ether(dst=self.pg0.local_mac, src=self.pg0.remote_mac) /
             IPv6(dst=self.pg0._remote_hosts[2].ip6, src=self.pg0.remote_ip6) /
             UDP(sport=10000, dport=20000) / Raw('\xa5' * 100))

        self.pg0.add_stream(t)
        self.pg_enable_capture(self.pg_interfaces)
        self.pg_start()
        rx = self.pg1.get_capture(1)
        rx = rx[0]

        self.assertEqual(rx[Ether].dst, self.pg0._remote_hosts[2].mac)
        self.assertEqual(rx[Ether].src, self.pg1.local_mac)

        self.assertEqual(rx[IPv6].src, t[IPv6].src)
        self.assertEqual(rx[IPv6].dst, t[IPv6].dst)

        #
        # Test we proxy for the host on the main interface
        #
        ns_pg0 = (Ether(dst=in6_getnsmac(nsma), src=self.pg0.remote_mac) /
                  IPv6(dst=d, src=self.pg0.remote_ip6) /
                  ICMPv6ND_NS(tgt=self.pg0._remote_hosts[2].ip6) /
                  ICMPv6NDOptSrcLLAddr(lladdr=self.pg0.remote_mac))

        self.pg0.add_stream(ns_pg0)
        self.pg_enable_capture(self.pg_interfaces)
        self.pg_start()
        rx = self.pg0.get_capture(1)

        self.validate_na(self.pg0,
                         rx[0],
                         tgt_ip=self.pg0._remote_hosts[2].ip6,
                         dst_ip=self.pg0.remote_ip6)

        #
        # Setup and resolve proxy for another host on another interface
        #
        ns_pg2 = (Ether(dst=in6_getnsmac(nsma), src=self.pg2.remote_mac) /
                  IPv6(dst=d, src=self.pg0._remote_hosts[3].ip6) /
                  ICMPv6ND_NS(tgt=self.pg0.local_ip6) /
                  ICMPv6NDOptSrcLLAddr(lladdr=self.pg0._remote_hosts[2].mac))

        self.vapi.ip6_nd_proxy(
            inet_pton(AF_INET6, self.pg0._remote_hosts[3].ip6),
            self.pg2.sw_if_index)

        self.pg2.add_stream(ns_pg2)
        self.pg_enable_capture(self.pg_interfaces)
        self.pg_start()
        rx = self.pg2.get_capture(1)

        self.validate_na(self.pg2,
                         rx[0],
                         dst_ip=self.pg0._remote_hosts[3].ip6,
                         tgt_ip=self.pg0.local_ip6)

        self.assertTrue(
            find_nbr(self,
                     self.pg2.sw_if_index,
                     self.pg0._remote_hosts[3].ip6,
                     inet=AF_INET6))

        #
        # hosts can communicate. pg2->pg1
        #
        t2 = (Ether(dst=self.pg2.local_mac, src=self.pg0.remote_hosts[3].mac) /
              IPv6(dst=self.pg0._remote_hosts[2].ip6,
                   src=self.pg0._remote_hosts[3].ip6) /
              UDP(sport=10000, dport=20000) / Raw('\xa5' * 100))

        self.pg2.add_stream(t2)
        self.pg_enable_capture(self.pg_interfaces)
        self.pg_start()
        rx = self.pg1.get_capture(1)
        rx = rx[0]

        self.assertEqual(rx[Ether].dst, self.pg0._remote_hosts[2].mac)
        self.assertEqual(rx[Ether].src, self.pg1.local_mac)

        self.assertEqual(rx[IPv6].src, t2[IPv6].src)
        self.assertEqual(rx[IPv6].dst, t2[IPv6].dst)

        #
        # remove the proxy configs
        #
        self.vapi.ip6_nd_proxy(inet_pton(AF_INET6,
                                         self.pg0._remote_hosts[2].ip6),
                               self.pg1.sw_if_index,
                               is_del=1)
        self.vapi.ip6_nd_proxy(inet_pton(AF_INET6,
                                         self.pg0._remote_hosts[3].ip6),
                               self.pg2.sw_if_index,
                               is_del=1)

        self.assertFalse(
            find_nbr(self,
                     self.pg2.sw_if_index,
                     self.pg0._remote_hosts[3].ip6,
                     inet=AF_INET6))
        self.assertFalse(
            find_nbr(self,
                     self.pg1.sw_if_index,
                     self.pg0._remote_hosts[2].ip6,
                     inet=AF_INET6))

        #
        # no longer proxy-ing...
        #
        self.send_and_assert_no_replies(self.pg0, ns_pg0, "Proxy unconfigured")
        self.send_and_assert_no_replies(self.pg1, ns_pg1, "Proxy unconfigured")
        self.send_and_assert_no_replies(self.pg2, ns_pg2, "Proxy unconfigured")

        #
        # no longer forwarding. traffic generates NS out of the glean/main
        # interface
        #
        self.pg2.add_stream(t2)
        self.pg_enable_capture(self.pg_interfaces)
        self.pg_start()

        rx = self.pg0.get_capture(1)

        self.assertTrue(rx[0].haslayer(ICMPv6ND_NS))
示例#15
0
    def test_ip4_mtu(self):
        """ IP4 MTU test """

        p_ether = Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac)
        p_ip4 = IP(src=self.pg0.remote_ip4,
                   dst=self.pg1.remote_ip4,
                   flags='DF')

        current_mtu = self.get_mtu(self.pg1.sw_if_index)

        p_payload = UDP(sport=1234,
                        dport=1234) / self.payload(current_mtu - 20 - 8)

        p4 = p_ether / p_ip4 / p_payload
        p4_reply = p_ip4 / p_payload
        p4_reply.ttl -= 1
        rx = self.send_and_expect(self.pg0, p4 * 11, self.pg1)
        for p in rx:
            self.validate(p[1], p4_reply)

        # MTU
        self.vapi.sw_interface_set_mtu(self.pg1.sw_if_index, [576, 0, 0, 0])
        self.assertEqual(576, self.get_mtu(self.pg1.sw_if_index))

        # Should fail. Too large MTU
        p_icmp4 = ICMP(type='dest-unreach',
                       code='fragmentation-needed',
                       nexthopmtu=576,
                       chksum=0x2dbb)
        icmp4_reply = (IP(src=self.pg0.local_ip4,
                          dst=self.pg0.remote_ip4,
                          ttl=254,
                          len=576,
                          id=0) / p_icmp4 / p_ip4 / p_payload)
        icmp4_reply[1].ttl -= 1
        n = icmp4_reply.__class__(str(icmp4_reply))
        s = str(icmp4_reply)
        icmp4_reply = s[0:576]
        rx = self.send_and_expect(self.pg0, p4 * 11, self.pg0)
        for p in rx:
            # p.show2()
            # n.show2()
            self.validate_bytes(str(p[1]), icmp4_reply)

        # Now with DF off. Expect fragments.
        # First go with 1500 byte packets.
        p_payload = UDP(sport=1234, dport=1234) / self.payload(1500 - 20 - 8)
        p4 = p_ether / p_ip4 / p_payload
        p4.flags = 0
        p4_reply = p_ip4 / p_payload
        p4_reply.ttl = 62  # check this
        p4_reply.flags = 0
        p4_reply.id = 256
        self.pg_enable_capture()
        self.pg0.add_stream(p4 * 1)
        self.pg_start()
        rx = self.pg1.get_capture(3)
        reass_pkt = reassemble(rx)
        self.validate(reass_pkt, p4_reply)
        '''
        # Now what happens with a 9K frame
        p_payload = UDP(sport=1234, dport=1234) / self.payload(
            current_mtu - 20 - 8)
        p4 = p_ether / p_ip4 / p_payload
        p4.flags = 0
        p4_reply = p_ip4 / p_payload
        p4_reply.ttl = 62 # check this
        p4_reply.flags = 0
        p4_reply.id = 512

        self.pg_enable_capture()
        self.pg0.add_stream(p4*1)
        self.pg_start()
        rx = self.pg1.get_capture(16)
        reass_pkt = reassemble(rx)
        reass_pkt.show2()
        p4_reply.show2()
        self.validate(reass_pkt, p4_reply)
        '''

        # Reset MTU
        self.vapi.sw_interface_set_mtu(self.pg1.sw_if_index,
                                       [current_mtu, 0, 0, 0])
示例#16
0
    def run(self):
        byteblower_instance = ByteBlower.InstanceGet()

        print("Connecting to ByteBlower server %s..." % self.server_address)
        self.server = byteblower_instance.ServerAdd(self.server_address)

        # Create the port which will be the HTTP server (port_1)
        print("Creating TX port")
        self.port_1 = self.provision_port(self.port_1_config)

        print("Creating RX port")
        # Create the port which will be the HTTP client (port_2)
        self.port_2 = self.provision_port(self.port_2_config)

        # now create the stream.
        # A stream transmits frames on the port on which it is created.
        stream = self.port_1.TxStreamAdd()

        # set the number of frames to transmit
        stream.NumberOfFramesSet(self.number_of_frames)

        # set the speed of the transmission
        stream.InterFrameGapSet(self.interframegap_ns)

        # Since a stream transmits frames, we need to tell the stream which
        # frames we want to transmit
        frame = stream.FrameAdd()

        # collect the frame header info.  We need to provide the
        # Layer2 (ethernet) and Layer3 (IPv4) addresses.
        src_ip = self.port_1_config['ip_address']
        src_mac = self.port_1.Layer2EthIIGet().MacGet()

        dst_ip = self.port_2_config['ip_address']

        # the destination MAC is the MAC address of the destination port if
        # the destination port is in the same subnet as the source port,
        # otherwise it will be the MAC address of the gateway.
        # ByteBlower has a function to resolve the correct MAC address in
        # the Layer3 configuration object
        dst_mac = self.port_1.Layer3IPv6Get().Resolve(dst_ip)

        frame_size = 512
        udp_src = 4096
        udp_dest = 4096
        payload = 'a' * (frame_size - 42)

        from scapy.layers.inet6 import UDP, IPv6, Ether
        from scapy.all import Raw
        udp_payload = Raw(payload.encode('ascii', 'strict'))
        udp_header = UDP(dport=udp_dest, sport=udp_src)
        ip_header = IPv6(src=src_ip, dst=dst_ip)
        eth_header = Ether(src=src_mac, dst=dst_mac)
        scapy_frame = eth_header / ip_header / udp_header / udp_payload

        frame_content = bytearray(bytes(scapy_frame))

        # The ByteBlower API expects an 'str' as input for the
        # frame.BytesSet() method, we need to convert the bytearray
        hex_bytes = ''.join((format(b, "02x") for b in frame_content))
        frame.BytesSet(hex_bytes)

        # Create a trigger.  A trigger is an object which receives data.
        # The Basic trigger just count packets
        trigger = self.port_2.RxTriggerBasicAdd()

        # Every trigger needs to know on which frames it will work.
        # The default filter is no filter, so it will analyze every frame,
        # which is not what we want here.
        # We will filter on the destination IP and the destination UDP port
        bpf_filter = "ip6 dst {} and udp port {}".format(dst_ip, udp_dest)
        trigger.FilterSet(bpf_filter)

        # print the configuration, this makes it easy to review what we have
        # done until now
        print("Current ByteBlower configuration:")
        print("port1:", self.port_1.DescriptionGet())
        print("port2:", self.port_2.DescriptionGet())

        # Start the traffic and clear the trigger.
        # Triggers are active as soon they are created, so we may want to clear
        # the data it already has collected.
        print("Starting traffic")
        trigger.ResultClear()
        stream_history = stream.ResultHistoryGet()
        trigger_history = trigger.ResultHistoryGet()

        duration_ns = self.interframegap_ns * self.number_of_frames
        duration_s = duration_ns / 1000000000 + 1

        stream.Start()

        # duration_s is a float, so we need to cast it to an integer first
        for iteration in range(1, int(duration_s)):
            # sleep one second
            sleep(1)

            # Refresh the history, the ByteBlower server will create interval
            # and cumulative results every second (by default).
            # The Refresh method will synchronize the server data with
            # the client.
            stream_history.Refresh()
            trigger_history.Refresh()

            last_interval_tx = stream_history.IntervalLatestGet()
            last_interval_rx = trigger_history.IntervalLatestGet()

            print("Sent {TX} frames, received {RX} frames".format(
                TX=last_interval_tx.PacketCountGet(),
                RX=last_interval_rx.PacketCountGet()))

        print("Done sending traffic (time elapsed)")

        # Waiting for a second after the stream is finished.
        # This has the advantage that frames that were transmitted but not
        # received yet, can be processed by the server
        print("Waiting for a second")
        sleep(1)

        # During the test itself we queried the interval counters, there are
        # also cumulative counters.  The last cumulative counter available in
        # the history is also available as the Result
        stream_result = stream.ResultGet()
        trigger_result = trigger.ResultGet()
        stream_result.Refresh()
        print("Stream result:", stream_result.DescriptionGet())
        trigger_result.Refresh()
        print("Trigger result:", trigger_result.DescriptionGet())

        tx_frames = stream_result.PacketCountGet()
        rx_frames = trigger_result.PacketCountGet()

        print("Sent {TX} frames, received {RX} frames".format(TX=tx_frames,
                                                              RX=rx_frames))

        return [tx_frames, rx_frames]
示例#17
0
    def test_dhcp_pd_send_solicit_receive_advertise(self):
        """ Verify DHCPv6 PD Solicit packet and Advertise event """

        self.vapi.dhcp6_clients_enable_disable(enable=1)

        self.pg_enable_capture(self.pg_interfaces)
        self.pg_start()

        prefix = {'prefix': {'address': '1:2:3::', 'len': 50},
                  'preferred_time': 60,
                  'valid_time': 120}
        prefixes = [prefix]
        self.vapi.dhcp6_pd_send_client_message(
            server_index=0xffffffff,
            mrc=1,
            msg_type=VppEnum.vl_api_dhcpv6_msg_type_t.DHCPV6_MSG_API_SOLICIT,
            sw_if_index=self.pg0.sw_if_index,
            T1=20,
            T2=40,
            prefixes=prefixes,
            n_prefixes=len(prefixes))
        rx_list = self.pg0.get_capture(1)
        self.assertEqual(len(rx_list), 1)
        packet = rx_list[0]

        self.assertEqual(packet.haslayer(IPv6), 1)
        self.assertEqual(packet[IPv6].haslayer(DHCP6_Solicit), 1)

        client_duid = packet[DHCP6OptClientId].duid
        trid = packet[DHCP6_Solicit].trid

        dst = ip6_normalize(packet[IPv6].dst)
        dst2 = ip6_normalize("ff02::1:2")
        self.assert_equal(dst, dst2)
        src = ip6_normalize(packet[IPv6].src)
        src2 = ip6_normalize(self.pg0.local_ip6_ll)
        self.assert_equal(src, src2)
        ia_pd = packet[DHCP6OptIA_PD]
        self.assert_equal(ia_pd.T1, 20)
        self.assert_equal(ia_pd.T2, 40)
        self.assert_equal(len(ia_pd.iapdopt), 1)
        prefix = ia_pd.iapdopt[0]
        self.assert_equal(prefix.prefix, '1:2:3::')
        self.assert_equal(prefix.plen, 50)
        self.assert_equal(prefix.preflft, 60)
        self.assert_equal(prefix.validlft, 120)

        self.vapi.want_dhcp6_pd_reply_events(enable_disable=1,
                                             pid=os.getpid())

        try:
            ia_pd_opts = DHCP6OptIAPrefix(prefix='7:8::', plen=56, preflft=60,
                                          validlft=120)
            p = (Ether(src=self.pg0.remote_mac, dst=self.pg0.local_mac) /
                 IPv6(src=util.mk_ll_addr(self.pg0.remote_mac),
                      dst=self.pg0.local_ip6_ll) /
                 UDP(sport=547, dport=546) /
                 DHCP6_Advertise(trid=trid) /
                 DHCP6OptServerId(duid=self.server_duid) /
                 DHCP6OptClientId(duid=client_duid) /
                 DHCP6OptPref(prefval=7) /
                 DHCP6OptStatusCode(statuscode=1) /
                 DHCP6OptIA_PD(iaid=1, T1=20, T2=40, iapdopt=ia_pd_opts)
                 )
            self.pg0.add_stream([p])
            self.pg_start()

            ev = self.vapi.wait_for_event(1, "dhcp6_pd_reply_event")

            self.assert_equal(ev.preference, 7)
            self.assert_equal(ev.status_code, 1)
            self.assert_equal(ev.T1, 20)
            self.assert_equal(ev.T2, 40)

            reported_prefix = ev.prefixes[0]
            prefix = ia_pd_opts.getfieldval("prefix")
            self.assert_equal(
                str(reported_prefix.prefix).split('/')[0], prefix)
            self.assert_equal(int(str(reported_prefix.prefix).split('/')[1]),
                              ia_pd_opts.getfieldval("plen"))
            self.assert_equal(reported_prefix.preferred_time,
                              ia_pd_opts.getfieldval("preflft"))
            self.assert_equal(reported_prefix.valid_time,
                              ia_pd_opts.getfieldval("validlft"))

        finally:
            self.vapi.want_dhcp6_pd_reply_events(enable_disable=0)
        self.vapi.dhcp6_clients_enable_disable(enable=0)
示例#18
0
def reply_udp_packet(pkt, payload: dict):
    # print(f'receive get client list request from {pkt[IPv6].src}', payload)
    sendp(
        Ether(src=LOCAL_MAC_ADDR, dst=NEXT_HOP_MAC) / IPv6(dst=pkt[IPv6].src) /
        UDP(sport=pkt[UDP].dport, dport=pkt[UDP].sport) / json.dumps(payload),
        iface=LOCAL_IPv6_IFACE)