Skip to content

Commit cc30c93

Browse files
wdebruijdavem330
authored andcommitted
selftests/net: ignore background traffic in psock_fanout
The packet fanout test generates UDP traffic and reads this with a pair of packet sockets, testing the various fanout algorithms. Avoid non-determinism from reading unrelated background traffic. Fanout decisions are made before unrelated packets can be dropped with a filter, so that is an insufficient strategy [*]. Run the packet socket tests in a network namespace, similar to msg_zerocopy. It it still good practice to install a filter on a packet socket before accepting traffic. Because this is example code, demonstrate that pattern. Open the socket initially bound to no protocol, install a filter, and only then bind to ETH_P_IP. Another source of non-determinism is hash collisions in FANOUT_HASH. The hash function used to select a socket in the fanout group includes the pseudorandom number hashrnd, which is not visible from userspace. To work around this, the test tries to find a pair of UDP source ports that do not collide. It gives up too soon (5 times, every 32 runs) and output is confusing. Increase tries to 20 and revise the error msg. [*] another approach would be to add a third socket to the fanout group and direct all unexpected traffic here. This is possible only when reimplementing methods like RR or HASH alongside this extra catch-all bucket, using the BPF fanout method. Signed-off-by: Willem de Bruijn <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 3c69f79 commit cc30c93

File tree

3 files changed

+51
-8
lines changed

3 files changed

+51
-8
lines changed
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
#!/bin/sh
2+
# SPDX-License-Identifier: GPL-2.0
3+
#
4+
# Execute a subprocess in a network namespace
5+
6+
set -e
7+
8+
readonly NETNS="ns-$(mktemp -u XXXXXX)"
9+
10+
setup() {
11+
ip netns add "${NETNS}"
12+
ip -netns "${NETNS}" link set lo up
13+
}
14+
15+
cleanup() {
16+
ip netns del "${NETNS}"
17+
}
18+
19+
trap cleanup EXIT
20+
setup
21+
22+
"$@"
23+
exit "$?"

tools/testing/selftests/net/psock_fanout.c

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@
5050
#include <linux/filter.h>
5151
#include <linux/bpf.h>
5252
#include <linux/if_packet.h>
53+
#include <net/if.h>
5354
#include <net/ethernet.h>
5455
#include <netinet/ip.h>
5556
#include <netinet/udp.h>
@@ -73,14 +74,29 @@
7374
* @return -1 if mode is bad, a valid socket otherwise */
7475
static int sock_fanout_open(uint16_t typeflags, uint16_t group_id)
7576
{
77+
struct sockaddr_ll addr = {0};
7678
int fd, val;
7779

78-
fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_IP));
80+
fd = socket(PF_PACKET, SOCK_RAW, 0);
7981
if (fd < 0) {
8082
perror("socket packet");
8183
exit(1);
8284
}
8385

86+
pair_udp_setfilter(fd);
87+
88+
addr.sll_family = AF_PACKET;
89+
addr.sll_protocol = htons(ETH_P_IP);
90+
addr.sll_ifindex = if_nametoindex("lo");
91+
if (addr.sll_ifindex == 0) {
92+
perror("if_nametoindex");
93+
exit(1);
94+
}
95+
if (bind(fd, (void *) &addr, sizeof(addr))) {
96+
perror("bind packet");
97+
exit(1);
98+
}
99+
84100
val = (((int) typeflags) << 16) | group_id;
85101
if (setsockopt(fd, SOL_PACKET, PACKET_FANOUT, &val, sizeof(val))) {
86102
if (close(fd)) {
@@ -90,7 +106,6 @@ static int sock_fanout_open(uint16_t typeflags, uint16_t group_id)
90106
return -1;
91107
}
92108

93-
pair_udp_setfilter(fd);
94109
return fd;
95110
}
96111

@@ -229,7 +244,7 @@ static int sock_fanout_read(int fds[], char *rings[], const int expect[])
229244

230245
if ((!(ret[0] == expect[0] && ret[1] == expect[1])) &&
231246
(!(ret[0] == expect[1] && ret[1] == expect[0]))) {
232-
fprintf(stderr, "ERROR: incorrect queue lengths\n");
247+
fprintf(stderr, "warning: incorrect queue lengths\n");
233248
return 1;
234249
}
235250

@@ -348,7 +363,8 @@ static int test_datapath(uint16_t typeflags, int port_off,
348363
uint8_t type = typeflags & 0xFF;
349364
int fds[2], fds_udp[2][2], ret;
350365

351-
fprintf(stderr, "test: datapath 0x%hx\n", typeflags);
366+
fprintf(stderr, "\ntest: datapath 0x%hx ports %hu,%hu\n",
367+
typeflags, PORT_BASE, PORT_BASE + port_off);
352368

353369
fds[0] = sock_fanout_open(typeflags, 0);
354370
fds[1] = sock_fanout_open(typeflags, 0);
@@ -419,7 +435,7 @@ int main(int argc, char **argv)
419435
const int expect_cpu1[2][2] = { { 0, 20 }, { 0, 20 } };
420436
const int expect_bpf[2][2] = { { 15, 5 }, { 15, 20 } };
421437
const int expect_uniqueid[2][2] = { { 20, 20}, { 20, 20 } };
422-
int port_off = 2, tries = 5, ret;
438+
int port_off = 2, tries = 20, ret;
423439

424440
test_control_single();
425441
test_control_group();
@@ -428,10 +444,14 @@ int main(int argc, char **argv)
428444
/* find a set of ports that do not collide onto the same socket */
429445
ret = test_datapath(PACKET_FANOUT_HASH, port_off,
430446
expect_hash[0], expect_hash[1]);
431-
while (ret && tries--) {
447+
while (ret) {
432448
fprintf(stderr, "info: trying alternate ports (%d)\n", tries);
433449
ret = test_datapath(PACKET_FANOUT_HASH, ++port_off,
434450
expect_hash[0], expect_hash[1]);
451+
if (!--tries) {
452+
fprintf(stderr, "too many collisions\n");
453+
return 1;
454+
}
435455
}
436456

437457
ret |= test_datapath(PACKET_FANOUT_HASH | PACKET_FANOUT_FLAG_ROLLOVER,

tools/testing/selftests/net/run_afpackettests

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ fi
99
echo "--------------------"
1010
echo "running psock_fanout test"
1111
echo "--------------------"
12-
./psock_fanout
12+
./in_netns.sh ./psock_fanout
1313
if [ $? -ne 0 ]; then
1414
echo "[FAIL]"
1515
else
@@ -19,7 +19,7 @@ fi
1919
echo "--------------------"
2020
echo "running psock_tpacket test"
2121
echo "--------------------"
22-
./psock_tpacket
22+
./in_netns.sh ./psock_tpacket
2323
if [ $? -ne 0 ]; then
2424
echo "[FAIL]"
2525
else

0 commit comments

Comments
 (0)