Page MenuHomeFreeBSD

D39431.1785232148.diff
No OneTemporary

Size
12 KB
Referenced Files
None
Subscribers
None

D39431.1785232148.diff

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

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)

Event Timeline