mirror of
https://github.com/torvalds/linux.git
synced 2026-11-07 06:17:02 +01:00
selftests: net: csum: filter packets by source address and port
Add source address and port verification in recv_verify_packet_* and
recv_udp: non-matching packets are skipped.
The receiver reads from PF_PACKET and UDP sockets to verify incoming
packets to test hardware checksum offload. It did not validate the
packet source address or source port.
During tests expecting an invalid checksum (-E) or zero checksum (-Z),
background packets can fail the test.
For -Z, build_packet_udp chooses a specific source port that causes
the checksum to sum to zero. When running in receive-only mode (-R),
call build_packet in do_rx to compute the expected source port so
that source port filtering can be applied to -Z as well.
Also
- add an inter-packet delay to avoid drops from bursts.
- remove a comment that is no longer correct.
Fixes: 91a7de8560 ("selftests/net: add csum offload test")
Signed-off-by: Willem de Bruijn <willemb@google.com>
Reviewed-by: Simon Horman <horms@kernel.org>
Link: https://patch.msgid.link/20260908155537.813889-1-willemdebruijn.kernel@gmail.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
parent
548b86839f
commit
8342c68435
|
|
@ -2,8 +2,7 @@
|
|||
|
||||
/* Test hardware checksum offload: Rx + Tx, IPv4 + IPv6, TCP + UDP.
|
||||
*
|
||||
* The test runs on two machines to exercise the NIC. For this reason it
|
||||
* is not integrated in kselftests.
|
||||
* The test runs on two machines to exercise the NIC.
|
||||
*
|
||||
* CMD=$((./csum -[46] -[tu] -S $SADDR -D $DADDR -[RT] -r 1 $EXTRA_ARGS))
|
||||
*
|
||||
|
|
@ -236,7 +235,8 @@ static void *build_packet_udp(void *_uh)
|
|||
uh->source = 0;
|
||||
uh->source = checksum(uh, IPPROTO_UDP, sizeof(*uh) + cfg_payload_len);
|
||||
|
||||
fprintf(stderr, "tx: changing sport: %hu -> %hu\n",
|
||||
fprintf(stderr, "%s: changing sport: %hu -> %hu\n",
|
||||
cfg_do_tx ? "tx" : "rx",
|
||||
cfg_port_src, ntohs(uh->source));
|
||||
cfg_port_src = ntohs(uh->source);
|
||||
}
|
||||
|
|
@ -249,7 +249,8 @@ static void *build_packet_udp(void *_uh)
|
|||
if (cfg_bad_csum)
|
||||
uh->check = ~uh->check;
|
||||
|
||||
fprintf(stderr, "tx: sending checksum: 0x%x\n", uh->check);
|
||||
if (cfg_do_tx)
|
||||
fprintf(stderr, "tx: sending checksum: 0x%x\n", uh->check);
|
||||
return uh + 1;
|
||||
}
|
||||
|
||||
|
|
@ -571,15 +572,36 @@ static int recv_prepare_packet(void)
|
|||
static int recv_udp(int fd)
|
||||
{
|
||||
static char buf[MAX_PAYLOAD_LEN];
|
||||
struct sockaddr_storage addr;
|
||||
socklen_t addrlen;
|
||||
int ret, count = 0;
|
||||
|
||||
while (1) {
|
||||
ret = recv(fd, buf, sizeof(buf), MSG_DONTWAIT);
|
||||
addrlen = sizeof(addr);
|
||||
ret = recvfrom(fd, buf, sizeof(buf), MSG_DONTWAIT,
|
||||
(struct sockaddr *)&addr, &addrlen);
|
||||
if (ret == -1 && errno == EAGAIN)
|
||||
break;
|
||||
if (ret == -1)
|
||||
error(1, errno, "recv r");
|
||||
|
||||
if (cfg_family == PF_INET) {
|
||||
struct sockaddr_in *sin = (void *)&addr;
|
||||
|
||||
if (sin->sin_addr.s_addr != cfg_saddr4.sin_addr.s_addr)
|
||||
continue;
|
||||
if (sin->sin_port != htons(cfg_port_src))
|
||||
continue;
|
||||
} else {
|
||||
struct sockaddr_in6 *sin6 = (void *)&addr;
|
||||
|
||||
if (memcmp(&sin6->sin6_addr, &cfg_saddr6.sin6_addr,
|
||||
sizeof(sin6->sin6_addr)))
|
||||
continue;
|
||||
if (sin6->sin6_port != htons(cfg_port_src))
|
||||
continue;
|
||||
}
|
||||
|
||||
fprintf(stderr, "rx: udp: len=%u\n", ret);
|
||||
count++;
|
||||
}
|
||||
|
|
@ -620,6 +642,9 @@ static int recv_verify_packet_tcp(void *th, int len)
|
|||
if (len < sizeof(*tcph) || tcph->dest != htons(cfg_port_dst))
|
||||
return -1;
|
||||
|
||||
if (tcph->source != htons(cfg_port_src))
|
||||
return -1;
|
||||
|
||||
return recv_verify_csum(th, len, ntohs(tcph->source), tcph->check);
|
||||
}
|
||||
|
||||
|
|
@ -647,6 +672,9 @@ static int recv_verify_packet_udp(void *th, int len)
|
|||
return recv_verify_packet_udp_encap(udph + 1,
|
||||
len - sizeof(*udph));
|
||||
|
||||
if (udph->source != htons(cfg_port_src))
|
||||
return -1;
|
||||
|
||||
return recv_verify_csum(th, len, ntohs(udph->source), udph->check);
|
||||
}
|
||||
|
||||
|
|
@ -659,6 +687,9 @@ static int recv_verify_packet_ipv4(void *nh, int len)
|
|||
if (len < sizeof(*iph) || iph->protocol != proto)
|
||||
return -1;
|
||||
|
||||
if (iph->saddr != cfg_saddr4.sin_addr.s_addr)
|
||||
return -1;
|
||||
|
||||
ip_len = ntohs(iph->tot_len);
|
||||
if (ip_len > len || ip_len < sizeof(*iph))
|
||||
return -1;
|
||||
|
|
@ -680,6 +711,9 @@ static int recv_verify_packet_ipv6(void *nh, int len)
|
|||
if (len < sizeof(*ip6h) || ip6h->nexthdr != proto)
|
||||
return -1;
|
||||
|
||||
if (memcmp(&ip6h->saddr, &cfg_saddr6.sin6_addr, sizeof(ip6h->saddr)))
|
||||
return -1;
|
||||
|
||||
payload_len = ntohs(ip6h->payload_len);
|
||||
if (payload_len > len - sizeof(*ip6h))
|
||||
return -1;
|
||||
|
|
@ -940,6 +974,9 @@ static void do_tx(void)
|
|||
cfg_payload_len = rand() % MAX_PAYLOAD_LEN;
|
||||
buf = build_packet(_buf, sizeof(_buf), &len);
|
||||
}
|
||||
|
||||
/* avoid bursting */
|
||||
usleep(20);
|
||||
}
|
||||
|
||||
if (close(fd))
|
||||
|
|
@ -952,6 +989,14 @@ static void do_rx(int fdp, int fdr)
|
|||
long tleft, tstop;
|
||||
struct pollfd pfd;
|
||||
|
||||
if (!cfg_do_tx && cfg_zero_sum) {
|
||||
static char _buf[MAX_HEADER_LEN + MAX_PAYLOAD_LEN];
|
||||
int len;
|
||||
|
||||
/* calculate source port that causes csum to add up to zero */
|
||||
build_packet(_buf, sizeof(_buf), &len);
|
||||
}
|
||||
|
||||
tstop = gettimeofday_ms() + cfg_timeout_ms;
|
||||
tleft = cfg_timeout_ms;
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user