Parse the output of tcpreplay and modify the results_dict to populate output information. # noqa: E501 Tested with tcpreplay v3.4.4 Tested with tcpreplay v4.1.2 :param stdout: stdout of tcpreplay subprocess call :param stderr: stderr of tcpreplay subprocess call :param argv
(stdout_b, stderr_b, argv)
| 613 | |
| 614 | |
| 615 | def _parse_tcpreplay_result(stdout_b, stderr_b, argv): |
| 616 | # type: (bytes, bytes, List[str]) -> Dict[str, Any] |
| 617 | """ |
| 618 | Parse the output of tcpreplay and modify the results_dict to populate output information. # noqa: E501 |
| 619 | Tested with tcpreplay v3.4.4 |
| 620 | Tested with tcpreplay v4.1.2 |
| 621 | :param stdout: stdout of tcpreplay subprocess call |
| 622 | :param stderr: stderr of tcpreplay subprocess call |
| 623 | :param argv: the command used in the subprocess call |
| 624 | :return: dictionary containing the results |
| 625 | """ |
| 626 | try: |
| 627 | results = {} |
| 628 | stdout = plain_str(stdout_b).lower() |
| 629 | stderr = plain_str(stderr_b).strip().split("\n") |
| 630 | elements = { |
| 631 | "actual": (int, int, float), |
| 632 | "rated": (float, float, float), |
| 633 | "flows": (int, float, int, int), |
| 634 | "attempted": (int,), |
| 635 | "successful": (int,), |
| 636 | "failed": (int,), |
| 637 | "truncated": (int,), |
| 638 | "retried packets (eno": (int,), |
| 639 | "retried packets (eag": (int,), |
| 640 | } |
| 641 | multi = { |
| 642 | "actual": ("packets", "bytes", "time"), |
| 643 | "rated": ("bps", "mbps", "pps"), |
| 644 | "flows": ("flows", "fps", "flow_packets", "non_flow"), |
| 645 | "retried packets (eno": ("retried_enobufs",), |
| 646 | "retried packets (eag": ("retried_eagain",), |
| 647 | } |
| 648 | float_reg = r"([0-9]*\.[0-9]+|[0-9]+)" |
| 649 | int_reg = r"([0-9]+)" |
| 650 | any_reg = r"[^0-9]*" |
| 651 | r_types = {int: int_reg, float: float_reg} |
| 652 | for line in stdout.split("\n"): |
| 653 | line = line.strip() |
| 654 | for elt, _types in elements.items(): |
| 655 | if line.startswith(elt): |
| 656 | regex = any_reg.join([r_types[x] for x in _types]) |
| 657 | matches = re.search(regex, line) |
| 658 | for i, typ in enumerate(_types): |
| 659 | name = multi.get(elt, [elt])[i] |
| 660 | if matches: |
| 661 | results[name] = typ(matches.group(i + 1)) |
| 662 | results["command"] = " ".join(argv) |
| 663 | results["warnings"] = stderr[:-1] |
| 664 | return results |
| 665 | except Exception as parse_exception: |
| 666 | if not conf.interactive: |
| 667 | raise |
| 668 | log_runtime.error("Error parsing output: %s", parse_exception) |
| 669 | return {} |
| 670 | |
| 671 | |
| 672 | def _interface_selection(packet: _PacketIterable) -> Tuple[NetworkInterface, bool]: |