Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

selftests/bpf: Add AF_INET packet generation to xdp_metadata

The easiest way to simulate stripped VLAN tag in veth is to send a packet
from VLAN interface, attached to veth. Unfortunately, this approach is
incompatible with AF_XDP on TX side, because VLAN interfaces do not have
such feature.

Check both packets sent via AF_XDP TX and regular socket.

AF_INET packet will also have a filled-in hash type (XDP_RSS_TYPE_L4),
unlike AF_XDP packet, so more values can be checked.

Signed-off-by: Larysa Zaremba <larysa.zaremba@intel.com>
Acked-by: Stanislav Fomichev <sdf@google.com>
Link: https://lore.kernel.org/r/20231205210847.28460-18-larysa.zaremba@intel.com
Signed-off-by: Alexei Starovoitov <ast@kernel.org>

authored by

Larysa Zaremba and committed by
Alexei Starovoitov
a3850af4 8e68a4be

+97 -19
+97 -19
tools/testing/selftests/bpf/prog_tests/xdp_metadata.c
··· 20 20 21 21 #define UDP_PAYLOAD_BYTES 4 22 22 23 - #define AF_XDP_SOURCE_PORT 1234 23 + #define UDP_SOURCE_PORT 1234 24 24 #define AF_XDP_CONSUMER_PORT 8080 25 25 26 26 #define UMEM_NUM 16 ··· 33 33 #define RX_ADDR "10.0.0.2" 34 34 #define PREFIX_LEN "8" 35 35 #define FAMILY AF_INET 36 + #define TX_NETNS_NAME "xdp_metadata_tx" 37 + #define RX_NETNS_NAME "xdp_metadata_rx" 38 + #define TX_MAC "00:00:00:00:00:01" 39 + #define RX_MAC "00:00:00:00:00:02" 40 + 41 + #define XDP_RSS_TYPE_L4 BIT(3) 36 42 37 43 struct xsk { 38 44 void *umem_area; ··· 187 181 ASSERT_EQ(inet_pton(FAMILY, RX_ADDR, &iph->daddr), 1, "inet_pton(RX_ADDR)"); 188 182 ip_csum(iph); 189 183 190 - udph->source = htons(AF_XDP_SOURCE_PORT); 184 + udph->source = htons(UDP_SOURCE_PORT); 191 185 udph->dest = htons(dst_port); 192 186 udph->len = htons(sizeof(*udph) + UDP_PAYLOAD_BYTES); 193 187 udph->check = ~csum_tcpudp_magic(iph->saddr, iph->daddr, ··· 208 202 return ret; 209 203 210 204 return 0; 205 + } 206 + 207 + static int generate_packet_inet(void) 208 + { 209 + char udp_payload[UDP_PAYLOAD_BYTES]; 210 + struct sockaddr_in rx_addr; 211 + int sock_fd, err = 0; 212 + 213 + /* Build a packet */ 214 + memset(udp_payload, 0xAA, UDP_PAYLOAD_BYTES); 215 + rx_addr.sin_addr.s_addr = inet_addr(RX_ADDR); 216 + rx_addr.sin_family = AF_INET; 217 + rx_addr.sin_port = htons(AF_XDP_CONSUMER_PORT); 218 + 219 + sock_fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); 220 + if (!ASSERT_GE(sock_fd, 0, "socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)")) 221 + return sock_fd; 222 + 223 + err = sendto(sock_fd, udp_payload, UDP_PAYLOAD_BYTES, MSG_DONTWAIT, 224 + (void *)&rx_addr, sizeof(rx_addr)); 225 + ASSERT_GE(err, 0, "sendto"); 226 + 227 + close(sock_fd); 228 + return err; 211 229 } 212 230 213 231 static void complete_tx(struct xsk *xsk) ··· 266 236 } 267 237 } 268 238 269 - static int verify_xsk_metadata(struct xsk *xsk) 239 + static int verify_xsk_metadata(struct xsk *xsk, bool sent_from_af_xdp) 270 240 { 271 241 const struct xdp_desc *rx_desc; 272 242 struct pollfd fds = {}; ··· 320 290 if (!ASSERT_NEQ(meta->rx_hash, 0, "rx_hash")) 321 291 return -1; 322 292 293 + if (!sent_from_af_xdp) { 294 + if (!ASSERT_NEQ(meta->rx_hash_type & XDP_RSS_TYPE_L4, 0, "rx_hash_type")) 295 + return -1; 296 + goto done; 297 + } 298 + 323 299 ASSERT_EQ(meta->rx_hash_type, 0, "rx_hash_type"); 324 300 325 301 /* checksum offload */ 326 302 ASSERT_EQ(udph->check, htons(0x721c), "csum"); 327 303 304 + done: 328 305 xsk_ring_cons__release(&xsk->rx, 1); 329 306 refill_rx(xsk, comp_addr); 330 307 331 308 return 0; 309 + } 310 + 311 + static void switch_ns_to_rx(struct nstoken **tok) 312 + { 313 + close_netns(*tok); 314 + *tok = open_netns(RX_NETNS_NAME); 315 + } 316 + 317 + static void switch_ns_to_tx(struct nstoken **tok) 318 + { 319 + close_netns(*tok); 320 + *tok = open_netns(TX_NETNS_NAME); 332 321 } 333 322 334 323 void test_xdp_metadata(void) ··· 367 318 int sock_fd; 368 319 int ret; 369 320 370 - /* Setup new networking namespace, with a veth pair. */ 321 + /* Setup new networking namespaces, with a veth pair. */ 322 + SYS(out, "ip netns add " TX_NETNS_NAME); 323 + SYS(out, "ip netns add " RX_NETNS_NAME); 371 324 372 - SYS(out, "ip netns add xdp_metadata"); 373 - tok = open_netns("xdp_metadata"); 325 + tok = open_netns(TX_NETNS_NAME); 374 326 SYS(out, "ip link add numtxqueues 1 numrxqueues 1 " TX_NAME 375 327 " type veth peer " RX_NAME " numtxqueues 1 numrxqueues 1"); 376 - SYS(out, "ip link set dev " TX_NAME " address 00:00:00:00:00:01"); 377 - SYS(out, "ip link set dev " RX_NAME " address 00:00:00:00:00:02"); 328 + SYS(out, "ip link set " RX_NAME " netns " RX_NETNS_NAME); 329 + 330 + SYS(out, "ip link set dev " TX_NAME " address " TX_MAC); 378 331 SYS(out, "ip link set dev " TX_NAME " up"); 379 - SYS(out, "ip link set dev " RX_NAME " up"); 380 332 SYS(out, "ip addr add " TX_ADDR "/" PREFIX_LEN " dev " TX_NAME); 333 + 334 + /* Avoid ARP calls */ 335 + SYS(out, "ip -4 neigh add " RX_ADDR " lladdr " RX_MAC " dev " TX_NAME); 336 + 337 + switch_ns_to_rx(&tok); 338 + 339 + SYS(out, "ip link set dev " RX_NAME " address " RX_MAC); 340 + SYS(out, "ip link set dev " RX_NAME " up"); 381 341 SYS(out, "ip addr add " RX_ADDR "/" PREFIX_LEN " dev " RX_NAME); 382 342 383 343 rx_ifindex = if_nametoindex(RX_NAME); 384 - tx_ifindex = if_nametoindex(TX_NAME); 385 344 386 - /* Setup separate AF_XDP for TX and RX interfaces. */ 387 - 388 - ret = open_xsk(tx_ifindex, &tx_xsk); 389 - if (!ASSERT_OK(ret, "open_xsk(TX_NAME)")) 390 - goto out; 345 + /* Setup separate AF_XDP for RX interface. */ 391 346 392 347 ret = open_xsk(rx_ifindex, &rx_xsk); 393 348 if (!ASSERT_OK(ret, "open_xsk(RX_NAME)")) ··· 432 379 if (!ASSERT_GE(ret, 0, "bpf_map_update_elem")) 433 380 goto out; 434 381 435 - /* Send packet destined to RX AF_XDP socket. */ 382 + switch_ns_to_tx(&tok); 383 + 384 + /* Setup separate AF_XDP for TX interface nad send packet to the RX socket. */ 385 + tx_ifindex = if_nametoindex(TX_NAME); 386 + ret = open_xsk(tx_ifindex, &tx_xsk); 387 + if (!ASSERT_OK(ret, "open_xsk(TX_NAME)")) 388 + goto out; 389 + 436 390 if (!ASSERT_GE(generate_packet(&tx_xsk, AF_XDP_CONSUMER_PORT), 0, 437 391 "generate AF_XDP_CONSUMER_PORT")) 438 392 goto out; 439 393 440 - /* Verify AF_XDP RX packet has proper metadata. */ 441 - if (!ASSERT_GE(verify_xsk_metadata(&rx_xsk), 0, 394 + switch_ns_to_rx(&tok); 395 + 396 + /* Verify packet sent from AF_XDP has proper metadata. */ 397 + if (!ASSERT_GE(verify_xsk_metadata(&rx_xsk, true), 0, 442 398 "verify_xsk_metadata")) 443 399 goto out; 444 400 401 + switch_ns_to_tx(&tok); 445 402 complete_tx(&tx_xsk); 403 + 404 + /* Now check metadata of packet, generated with network stack */ 405 + if (!ASSERT_GE(generate_packet_inet(), 0, "generate UDP packet")) 406 + goto out; 407 + 408 + switch_ns_to_rx(&tok); 409 + 410 + if (!ASSERT_GE(verify_xsk_metadata(&rx_xsk, false), 0, 411 + "verify_xsk_metadata")) 412 + goto out; 446 413 447 414 /* Make sure freplace correctly picks up original bound device 448 415 * and doesn't crash. ··· 481 408 if (!ASSERT_OK(xdp_metadata2__attach(bpf_obj2), "attach freplace")) 482 409 goto out; 483 410 411 + switch_ns_to_tx(&tok); 412 + 484 413 /* Send packet to trigger . */ 485 414 if (!ASSERT_GE(generate_packet(&tx_xsk, AF_XDP_CONSUMER_PORT), 0, 486 415 "generate freplace packet")) 487 416 goto out; 417 + 418 + switch_ns_to_rx(&tok); 488 419 489 420 while (!retries--) { 490 421 if (bpf_obj2->bss->called) ··· 504 427 xdp_metadata__destroy(bpf_obj); 505 428 if (tok) 506 429 close_netns(tok); 507 - SYS_NOFAIL("ip netns del xdp_metadata"); 430 + SYS_NOFAIL("ip netns del " RX_NETNS_NAME); 431 + SYS_NOFAIL("ip netns del " TX_NETNS_NAME); 508 432 }