コード例 #1
0
def main():
    """Check server info and quit."""
    client = STLClient()
    try:
        # connect to server
        client.connect()

        # get server info
        print(client.get_server_system_info())
    except STLError as ex_error:
        print(ex_error, file=sys.stderr)
        sys.exit(1)
    finally:
        client.disconnect()
コード例 #2
0
class TrexTest(BaseTest):
    """
    Base test for setting up and tearing down TRex client instance for
    linerate tests.
    """
    def setUp(self):
        super(TrexTest, self).setUp()
        trex_server_addr = testutils.test_param_get("trex_server_addr")
        self.trex_client = STLClient(server=trex_server_addr)
        self.trex_client.connect()
        self.trex_client.acquire()
        self.trex_client.reset()  # Resets configs from all ports
        self.trex_client.clear_stats()  # Clear status from all ports
        # Put all ports to promiscuous mode, otherwise they will drop all
        # incoming packets if the destination mac is not the port mac address.
        self.trex_client.set_port_attr(self.trex_client.get_all_ports(),
                                       promiscuous=True)

    def tearDown(self):
        print("Tearing down STLClient...")
        self.trex_client.stop()
        self.trex_client.release()
        self.trex_client.disconnect()
        super(TrexTest, self).tearDown()
コード例 #3
0
def main():
    parser = argparse.ArgumentParser(
        description=
        "STL traffic used for test the scalability of the network functions.")
    parser.add_argument(
        "--ip_src",
        type=str,
        default="192.168.17.1",
        help="Source IP address for all packets in the stream.",
    )
    parser.add_argument(
        "--ip_dst",
        type=str,
        default="192.168.17.2",
        help="Destination IP address for all packets in the stream.",
    )
    parser.add_argument("--pps",
                        type=int,
                        default=1e3,
                        help="Packet per second.")
    parser.add_argument("--duration",
                        type=int,
                        default=3,
                        help="Test duration.")
    # Potential lens: 64, 128, 256, 512, 1024
    parser.add_argument("--ip_tot_len",
                        type=int,
                        default=64,
                        help="IP total length")
    parser.add_argument("--num",
                        type=int,
                        default=1,
                        help="Number of rounds tested")
    parser.add_argument(
        "--estimate_pps",
        action="store_true",
        help="Estimate the maximal pps without dropping packets.",
    )

    args = parser.parse_args()
    print(
        "Test information:\n PPS: {}, Duration: {}s, IP_TOT_LEN: {}B, Number of rounds: {}"
        .format(args.pps, args.duration, args.ip_tot_len, args.num))

    test_data = {
        "pps": args.pps,
        "duration": args.duration,
        "ip_tot_len": args.ip_tot_len,
        "ip_src": args.ip_src,
        "ip_dst": args.ip_dst,
        "num": args.num,
    }

    try:
        client = STLClient()
        client.connect()
        tx_port, rx_port = init_ports(client)

        if args.estimate_pps:
            run_estimate_pps(test_data, client, rx_port, tx_port)
        else:
            run_test(test_data, client, rx_port, tx_port, save_data=True)
            print("All tests finished! Results are in *.data files")

    except STLError as error:
        print(error)

    finally:
        client.disconnect()
