[ovs-dev] [PATCH v3 2/4] system-dpdk: Use dummy-pmd port for packet injection.

David Marchand david.marchand at redhat.com
Tue Nov 30 15:00:11 UTC 2021


net_pcap is not always available in DPDK (like, in a dev
environment when you forgot to install the libpcap-devel).
On the other hand, OVS already has its own way to inject packets into a
bridge. Let's make use of it.

This solution is slower than net/pcap DPDK, so lower the number of
expected packets so that it runs in OVS_CTL_TIMEOUT seconds.

While at it, convert "known" packets from pcap to scapy so that the
injected packets can be updated without having to read/write a pcap file.

Note: this change also (avoids/) fixes a python exception in PcapWriter
with scapy 2.4.3 that comes from EPEL.

Suggested-by: Ilya Maximets <i.maximets at ovn.org>
Signed-off-by: David Marchand <david.marchand at redhat.com>
---
Changes since v2:
- updated documentation,
- cleaned tests/automake.mk,
- fixed shebang in python script,
- added missing check for scapy availability,

Changes since v1:
- renamed generator script,
- decreased packet count for fuzzy test,
- simplified wait expression for packet count,

---
 Documentation/topics/dpdk/bridge.rst |   7 ++--
 tests/automake.mk                    |   7 +---
 tests/genpkts.py                     |  56 +++++++++++++++++++++++++++
 tests/mfex_fuzzy.py                  |  32 ---------------
 tests/pcap/mfex_test.pcap            | Bin 416 -> 0 bytes
 tests/system-dpdk-macros.at          |   4 +-
 tests/system-dpdk.at                 |  33 +++++++++++++---
 7 files changed, 89 insertions(+), 50 deletions(-)
 create mode 100755 tests/genpkts.py
 delete mode 100755 tests/mfex_fuzzy.py
 delete mode 100644 tests/pcap/mfex_test.pcap

diff --git a/Documentation/topics/dpdk/bridge.rst b/Documentation/topics/dpdk/bridge.rst
index f645b9ade5..648ce203eb 100644
--- a/Documentation/topics/dpdk/bridge.rst
+++ b/Documentation/topics/dpdk/bridge.rst
@@ -408,7 +408,7 @@ Fuzzy tests can also be done on miniflow extract with the help of
 auto-validator and Scapy. The steps below describes the steps to
 reproduce the setup with IP being fuzzed to generate packets.
 
-Scapy is used to create fuzzy IP packets and save them into a PCAP ::
+Scapy is used to create fuzzy IP packets (see tests/genpkts.py) ::
 
     pkt = fuzz(Ether()/IP()/TCP())
 
@@ -418,9 +418,8 @@ Set the miniflow extract to autovalidator using ::
 
 OVS is configured to receive the generated packets ::
 
-    $ ovs-vsctl add-port br0 pcap0 -- \
-        set Interface pcap0 type=dpdk options:dpdk-devargs=net_pcap0
-        "rx_pcap=fuzzy.pcap"
+    $ ovs-vsctl add-port br0 p1 -- \
+        set Interface p1 type=dummy-pmd
 
 With this workflow, the autovalidator will ensure that all MFEX
 implementations are classifying each packet in exactly the same way.
diff --git a/tests/automake.mk b/tests/automake.mk
index 43731d0973..3bc74a5aff 100644
--- a/tests/automake.mk
+++ b/tests/automake.mk
@@ -143,11 +143,6 @@ $(srcdir)/tests/fuzz-regression-list.at: tests/automake.mk
 	    echo "TEST_FUZZ_REGRESSION([$$basename])"; \
 	done > $@.tmp && mv $@.tmp $@
 
-EXTRA_DIST += $(MFEX_AUTOVALIDATOR_TESTS)
-MFEX_AUTOVALIDATOR_TESTS = \
-	tests/pcap/mfex_test.pcap \
-	tests/mfex_fuzzy.py
-
 OVSDB_CLUSTER_TESTSUITE_AT = \
 	tests/ovsdb-cluster-testsuite.at \
 	tests/ovsdb-execution.at \
@@ -518,7 +513,7 @@ tests_test_type_props_SOURCES = tests/test-type-props.c
 CHECK_PYFILES = \
 	tests/appctl.py \
 	tests/flowgen.py \
-	tests/mfex_fuzzy.py \
+	tests/genpkts.py \
 	tests/ovsdb-monitor-sort.py \
 	tests/test-daemon.py \
 	tests/test-json.py \
