Esempio n. 1
0
    def cleanup(self):
        """Cleanup sockets and network interfaces"""
        # Signal to end connection
        msg = TrafficRequest(TrafficRequestType.EXIT)
        msg.send(self.sc_out)

        # Close out network ifaces
        # For now multiple UEs with mixed ip addresses is not supported
        # so check the version of the first ip address
        # TODO: Add support for handling multiple UE with mixed ipv4 and ipv6
        # addresses
        intf = TrafficTest._net_iface_ipv4
        for instance in self.instances:
            if instance.ip.version == 6:
                intf = TrafficTest._net_iface_ipv6
            break
        net_iface = TrafficTest._iproute.link_lookup(
            ifname=intf,
        )
        if net_iface:
            net_iface_index = net_iface[0]
            # For some reason the first call to flush this address flushes all
            # the addresses brought up during testing. But subsequent flushes
            # do nothing if the address doesn't exist
            for instance in self.instances:
                TrafficTest._iproute.flush_addr(
                    index=net_iface_index,
                    address=instance.ip.exploded,
                )

        # Do socket cleanup
        self.sc_in.close()
        self.sc_out.close()
        self.sc.shutdown(socket.SHUT_RDWR)  # Ensures safe socket closure
        self.sc.close()
Esempio n. 2
0
    def cleanup(self):
        """Cleanup sockets and network interfaces"""
        # Signal to end connection
        msg = TrafficRequest(TrafficRequestType.EXIT)
        msg.send(self.sc_out)

        # Close out network ifaces
        net_iface = TrafficTest._iproute.link_lookup(
            ifname=TrafficTest._net_iface,
        )
        if net_iface:
            net_iface_index = net_iface[0]
            # For some reason the first call to flush this address flushes all
            # the addresses brought up during testing. But subsequent flushes
            # do nothing if the address doesn't exist
            for instance in self.instances:
                TrafficTest._iproute.flush_addr(
                    index=net_iface_index,
                    address=instance.ip.exploded,
                )

        # Do socket cleanup
        self.sc_in.close()
        self.sc_out.close()
        self.sc.shutdown(socket.SHUT_RDWR)  # Ensures safe socket closure
        self.sc.close()
Esempio n. 3
0
    def _run(self):
        ''' Run the traffic test

        Sets up traffic test with remote traffic server and local ifaces, then
        runs the runner hook into the trfgen binary and collects the results to
        cache

        Will block until the test ends
        '''
        # Create a snapshot of the test's states, in case they get changed or
        # wiped in a later operation. Basically, render tests immune to later
        # operations after the test has started.
        with self._test_lock:
            instances = copy.deepcopy(self._instances)
            test_ids = copy.deepcopy(self._test_ids)

        try:
            # Set up sockets and associated streams
            sc = socket.create_connection(self._remote_server)
            sc_in = sc.makefile('rb')
            sc_out = sc.makefile('wb')

            # Set up network ifaces and get UL port assignments for DL
            aliases = ()
            for instance in instances:
                aliases += (TrafficTest._iface_up(instance.ip),)
                if not instance.is_uplink:
                    # Assign a local port for the downlink UE server
                    instance.port = TrafficTest._get_port()

            # Create and send TEST message
            msg = TrafficRequest(
                TrafficRequestType.TEST, payload=instances)
            msg.send(sc_out)

            # Receive SERVER message and update test instances
            msg = TrafficMessage.recv(sc_in)
            assert msg.message is TrafficResponseType.SERVER
            r_id = msg.id  # Remote server test identifier
            server_instances = msg.payload  # (TrafficServerInstance, ...)

            # Locally keep references to arguments passed into trfgen
            args = [None] * len(instances)

            # Post-SERVER, pre-START logic
            for i in range(len(instances)):
                instance = instances[i]
                server_instance = server_instances[i]

                # Add ip network route
                net_iface_index = TrafficTest._iproute.link_lookup(
                    ifname=TrafficTest._net_iface)[0]
                server_instance_network = \
                    TrafficTest._network_from_ip(server_instance.ip, 8)
                TrafficTest._iproute.route(
                    'replace', dst=server_instance_network.exploded,
                    iif=net_iface_index, oif=net_iface_index, scope='link')

                # Add arp table entry
                os.system('/usr/sbin/arp -s %s %s' % (
                    server_instance.ip.exploded, server_instance.mac))

                if instance.is_uplink:
                    # Port should be the port of the remote for uplink
                    instance.port = server_instance.port
                else:
                    args[i] = self._run_test(
                        test_ids[i], server_instance.ip, instance.ip,
                        instance.port)

            # Send START for the given r_id
            msg = TrafficRequest(
                TrafficRequestType.START, identifier=r_id)
            msg.send(sc_out)

            # Wait for STARTED response
            msg = TrafficMessage.recv(sc_in)
            assert msg.message is TrafficResponseType.STARTED
            assert msg.id == r_id

            # Post-STARTED, pre-RESULTS logic
            for i in range(len(instances)):
                instance = instances[i]
                if instance.is_uplink:
                    args[i] = self._run_test(
                        test_ids[i], server_instances[i].ip, instance.ip,
                        server_instances[i].port)

            # Wait for RESULTS message
            msg = TrafficMessage.recv(sc_in)
            assert msg.message is TrafficResponseType.RESULTS
            assert msg.id == r_id
            results = msg.payload

            # Signal to end connection
            msg = TrafficRequest(TrafficRequestType.EXIT)
            msg.send(sc_out)

            # Close out network ifaces
            net_iface_index = TrafficTest._iproute.link_lookup(
                ifname=TrafficTest._net_iface)[0]
            # For some reason the first call to flush this address flushes all
            # the addresses brought up during testing. But subsequent flushes
            # do nothing if the address doesn't exist
            for i in range(len(instances)):
                TrafficTest._iproute.flush_addr(index=net_iface_index,
                                                address=instances[i].ip.exploded)
            # Do socket cleanup
            sc_in.close()
            sc_out.close()
            sc.shutdown(socket.SHUT_RDWR)  # Ensures safe socket closure
            sc.close()

            # Cache results after cleanup
            with self._test_lock:
                self._results = results
        finally:
            # Signal that we're done
            self._done.set()