コード例 #4
0
class TRex(TrafficGeneratorChassis):
    def __init__(self, **kwargs):
        super(TRex, self).__init__(**kwargs)
        self.hostname = kwargs.pop("hostname", "localhost")
        self.__trex_client = STLClient(server=self.hostname)

    def _verify_port_action(self, port_name):
        if self.is_connected() and self._verify_port_string(port_name) and \
           port_name in self.port_data:
            return (True)
        return (False)

    def _verify_port_string(self, port_name):
        try:
            if int(port_name) < 0:
                return False

        except ValueError:
            return False

        return True

    def connect(self):
        if not self.is_connected():
            self.__trex_client.connect()

        return self.is_connected()

    def disconnect(self):
        if self.is_connected:
            for port in list(self.port_data.keys()):
                self.port_data[port] = self.release_port(port)
            self.__trex_client.disconnect()
        return True

    def is_connected(self):
        return self.__trex_client.is_connected()

    def reserve_port(self, port_name):
        if not self._verify_port_string(port_name):
            return False

        try:
            self.__trex_client.acquire(ports=[int(port_name)], force=True)
        except STLError:
            return False

        try:
            self.__trex_client.reset(ports=[int(port_name)])
        except STLError:
            self.__trex_client.release(ports=[int(port_name)])
            return False

        tport = _TRexPort(port_name, self.__trex_client)

        if tport is None:
            return False

        return super(TRex, self).reserve_port(port_name, tport)

    def release_port(self, port_name):
        if not self._verify_port_string(port_name) or \
           port_name not in self.port_data:
            return False

        try:
            self.__trex_client.release(ports=[port_name])
        except STLError:
            pass

        return super(TRex, self).release_port(port_name)

    #
    # FIXME: All the port specific functions should be re factored to use the
    #        base class so the shared code in _xena and _trex can be removed.
    #
    def clear_statistics(self, port_name):
        if self._verify_port_action(port_name):
            self.port_data[port_name].clear_statistics()

    def take_tx_statistics_snapshot(self, port_name):
        if self._verify_port_action(port_name):
            self.port_data[port_name].take_tx_statistics_snapshot()

    def take_rx_statistics_snapshot(self, port_name):
        if self._verify_port_action(port_name):
            self.port_data[port_name].take_rx_statistics_snapshot()

    def get_tx_statistics_snapshots(self, port_name):
        if self._verify_port_action(port_name):
            return self.port_data[port_name].get_tx_statistics_snapshots()
        return None

    def get_rx_statistics_snapshots(self, port_name):
        if self._verify_port_action(port_name):
            return self.port_data[port_name].get_rx_statistics_snapshots()
        return None

    def start_traffic(self, port_name):
        if self._verify_port_action(port_name):
            return self.port_data[port_name].start_traffic()
        return False

    def stop_traffic(self, port_name):
        if self._verify_port_action(port_name):
            return self.port_data[port_name].stop_traffic()
        return False

    def configure_traffic_stream(self, port_name, traffic_flows, nr_of_flows,
                                 packet_size, **kwargs):
        if self._verify_port_action(port_name):
            return self.port_data[port_name].configure_traffic_stream(
                traffic_flows, nr_of_flows, packet_size, **kwargs)
        return False

    def next_traffic_stream(self, port_name):
        if self._verify_port_action(port_name):
            return self.port_data[port_name].next_traffic_stream()
        return False

    def get_port_limits(self, port_name):
        if self._verify_port_action(port_name):
            return self.port_data[port_name].get_port_limits()
        return dict()
コード例 #5
0
def main() -> int:
    # Initialize the argument parser and subparsers
    # First we initialize general arguments.
    parser = argparse.ArgumentParser(description="Linerate test control plane")
    parser.add_argument(
        "--server-addr",
        type=str,
        help="The server address",
        default="127.0.0.1",
        required=False,
    )
    parser.add_argument(
        "--trex-config",
        type=str,
        help="The Trex config to be placed on the server.",
        required=True,
    )
    parser.add_argument(
        "--keep-running",
        action="store_true",
        default=False,
        help="Keep Trex running after the test.",
    )
    parser.add_argument(
        "--force-restart",
        action="store_true",
        default=False,
        help="Force restart the Trex process " + "if there is one running.",
    )

    # Second, we initialize subparsers from all test scripts
    subparsers = parser.add_subparsers(
        dest="test",
        help="The test profile, which is the " +
        "filename(without .py) in the test directory",
        required=True,
    )
    test_py_list = glob.glob(join(dirname(__file__), "tests", "*.py"))
    test_list = [
        basename(f)[:-3] for f in test_py_list
        if isfile(f) and not f.endswith("__init__.py")
    ]

    for test in test_list:
        test_class = get_test_class(test)
        if not test_class:
            continue
        test_parser = subparsers.add_parser(test)
        test_class.setup_subparser(test_parser)

    # Finally, we get the arguments
    args = parser.parse_args()

    # Set up the Trex server
    if not os.path.exists(args.trex_config):
        logging.error("Can not find Trex config file: %s", args.trex_config)
        return

    if not os.path.isfile(args.trex_config):
        logging.error("%s is not a file", args.trex_config)
        return 1

    trex_config_file_on_server = TREX_FILES_DIR + os.path.basename(
        args.trex_config)

    trex_daemon_client = CTRexClient(args.server_addr)
    trex_started = False

    try:
        logging.info("Pushing Trex config %s to the server", args.trex_config)
        if not trex_daemon_client.push_files(args.trex_config):
            logging.error("Unable to push %s to Trex server", args.trex_config)
            return 1

        if args.force_restart:
            logging.info("Killing all Trexes... with meteorite... Boom!")
            trex_daemon_client.kill_all_trexes()

            # Wait until Trex enter the Idle state
            start_time = time.time()
            success = False
            while time.time() - start_time < DEFAULT_KILL_TIMEOUT:
                if trex_daemon_client.is_idle():
                    success = True
                    break
                time.sleep(1)

            if not success:
                logging.error("Unable to kill Trex process, please login " +
                              "to the server and kill it manually.")
                return 1

        if not trex_daemon_client.is_idle():
            logging.info("The Trex server process is running")
            logging.warning("A Trex server process is still running, " +
                            "use --force-restart to kill it if necessary.")
            return 1

        test_class = get_test_class(args.test)

        if not test_class:
            logging.error("Unable to get test class for test %s", args.test)
            return 1

        test_type = test_class.test_type()
        logging.info("Starting Trex with %s mode", test_class.test_type())
        try:
            start_trex_function = getattr(trex_daemon_client,
                                          "start_{}".format(test_type))
        except AttributeError:
            logging.error("Unkonwon test type %s", test_type)
            return 1

        # Not checking the return value from this
        # call since it always return True
        start_trex_function(cfg=trex_config_file_on_server)
        trex_started = True

        # Start the test
        if test_type == "stateless":
            trex_client = STLClient(server=args.server_addr)
        elif test_type == "astf":
            trex_client = ASTFClient(server=args.server_addr)
        else:
            logging.error("Unknown test type %s", test_type)
            return 1

        test = test_class(trex_client)
        try:
            logging.info("Connecting to Trex server...")
            trex_client.connect()
            logging.info("Acquaring ports...")
            trex_client.acquire()
            logging.info("Resetting and clearing port...")
            trex_client.reset()  # Resets configs from all ports
            trex_client.clear_stats()  # Clear status from all ports

            logging.info("Running the test: %s...", test)
            test.start(args)
        except STLError as e:
            logging.error("Got error from Trex server: %s", e)
            return 1
        finally:
            logging.info("Cleaning up Trex client")
            trex_client.stop()
            trex_client.release()
            trex_client.disconnect()
    except ConnectionRefusedError:
        logging.error(
            "Unable to connect to server %s.\n" +
            "Did you start the Trex daemon?",
            args.server_addr,
        )
        return 1
    except ProtocolError as pe:
        logging.error("%s", pe)
        return 1
    except TRexError as te:
        logging.error("TRex error: %s", te.msg)
        return 1
    except TRexInUseError as tiue:
        logging.error("TRex is already taken: %s", tiue.msg)
        return 1
    except TRexRequestDenied as trd:
        logging.error("Request denied: %s", trd.msg)
        return 1
    finally:
        if trex_started and not args.keep_running:
            logging.info("Stopping Trex server")
            trex_daemon_client.stop_trex()