diff --git a/tests/genpkts.py b/tests/genpkts.py
new file mode 100755
index 0000000000..f64f786ccb
--- /dev/null
+++ b/tests/genpkts.py
@@ -0,0 +1,56 @@
+#!/usr/bin/env python3
+
+import sys
+
+from scapy.all import RandMAC, RandIP, RandIP6, RandShort, fuzz
+from scapy.all import IPv6, Dot1Q, IP, Ether, UDP, TCP
+
+if len(sys.argv) < 2:
+    print('usage: {} packets_count [fuzz]'.format(sys.argv[0]))
+    sys.exit(1)
+
+tmpl = []
+
+if len(sys.argv) == 2:
+    eth = Ether(dst='ff:ff:ff:ff:ff:ff')
+    vlan = eth / Dot1Q(vlan=1)
+    p = eth / IP() / TCP(sport=20, dport=80, flags='SA', window=8192)
+    tmpl += [p.build().hex()]
+    p = eth / IP() / UDP(sport=53, dport=53)
+    tmpl += [p.build().hex()]
+    p = eth / IP() / TCP(sport=20, dport=80, flags='S', window=8192)
+    tmpl += [p.build().hex()]
+    p = eth / IP() / UDP(sport=53, dport=53)
+    tmpl += [p.build().hex()]
+    p = vlan / IP() / UDP(sport=53, dport=53)
+    tmpl += [p.build().hex()]
+    p = vlan / IP() / TCP(sport=20, dport=80, flags='S', window=8192)
+    tmpl += [p.build().hex()]
+elif sys.argv[2] == 'fuzz':
+    # Generate random protocol bases, use a fuzz() over the combined packet
+    # for full fuzzing.
+    eth = Ether(src=RandMAC(), dst=RandMAC())
+    vlan = Dot1Q()
+    ipv4 = IP(src=RandIP(), dst=RandIP())
+    ipv6 = IPv6(src=RandIP6(), dst=RandIP6())
+    udp = UDP(dport=RandShort(), sport=RandShort())
+    tcp = TCP(dport=RandShort(), sport=RandShort())
+
+    # IPv4 packets with fuzzing
+    tmpl += [fuzz(eth / ipv4 / udp).build().hex()]
+    tmpl += [fuzz(eth / ipv4 / tcp).build().hex()]
+    tmpl += [fuzz(eth / vlan / ipv4 / udp).build().hex()]
+    tmpl += [fuzz(eth / vlan / ipv4 / tcp).build().hex()]
+
+    # IPv6 packets with fuzzing
+    tmpl += [fuzz(eth / ipv6 / udp).build().hex()]
+    tmpl += [fuzz(eth / ipv6 / tcp).build().hex()]
+    tmpl += [fuzz(eth / vlan / ipv6 / udp).build().hex()]
+    tmpl += [fuzz(eth / vlan / ipv6 / tcp).build().hex()]
+
+i = 0
+count = int(sys.argv[1])
+while count != 0:
+    print(tmpl[i % len(tmpl)])
+    i += 1
+    count -= 1
diff --git a/tests/mfex_fuzzy.py b/tests/mfex_fuzzy.py
deleted file mode 100755
index 3efe1152da..0000000000
--- a/tests/mfex_fuzzy.py
+++ /dev/null
@@ -1,32 +0,0 @@
-#!/usr/bin/python3
-
-import sys
-
-from scapy.all import RandMAC, RandIP, PcapWriter, RandIP6, RandShort, fuzz
-from scapy.all import IPv6, Dot1Q, IP, Ether, UDP, TCP
-
-path = str(sys.argv[1]) + "/pcap/fuzzy.pcap"
-pktdump = PcapWriter(path, append=False, sync=True)
-
-for i in range(0, 2000):
-
-    # Generate random protocol bases, use a fuzz() over the combined packet
-    # for full fuzzing.
-    eth = Ether(src=RandMAC(), dst=RandMAC())
-    vlan = Dot1Q()
-    ipv4 = IP(src=RandIP(), dst=RandIP())
-    ipv6 = IPv6(src=RandIP6(), dst=RandIP6())
-    udp = UDP(dport=RandShort(), sport=RandShort())
-    tcp = TCP(dport=RandShort(), sport=RandShort())
-
-    # IPv4 packets with fuzzing
-    pktdump.write(fuzz(eth / ipv4 / udp))
-    pktdump.write(fuzz(eth / ipv4 / tcp))
-    pktdump.write(fuzz(eth / vlan / ipv4 / udp))
-    pktdump.write(fuzz(eth / vlan / ipv4 / tcp))
-
-    # IPv6 packets with fuzzing
-    pktdump.write(fuzz(eth / ipv6 / udp))
-    pktdump.write(fuzz(eth / ipv6 / tcp))
-    pktdump.write(fuzz(eth / vlan / ipv6 / udp))
-    pktdump.write(fuzz(eth / vlan / ipv6 / tcp))
diff --git a/tests/pcap/mfex_test.pcap b/tests/pcap/mfex_test.pcap
deleted file mode 100644
index 1aac67b8d643ecb016c758cba4cc32212a80f52a..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 416
zcmca|c+)~A1{MYw`2U}Qff2}Q<eHVR>K`M68ITRa|G at yFii5$Gfk6YL%z>@uY&}o|
z2s4N<1VH2&7y^V87$)XGOtD~MV$cFgfG~zBGGJ2#YtF$<F=a4i;9x8Q*<ZrSM6Ufz
xK>KST_NTIwYriok6N4Vm)gX-Q@<yO<!C`>c^{cp<7_5LgK^UuU{2>VS0RZ!RQ+EIW

diff --git a/tests/system-dpdk-macros.at b/tests/system-dpdk-macros.at
index ef0e84e939..5a6b3cbff9 100644
--- a/tests/system-dpdk-macros.at
+++ b/tests/system-dpdk-macros.at
@@ -37,7 +37,7 @@ m4_define([OVS_DPDK_PRE_PHY_SKIP],
 #
 # Create an empty database and start ovsdb-server. Add special configuration
 # dpdk-init to enable DPDK functionality. Start ovs-vswitchd connected to that
-# database using system devices (no dummies).
+# database using system devices.
 #
 m4_define([OVS_DPDK_START],
   [dnl Create database.
@@ -62,7 +62,7 @@ m4_define([OVS_DPDK_START],
    AT_CHECK([ovs-vsctl --no-wait set Open_vSwitch . other_config:dpdk-extra=--log-level=pmd.*:error])
 
    dnl Start ovs-vswitchd.
-   AT_CHECK([ovs-vswitchd --detach --no-chdir --pidfile --log-file -vvconn -vofproto_dpif -vunixctl], [0], [stdout], [stderr])
+   AT_CHECK([ovs-vswitchd --enable-dummy --detach --no-chdir --pidfile --log-file -vvconn -vofproto_dpif -vunixctl], [0], [stdout], [stderr])
    AT_CAPTURE_FILE([ovs-vswitchd.log])
    on_exit "kill_ovs_vswitchd `cat ovs-vswitchd.pid`"
 ])
diff --git a/tests/system-dpdk.at b/tests/system-dpdk.at
index 9c8f4bb15a..73c58030b1 100644
--- a/tests/system-dpdk.at
+++ b/tests/system-dpdk.at
@@ -224,22 +224,29 @@ dnl --------------------------------------------------------------------------
 dnl Add standard DPDK PHY port
 AT_SETUP([OVS-DPDK - MFEX Autovalidator])
 AT_KEYWORDS([dpdk])
+AT_SKIP_IF([! $PYTHON3 -c "import scapy"], [], [])
 
 OVS_DPDK_START()
 
 dnl Add userspace bridge and attach it to OVS
 AT_CHECK([ovs-vsctl add-br br0 -- set bridge br0 datapath_type=netdev])
-AT_CHECK([ovs-vsctl add-port br0 p1 -- set Interface p1 type=dpdk options:dpdk-devargs=net_pcap1,rx_pcap=$srcdir/pcap/mfex_test.pcap,infinite_rx=1], [], [stdout], [stderr])
+AT_CHECK([ovs-vsctl add-port br0 p1 -- set interface p1 type=dummy-pmd])
 AT_CHECK([ovs-vsctl show], [], [stdout])
 
 AT_SKIP_IF([! ovs-appctl dpif-netdev/miniflow-parser-get | sed 1,4d | grep "True"], [], [dnl
 ])
 
+on_exit "pkill -f -x -9 '$PYTHON3 $srcdir/genpkts.py -1'"
+($PYTHON3 $srcdir/genpkts.py -1 | while read pkt; do
+     ovs-appctl netdev-dummy/receive p1 "$pkt" || break
+ done) &
+
 AT_CHECK([ovs-appctl dpif-netdev/miniflow-parser-set autovalidator], [0], [dnl
 Miniflow extract implementation set to autovalidator.
 ])
 
-OVS_WAIT_UNTIL([test `ovs-vsctl get interface p1 statistics | grep -oP 'rx_packets=\s*\K\d+'` -ge 1000])
+OVS_WAIT_UNTIL([test `ovs-vsctl get interface p1 statistics:rx_packets` -ge 1000])
+pkill -f -x -9 '$PYTHON3 $srcdir/genpkts.py -1'
 
 dnl Clean up
 AT_CHECK([ovs-vsctl del-port br0 p1], [], [stdout], [stderr])
@@ -252,22 +259,27 @@ dnl Add standard DPDK PHY port
 AT_SETUP([OVS-DPDK - MFEX Autovalidator Fuzzy])
 AT_KEYWORDS([dpdk])
 AT_SKIP_IF([! $PYTHON3 -c "import scapy"], [], [])
-AT_CHECK([$PYTHON3 $srcdir/mfex_fuzzy.py $srcdir], [], [stdout])
 OVS_DPDK_START()
 
 dnl Add userspace bridge and attach it to OVS
 AT_CHECK([ovs-vsctl add-br br0 -- set bridge br0 datapath_type=netdev])
-AT_CHECK([ovs-vsctl add-port br0 p1 -- set Interface p1 type=dpdk options:dpdk-devargs=net_pcap1,rx_pcap=$srcdir/pcap/fuzzy.pcap,infinite_rx=1], [], [stdout], [stderr])
+AT_CHECK([ovs-vsctl add-port br0 p1 -- set interface p1 type=dummy-pmd])
 AT_CHECK([ovs-vsctl show], [], [stdout])
 
 AT_SKIP_IF([! ovs-appctl dpif-netdev/miniflow-parser-get | sed 1,4d | grep "True"], [], [dnl
 ])
 
+on_exit "pkill -f -x -9 '$PYTHON3 $srcdir/genpkts.py -1 fuzz'"
+($PYTHON3 $srcdir/genpkts.py -1 fuzz | while read pkt; do
+     ovs-appctl netdev-dummy/receive p1 "$pkt" || break
+ done) &
+
 AT_CHECK([ovs-appctl dpif-netdev/miniflow-parser-set autovalidator], [0], [dnl
 Miniflow extract implementation set to autovalidator.
 ])
 
-OVS_WAIT_UNTIL([test `ovs-vsctl get interface p1 statistics | grep -oP 'rx_packets=\s*\K\d+'` -ge 100000])
+OVS_WAIT_UNTIL([test `ovs-vsctl get interface p1 statistics:rx_packets` -ge 1000])
+pkill -f -x -9 '$PYTHON3 $srcdir/genpkts.py -1 fuzz'
 
 dnl Clean up
 AT_CHECK([ovs-vsctl del-port br0 p1], [], [stdout], [stderr])
@@ -278,13 +290,20 @@ dnl --------------------------------------------------------------------------
 dnl --------------------------------------------------------------------------
 AT_SETUP([OVS-DPDK - MFEX Configuration])
 AT_KEYWORDS([dpdk])
+AT_SKIP_IF([! $PYTHON3 -c "import scapy"], [], [])
+
 OVS_DPDK_START()
 AT_CHECK([ovs-vsctl --no-wait set Open_vSwitch . other_config:pmd-cpu-mask=0xC])
 dnl Add userspace bridge and attach it to OVS
 AT_CHECK([ovs-vsctl add-br br0 -- set bridge br0 datapath_type=netdev])
-AT_CHECK([ovs-vsctl add-port br0 p1 -- set Interface p1 type=dpdk options:dpdk-devargs=net_pcap1,rx_pcap=$srcdir/pcap/mfex_test.pcap,infinite_rx=1], [], [stdout], [stderr])
+AT_CHECK([ovs-vsctl add-port br0 p1 -- set interface p1 type=dummy-pmd])
 AT_CHECK([ovs-vsctl show], [], [stdout])
 
+on_exit "pkill -f -x -9 '$PYTHON3 $srcdir/genpkts.py -1'"
+($PYTHON3 $srcdir/genpkts.py -1 | while read pkt; do
+     ovs-appctl netdev-dummy/receive p1 "$pkt" || break
+ done) &
+
 AT_CHECK([ovs-appctl dpif-netdev/miniflow-parser-set scalar 1], [2],
 [], [dnl
 Error: unknown argument 1.
@@ -377,6 +396,8 @@ Error: invalid study_pkt_cnt value: -pmd.
 ovs-appctl: ovs-vswitchd: server returned an error
 ])
 
+pkill -f -x -9 '$PYTHON3 $srcdir/genpkts.py -1'
+
 dnl Clean up
 AT_CHECK([ovs-vsctl del-port br0 p1], [], [stdout], [stderr])
 OVS_VSWITCHD_STOP("m4_join([], [SYSTEM_DPDK_ALLOWED_LOGS], [
-- 
2.23.0



More information about the dev mailing list