Esempio n. 4
0
    def _run(self):
        """Run the traffic test

        Sets up traffic test with remote traffic server and local ifaces, then
        runs the runner hook into the trfgen binary and collects the results to
        cache

        Will block until the test ends
        """
        # Create a snapshot of the test's states, in case they get changed or
        # wiped in a later operation. Basically, render tests immune to later
        # operations after the test has started.
        with self._test_lock:
            self.instances = copy.deepcopy(self._instances)
            test_ids = copy.deepcopy(self._test_ids)

        try:
            # Set up sockets and associated streams
            self.sc = socket.create_connection(self._remote_server)
            self.sc_in = self.sc.makefile("rb")
            self.sc_out = self.sc.makefile("wb")
            self.sc.settimeout(IPERF_DATA_TIMEOUT_SEC)

            # Flush all the addresses left by previous failed tests
            net_iface = 0

            # For now multiple UEs with mixed ip addresses is not supported
            # so check the version of the first ip address
            # TODO: Add support for handling multiple UE with mixed ipv4 and ipv6
            # addresses
            for instance in self.instances:
                if instance.ip.version == 4:
                    net_iface = TrafficTest._net_iface_ipv4
                else:
                    net_iface = TrafficTest._net_iface_ipv6
                break
            net_iface_index = TrafficTest._iproute.link_lookup(
                ifname=net_iface,
            )[0]
            for instance in self.instances:
                TrafficTest._iproute.flush_addr(
                    index=net_iface_index,
                    address=instance.ip.exploded,
                )

            # Set up network ifaces and get UL port assignments for DL
            for instance in self.instances:
                if instance.ip.version == 4:
                    (TrafficTest._iface_up_ipv4(instance.ip),)
                else:
                    (TrafficTest._iface_up_ipv6(instance.ip),)
                if not instance.is_uplink:
                    # Assign a local port for the downlink UE server
                    instance.port = TrafficTest._get_port()

            # Create and send TEST message
            msg = TrafficRequest(
                TrafficRequestType.TEST,
                payload=self.instances,
            )
            msg.send(self.sc_out)

            # Receive SERVER message and update test instances
            msg = TrafficMessage.recv(self.sc_in)
            assert msg.message is TrafficResponseType.SERVER
            r_id = msg.id  # Remote server test identifier
            server_instances = msg.payload  # (TrafficServerInstance, ...)

            # Locally keep references to arguments passed into trfgen
            num_instances = len(self.instances)
            args = [None for _ in range(num_instances)]

            # Post-SERVER, pre-START logic
            for i in range(num_instances):
                instance = self.instances[i]
                server_instance = server_instances[i]

                # Add ip network route
                net_iface_index = TrafficTest._iproute.link_lookup(
                    ifname=net_iface,
                )[0]
                server_instance_network = TrafficTest._network_from_ip(
                    server_instance.ip,
                    8,
                )
                TrafficTest._iproute.route(
                    "replace",
                    dst=server_instance_network.exploded,
                    iif=net_iface_index,
                    oif=net_iface_index,
                    scope="link",
                )

                # Add arp table entry
                if server_instance.ip.version == 4:
                    os.system(
                        "/usr/sbin/arp -s %s %s"
                        % (
                            server_instance.ip.exploded,
                            server_instance.mac,
                        ),
                    )
                else:
                    os.system(
                        'ip -6 neigh add %s lladdr %s dev eth3' % (
                            server_instance.ip.exploded, server_instance.mac,
                        ),
                    )

                if instance.is_uplink:
                    # Port should be the port of the remote for uplink
                    instance.port = server_instance.port
                else:
                    args[i] = self._run_test(
                        test_ids[i],
                        server_instance.ip,
                        instance.ip,
                        instance.port,
                    )

            # Send START for the given r_id
            msg = TrafficRequest(
                TrafficRequestType.START,
                identifier=r_id,
            )
            msg.send(self.sc_out)

            # Wait for STARTED response
            msg = TrafficMessage.recv(self.sc_in)
            assert msg.message is TrafficResponseType.STARTED
            assert msg.id == r_id

            # Post-STARTED, pre-RESULTS logic
            for i in range(num_instances):
                instance = self.instances[i]
                if instance.is_uplink:
                    args[i] = self._run_test(
                        test_ids[i],
                        server_instances[i].ip,
                        instance.ip,
                        server_instances[i].port,
                    )

            # Wait for RESULTS message
            msg = TrafficMessage.recv(self.sc_in)
            assert msg.message is TrafficResponseType.RESULTS
            assert msg.id == r_id
            results = msg.payload

            # Call cleanup to close network interfaces and open sockets
            self.cleanup()

            # Cache results after cleanup
            with self._test_lock:
                self._results = results

        except ConnectionRefusedError as e:
            print("Running iperf data failed. Error: " + str(e))
            self.is_trf_server_connection_refused = True
        except socket.timeout:
            print("Running iperf data failed with timeout")
            TrafficUtil.need_to_close_iperf3_server = True
            self.cleanup()
        except Exception as e:
            print("Running iperf data failed. Error: " + str(e))
            TrafficUtil.need_to_close_iperf3_server = True
            self.cleanup()
        finally:
            # Signal that we're done
            self._done.set()