コード例 #6
0
    passed = True

    try:
        udp_payload = "A" * 50
        pkt = STLPktBuilder(
            pkt=Ether() / IP(src="192.168.17.1", dst="192.168.17.2") /
            UDP(dport=8888, sport=9999, chksum=0) / udp_payload)
        st = STLStream(
            name="udp_single_burst",
            packet=pkt,
            # Packet group id
            flow_stats=STLFlowLatencyStats(pg_id=PG_ID),
            mode=STLTXSingleBurst(total_pkts=TOTAL_PKTS, pps=PPS),
        )

        clt.connect()
        all_ports = clt.get_all_ports()
        print("All ports: {}".format(",".join(map(str, all_ports))))
        tx_port, rx_port = all_ports
        print(f"TX port: {tx_port}, RX port: {rx_port}")
        tx_port_attr = clt.get_port_attr(tx_port)
        rx_port_attr = clt.get_port_attr(rx_port)
        assert tx_port_attr["src_ipv4"] == "192.168.17.1"
        assert rx_port_attr["src_ipv4"] == "192.168.18.1"
        clt.reset(ports=all_ports)
        clt.add_streams([st], ports=[tx_port])
        print(f"Inject {TOTAL_PKTS} packets on port {all_ports[0]}")

        ret = rx_interation(clt, tx_port, rx_port, TOTAL_PKTS,
                            pkt.get_pkt_len())
        if not ret:
コード例 #7
0
def main():
    """Stop traffic if any is running. Report xstats."""
    parser = argparse.ArgumentParser()
    parser.add_argument(u"--xstat0",
                        type=str,
                        default=u"",
                        help=u"Reference xstat object if any.")
    parser.add_argument(u"--xstat1",
                        type=str,
                        default=u"",
                        help=u"Reference xstat object if any.")
    args = parser.parse_args()

    client = STLClient()
    try:
        # connect to server
        client.connect()

        client.acquire(force=True)
        # TODO: Support unidirection.
        client.stop(ports=[0, 1])

        # Read the stats after the test,
        # we need to update values before the last trial started.
        if args.xstat0:
            snapshot = eval(args.xstat0)
            client.ports[0].get_xstats().reference_stats = snapshot
        if args.xstat1:
            snapshot = eval(args.xstat1)
            client.ports[1].get_xstats().reference_stats = snapshot
        # Now we can call the official method to get differences.
        xstats0 = client.get_xstats(0)
        xstats1 = client.get_xstats(1)

    # If STLError happens, let the script fail with stack trace.
    finally:
        client.disconnect()

    print(u"##### statistics port 0 #####")
    print(json.dumps(xstats0, indent=4, separators=(u",", u": ")))
    print(u"##### statistics port 1 #####")
    print(json.dumps(xstats1, indent=4, separators=(u",", u": ")))

    tx_0, rx_0 = xstats0[u"tx_good_packets"], xstats0[u"rx_good_packets"]
    tx_1, rx_1 = xstats1[u"tx_good_packets"], xstats1[u"rx_good_packets"]
    lost_a, lost_b = tx_0 - rx_1, tx_1 - rx_0

    print(f"\npackets lost from 0 --> 1:   {lost_a} pkts")
    print(f"packets lost from 1 --> 0:   {lost_b} pkts")

    total_rcvd, total_sent = rx_0 + rx_1, tx_0 + tx_1
    total_lost = total_sent - total_rcvd
    print(f"rate='unknown'; "
          f"total_received={total_rcvd}; "
          f"total_sent={total_sent}; "
          f"frame_loss={total_lost}; "
          f"target_duration='manual'; "
          f"approximated_duration='manual'; "
          f"approximated_rate='unknown'; "
          f"latency_stream_0(usec)=-1/-1/-1; "
          f"latency_stream_1(usec)=-1/-1/-1; ")
