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

libeth: xsk: add XSk Rx processing support

Add XSk counterparts for preparing XSk &libeth_xdp_buff (adding head and
frags), running the program, and handling the verdict, inc. XDP_PASS.
Shortcuts in comparison with regular Rx: frags and all verdicts except
XDP_REDIRECT are under unlikely() and out of line; no checks for XDP
program presence as it's always true for XSk.

Suggested-by: Maciej Fijalkowski <maciej.fijalkowski@intel.com> # optimizations
Signed-off-by: Alexander Lobakin <aleksander.lobakin@intel.com>
Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>

authored by

Alexander Lobakin and committed by
Tony Nguyen
5495c58c 40e846d1

+398 -8
+3
drivers/net/ethernet/intel/libeth/priv.h
··· 8 8 9 9 /* XDP */ 10 10 11 + enum xdp_action; 11 12 struct libeth_xdp_buff; 12 13 struct libeth_xdp_tx_frame; 13 14 struct skb_shared_info; ··· 18 17 19 18 void libeth_xsk_tx_return_bulk(const struct libeth_xdp_tx_frame *bq, 20 19 u32 count); 20 + u32 libeth_xsk_prog_exception(struct libeth_xdp_buff *xdp, enum xdp_action act, 21 + int ret); 21 22 22 23 struct libeth_xdp_ops { 23 24 void (*bulk)(const struct skb_shared_info *sinfo,
+5 -1
drivers/net/ethernet/intel/libeth/xdp.c
··· 286 286 * @act: original XDP prog verdict 287 287 * @ret: error code if redirect failed 288 288 * 289 - * External helper used by __libeth_xdp_run_prog(), do not call directly. 289 + * External helper used by __libeth_xdp_run_prog() and 290 + * __libeth_xsk_run_prog_slow(), do not call directly. 290 291 * Reports invalid @act, XDP exception trace event and frees the buffer. 291 292 * 292 293 * Return: libeth_xdp XDP prog verdict. ··· 300 299 bpf_warn_invalid_xdp_action(bq->dev, bq->prog, act); 301 300 302 301 libeth_trace_xdp_exception(bq->dev, bq->prog, act); 302 + 303 + if (xdp->base.rxq->mem.type == MEM_TYPE_XSK_BUFF_POOL) 304 + return libeth_xsk_prog_exception(xdp, act, ret); 303 305 304 306 libeth_xdp_return_buff_slow(xdp); 305 307
+107
drivers/net/ethernet/intel/libeth/xsk.c
··· 38 38 xsk_buff_free(&xdp->base); 39 39 } 40 40 EXPORT_SYMBOL_GPL(libeth_xsk_buff_free_slow); 41 + 42 + /** 43 + * libeth_xsk_buff_add_frag - add frag to XSk Rx buffer 44 + * @head: head buffer 45 + * @xdp: frag buffer 46 + * 47 + * External helper used by libeth_xsk_process_buff(), do not call directly. 48 + * Frees both main and frag buffers on error. 49 + * 50 + * Return: main buffer with attached frag on success, %NULL on error (no space 51 + * for a new frag). 52 + */ 53 + struct libeth_xdp_buff *libeth_xsk_buff_add_frag(struct libeth_xdp_buff *head, 54 + struct libeth_xdp_buff *xdp) 55 + { 56 + if (!xsk_buff_add_frag(&head->base, &xdp->base)) 57 + goto free; 58 + 59 + return head; 60 + 61 + free: 62 + libeth_xsk_buff_free_slow(xdp); 63 + libeth_xsk_buff_free_slow(head); 64 + 65 + return NULL; 66 + } 67 + EXPORT_SYMBOL_GPL(libeth_xsk_buff_add_frag); 68 + 69 + /** 70 + * libeth_xsk_buff_stats_frags - update onstack RQ stats with XSk frags info 71 + * @rs: onstack stats to update 72 + * @xdp: buffer to account 73 + * 74 + * External helper used by __libeth_xsk_run_pass(), do not call directly. 75 + * Adds buffer's frags count and total len to the onstack stats. 76 + */ 77 + void libeth_xsk_buff_stats_frags(struct libeth_rq_napi_stats *rs, 78 + const struct libeth_xdp_buff *xdp) 79 + { 80 + libeth_xdp_buff_stats_frags(rs, xdp); 81 + } 82 + EXPORT_SYMBOL_GPL(libeth_xsk_buff_stats_frags); 83 + 84 + /** 85 + * __libeth_xsk_run_prog_slow - process the non-``XDP_REDIRECT`` verdicts 86 + * @xdp: buffer to process 87 + * @bq: Tx bulk for queueing on ``XDP_TX`` 88 + * @act: verdict to process 89 + * @ret: error code if ``XDP_REDIRECT`` failed 90 + * 91 + * External helper used by __libeth_xsk_run_prog(), do not call directly. 92 + * ``XDP_REDIRECT`` is the most common and hottest verdict on XSk, thus 93 + * it is processed inline. The rest goes here for out-of-line processing, 94 + * together with redirect errors. 95 + * 96 + * Return: libeth_xdp XDP prog verdict. 97 + */ 98 + u32 __libeth_xsk_run_prog_slow(struct libeth_xdp_buff *xdp, 99 + const struct libeth_xdp_tx_bulk *bq, 100 + enum xdp_action act, int ret) 101 + { 102 + switch (act) { 103 + case XDP_DROP: 104 + xsk_buff_free(&xdp->base); 105 + 106 + return LIBETH_XDP_DROP; 107 + case XDP_TX: 108 + return LIBETH_XDP_TX; 109 + case XDP_PASS: 110 + return LIBETH_XDP_PASS; 111 + default: 112 + break; 113 + } 114 + 115 + return libeth_xdp_prog_exception(bq, xdp, act, ret); 116 + } 117 + EXPORT_SYMBOL_GPL(__libeth_xsk_run_prog_slow); 118 + 119 + /** 120 + * libeth_xsk_prog_exception - handle XDP prog exceptions on XSk 121 + * @xdp: buffer to process 122 + * @act: verdict returned by the prog 123 + * @ret: error code if ``XDP_REDIRECT`` failed 124 + * 125 + * Internal. Frees the buffer and, if the queue uses XSk wakeups, stop the 126 + * current NAPI poll when there are no free buffers left. 127 + * 128 + * Return: libeth_xdp's XDP prog verdict. 129 + */ 130 + u32 __cold libeth_xsk_prog_exception(struct libeth_xdp_buff *xdp, 131 + enum xdp_action act, int ret) 132 + { 133 + const struct xdp_buff_xsk *xsk; 134 + u32 __ret = LIBETH_XDP_DROP; 135 + 136 + if (act != XDP_REDIRECT) 137 + goto drop; 138 + 139 + xsk = container_of(&xdp->base, typeof(*xsk), xdp); 140 + if (xsk_uses_need_wakeup(xsk->pool) && ret == -ENOBUFS) 141 + __ret = LIBETH_XDP_ABORTED; 142 + 143 + drop: 144 + libeth_xsk_buff_free_slow(xdp); 145 + 146 + return __ret; 147 + }
+10 -7
include/net/libeth/xdp.h
··· 1122 1122 * Should be called on an onstack XDP Tx bulk before the NAPI polling loop. 1123 1123 * Initializes all the needed fields to run libeth_xdp functions. If @num == 0, 1124 1124 * assumes XDP is not enabled. 1125 + * Do not use for XSk, it has its own optimized helper. 1125 1126 */ 1126 1127 #define libeth_xdp_tx_init_bulk(bq, prog, dev, xdpsqs, num) \ 1127 1128 __libeth_xdp_tx_init_bulk(bq, prog, dev, xdpsqs, num, false, \ 1128 1129 __UNIQUE_ID(bq_), __UNIQUE_ID(nqs_)) 1129 1130 1130 - #define __libeth_xdp_tx_init_bulk(bq, pr, d, xdpsqs, num, ub, un) do { \ 1131 + #define __libeth_xdp_tx_init_bulk(bq, pr, d, xdpsqs, num, xsk, ub, un) do { \ 1131 1132 typeof(bq) ub = (bq); \ 1132 1133 u32 un = (num); \ 1133 1134 \ 1134 1135 rcu_read_lock(); \ 1135 1136 \ 1136 - if (un) { \ 1137 + if (un || (xsk)) { \ 1137 1138 ub->prog = rcu_dereference(pr); \ 1138 1139 ub->dev = (d); \ 1139 1140 ub->xdpsq = (xdpsqs)[libeth_xdpsq_id(un)]; \ ··· 1160 1159 * 1161 1160 * Should be called before the main NAPI polling loop. Loads the content of 1162 1161 * the previously saved stash or initializes the buffer from scratch. 1162 + * Do not use for XSk. 1163 1163 */ 1164 1164 static inline void 1165 1165 libeth_xdp_init_buff(struct libeth_xdp_buff *dst, ··· 1380 1378 * @flush_bulk: driver callback for flushing a bulk 1381 1379 * 1382 1380 * Internal inline abstraction to run XDP program and additionally handle 1383 - * ``XDP_TX`` verdict. 1381 + * ``XDP_TX`` verdict. Used by both XDP and XSk, hence @run and @queue. 1384 1382 * Do not use directly. 1385 1383 * 1386 1384 * Return: libeth_xdp prog verdict depending on the prog's verdict. ··· 1410 1408 } 1411 1409 1412 1410 /** 1413 - * libeth_xdp_run_prog - run XDP program and handle all verdicts 1411 + * libeth_xdp_run_prog - run XDP program (non-XSk path) and handle all verdicts 1414 1412 * @xdp: XDP buffer to process 1415 1413 * @bq: XDP Tx bulk to queue ``XDP_TX`` buffers 1416 1414 * @fl: driver ``XDP_TX`` bulk flush callback 1417 1415 * 1418 - * Run the attached XDP program and handle all possible verdicts. 1416 + * Run the attached XDP program and handle all possible verdicts. XSk has its 1417 + * own version. 1419 1418 * Prefer using it via LIBETH_XDP_DEFINE_RUN{,_PASS,_PROG}(). 1420 1419 * 1421 1420 * Return: true if the buffer should be passed up the stack, false if the poll ··· 1438 1435 * @run: driver wrapper to run XDP program 1439 1436 * @populate: driver callback to populate an skb with the HW descriptor data 1440 1437 * 1441 - * Inline abstraction that does the following: 1438 + * Inline abstraction that does the following (non-XSk path): 1442 1439 * 1) adds frame size and frag number (if needed) to the onstack stats; 1443 1440 * 2) fills the descriptor metadata to the onstack &libeth_xdp_buff 1444 1441 * 3) runs XDP program if present; ··· 1521 1518 run, populate) 1522 1519 1523 1520 /** 1524 - * libeth_xdp_finalize_rx - finalize XDPSQ after a NAPI polling loop 1521 + * libeth_xdp_finalize_rx - finalize XDPSQ after a NAPI polling loop (non-XSk) 1525 1522 * @bq: ``XDP_TX`` frame bulk 1526 1523 * @flush: driver callback to flush the bulk 1527 1524 * @finalize: driver callback to start sending the frames and run the timer
+273
include/net/libeth/xsk.h
··· 311 311 return n < budget; 312 312 } 313 313 314 + /* Rx polling path */ 315 + 316 + /** 317 + * libeth_xsk_tx_init_bulk - initialize XDP Tx bulk for an XSk Rx NAPI poll 318 + * @bq: bulk to initialize 319 + * @prog: RCU pointer to the XDP program (never %NULL) 320 + * @dev: target &net_device 321 + * @xdpsqs: array of driver XDPSQ structs 322 + * @num: number of active XDPSQs, the above array length 323 + * 324 + * Should be called on an onstack XDP Tx bulk before the XSk NAPI polling loop. 325 + * Initializes all the needed fields to run libeth_xdp functions. 326 + * Never checks if @prog is %NULL or @num == 0 as XDP must always be enabled 327 + * when hitting this path. 328 + */ 329 + #define libeth_xsk_tx_init_bulk(bq, prog, dev, xdpsqs, num) \ 330 + __libeth_xdp_tx_init_bulk(bq, prog, dev, xdpsqs, num, true, \ 331 + __UNIQUE_ID(bq_), __UNIQUE_ID(nqs_)) 332 + 333 + struct libeth_xdp_buff *libeth_xsk_buff_add_frag(struct libeth_xdp_buff *head, 334 + struct libeth_xdp_buff *xdp); 335 + 336 + /** 337 + * libeth_xsk_process_buff - attach XSk Rx buffer to &libeth_xdp_buff 338 + * @head: head XSk buffer to attach the XSk buffer to (or %NULL) 339 + * @xdp: XSk buffer to process 340 + * @len: received data length from the descriptor 341 + * 342 + * If @head == %NULL, treats the XSk buffer as head and initializes 343 + * the required fields. Otherwise, attaches the buffer as a frag. 344 + * Already performs DMA sync-for-CPU and frame start prefetch 345 + * (for head buffers only). 346 + * 347 + * Return: head XSk buffer on success or if the descriptor must be skipped 348 + * (empty), %NULL if there is no space for a new frag. 349 + */ 350 + static inline struct libeth_xdp_buff * 351 + libeth_xsk_process_buff(struct libeth_xdp_buff *head, 352 + struct libeth_xdp_buff *xdp, u32 len) 353 + { 354 + if (unlikely(!len)) { 355 + libeth_xsk_buff_free_slow(xdp); 356 + return head; 357 + } 358 + 359 + xsk_buff_set_size(&xdp->base, len); 360 + xsk_buff_dma_sync_for_cpu(&xdp->base); 361 + 362 + if (head) 363 + return libeth_xsk_buff_add_frag(head, xdp); 364 + 365 + prefetch(xdp->data); 366 + 367 + return xdp; 368 + } 369 + 370 + void libeth_xsk_buff_stats_frags(struct libeth_rq_napi_stats *rs, 371 + const struct libeth_xdp_buff *xdp); 372 + 373 + u32 __libeth_xsk_run_prog_slow(struct libeth_xdp_buff *xdp, 374 + const struct libeth_xdp_tx_bulk *bq, 375 + enum xdp_action act, int ret); 376 + 377 + /** 378 + * __libeth_xsk_run_prog - run XDP program on XSk buffer 379 + * @xdp: XSk buffer to run the prog on 380 + * @bq: buffer bulk for ``XDP_TX`` queueing 381 + * 382 + * Internal inline abstraction to run XDP program on XSk Rx path. Handles 383 + * only the most common ``XDP_REDIRECT`` inline, the rest is processed 384 + * externally. 385 + * Reports an XDP prog exception on errors. 386 + * 387 + * Return: libeth_xdp prog verdict depending on the prog's verdict. 388 + */ 389 + static __always_inline u32 390 + __libeth_xsk_run_prog(struct libeth_xdp_buff *xdp, 391 + const struct libeth_xdp_tx_bulk *bq) 392 + { 393 + enum xdp_action act; 394 + int ret = 0; 395 + 396 + act = bpf_prog_run_xdp(bq->prog, &xdp->base); 397 + if (unlikely(act != XDP_REDIRECT)) 398 + rest: 399 + return __libeth_xsk_run_prog_slow(xdp, bq, act, ret); 400 + 401 + ret = xdp_do_redirect(bq->dev, &xdp->base, bq->prog); 402 + if (unlikely(ret)) 403 + goto rest; 404 + 405 + return LIBETH_XDP_REDIRECT; 406 + } 407 + 408 + /** 409 + * libeth_xsk_run_prog - run XDP program on XSk path and handle all verdicts 410 + * @xdp: XSk buffer to process 411 + * @bq: XDP Tx bulk to queue ``XDP_TX`` buffers 412 + * @fl: driver ``XDP_TX`` bulk flush callback 413 + * 414 + * Run the attached XDP program and handle all possible verdicts. 415 + * Prefer using it via LIBETH_XSK_DEFINE_RUN{,_PASS,_PROG}(). 416 + * 417 + * Return: libeth_xdp prog verdict depending on the prog's verdict. 418 + */ 419 + #define libeth_xsk_run_prog(xdp, bq, fl) \ 420 + __libeth_xdp_run_flush(xdp, bq, __libeth_xsk_run_prog, \ 421 + libeth_xsk_tx_queue_bulk, fl) 422 + 423 + /** 424 + * __libeth_xsk_run_pass - helper to run XDP program and handle the result 425 + * @xdp: XSk buffer to process 426 + * @bq: XDP Tx bulk to queue ``XDP_TX`` frames 427 + * @napi: NAPI to build an skb and pass it up the stack 428 + * @rs: onstack libeth RQ stats 429 + * @md: metadata that should be filled to the XSk buffer 430 + * @prep: callback for filling the metadata 431 + * @run: driver wrapper to run XDP program 432 + * @populate: driver callback to populate an skb with the HW descriptor data 433 + * 434 + * Inline abstraction, XSk's counterpart of __libeth_xdp_run_pass(), see its 435 + * doc for details. 436 + * 437 + * Return: false if the polling loop must be exited due to lack of free 438 + * buffers, true otherwise. 439 + */ 440 + static __always_inline bool 441 + __libeth_xsk_run_pass(struct libeth_xdp_buff *xdp, 442 + struct libeth_xdp_tx_bulk *bq, struct napi_struct *napi, 443 + struct libeth_rq_napi_stats *rs, const void *md, 444 + void (*prep)(struct libeth_xdp_buff *xdp, 445 + const void *md), 446 + u32 (*run)(struct libeth_xdp_buff *xdp, 447 + struct libeth_xdp_tx_bulk *bq), 448 + bool (*populate)(struct sk_buff *skb, 449 + const struct libeth_xdp_buff *xdp, 450 + struct libeth_rq_napi_stats *rs)) 451 + { 452 + struct sk_buff *skb; 453 + u32 act; 454 + 455 + rs->bytes += xdp->base.data_end - xdp->data; 456 + rs->packets++; 457 + 458 + if (unlikely(xdp_buff_has_frags(&xdp->base))) 459 + libeth_xsk_buff_stats_frags(rs, xdp); 460 + 461 + if (prep && (!__builtin_constant_p(!!md) || md)) 462 + prep(xdp, md); 463 + 464 + act = run(xdp, bq); 465 + if (likely(act == LIBETH_XDP_REDIRECT)) 466 + return true; 467 + 468 + if (act != LIBETH_XDP_PASS) 469 + return act != LIBETH_XDP_ABORTED; 470 + 471 + skb = xdp_build_skb_from_zc(&xdp->base); 472 + if (unlikely(!skb)) { 473 + libeth_xsk_buff_free_slow(xdp); 474 + return true; 475 + } 476 + 477 + if (unlikely(!populate(skb, xdp, rs))) { 478 + napi_consume_skb(skb, true); 479 + return true; 480 + } 481 + 482 + napi_gro_receive(napi, skb); 483 + 484 + return true; 485 + } 486 + 487 + /** 488 + * libeth_xsk_run_pass - helper to run XDP program and handle the result 489 + * @xdp: XSk buffer to process 490 + * @bq: XDP Tx bulk to queue ``XDP_TX`` frames 491 + * @napi: NAPI to build an skb and pass it up the stack 492 + * @rs: onstack libeth RQ stats 493 + * @desc: pointer to the HW descriptor for that frame 494 + * @run: driver wrapper to run XDP program 495 + * @populate: driver callback to populate an skb with the HW descriptor data 496 + * 497 + * Wrapper around the underscored version when "fill the descriptor metadata" 498 + * means just writing the pointer to the HW descriptor as @xdp->desc. 499 + */ 500 + #define libeth_xsk_run_pass(xdp, bq, napi, rs, desc, run, populate) \ 501 + __libeth_xsk_run_pass(xdp, bq, napi, rs, desc, libeth_xdp_prep_desc, \ 502 + run, populate) 503 + 504 + /** 505 + * libeth_xsk_finalize_rx - finalize XDPSQ after an XSk NAPI polling loop 506 + * @bq: ``XDP_TX`` frame bulk 507 + * @flush: driver callback to flush the bulk 508 + * @finalize: driver callback to start sending the frames and run the timer 509 + * 510 + * Flush the bulk if there are frames left to send, kick the queue and flush 511 + * the XDP maps. 512 + */ 513 + #define libeth_xsk_finalize_rx(bq, flush, finalize) \ 514 + __libeth_xdp_finalize_rx(bq, LIBETH_XDP_TX_XSK, flush, finalize) 515 + 516 + /* 517 + * Helpers to reduce boilerplate code in drivers. 518 + * 519 + * Typical driver XSk Rx flow would be (excl. bulk and buff init, frag attach): 520 + * 521 + * LIBETH_XDP_DEFINE_START(); 522 + * LIBETH_XSK_DEFINE_FLUSH_TX(static driver_xsk_flush_tx, driver_xsk_tx_prep, 523 + * driver_xdp_xmit); 524 + * LIBETH_XSK_DEFINE_RUN(static driver_xsk_run, driver_xsk_run_prog, 525 + * driver_xsk_flush_tx, driver_populate_skb); 526 + * LIBETH_XSK_DEFINE_FINALIZE(static driver_xsk_finalize_rx, 527 + * driver_xsk_flush_tx, driver_xdp_finalize_sq); 528 + * LIBETH_XDP_DEFINE_END(); 529 + * 530 + * This will build a set of 4 static functions. The compiler is free to decide 531 + * whether to inline them. 532 + * Then, in the NAPI polling function: 533 + * 534 + * while (packets < budget) { 535 + * // ... 536 + * if (!driver_xsk_run(xdp, &bq, napi, &rs, desc)) 537 + * break; 538 + * } 539 + * driver_xsk_finalize_rx(&bq); 540 + */ 541 + 542 + /** 543 + * LIBETH_XSK_DEFINE_FLUSH_TX - define a driver XSk ``XDP_TX`` flush function 544 + * @name: name of the function to define 545 + * @prep: driver callback to clean an XDPSQ 546 + * @xmit: driver callback to write a HW Tx descriptor 547 + */ 548 + #define LIBETH_XSK_DEFINE_FLUSH_TX(name, prep, xmit) \ 549 + __LIBETH_XDP_DEFINE_FLUSH_TX(name, prep, xmit, xsk) 550 + 551 + /** 552 + * LIBETH_XSK_DEFINE_RUN_PROG - define a driver XDP program run function 553 + * @name: name of the function to define 554 + * @flush: driver callback to flush an XSk ``XDP_TX`` bulk 555 + */ 556 + #define LIBETH_XSK_DEFINE_RUN_PROG(name, flush) \ 557 + u32 __LIBETH_XDP_DEFINE_RUN_PROG(name, flush, xsk) 558 + 559 + /** 560 + * LIBETH_XSK_DEFINE_RUN_PASS - define a driver buffer process + pass function 561 + * @name: name of the function to define 562 + * @run: driver callback to run XDP program (above) 563 + * @populate: driver callback to fill an skb with HW descriptor info 564 + */ 565 + #define LIBETH_XSK_DEFINE_RUN_PASS(name, run, populate) \ 566 + bool __LIBETH_XDP_DEFINE_RUN_PASS(name, run, populate, xsk) 567 + 568 + /** 569 + * LIBETH_XSK_DEFINE_RUN - define a driver buffer process, run + pass function 570 + * @name: name of the function to define 571 + * @run: name of the XDP prog run function to define 572 + * @flush: driver callback to flush an XSk ``XDP_TX`` bulk 573 + * @populate: driver callback to fill an skb with HW descriptor info 574 + */ 575 + #define LIBETH_XSK_DEFINE_RUN(name, run, flush, populate) \ 576 + __LIBETH_XDP_DEFINE_RUN(name, run, flush, populate, XSK) 577 + 578 + /** 579 + * LIBETH_XSK_DEFINE_FINALIZE - define a driver XSk NAPI poll finalize function 580 + * @name: name of the function to define 581 + * @flush: driver callback to flush an XSk ``XDP_TX`` bulk 582 + * @finalize: driver callback to finalize an XDPSQ and run the timer 583 + */ 584 + #define LIBETH_XSK_DEFINE_FINALIZE(name, flush, finalize) \ 585 + __LIBETH_XDP_DEFINE_FINALIZE(name, flush, finalize, xsk) 586 + 314 587 #endif /* __LIBETH_XSK_H */