On Thu, Sep 14, 2023 at 9:56 PM Ihar Hrachyshka <ihrac...@redhat.com> wrote:

> The daemon life cycle spans over the whole test case life time, which
> significantly speeds up test cases that rely on fmt_pkt for packet byte
> representations.
>
> The speed-up comes from the fact that we no longer start a python
> environment with all scapy modules imported on any fmt_pkt invocation;
> but only on the first call to fmt_pkt.
>
> The daemon is not started for test cases that don't trigger fmt_pkt.
> (The server is started lazily as part of fmt_pkt call.)
>
> For example, without the daemon, all tests that use fmt_pkt took the
> following on my vagrant box:
>
> real    17m23.092s
> user    26m27.935s
> sys     5m25.486s
>
> With the daemon, the same set of tests run in:
>
> real    2m16.741s
> user    2m40.155s
> sys     0m47.514s
>
> We may want to make the daemon global, so that it's invoked once per
> test suite run. But I haven't figured out, yet, how to run a trap to
> clean up the deamon and its socket and pid files on suite exit (and not
> on test case exit.)
>
> Signed-off-by: Ihar Hrachyshka <ihrac...@redhat.com>
>
> unixctl impl
> ---
>  tests/automake.mk   |  3 +-
>  tests/ovn-macros.at | 16 ++++++++---
>  tests/scapy-server  | 69 +++++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 83 insertions(+), 5 deletions(-)
>  create mode 100755 tests/scapy-server
>
> diff --git a/tests/automake.mk b/tests/automake.mk
> index eea0d00f4..f23ec353e 100644
> --- a/tests/automake.mk
> +++ b/tests/automake.mk
> @@ -310,7 +310,8 @@ CHECK_PYFILES = \
>         tests/test-l7.py \
>         tests/uuidfilt.py \
>         tests/test-tcp-rst.py \
> -       tests/check_acl_log.py
> +       tests/check_acl_log.py \
> +       tests/scapy-server
>
>  EXTRA_DIST += $(CHECK_PYFILES)
>  PYCOV_CLEAN_FILES += $(CHECK_PYFILES:.py=.py,cover) .coverage
> diff --git a/tests/ovn-macros.at b/tests/ovn-macros.at
> index 13d5dc3d4..b1b2a8156 100644
> --- a/tests/ovn-macros.at
> +++ b/tests/ovn-macros.at
> @@ -833,10 +833,18 @@ ovn_trace_client() {
>  # ovs-appctl netdev-dummy/receive $vif $packet
>  #
>  fmt_pkt() {
> -    echo "from scapy.all import *; \
> -          import binascii; \
> -          out = binascii.hexlify(raw($1)); \
> -          print(out.decode())" | $PYTHON3
> +    ctlfile=$ovs_base/scapy.ctl
> +    if [[ ! -e $ctlfile ]]; then
> +        start_scapy_server
> +    fi
> +    echo $(ovs-appctl -t $ctlfile payload "$1")
> +}
> +
> +start_scapy_server() {
> +    pidfile=$ovs_base/scapy.pid
> +    ctlfile=$ovs_base/scapy.ctl
> +    "$top_srcdir"/tests/scapy-server --pidfile=$pidfile
> --unixctl=$ctlfile --detach
> +    on_exit "test -e \"$pidfile\" && ovs-appctl -t $ctlfile exit"
>  }
>
>  sleep_sb() {
> diff --git a/tests/scapy-server b/tests/scapy-server
> new file mode 100755
> index 000000000..a7255c84d
> --- /dev/null
> +++ b/tests/scapy-server
> @@ -0,0 +1,69 @@
> +#!/usr/bin/env python3
> +
> +import argparse
> +
> +import ovs.daemon
> +import ovs.unixctl
> +import ovs.unixctl.server
> +
> +import binascii
> +from scapy.all import *  # noqa: F401,F403
> +from scapy.all import raw
> +
> +
> +vlog = ovs.vlog.Vlog("scapy-server")
> +exiting = False
> +
> +
> +def exit(conn, argv, aux):
> +    global exiting
> +
> +    exiting = True
> +    conn.reply(None)
> +
> +
> +def process(data):
> +    try:
> +        data = data.replace('\n', '')
> +        return binascii.hexlify(raw(eval(data))).decode()
> +    except Exception:
> +        return ""
> +
> +
> +def payload(conn, argv, aux):
> +    conn.reply(process(argv[0]))
> +
> +
> +def main():
> +    parser = argparse.ArgumentParser(
> +        description="Scapy-based Frame Payload Generator")
> +    parser.add_argument("--unixctl", help="UNIXCTL socket location or
> 'none'.")
> +
> +    ovs.daemon.add_args(parser)
> +    ovs.vlog.add_args(parser)
> +    args = parser.parse_args()
> +    ovs.daemon.handle_args(args)
> +    ovs.vlog.handle_args(args)
> +
> +    ovs.daemon.daemonize_start()
> +    error, server = ovs.unixctl.server.UnixctlServer.create(args.unixctl)
> +    if error:
> +        ovs.util.ovs_fatal(error, "could not create unixctl server at %s"
> +                           % args.unixctl, vlog)
> +
> +    ovs.unixctl.command_register("exit", "", 0, 0, exit, None)
> +    ovs.unixctl.command_register("payload", "", 1, 1, payload, None)
> +    ovs.daemon.daemonize_complete()
> +
> +    poller = ovs.poller.Poller()
> +    while not exiting:
> +        server.run()
> +        server.wait(poller)
> +        if exiting:
> +            poller.immediate_wake()
> +        poller.block()
> +    server.close()
> +
> +
> +if __name__ == '__main__':
> +    main()
> --
> 2.38.1
>
> _______________________________________________
> dev mailing list
> d...@openvswitch.org
> https://mail.openvswitch.org/mailman/listinfo/ovs-dev
>
>

Looks good to me, thanks!

Acked-by: Ales Musil <amu...@redhat.com>

-- 

Ales Musil

Senior Software Engineer - OVN Core

Red Hat EMEA <https://www.redhat.com>

amu...@redhat.com
<https://red.ht/sig>
_______________________________________________
dev mailing list
d...@openvswitch.org
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to