コード例 #8
0
def main():

    parser = argparse.ArgumentParser(description="")

    parser.add_argument(
        "--ip_src",
        type=str,
        default="192.168.17.1",
        help="Source IP address for all packets in the stream.",
    )
    parser.add_argument(
        "--ip_dst",
        type=str,
        default="192.168.17.2",
        help="Destination IP address for all packets in the stream.",
    )

    # Due to different packet sizes, it is easier to keep the PPS fixed.
    # 0.25 Mpps -> about 3Gbps bit rate.
    parser.add_argument(
        "--pps", type=float, default=0.25, help="Transmit L1 rate in Mpps."
    )

    # This is "configured" to give some space for power management ;)
    parser.add_argument(
        "--tot_pkts_burst",
        type=int,
        default=50 * 10 ** 3,
        help="Total number of packets in each single burst.",
    )

    parser.add_argument(
        "--model",
        type=str,
        default="poisson",
        choices=["poisson", "pareto"],
        help="To be used traffic model.",
    )
    # MARK: Currently NOT implemented.
    parser.add_argument(
        "--src_num", type=int, default=1, help="Number of flow sources."
    )

    parser.add_argument(
        "--burst_num",
        type=int,
        default=100,
        help="The number of bursts in one test round.",
    )

    parser.add_argument("--test", action="store_true", help="Just used for debug.")

    parser.add_argument(
        "--out", type=str, default="", help="Stores file with given name"
    )

    args = parser.parse_args()
    print(f"* The fastest reaction time of X-MEN: {X_MEN_REACTION_TIME} seconds.")
    print(f"* Traffic model: {args.model}")

    l3_data = {"ip_src": args.ip_src, "ip_dst": args.ip_dst}
    streams, flow_duration = get_streams(
        args.pps,
        args.burst_num,
        args.model,
        args.src_num,
        args.tot_pkts_burst,
        l3_data,
        args.test,
    )

    if args.test:
        pprint.pp([s.to_json() for s in streams[:3]])
        sys.exit(0)

    print(f"* Flow duration: {flow_duration} seconds.")

    try:
        client = STLClient()
        client.connect()
        tx_port, rx_port = init_ports(client)
        client.add_streams(streams, ports=[tx_port])

        start_ts = time.time()
        client.clear_stats()
        client.start(ports=[tx_port], force=True)

        rx_delay_sec = flow_duration + 5
        print(f"The estimated RX delay: {rx_delay_sec} seconds.")
        client.wait_on_traffic(rx_delay_ms=3000)  # rx_delay_sec * 10 ** 3)
        end_ts = time.time()
        test_dur = end_ts - start_ts
        print(f"Total test duration: {test_dur} seconds")

        err_cntrs_results, latency_results = get_rx_stats(
            client, tx_port, rx_port, args.burst_num
        )

        print("--- The latency results of all streams:")
        for m_burst in range(args.burst_num):
            # Include ISG duratio, packet size and time stamps into .json dump
            err_cntrs_results[m_burst]["isg"] = ISGS_SAVE[m_burst]
            err_cntrs_results[m_burst]["len"] = IP_TOT_LENS_SAVE[m_burst]
            err_cntrs_results[m_burst]["start_ts"] = start_ts
            err_cntrs_results[m_burst]["end_ts"] = end_ts
            print("Burst ", m_burst)
            print("ISG: ", ISGS_SAVE[m_burst])
            print("Dropped: ", err_cntrs_results[m_burst]["dropped"])
            print("Latency: ", latency_results[m_burst]["average"])
            # print(err_cntrs_results[m_burst])
            # print(latency_results[m_burst])
        if args.out:
            savedir_latency = "/home/malte/malte/latency/"
            savedir_error = "/home/malte/malte/error/"
            if not os.path.exists(savedir_latency):
                os.mkdir(savedir_latency)
            if not os.path.exists(savedir_error):
                os.mkdir(savedir_error)
            savedir_latency += args.out + "_latency.json"
            savedir_error += args.out + "_error.json"
            print("\nResults: ", savedir_latency, ", ", savedir_error)
            save_rx_stats(err_cntrs_results, savedir_error, args.burst_num)
            save_rx_stats(latency_results, savedir_latency, args.burst_num)

    except STLError as error:
        print(error)

    finally:
        client.disconnect()
