Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F148054383
D39431.1785232148.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Size
12 KB
Referenced Files
None
Subscribers
None
D39431.1785232148.diff
View Options
diff --git a/etc/mtree/BSD.tests.dist b/etc/mtree/BSD.tests.dist
--- a/etc/mtree/BSD.tests.dist
+++ b/etc/mtree/BSD.tests.dist
@@ -837,6 +837,8 @@
netlink
..
netmap
+ ifnet
+ ..
..
netpfil
common
diff --git a/tests/sys/netmap/Makefile b/tests/sys/netmap/Makefile
--- a/tests/sys/netmap/Makefile
+++ b/tests/sys/netmap/Makefile
@@ -12,4 +12,6 @@
LIBADD+= pthread
LIBADD+= netmap
+TESTS_SUBDIRS+= ifnet
+
.include <bsd.test.mk>
diff --git a/tests/sys/netmap/ifnet/Makefile b/tests/sys/netmap/ifnet/Makefile
new file mode 100644
--- /dev/null
+++ b/tests/sys/netmap/ifnet/Makefile
@@ -0,0 +1,10 @@
+PACKAGE= tests
+
+TESTSDIR= ${TESTSBASE}/sys/netmap/ifnet
+
+ATF_TESTS_SH= ifnet_test
+
+SUBDIR+= pkt-gen
+SUBDIR+= simplebridge
+
+.include <bsd.test.mk>
diff --git a/tests/sys/netmap/ifnet/ifnet_test.sh b/tests/sys/netmap/ifnet/ifnet_test.sh
new file mode 100644
--- /dev/null
+++ b/tests/sys/netmap/ifnet/ifnet_test.sh
@@ -0,0 +1,226 @@
+# SPDX-License-Identifier: BSD-2-Clause
+#
+# Copyright (c) 2023 Klara, Inc.
+
+#
+# Test basic netmap functionality with software interfaces.
+#
+# Two netmap applications are used: pkt-gen, and a simplified version of bridge
+# which reports the number of packets forwarded in each direction.
+#
+
+. $(atf_get_srcdir)/../../common/vnet.subr
+
+PKTGEN=$(atf_get_srcdir)/pkt-gen
+NMBRIDGE=$(atf_get_srcdir)/simplebridge
+BRIDGEPIDFILE=bridge.pid
+
+# Start a process that forwards packets between two interfaces in netmap mode.
+join_interfaces()
+{
+ local jail ifa ifb outf
+
+ jail=$1
+ ifa=$2
+ ifb=$3
+ outf=$4
+
+ jexec $jail $NMBRIDGE -i $ifa -i $ifb >$outf 2>&1 &
+ echo $! > $BRIDGEPIDFILE
+ sleep 1 # Let the netmap program initialize itself.
+}
+
+# Stop a bridge process previously started by join_interfaces().
+unjoin_interfaces()
+{
+ atf_check pkill -INT -F $BRIDGEPIDFILE
+ atf_check rm $BRIDGEPIDFILE
+}
+
+# Return the ethernet address of the specified interface.
+iface_etheraddr()
+{
+ local jail iface
+
+ jail=$1
+ iface=$2
+
+ jexec $jail ifconfig $iface ether | awk '/ether/{print $2}'
+}
+
+#
+# Verify that a netmap-enabled if_bridge interface can forward packets between
+# interfaces.
+#
+atf_test_case "bridge_l2_forwarding" "cleanup"
+bridge_l2_forwarding_head()
+{
+ atf_set descr 'Make sure that L2 forwarding works in netmap mode'
+ atf_set require.user root
+}
+bridge_l2_forwarding_body()
+{
+ vnet_init
+
+ epair_left=$(vnet_mkepair)
+ epair_right=$(vnet_mkepair)
+ bridge=$(vnet_mkbridge)
+
+ vnet_mkjail bridge ${bridge} ${epair_left}b ${epair_right}b
+ vnet_mkjail left ${epair_left}a
+ vnet_mkjail right ${epair_right}a
+
+ jexec bridge ifconfig ${epair_left}b up
+ jexec bridge ifconfig ${epair_right}b up
+ jexec bridge ifconfig ${bridge} up addm ${epair_left}b addm ${epair_right}b
+
+ jexec left ifconfig ${epair_left}a inet 169.254.0.1/16
+ jexec right ifconfig ${epair_right}a inet 169.254.0.2/16
+
+ # Let the endpoints communicate without needing to ARP.
+ macleft=$(iface_etheraddr left ${epair_left}a)
+ jexec right arp -s 169.254.0.1 $macleft
+ macright=$(iface_etheraddr right ${epair_right}a)
+ jexec left arp -s 169.254.0.2 $macright
+
+ join_interfaces bridge netmap:${bridge} netmap:${bridge}^ pktcount
+
+ # Send five pings from each end to the other.
+ atf_check -o ignore jexec left ping -i 0.2 -t 3 -c 5 169.254.0.2
+ atf_check -o ignore jexec right ping -i 0.2 -t 3 -c 5 169.254.0.1
+
+ unjoin_interfaces
+
+ # The pings above should generate 10 echo requests and 10 echo replies,
+ # so we should have 20 packets arrive on the bridge, and we don't expect
+ # to see any packets transmitted from the bridge host.
+ atf_check -o match:"[[:space:]]1 pktcount" wc -l pktcount
+ atf_check -o inline:'20 0\n' cat pktcount
+}
+bridge_l2_forwarding_cleanup()
+{
+ vnet_cleanup
+}
+
+#
+# Verify that a netmap-enabled if_bridge interface can receive packets locally.
+#
+atf_test_case "bridge_l3" "cleanup"
+bridge_l3_head()
+{
+ atf_set descr 'Test that a bridge interface can receive packets locally in netmap mode'
+ atf_set require.user root
+}
+bridge_l3_body()
+{
+ vnet_init
+
+ epair=$(vnet_mkepair)
+ bridge=$(vnet_mkbridge)
+
+ vnet_mkjail bridge ${bridge} ${epair}b
+ vnet_mkjail host ${epair}a
+
+ jexec bridge ifconfig ${epair}b up
+ jexec bridge ifconfig ${bridge} up addm ${epair}b
+ jexec bridge ifconfig ${bridge} inet 169.254.0.2/16
+
+ jexec host ifconfig ${epair}a inet 169.254.0.1/16
+
+ machost=$(iface_etheraddr host ${epair}a)
+ jexec bridge arp -s 169.254.0.1 $machost
+ macbridge=$(iface_etheraddr bridge ${bridge})
+ jexec host arp -s 169.254.0.2 $macbridge
+
+ join_interfaces bridge netmap:${bridge} netmap:${bridge}^ pktcount
+
+ # Send five pings from each end to the other.
+ atf_check -o ignore jexec host ping -i 0.2 -t 3 -c 5 169.254.0.2
+ atf_check -o ignore jexec bridge ping -i 0.2 -t 3 -c 5 169.254.0.1
+
+ unjoin_interfaces
+
+ # The pings above should generate 10 echo requests and 10 echo replies.
+ # We should see 10 packets arrive on the bridge, and 10 packets sent via
+ # the bridge.
+ atf_check -o match:"[[:space:]]1 pktcount" wc -l pktcount
+ atf_check -o inline:'10 10\n' cat pktcount
+}
+bridge_l3_cleanup()
+{
+ vnet_cleanup
+}
+
+#
+# Use netmap to transfer packets over an epair.
+#
+atf_test_case "epair_simple" "cleanup"
+epair_simple_head()
+{
+ atf_set descr 'Test epair interfaces can be used in netmap mode'
+ atf_set require.user root
+ atf_set timeout 10
+}
+epair_simple_body()
+{
+ vnet_init
+
+ epair=$(vnet_mkepair)
+
+ ifconfig ${epair}a up
+ ifconfig ${epair}b up
+
+ $PKTGEN -i netmap:${epair}a -f rx -n 100000 &
+ sleep 1 # Give pkt-gen a chance to start.
+
+ atf_check -o ignore -e ignore $PKTGEN -i netmap:${epair}b -f tx -n 100000
+
+ wait
+}
+epair_simple_cleanup()
+{
+ vnet_cleanup
+}
+
+#
+# Verify that pkt-gen can transfer packets over a vlan.
+#
+atf_test_case "vlan_simple" "cleanup"
+vlan_simple_head()
+{
+ atf_set descr 'Test that vlan interfaces can be used in netmap mode'
+ atf_set require.user root
+}
+vlan_simple_body()
+{
+ vnet_init
+
+ epair=$(vnet_mkepair)
+ vlana=$(vnet_mkvlan)
+ vlanb=$(vnet_mkvlan)
+
+ ifconfig ${epair}a up
+ ifconfig ${vlana} up vlan 42 vlandev ${epair}a
+
+ ifconfig ${epair}b up
+ ifconfig ${vlanb} up vlan 42 vlandev ${epair}b
+
+ $PKTGEN -i netmap:${vlana} -f rx -n 100000 &
+ sleep 1 # Give pkt-gen a chance to start.
+
+ atf_check -o ignore -e ignore $PKTGEN -i netmap:${vlanb} -f tx -n 100000
+
+ wait
+}
+vlan_simple_cleanup()
+{
+ vnet_cleanup
+}
+
+atf_init_test_cases()
+{
+ atf_add_test_case bridge_l2_forwarding
+ atf_add_test_case bridge_l3
+ atf_add_test_case epair_simple
+ atf_add_test_case vlan_simple
+}
diff --git a/tests/sys/netmap/ifnet/pkt-gen/Makefile b/tests/sys/netmap/ifnet/pkt-gen/Makefile
new file mode 100644
--- /dev/null
+++ b/tests/sys/netmap/ifnet/pkt-gen/Makefile
@@ -0,0 +1,13 @@
+.PATH: ${SRCTOP}/tools/tools/netmap
+
+BINDIR= ${TESTSBASE}/sys/netmap/ifnet
+
+PROG= pkt-gen
+
+CFLAGS+= -DNO_PCAP
+LIBADD= netmap pthread
+WARNS?= 3
+
+MK_MAN= no
+
+.include <bsd.prog.mk>
diff --git a/tests/sys/netmap/ifnet/simplebridge/Makefile b/tests/sys/netmap/ifnet/simplebridge/Makefile
new file mode 100644
--- /dev/null
+++ b/tests/sys/netmap/ifnet/simplebridge/Makefile
@@ -0,0 +1,7 @@
+BINDIR= ${TESTSBASE}/sys/netmap/ifnet
+
+PROG= simplebridge
+LIBADD= netmap
+MK_MAN= no
+
+.include <bsd.prog.mk>
diff --git a/tests/sys/netmap/ifnet/simplebridge/simplebridge.c b/tests/sys/netmap/ifnet/simplebridge/simplebridge.c
new file mode 100644
--- /dev/null
+++ b/tests/sys/netmap/ifnet/simplebridge/simplebridge.c
@@ -0,0 +1,215 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (C) 2011-2014 Luigi Rizzo, Matteo Landi
+ *
+ * A trimmed-down version of tools/tools/netmap/bridge.c which prints the number
+ * of packets sent in each direction before exiting.
+ */
+
+#include <sys/ioctl.h>
+#include <sys/poll.h>
+
+#include <assert.h>
+#include <err.h>
+#include <errno.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <libnetmap.h>
+
+static int do_abort = 0;
+
+static void
+sigint_h(int sig __unused)
+{
+ do_abort = 1;
+ signal(SIGINT, SIG_DFL);
+}
+
+/*
+ * How many slots do we (user application) have on this
+ * set of queues ?
+ */
+static int
+rx_slots_avail(struct nmport_d *d)
+{
+ u_int i, tot = 0;
+
+ for (i = d->first_rx_ring; i <= d->last_rx_ring; i++) {
+ tot += nm_ring_space(NETMAP_RXRING(d->nifp, i));
+ }
+
+ return tot;
+}
+
+/*
+ * Move up to 'limit' pkts from rxring to txring, swapping buffers
+ * if zerocopy is possible. Otherwise fall back on packet copying.
+ */
+static int
+rings_move(struct netmap_ring *rxring, struct netmap_ring *txring, u_int limit)
+{
+ u_int j, k, m = 0;
+
+ assert(rxring->flags == 0);
+ assert(txring->flags == 0);
+
+ j = rxring->head;
+ k = txring->head;
+ m = nm_ring_space(rxring);
+ if (m < limit)
+ limit = m;
+ m = nm_ring_space(txring);
+ if (m < limit)
+ limit = m;
+ m = limit;
+ while (limit-- > 0) {
+ struct netmap_slot *rs = &rxring->slot[j];
+ struct netmap_slot *ts = &txring->slot[k];
+ uint32_t pkt;
+
+ ts->len = rs->len;
+ pkt = ts->buf_idx;
+ ts->buf_idx = rs->buf_idx;
+ rs->buf_idx = pkt;
+ /* report the buffer change. */
+ ts->flags |= NS_BUF_CHANGED;
+ rs->flags |= NS_BUF_CHANGED;
+
+ /*
+ * Copy the NS_MOREFRAG from rs to ts, leaving any
+ * other flags unchanged.
+ */
+ ts->flags = (ts->flags & ~NS_MOREFRAG) | (rs->flags & NS_MOREFRAG);
+ j = nm_ring_next(rxring, j);
+ k = nm_ring_next(txring, k);
+ }
+ rxring->head = rxring->cur = j;
+ txring->head = txring->cur = k;
+
+ return (m);
+}
+
+/* Move packets from source port to destination port. */
+static int
+ports_move(struct nmport_d *src, struct nmport_d *dst, u_int limit)
+{
+ struct netmap_ring *txring, *rxring;
+ u_int m = 0, si = src->first_rx_ring, di = dst->first_tx_ring;
+
+ while (si <= src->last_rx_ring && di <= dst->last_tx_ring) {
+ rxring = NETMAP_RXRING(src->nifp, si);
+ txring = NETMAP_TXRING(dst->nifp, di);
+ if (nm_ring_empty(rxring)) {
+ si++;
+ continue;
+ }
+ if (nm_ring_empty(txring)) {
+ di++;
+ continue;
+ }
+ m += rings_move(rxring, txring, limit);
+ }
+
+ return (m);
+}
+
+static void
+usage(void)
+{
+ fprintf(stderr, "usage: %s [-h] -i <iface1> -i <iface2>\n",
+ getprogname());
+ exit(1);
+}
+
+int
+main(int argc, char **argv)
+{
+ struct pollfd pollfd[2];
+ struct nmport_d *pa = NULL, *pb = NULL;
+ char *ifa = NULL, *ifb = NULL;
+ uint64_t atob, btoa;
+ int ch;
+
+ while ((ch = getopt(argc, argv, "hi:")) != -1) {
+ switch (ch) {
+ default:
+ case 'h':
+ usage();
+ break;
+ case 'i':
+ if (ifa == NULL)
+ ifa = optarg;
+ else if (ifb == NULL)
+ ifb = optarg;
+ else
+ D("%s ignored, already have 2 interfaces",
+ optarg);
+ break;
+ }
+
+ }
+ argc -= optind;
+ argv += optind;
+
+ if (argc != 0 || ifa == NULL || ifb == NULL)
+ usage();
+ if (strcmp(ifa, ifb) == 0)
+ errx(1, "specific interfaces must be distinct");
+
+ pa = nmport_open(ifa);
+ if (pa == NULL)
+ errx(1, "cannot open %s", ifa);
+ pb = nmport_open(ifb);
+ if (pb == NULL)
+ errx(1, "cannot open %s", ifa);
+
+ memset(pollfd, 0, sizeof(pollfd));
+ pollfd[0].fd = pa->fd;
+ pollfd[1].fd = pb->fd;
+
+ signal(SIGINT, sigint_h);
+
+ atob = btoa = 0;
+ while (!do_abort) {
+ int n0, n1, ret;
+
+ pollfd[0].events = pollfd[1].events = 0;
+ pollfd[0].revents = pollfd[1].revents = 0;
+
+ n0 = rx_slots_avail(pa);
+ n1 = rx_slots_avail(pb);
+ if (n0)
+ pollfd[1].events |= POLLOUT;
+ else
+ pollfd[0].events |= POLLIN;
+ if (n1)
+ pollfd[0].events |= POLLOUT;
+ else
+ pollfd[1].events |= POLLIN;
+
+ ret = poll(pollfd, 2, -1);
+ if (ret < 0) {
+ if (errno == EINTR)
+ break;
+ err(1, "poll");
+ }
+ if (pollfd[0].revents & POLLERR)
+ errx(1, "poll error on iface1");
+ if (pollfd[1].revents & POLLERR)
+ errx(1, "poll error on iface2");
+ if (pollfd[0].revents & POLLOUT)
+ btoa += ports_move(pb, pa, 128);
+ if (pollfd[1].revents & POLLOUT)
+ atob += ports_move(pa, pb, 128);
+ }
+ nmport_close(pb);
+ nmport_close(pa);
+
+ printf("%ju %ju\n", (uintmax_t)atob, (uintmax_t)btoa);
+
+ return (0);
+}
diff --git a/tests/sys/netmap/ifnet/tools/Makefile b/tests/sys/netmap/ifnet/tools/Makefile
new file mode 100644
--- /dev/null
+++ b/tests/sys/netmap/ifnet/tools/Makefile
@@ -0,0 +1,8 @@
+PROGS= bridge
+
+BINDIR= ${TESTSBASE}/sys/netmap/if_bridge/tools
+MK_MAN= no
+LIBADD.bridge= netmap
+WARNS= 6
+
+.include <bsd.test.mk>
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Tue, Jul 28, 9:49 AM (11 h, 39 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
29289413
Default Alt Text
D39431.1785232148.diff (12 KB)
Attached To
Mode
D39431: netmap: Add some simple regression tests
Attached
Detach File
Event Timeline
Log In to Comment