コード例 #9
0
def simple_burst(
    profile_file,
    duration,
    framesize,
    rate,
    port_0,
    port_1,
    latency,
    async_start=False,
    traffic_directions=2,
    force=False,
    delay=0.0,
):
    """Send traffic and measure packet loss and latency.

    Procedure:
     - reads the given traffic profile with streams,
     - connects to the T-rex client,
     - resets the ports,
     - removes all existing streams,
     - adds streams from the traffic profile to the ports,
     - if the warm-up time is more than 0, sends the warm-up traffic, reads the
       statistics,
     - clears the statistics from the client,
     - starts the traffic,
     - waits for the defined time (or runs forever if async mode is defined),
     - stops the traffic,
     - reads and displays the statistics and
     - disconnects from the client.

    :param profile_file: A python module with T-rex traffic profile.
    :param framesize: Frame size.
    :param duration: Duration of traffic run in seconds (-1=infinite).
    :param rate: Traffic rate [percentage, pps, bps].
    :param port_0: Port 0 on the traffic generator.
    :param port_1: Port 1 on the traffic generator.
    :param latency: With latency stats.
    :param async_start: Start the traffic and exit.
    :param traffic_directions: Bidirectional (2) or unidirectional (1) traffic.
    :param force: Force start regardless of ports state.
    :param delay: Sleep overhead [s].
    :type profile_file: str
    :type framesize: int or str
    :type duration: float
    :type rate: str
    :type port_0: int
    :type port_1: int
    :type latency: bool
    :type async_start: bool
    :type traffic_directions: int
    :type force: bool
    :type delay: float
    """
    client = None
    total_rcvd = 0
    total_sent = 0
    approximated_duration = 0.0
    lost_a = 0
    lost_b = 0
    lat_a = u"-1/-1/-1/"
    lat_b = u"-1/-1/-1/"

    # Read the profile:
    try:
        print(f"### Profile file:\n{profile_file}")
        profile = STLProfile.load(profile_file,
                                  direction=0,
                                  port_id=0,
                                  framesize=framesize,
                                  rate=rate)
        streams = profile.get_streams()
    except STLError:
        print(f"Error while loading profile '{profile_file}'!")
        raise

    try:
        # Create the client:
        client = STLClient()
        # Connect to server:
        client.connect()
        # Prepare our ports (the machine has 0 <--> 1 with static route):
        client.reset(ports=[port_0, port_1])
        client.remove_all_streams(ports=[port_0, port_1])

        if u"macsrc" in profile_file:
            client.set_port_attr(ports=[port_0, port_1], promiscuous=True)
        if isinstance(framesize, int):
            last_stream_a = int((len(streams) - 2) / 2)
            last_stream_b = (last_stream_a * 2)
            client.add_streams(streams[0:last_stream_a], ports=[port_0])
            if traffic_directions > 1:
                client.add_streams(streams[last_stream_a:last_stream_b],
                                   ports=[port_1])
        elif isinstance(framesize, str):
            client.add_streams(streams[0:3], ports=[port_0])
            if traffic_directions > 1:
                client.add_streams(streams[3:6], ports=[port_1])
        if latency:
            try:
                if isinstance(framesize, int):
                    client.add_streams(streams[last_stream_b], ports=[port_0])
                    if traffic_directions > 1:
                        client.add_streams(streams[last_stream_b + 1],
                                           ports=[port_1])
                elif isinstance(framesize, str):
                    latency = False
            except STLError:
                # Disable latency if NIC does not support requested stream type
                print(u"##### FAILED to add latency streams #####")
                latency = False
        ports = [port_0]
        if traffic_directions > 1:
            ports.append(port_1)

        # Clear the stats before injecting:
        client.clear_stats()
        lost_a = 0
        lost_b = 0

        # Choose rate and start traffic:
        client.start(
            ports=ports,
            mult=rate,
            duration=duration,
            force=force,
            core_mask=STLClient.CORE_MASK_PIN,
        )

        if async_start:
            # For async stop, we need to export the current snapshot.
            xsnap0 = client.ports[0].get_xstats().reference_stats
            print(f"Xstats snapshot 0: {xsnap0!r}")
            if traffic_directions > 1:
                xsnap1 = client.ports[1].get_xstats().reference_stats
                print(f"Xstats snapshot 1: {xsnap1!r}")
        else:
            time_start = time.monotonic()
            # wait_on_traffic fails if duration stretches by 30 seconds or more.
            # TRex has some overhead, wait some more.
            time.sleep(duration + delay)
            client.stop()
            time_stop = time.monotonic()
            approximated_duration = time_stop - time_start - delay
            # Read the stats after the traffic stopped (or time up).
            stats = client.get_stats()
            if client.get_warnings():
                for warning in client.get_warnings():
                    print(warning)
            # Now finish the complete reset.
            client.reset()

            print(u"##### Statistics #####")
            print(json.dumps(stats, indent=4, separators=(u",", u": ")))

            lost_a = stats[port_0][u"opackets"] - stats[port_1][u"ipackets"]
            if traffic_directions > 1:
                lost_b = stats[port_1][u"opackets"] - stats[port_0][u"ipackets"]

            # Stats index is not a port number, but "pgid".
            if latency:
                lat_obj = stats[u"latency"][0][u"latency"]
                lat_a = fmt_latency(str(lat_obj[u"total_min"]),
                                    str(lat_obj[u"average"]),
                                    str(lat_obj[u"total_max"]),
                                    str(lat_obj[u"hdrh"]))
                if traffic_directions > 1:
                    lat_obj = stats[u"latency"][1][u"latency"]
                    lat_b = fmt_latency(str(lat_obj[u"total_min"]),
                                        str(lat_obj[u"average"]),
                                        str(lat_obj[u"total_max"]),
                                        str(lat_obj[u"hdrh"]))

            if traffic_directions > 1:
                total_sent = stats[0][u"opackets"] + stats[1][u"opackets"]
                total_rcvd = stats[0][u"ipackets"] + stats[1][u"ipackets"]
            else:
                total_sent = stats[port_0][u"opackets"]
                total_rcvd = stats[port_1][u"ipackets"]

            print(f"\npackets lost from {port_0} --> {port_1}: {lost_a} pkts")
            if traffic_directions > 1:
                print(
                    f"packets lost from {port_1} --> {port_0}: {lost_b} pkts")

    except STLError:
        print(u"T-Rex STL runtime error!", file=sys.stderr)
        raise

    finally:
        if async_start:
            if client:
                client.disconnect(stop_traffic=False, release_ports=True)
        else:
            if client:
                client.disconnect()
            print(f"rate={rate!r}; "
                  f"total_received={total_rcvd}; "
                  f"total_sent={total_sent}; "
                  f"frame_loss={lost_a + lost_b}; "
                  f"target_duration={duration!r}; "
                  f"approximated_duration={approximated_duration!r}; "
                  f"latency_stream_0(usec)={lat_a}; "
                  f"latency_stream_1(usec)={lat_b}; ")
コード例 #10
0
def main():
    global IP_TOT_LEN

    parser = argparse.ArgumentParser(
        description=
        "On/Off traffic of a deterministic and stateless stream profile.")

    parser.add_argument(
        "--ip_src",
        type=str,
        default="192.168.17.1",
        help="Source IP address for all packets in the stream.",
    )
    parser.add_argument(
        "--ip_dst",
        type=str,
        default="192.168.17.2",
        help="Destination IP address for all packets in the stream.",
    )

    parser.add_argument(
        "--max_bit_rate",
        type=float,
        default=1,
        help="Maximal bit rate (with the unit Gbps) of the underlying network.",
    )
    parser.add_argument("--on_time",
                        type=int,
                        default=2,
                        help="ON time in seconds.")
    parser.add_argument(
        "--init_off_on_ratio",
        type=float,
        default=0.5,
        help="Initial ratio between OFF and ON time.",
    )
    parser.add_argument(
        "--iteration",
        type=int,
        default=1,
        help="Number of iterations for the ON state of each PPS.",
    )
    parser.add_argument(
        "--numa_node",
        type=int,
        default=0,
        help="The NUMA node of cores used for TX and RX.",
    )
    parser.add_argument("--test",
                        action="store_true",
                        help="Just used for debug.")
    parser.add_argument(
        "--out",
        type=str,
        default="",
        help=
        "The name of the output file, stored in /home/malte/malte/latency if given",
    )
    parser.add_argument(
        "--ip_tot_len",
        type=int,
        default=IP_TOT_LEN,
        help="The IP total length of packets to be transmitted.",
    )
    parser.add_argument(
        "--enable_second_flow",
        action="store_true",
        help="Enable the second flow, used to test two-vnf setup.",
    )
    parser.add_argument(
        "--soft",
        action="store_true",
        help="Different overlap for sencond flow, it's easier to scale ;)",
    )

    args = parser.parse_args()

    IP_TOT_LEN = args.ip_tot_len

    stream_params = create_stream_params(
        args.max_bit_rate,
        args.on_time,
        args.init_off_on_ratio,
        args.iteration,
        args.test,
    )
    print("\n--- Initial stream parameters:")
    pprint.pp(stream_params)
    print()

    if args.enable_second_flow:
        print(
            "INFO: The second flow is enabled. Two flows share the physical link."
        )
        # Simply reverse the link utilizations
        second_stream_params = copy.deepcopy(list(reversed(stream_params)))
        # Change ISG's of 2nd flow to 2s
        for s in second_stream_params:
            s["on_time"] = args.on_time - (args.on_time * 0.2)
            s["isg"] = s["isg"] + (args.on_time * 0.2) * 10**6
        # Reset ISG of first stream of the 2nd flow back to 1
        # -> they always start together then
        if args.soft:
            second_stream_params[0]["isg"] = 1 * 10**6
        print("\n--- Updated stream parameters with the second flow:")
        pprint.pp(second_stream_params)

    # Does not work on the blackbox
    # core_mask = get_core_mask(args.numa_node)
    # print(f"The core mask for RX and TX: {hex(core_mask)}")

    if args.enable_second_flow:
        streams = create_streams_with_second_flow(stream_params,
                                                  second_stream_params,
                                                  args.ip_src, args.ip_dst)
    else:
        streams = create_streams(stream_params, args.ip_src, args.ip_dst)
        second_stream_params = None

    if args.test:
        pprint.pp([s.to_json() for s in streams])
        import sys

        sys.exit(0)

    if args.enable_second_flow:
        RX_DELAY_S = (sum([s["on_time"] for s in stream_params])) / 2.0 + 3
    else:
        RX_DELAY_S = sum([s["on_time"] for s in stream_params]) + 3

    RX_DELAY_MS = 3 * 1000  # Time after last Tx to wait for the last packet at Rx side

    try:
        client = STLClient()
        client.connect()
        tx_port, rx_port = init_ports(client)
        client.add_streams(streams, ports=[tx_port])

        # Start TX
        start_ts = time.time()
        client.clear_stats()
        # All cores in the core_mask is used by the tx_port and its adjacent
        # port, so it is the rx_port normally.
        # client.start(ports=[tx_port], core_mask=[core_mask], force=True)
        client.start(ports=[tx_port], force=True)

        print(f"The estimated RX delay: {RX_DELAY_MS / 1000} seconds.")
        client.wait_on_traffic(rx_delay_ms=RX_DELAY_MS)
        end_ts = time.time()
        test_dur = end_ts - start_ts
        print(f"Total test duration: {test_dur} seconds")

        # Check RX stats.
        # MARK: All latency results are in usec.
        err_cntrs_results, latency_results = get_rx_stats(
            client,
            tx_port,
            rx_port,
            stream_params,
            second_stream_params=second_stream_params,
        )
        print("--- The latency results of all streams:")
        print(f"- Number of streams first flow: {len(latency_results[0])}")
        for index, _ in enumerate(stream_params):
            print(f"- Stream: {index}")
            # Add timestamps to .json dump to parse turbostat results later
            err_cntrs_results[0][index]["start_ts"] = start_ts
            err_cntrs_results[0][index]["end_ts"] = end_ts
            print(err_cntrs_results[0][index])
            print(latency_results[0][index])
        # Save stats as .json dump
        if args.out:
            savedir_latency = "/home/malte/malte/latency/flow1/"
            savedir_error = "/home/malte/malte/error/flow1/"
            if not os.path.exists(savedir_latency):
                os.mkdir(savedir_latency)
            if not os.path.exists(savedir_error):
                os.mkdir(savedir_error)
            savedir_latency += args.out + "_latency.json"
            savedir_error += args.out + "_error.json"
            print("\nResults: ", savedir_latency, ", ", savedir_error)
            save_rx_stats(err_cntrs_results[0], savedir_error, stream_params)
            save_rx_stats(latency_results[0], savedir_latency, stream_params)
        if second_stream_params is not None:
            print(
                f"\n\n- Number of streams second flow: {len(latency_results[1])}"
            )
            for index, _ in enumerate(stream_params):
                print(f"- Stream: {index}")
                err_cntrs_results[1][index]["start_ts"] = start_ts
                err_cntrs_results[1][index]["end_ts"] = end_ts
                print(err_cntrs_results[1][index])
                print(latency_results[1][index])
            if args.out:
                savedir_latency = "/home/malte/malte/latency/flow2/"
                savedir_error = "/home/malte/malte/error/flow2/"
                if not os.path.exists(savedir_latency):
                    os.mkdir(savedir_latency)
                if not os.path.exists(savedir_error):
                    os.mkdir(savedir_error)
                savedir_latency += args.out + "_latency.json"
                savedir_error += args.out + "_error.json"
                print("\nResults: ", savedir_latency, ", ", savedir_error)
                save_rx_stats(err_cntrs_results[1], savedir_error,
                              stream_params)
                save_rx_stats(latency_results[1], savedir_latency,
                              stream_params)

    except STLError as error:
        print(error)

    finally:
        client.disconnect()
コード例 #11
0
def main():
    global PAYLOAD_SIZE

    parser = argparse.ArgumentParser(
        description=
        "On/Off traffic of a deterministic and stateless stream profile.")

    parser.add_argument(
        "--ip_src",
        type=str,
        default="192.168.17.1",
        help="Source IP address for all packets in the stream.",
    )
    parser.add_argument(
        "--ip_dst",
        type=str,
        default="192.168.17.2",
        help="Destination IP address for all packets in the stream.",
    )

    parser.add_argument(
        "--max_bit_rate",
        type=float,
        default=1,
        help="Maximal bit rate (with the unit Gbps) of the underlying network.",
    )
    parser.add_argument("--on_time",
                        type=int,
                        default=2,
                        help="ON time in seconds.")
    parser.add_argument(
        "--init_off_on_ratio",
        type=float,
        default=0.5,
        help="Initial ratio between OFF and ON time.",
    )
    parser.add_argument(
        "--iteration",
        type=int,
        default=1,
        help="Number of iterations for the ON state of each PPS.",
    )
    parser.add_argument(
        "--numa_node",
        type=int,
        default=0,
        help="The NUMA node of cores used for TX and RX.",
    )
    parser.add_argument("--test",
                        action="store_true",
                        help="Just used for debug.")
    parser.add_argument(
        "--out",
        type=str,
        default="",
        help=
        "The name of the output file, stored in /home/malte/malte/latency if given",
    )
    parser.add_argument(
        "--payload_size",
        type=int,
        default=PAYLOAD_SIZE,
        help="Payload size of the packets",
    )

    args = parser.parse_args()

    PAYLOAD_SIZE = args.payload_size

    stream_params = create_stream_params(
        args.max_bit_rate,
        args.on_time,
        args.init_off_on_ratio,
        args.iteration,
        args.test,
    )
    print("\n--- To be used stream parameters:")
    pprint.pp(stream_params)
    print()

    # Does not work on the blackbox
    # core_mask = get_core_mask(args.numa_node)
    # print(f"The core mask for RX and TX: {hex(core_mask)}")

    streams = create_streams(stream_params, args.ip_src, args.ip_dst)
    if args.test:
        pprint.pp(streams)
        pprint.pp([s.to_json() for s in streams])

    RX_DELAY_S = sum([s["on_time"] for s in stream_params]) + 3
    RX_DELAY_MS = 3 * 1000  # Time after last Tx to wait for the last packet at Rx side

    try:
        client = STLClient()
        client.connect()
        tx_port, rx_port = init_ports(client)
        client.add_streams(streams, ports=[tx_port])

        # Start TX
        start_ts = time.time()
        client.clear_stats()
        # All cores in the core_mask is used by the tx_port and its adjacent
        # port, so it is the rx_port normally.
        # client.start(ports=[tx_port], core_mask=[core_mask], force=True)
        client.start(ports=[tx_port], force=True)

        print(f"The estimated RX delay: {RX_DELAY_MS / 1000} seconds.")
        client.wait_on_traffic(rx_delay_ms=RX_DELAY_MS)
        end_ts = time.time()
        test_dur = end_ts - start_ts
        print(f"Total test duration: {test_dur} seconds")

        # Check RX stats.
        # MARK: All latency results are in usec.
        # err_cntrs_results, latency_results = get_rx_stats(
        # client, tx_port, rx_port, stream_params
        # )
        err_cntrs_results, latency_results, flow_results = get_rx_stats(
            client, tx_port, rx_port, stream_params)
        print("--- The latency results of all streams:")
        print(f"- Number of streams: {len(latency_results)}")
        for index, _ in enumerate(stream_params):
            print(f"- Stream: {index}")
            err_cntrs_results[index]["start_ts"] = start_ts
            err_cntrs_results[index]["end_ts"] = end_ts
            print(err_cntrs_results[index])
            print(latency_results[index])
            print(flow_results[index])
        if args.out:
            savedir_latency = "/home/malte/malte/latency/" + args.out + "_latency.json"
            savedir_error = "/home/malte/malte/error/" + args.out + "_error.json"
            print("Results: ", savedir_latency, ", ", savedir_error)
            save_rx_stats(err_cntrs_results, savedir_error, stream_params)
            save_rx_stats(latency_results, savedir_latency, stream_params)

    except STLError as error:
        print(error)

    finally:
        client.disconnect()