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

Configure Feed

Select the types of activity you want to include in your feed.

vmxnet3: Add XDP support.

The patch adds native-mode XDP support: XDP DROP, PASS, TX, and REDIRECT.

Background:
The vmxnet3 rx consists of three rings: ring0, ring1, and dataring.
For r0 and r1, buffers at r0 are allocated using alloc_skb APIs and dma
mapped to the ring's descriptor. If LRO is enabled and packet size larger
than 3K, VMXNET3_MAX_SKB_BUF_SIZE, then r1 is used to mapped the rest of
the buffer larger than VMXNET3_MAX_SKB_BUF_SIZE. Each buffer in r1 is
allocated using alloc_page. So for LRO packets, the payload will be in one
buffer from r0 and multiple from r1, for non-LRO packets, only one
descriptor in r0 is used for packet size less than 3k.

When receiving a packet, the first descriptor will have the sop (start of
packet) bit set, and the last descriptor will have the eop (end of packet)
bit set. Non-LRO packets will have only one descriptor with both sop and
eop set.

Other than r0 and r1, vmxnet3 dataring is specifically designed for
handling packets with small size, usually 128 bytes, defined in
VMXNET3_DEF_RXDATA_DESC_SIZE, by simply copying the packet from the backend
driver in ESXi to the ring's memory region at front-end vmxnet3 driver, in
order to avoid memory mapping/unmapping overhead. In summary, packet size:
A. < 128B: use dataring
B. 128B - 3K: use ring0 (VMXNET3_RX_BUF_SKB)
C. > 3K: use ring0 and ring1 (VMXNET3_RX_BUF_SKB + VMXNET3_RX_BUF_PAGE)
As a result, the patch adds XDP support for packets using dataring
and r0 (case A and B), not the large packet size when LRO is enabled.

XDP Implementation:
When user loads and XDP prog, vmxnet3 driver checks configurations, such
as mtu, lro, and re-allocate the rx buffer size for reserving the extra
headroom, XDP_PACKET_HEADROOM, for XDP frame. The XDP prog will then be
associated with every rx queue of the device. Note that when using dataring
for small packet size, vmxnet3 (front-end driver) doesn't control the
buffer allocation, as a result we allocate a new page and copy packet
from the dataring to XDP frame.

The receive side of XDP is implemented for case A and B, by invoking the
bpf program at vmxnet3_rq_rx_complete and handle its returned action.
The vmxnet3_process_xdp(), vmxnet3_process_xdp_small() function handles
the ring0 and dataring case separately, and decides the next journey of
the packet afterward.

For TX, vmxnet3 has split header design. Outgoing packets are parsed
first and protocol headers (L2/L3/L4) are copied to the backend. The
rest of the payload are dma mapped. Since XDP_TX does not parse the
packet protocol, the entire XDP frame is dma mapped for transmission
and transmitted in a batch. Later on, the frame is freed and recycled
back to the memory pool.

Performance:
Tested using two VMs inside one ESXi vSphere 7.0 machine, using single
core on each vmxnet3 device, sender using DPDK testpmd tx-mode attached
to vmxnet3 device, sending 64B or 512B UDP packet.

VM1 txgen:
$ dpdk-testpmd -l 0-3 -n 1 -- -i --nb-cores=3 \
--forward-mode=txonly --eth-peer=0,<mac addr of vm2>
option: add "--txonly-multi-flow"
option: use --txpkts=512 or 64 byte

VM2 running XDP:
$ ./samples/bpf/xdp_rxq_info -d ens160 -a <options> --skb-mode
$ ./samples/bpf/xdp_rxq_info -d ens160 -a <options>
options: XDP_DROP, XDP_PASS, XDP_TX

To test REDIRECT to cpu 0, use
$ ./samples/bpf/xdp_redirect_cpu -d ens160 -c 0 -e drop

Single core performance comparison with skb-mode.
64B: skb-mode -> native-mode
XDP_DROP: 1.6Mpps -> 2.4Mpps
XDP_PASS: 338Kpps -> 367Kpps
XDP_TX: 1.1Mpps -> 2.3Mpps
REDIRECT-drop: 1.3Mpps -> 2.3Mpps

512B: skb-mode -> native-mode
XDP_DROP: 863Kpps -> 1.3Mpps
XDP_PASS: 275Kpps -> 376Kpps
XDP_TX: 554Kpps -> 1.2Mpps
REDIRECT-drop: 659Kpps -> 1.2Mpps

Demo: https://youtu.be/4lm1CSCi78Q

Future work:
- XDP frag support
- use napi_consume_skb() instead of dev_kfree_skb_any at unmap
- stats using u64_stats_t
- using bitfield macro BIT()
- optimization for DMA synchronization using actual frame length,
instead of always max_len

Signed-off-by: William Tu <u9012063@gmail.com>
Reviewed-by: Alexander Duyck <alexanderduyck@fb.com>
Reviewed-by: Alexander Lobakin <alexandr.lobakin@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

William Tu and committed by
David S. Miller
54f00cce 76fa3635

+729 -42
+1
drivers/net/Kconfig
··· 571 571 tristate "VMware VMXNET3 ethernet driver" 572 572 depends on PCI && INET 573 573 depends on PAGE_SIZE_LESS_THAN_64KB 574 + select PAGE_POOL 574 575 help 575 576 This driver supports VMware's vmxnet3 virtual ethernet NIC. 576 577 To compile this driver as a module, choose M here: the
+1 -1
drivers/net/vmxnet3/Makefile
··· 32 32 33 33 obj-$(CONFIG_VMXNET3) += vmxnet3.o 34 34 35 - vmxnet3-objs := vmxnet3_drv.o vmxnet3_ethtool.o 35 + vmxnet3-objs := vmxnet3_drv.o vmxnet3_ethtool.o vmxnet3_xdp.o
+205 -31
drivers/net/vmxnet3/vmxnet3_drv.c
··· 28 28 #include <net/ip6_checksum.h> 29 29 30 30 #include "vmxnet3_int.h" 31 + #include "vmxnet3_xdp.h" 31 32 32 33 char vmxnet3_driver_name[] = "vmxnet3"; 33 34 #define VMXNET3_DRIVER_DESC "VMware vmxnet3 virtual NIC driver" ··· 339 338 vmxnet3_unmap_tx_buf(struct vmxnet3_tx_buf_info *tbi, 340 339 struct pci_dev *pdev) 341 340 { 342 - if (tbi->map_type == VMXNET3_MAP_SINGLE) 341 + u32 map_type = tbi->map_type; 342 + 343 + if (map_type & VMXNET3_MAP_SINGLE) 343 344 dma_unmap_single(&pdev->dev, tbi->dma_addr, tbi->len, 344 345 DMA_TO_DEVICE); 345 - else if (tbi->map_type == VMXNET3_MAP_PAGE) 346 + else if (map_type & VMXNET3_MAP_PAGE) 346 347 dma_unmap_page(&pdev->dev, tbi->dma_addr, tbi->len, 347 348 DMA_TO_DEVICE); 348 349 else 349 - BUG_ON(tbi->map_type != VMXNET3_MAP_NONE); 350 + BUG_ON(map_type & ~VMXNET3_MAP_XDP); 350 351 351 352 tbi->map_type = VMXNET3_MAP_NONE; /* to help debugging */ 352 353 } ··· 356 353 357 354 static int 358 355 vmxnet3_unmap_pkt(u32 eop_idx, struct vmxnet3_tx_queue *tq, 359 - struct pci_dev *pdev, struct vmxnet3_adapter *adapter) 356 + struct pci_dev *pdev, struct vmxnet3_adapter *adapter, 357 + struct xdp_frame_bulk *bq) 360 358 { 361 - struct sk_buff *skb; 359 + struct vmxnet3_tx_buf_info *tbi; 362 360 int entries = 0; 361 + u32 map_type; 363 362 364 363 /* no out of order completion */ 365 364 BUG_ON(tq->buf_info[eop_idx].sop_idx != tq->tx_ring.next2comp); 366 365 BUG_ON(VMXNET3_TXDESC_GET_EOP(&(tq->tx_ring.base[eop_idx].txd)) != 1); 367 366 368 - skb = tq->buf_info[eop_idx].skb; 369 - BUG_ON(skb == NULL); 370 - tq->buf_info[eop_idx].skb = NULL; 371 - 367 + tbi = &tq->buf_info[eop_idx]; 368 + BUG_ON(!tbi->skb); 369 + map_type = tbi->map_type; 372 370 VMXNET3_INC_RING_IDX_ONLY(eop_idx, tq->tx_ring.size); 373 371 374 372 while (tq->tx_ring.next2comp != eop_idx) { ··· 385 381 entries++; 386 382 } 387 383 388 - dev_kfree_skb_any(skb); 384 + if (map_type & VMXNET3_MAP_XDP) 385 + xdp_return_frame_bulk(tbi->xdpf, bq); 386 + else 387 + dev_kfree_skb_any(tbi->skb); 388 + 389 + /* xdpf and skb are in an anonymous union. */ 390 + tbi->skb = NULL; 391 + 389 392 return entries; 390 393 } 391 394 ··· 401 390 vmxnet3_tq_tx_complete(struct vmxnet3_tx_queue *tq, 402 391 struct vmxnet3_adapter *adapter) 403 392 { 404 - int completed = 0; 405 393 union Vmxnet3_GenericDesc *gdesc; 394 + struct xdp_frame_bulk bq; 395 + int completed = 0; 396 + 397 + xdp_frame_bulk_init(&bq); 398 + rcu_read_lock(); 406 399 407 400 gdesc = tq->comp_ring.base + tq->comp_ring.next2proc; 408 401 while (VMXNET3_TCD_GET_GEN(&gdesc->tcd) == tq->comp_ring.gen) { ··· 417 402 418 403 completed += vmxnet3_unmap_pkt(VMXNET3_TCD_GET_TXIDX( 419 404 &gdesc->tcd), tq, adapter->pdev, 420 - adapter); 405 + adapter, &bq); 421 406 422 407 vmxnet3_comp_ring_adv_next2proc(&tq->comp_ring); 423 408 gdesc = tq->comp_ring.base + tq->comp_ring.next2proc; 424 409 } 410 + xdp_flush_frame_bulk(&bq); 411 + rcu_read_unlock(); 425 412 426 413 if (completed) { 427 414 spin_lock(&tq->tx_lock); ··· 443 426 vmxnet3_tq_cleanup(struct vmxnet3_tx_queue *tq, 444 427 struct vmxnet3_adapter *adapter) 445 428 { 429 + struct xdp_frame_bulk bq; 430 + u32 map_type; 446 431 int i; 432 + 433 + xdp_frame_bulk_init(&bq); 434 + rcu_read_lock(); 447 435 448 436 while (tq->tx_ring.next2comp != tq->tx_ring.next2fill) { 449 437 struct vmxnet3_tx_buf_info *tbi; 450 438 451 439 tbi = tq->buf_info + tq->tx_ring.next2comp; 440 + map_type = tbi->map_type; 452 441 453 442 vmxnet3_unmap_tx_buf(tbi, adapter->pdev); 454 443 if (tbi->skb) { 455 - dev_kfree_skb_any(tbi->skb); 444 + if (map_type & VMXNET3_MAP_XDP) 445 + xdp_return_frame_bulk(tbi->xdpf, &bq); 446 + else 447 + dev_kfree_skb_any(tbi->skb); 456 448 tbi->skb = NULL; 457 449 } 458 450 vmxnet3_cmd_ring_adv_next2comp(&tq->tx_ring); 459 451 } 460 452 461 - /* sanity check, verify all buffers are indeed unmapped and freed */ 462 - for (i = 0; i < tq->tx_ring.size; i++) { 463 - BUG_ON(tq->buf_info[i].skb != NULL || 464 - tq->buf_info[i].map_type != VMXNET3_MAP_NONE); 465 - } 453 + xdp_flush_frame_bulk(&bq); 454 + rcu_read_unlock(); 455 + 456 + /* sanity check, verify all buffers are indeed unmapped */ 457 + for (i = 0; i < tq->tx_ring.size; i++) 458 + BUG_ON(tq->buf_info[i].map_type != VMXNET3_MAP_NONE); 466 459 467 460 tq->tx_ring.gen = VMXNET3_INIT_GEN; 468 461 tq->tx_ring.next2fill = tq->tx_ring.next2comp = 0; ··· 626 599 gd = ring->base + ring->next2fill; 627 600 rbi->comp_state = VMXNET3_RXD_COMP_PENDING; 628 601 629 - if (rbi->buf_type == VMXNET3_RX_BUF_SKB) { 602 + if (rbi->buf_type == VMXNET3_RX_BUF_XDP) { 603 + void *data = vmxnet3_pp_get_buff(rq->page_pool, 604 + &rbi->dma_addr, 605 + GFP_KERNEL); 606 + if (!data) { 607 + rq->stats.rx_buf_alloc_failure++; 608 + break; 609 + } 610 + rbi->page = virt_to_page(data); 611 + val = VMXNET3_RXD_BTYPE_HEAD << VMXNET3_RXD_BTYPE_SHIFT; 612 + } else if (rbi->buf_type == VMXNET3_RX_BUF_SKB) { 630 613 if (rbi->skb == NULL) { 631 614 rbi->skb = __netdev_alloc_skb_ip_align(adapter->netdev, 632 615 rbi->len, ··· 1300 1263 return NETDEV_TX_OK; 1301 1264 } 1302 1265 1266 + static int 1267 + vmxnet3_create_pp(struct vmxnet3_adapter *adapter, 1268 + struct vmxnet3_rx_queue *rq, int size) 1269 + { 1270 + bool xdp_prog = vmxnet3_xdp_enabled(adapter); 1271 + const struct page_pool_params pp_params = { 1272 + .order = 0, 1273 + .flags = PP_FLAG_DMA_MAP | PP_FLAG_DMA_SYNC_DEV, 1274 + .pool_size = size, 1275 + .nid = NUMA_NO_NODE, 1276 + .dev = &adapter->pdev->dev, 1277 + .offset = VMXNET3_XDP_RX_OFFSET, 1278 + .max_len = VMXNET3_XDP_MAX_FRSIZE, 1279 + .dma_dir = xdp_prog ? DMA_BIDIRECTIONAL : DMA_FROM_DEVICE, 1280 + }; 1281 + struct page_pool *pp; 1282 + int err; 1283 + 1284 + pp = page_pool_create(&pp_params); 1285 + if (IS_ERR(pp)) 1286 + return PTR_ERR(pp); 1287 + 1288 + err = xdp_rxq_info_reg(&rq->xdp_rxq, adapter->netdev, rq->qid, 1289 + rq->napi.napi_id); 1290 + if (err < 0) 1291 + goto err_free_pp; 1292 + 1293 + err = xdp_rxq_info_reg_mem_model(&rq->xdp_rxq, MEM_TYPE_PAGE_POOL, pp); 1294 + if (err) 1295 + goto err_unregister_rxq; 1296 + 1297 + rq->page_pool = pp; 1298 + 1299 + return 0; 1300 + 1301 + err_unregister_rxq: 1302 + xdp_rxq_info_unreg(&rq->xdp_rxq); 1303 + err_free_pp: 1304 + page_pool_destroy(pp); 1305 + 1306 + return err; 1307 + } 1308 + 1309 + void * 1310 + vmxnet3_pp_get_buff(struct page_pool *pp, dma_addr_t *dma_addr, 1311 + gfp_t gfp_mask) 1312 + { 1313 + struct page *page; 1314 + 1315 + page = page_pool_alloc_pages(pp, gfp_mask | __GFP_NOWARN); 1316 + if (unlikely(!page)) 1317 + return NULL; 1318 + 1319 + *dma_addr = page_pool_get_dma_addr(page) + pp->p.offset; 1320 + 1321 + return page_address(page); 1322 + } 1303 1323 1304 1324 static netdev_tx_t 1305 1325 vmxnet3_xmit_frame(struct sk_buff *skb, struct net_device *netdev) ··· 1517 1423 struct Vmxnet3_RxDesc rxCmdDesc; 1518 1424 struct Vmxnet3_RxCompDesc rxComp; 1519 1425 #endif 1426 + bool need_flush = false; 1427 + 1520 1428 vmxnet3_getRxComp(rcd, &rq->comp_ring.base[rq->comp_ring.next2proc].rcd, 1521 1429 &rxComp); 1522 1430 while (rcd->gen == rq->comp_ring.gen) { ··· 1559 1463 goto rcd_done; 1560 1464 } 1561 1465 1466 + if (rcd->sop && rcd->eop && vmxnet3_xdp_enabled(adapter)) { 1467 + struct sk_buff *skb_xdp_pass; 1468 + int act; 1469 + 1470 + if (VMXNET3_RX_DATA_RING(adapter, rcd->rqID)) { 1471 + ctx->skb = NULL; 1472 + goto skip_xdp; /* Handle it later. */ 1473 + } 1474 + 1475 + if (rbi->buf_type != VMXNET3_RX_BUF_XDP) 1476 + goto rcd_done; 1477 + 1478 + act = vmxnet3_process_xdp(adapter, rq, rcd, rbi, rxd, 1479 + &skb_xdp_pass); 1480 + if (act == XDP_PASS) { 1481 + ctx->skb = skb_xdp_pass; 1482 + goto sop_done; 1483 + } 1484 + ctx->skb = NULL; 1485 + need_flush |= act == XDP_REDIRECT; 1486 + 1487 + goto rcd_done; 1488 + } 1489 + skip_xdp: 1490 + 1562 1491 if (rcd->sop) { /* first buf of the pkt */ 1563 1492 bool rxDataRingUsed; 1564 1493 u16 len; ··· 1592 1471 (rcd->rqID != rq->qid && 1593 1472 rcd->rqID != rq->dataRingQid)); 1594 1473 1595 - BUG_ON(rbi->buf_type != VMXNET3_RX_BUF_SKB); 1474 + BUG_ON(rbi->buf_type != VMXNET3_RX_BUF_SKB && 1475 + rbi->buf_type != VMXNET3_RX_BUF_XDP); 1596 1476 BUG_ON(ctx->skb != NULL || rbi->skb == NULL); 1597 1477 1598 1478 if (unlikely(rcd->len == 0)) { ··· 1611 1489 rxDataRingUsed = 1612 1490 VMXNET3_RX_DATA_RING(adapter, rcd->rqID); 1613 1491 len = rxDataRingUsed ? rcd->len : rbi->len; 1492 + 1493 + if (rxDataRingUsed && vmxnet3_xdp_enabled(adapter)) { 1494 + struct sk_buff *skb_xdp_pass; 1495 + size_t sz; 1496 + int act; 1497 + 1498 + sz = rcd->rxdIdx * rq->data_ring.desc_size; 1499 + act = vmxnet3_process_xdp_small(adapter, rq, 1500 + &rq->data_ring.base[sz], 1501 + rcd->len, 1502 + &skb_xdp_pass); 1503 + if (act == XDP_PASS) { 1504 + ctx->skb = skb_xdp_pass; 1505 + goto sop_done; 1506 + } 1507 + need_flush |= act == XDP_REDIRECT; 1508 + 1509 + goto rcd_done; 1510 + } 1614 1511 new_skb = netdev_alloc_skb_ip_align(adapter->netdev, 1615 1512 len); 1616 1513 if (new_skb == NULL) { ··· 1762 1621 } 1763 1622 1764 1623 1624 + sop_done: 1765 1625 skb = ctx->skb; 1766 1626 if (rcd->eop) { 1767 1627 u32 mtu = adapter->netdev->mtu; ··· 1899 1757 vmxnet3_getRxComp(rcd, 1900 1758 &rq->comp_ring.base[rq->comp_ring.next2proc].rcd, &rxComp); 1901 1759 } 1760 + if (need_flush) 1761 + xdp_do_flush(); 1902 1762 1903 1763 return num_pkts; 1904 1764 } ··· 1919 1775 1920 1776 for (ring_idx = 0; ring_idx < 2; ring_idx++) { 1921 1777 for (i = 0; i < rq->rx_ring[ring_idx].size; i++) { 1778 + struct vmxnet3_rx_buf_info *rbi; 1922 1779 #ifdef __BIG_ENDIAN_BITFIELD 1923 1780 struct Vmxnet3_RxDesc rxDesc; 1924 1781 #endif 1782 + 1783 + rbi = &rq->buf_info[ring_idx][i]; 1925 1784 vmxnet3_getRxDesc(rxd, 1926 1785 &rq->rx_ring[ring_idx].base[i].rxd, &rxDesc); 1927 1786 1928 1787 if (rxd->btype == VMXNET3_RXD_BTYPE_HEAD && 1929 - rq->buf_info[ring_idx][i].skb) { 1788 + rbi->page && rbi->buf_type == VMXNET3_RX_BUF_XDP) { 1789 + page_pool_recycle_direct(rq->page_pool, 1790 + rbi->page); 1791 + rbi->page = NULL; 1792 + } else if (rxd->btype == VMXNET3_RXD_BTYPE_HEAD && 1793 + rbi->skb) { 1930 1794 dma_unmap_single(&adapter->pdev->dev, rxd->addr, 1931 1795 rxd->len, DMA_FROM_DEVICE); 1932 - dev_kfree_skb(rq->buf_info[ring_idx][i].skb); 1933 - rq->buf_info[ring_idx][i].skb = NULL; 1796 + dev_kfree_skb(rbi->skb); 1797 + rbi->skb = NULL; 1934 1798 } else if (rxd->btype == VMXNET3_RXD_BTYPE_BODY && 1935 - rq->buf_info[ring_idx][i].page) { 1799 + rbi->page) { 1936 1800 dma_unmap_page(&adapter->pdev->dev, rxd->addr, 1937 1801 rxd->len, DMA_FROM_DEVICE); 1938 - put_page(rq->buf_info[ring_idx][i].page); 1939 - rq->buf_info[ring_idx][i].page = NULL; 1802 + put_page(rbi->page); 1803 + rbi->page = NULL; 1940 1804 } 1941 1805 } 1942 1806 ··· 1965 1813 1966 1814 for (i = 0; i < adapter->num_rx_queues; i++) 1967 1815 vmxnet3_rq_cleanup(&adapter->rx_queue[i], adapter); 1816 + rcu_assign_pointer(adapter->xdp_bpf_prog, NULL); 1968 1817 } 1969 1818 1970 1819 ··· 1994 1841 rq->rx_ring[i].base = NULL; 1995 1842 } 1996 1843 } 1844 + 1845 + if (xdp_rxq_info_is_reg(&rq->xdp_rxq)) 1846 + xdp_rxq_info_unreg(&rq->xdp_rxq); 1847 + page_pool_destroy(rq->page_pool); 1848 + rq->page_pool = NULL; 1997 1849 1998 1850 if (rq->data_ring.base) { 1999 1851 dma_free_coherent(&adapter->pdev->dev, ··· 2043 1885 vmxnet3_rq_init(struct vmxnet3_rx_queue *rq, 2044 1886 struct vmxnet3_adapter *adapter) 2045 1887 { 2046 - int i; 1888 + int i, err; 2047 1889 2048 1890 /* initialize buf_info */ 2049 1891 for (i = 0; i < rq->rx_ring[0].size; i++) { 2050 1892 2051 - /* 1st buf for a pkt is skbuff */ 1893 + /* 1st buf for a pkt is skbuff or xdp page */ 2052 1894 if (i % adapter->rx_buf_per_pkt == 0) { 2053 - rq->buf_info[0][i].buf_type = VMXNET3_RX_BUF_SKB; 1895 + rq->buf_info[0][i].buf_type = vmxnet3_xdp_enabled(adapter) ? 1896 + VMXNET3_RX_BUF_XDP : 1897 + VMXNET3_RX_BUF_SKB; 2054 1898 rq->buf_info[0][i].len = adapter->skb_buf_size; 2055 1899 } else { /* subsequent bufs for a pkt is frag */ 2056 1900 rq->buf_info[0][i].buf_type = VMXNET3_RX_BUF_PAGE; ··· 2073 1913 rq->rx_ring[i].gen = VMXNET3_INIT_GEN; 2074 1914 rq->rx_ring[i].isOutOfOrder = 0; 2075 1915 } 1916 + 1917 + err = vmxnet3_create_pp(adapter, rq, 1918 + rq->rx_ring[0].size + rq->rx_ring[1].size); 1919 + if (err) 1920 + return err; 1921 + 2076 1922 if (vmxnet3_rq_alloc_rx_buf(rq, 0, rq->rx_ring[0].size - 1, 2077 1923 adapter) == 0) { 1924 + xdp_rxq_info_unreg(&rq->xdp_rxq); 1925 + page_pool_destroy(rq->page_pool); 1926 + rq->page_pool = NULL; 1927 + 2078 1928 /* at least has 1 rx buffer for the 1st ring */ 2079 1929 return -ENOMEM; 2080 1930 } ··· 2186 2016 } 2187 2017 2188 2018 2189 - static int 2019 + int 2190 2020 vmxnet3_rq_create_all(struct vmxnet3_adapter *adapter) 2191 2021 { 2192 2022 int i, err = 0; ··· 3223 3053 } 3224 3054 3225 3055 3226 - static void 3056 + void 3227 3057 vmxnet3_adjust_rx_ring_size(struct vmxnet3_adapter *adapter) 3228 3058 { 3229 3059 size_t sz, i, ring0_size, ring1_size, comp_size; ··· 3782 3612 #ifdef CONFIG_NET_POLL_CONTROLLER 3783 3613 .ndo_poll_controller = vmxnet3_netpoll, 3784 3614 #endif 3615 + .ndo_bpf = vmxnet3_xdp, 3616 + .ndo_xdp_xmit = vmxnet3_xdp_xmit, 3785 3617 }; 3786 3618 int err; 3787 3619 u32 ver; ··· 4036 3864 4037 3865 SET_NETDEV_DEV(netdev, &pdev->dev); 4038 3866 vmxnet3_declare_features(adapter); 3867 + netdev->xdp_features = NETDEV_XDP_ACT_BASIC | NETDEV_XDP_ACT_REDIRECT | 3868 + NETDEV_XDP_ACT_NDO_XMIT; 4039 3869 4040 3870 adapter->rxdata_desc_size = VMXNET3_VERSION_GE_3(adapter) ? 4041 3871 VMXNET3_DEF_RXDATA_DESC_SIZE : 0;
+23
drivers/net/vmxnet3/vmxnet3_ethtool.c
··· 28 28 #include "vmxnet3_int.h" 29 29 #include <net/vxlan.h> 30 30 #include <net/geneve.h> 31 + #include "vmxnet3_xdp.h" 31 32 32 33 #define VXLAN_UDP_PORT 8472 33 34 ··· 77 76 copy_skb_header) }, 78 77 { " giant hdr", offsetof(struct vmxnet3_tq_driver_stats, 79 78 oversized_hdr) }, 79 + { " xdp xmit", offsetof(struct vmxnet3_tq_driver_stats, 80 + xdp_xmit) }, 81 + { " xdp xmit err", offsetof(struct vmxnet3_tq_driver_stats, 82 + xdp_xmit_err) }, 80 83 }; 81 84 82 85 /* per rq stats maintained by the device */ ··· 111 106 drop_fcs) }, 112 107 { " rx buf alloc fail", offsetof(struct vmxnet3_rq_driver_stats, 113 108 rx_buf_alloc_failure) }, 109 + { " xdp packets", offsetof(struct vmxnet3_rq_driver_stats, 110 + xdp_packets) }, 111 + { " xdp tx", offsetof(struct vmxnet3_rq_driver_stats, 112 + xdp_tx) }, 113 + { " xdp redirects", offsetof(struct vmxnet3_rq_driver_stats, 114 + xdp_redirects) }, 115 + { " xdp drops", offsetof(struct vmxnet3_rq_driver_stats, 116 + xdp_drops) }, 117 + { " xdp aborted", offsetof(struct vmxnet3_rq_driver_stats, 118 + xdp_aborted) }, 114 119 }; 115 120 116 121 /* global stats maintained by the driver */ ··· 264 249 netdev_features_t vmxnet3_fix_features(struct net_device *netdev, 265 250 netdev_features_t features) 266 251 { 252 + struct vmxnet3_adapter *adapter = netdev_priv(netdev); 253 + 267 254 /* If Rx checksum is disabled, then LRO should also be disabled */ 268 255 if (!(features & NETIF_F_RXCSUM)) 269 256 features &= ~NETIF_F_LRO; 257 + 258 + /* If XDP is enabled, then LRO should not be enabled */ 259 + if (vmxnet3_xdp_enabled(adapter) && (features & NETIF_F_LRO)) { 260 + netdev_err(netdev, "LRO is not supported with XDP"); 261 + features &= ~NETIF_F_LRO; 262 + } 270 263 271 264 return features; 272 265 }
+33 -10
drivers/net/vmxnet3/vmxnet3_int.h
··· 56 56 #include <linux/if_arp.h> 57 57 #include <linux/inetdevice.h> 58 58 #include <linux/log2.h> 59 + #include <linux/bpf.h> 60 + #include <net/page_pool/helpers.h> 61 + #include <net/xdp.h> 59 62 60 63 #include "vmxnet3_defs.h" 61 64 ··· 191 188 dma_addr_t basePA; 192 189 }; 193 190 194 - enum vmxnet3_buf_map_type { 195 - VMXNET3_MAP_INVALID = 0, 196 - VMXNET3_MAP_NONE, 197 - VMXNET3_MAP_SINGLE, 198 - VMXNET3_MAP_PAGE, 199 - }; 191 + #define VMXNET3_MAP_NONE 0 192 + #define VMXNET3_MAP_SINGLE BIT(0) 193 + #define VMXNET3_MAP_PAGE BIT(1) 194 + #define VMXNET3_MAP_XDP BIT(2) 200 195 201 196 struct vmxnet3_tx_buf_info { 202 197 u32 map_type; 203 198 u16 len; 204 199 u16 sop_idx; 205 200 dma_addr_t dma_addr; 206 - struct sk_buff *skb; 201 + union { 202 + struct sk_buff *skb; 203 + struct xdp_frame *xdpf; 204 + }; 207 205 }; 208 206 209 207 struct vmxnet3_tq_driver_stats { ··· 221 217 u64 linearized; /* # of pkts linearized */ 222 218 u64 copy_skb_header; /* # of times we have to copy skb header */ 223 219 u64 oversized_hdr; 220 + 221 + u64 xdp_xmit; 222 + u64 xdp_xmit_err; 224 223 }; 225 224 226 225 struct vmxnet3_tx_ctx { ··· 260 253 * stopped */ 261 254 int qid; 262 255 u16 txdata_desc_size; 263 - } __attribute__((__aligned__(SMP_CACHE_BYTES))); 256 + } ____cacheline_aligned; 264 257 265 258 enum vmxnet3_rx_buf_type { 266 259 VMXNET3_RX_BUF_NONE = 0, 267 260 VMXNET3_RX_BUF_SKB = 1, 268 - VMXNET3_RX_BUF_PAGE = 2 261 + VMXNET3_RX_BUF_PAGE = 2, 262 + VMXNET3_RX_BUF_XDP = 3, 269 263 }; 270 264 271 265 #define VMXNET3_RXD_COMP_PENDING 0 ··· 293 285 u64 drop_err; 294 286 u64 drop_fcs; 295 287 u64 rx_buf_alloc_failure; 288 + 289 + u64 xdp_packets; /* Total packets processed by XDP. */ 290 + u64 xdp_tx; 291 + u64 xdp_redirects; 292 + u64 xdp_drops; 293 + u64 xdp_aborted; 296 294 }; 297 295 298 296 struct vmxnet3_rx_data_ring { ··· 321 307 struct vmxnet3_rx_buf_info *buf_info[2]; 322 308 struct Vmxnet3_RxQueueCtrl *shared; 323 309 struct vmxnet3_rq_driver_stats stats; 324 - } __attribute__((__aligned__(SMP_CACHE_BYTES))); 310 + struct page_pool *page_pool; 311 + struct xdp_rxq_info xdp_rxq; 312 + } ____cacheline_aligned; 325 313 326 314 #define VMXNET3_DEVICE_MAX_TX_QUEUES 32 327 315 #define VMXNET3_DEVICE_MAX_RX_QUEUES 32 /* Keep this value as a power of 2 */ ··· 431 415 u16 tx_prod_offset; 432 416 u16 rx_prod_offset; 433 417 u16 rx_prod2_offset; 418 + struct bpf_prog __rcu *xdp_bpf_prog; 434 419 }; 435 420 436 421 #define VMXNET3_WRITE_BAR0_REG(adapter, reg, val) \ ··· 506 489 507 490 void 508 491 vmxnet3_rq_destroy_all(struct vmxnet3_adapter *adapter); 492 + 493 + int 494 + vmxnet3_rq_create_all(struct vmxnet3_adapter *adapter); 495 + 496 + void 497 + vmxnet3_adjust_rx_ring_size(struct vmxnet3_adapter *adapter); 509 498 510 499 netdev_features_t 511 500 vmxnet3_fix_features(struct net_device *netdev, netdev_features_t features);
+419
drivers/net/vmxnet3/vmxnet3_xdp.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-or-later 2 + /* 3 + * Linux driver for VMware's vmxnet3 ethernet NIC. 4 + * Copyright (C) 2008-2023, VMware, Inc. All Rights Reserved. 5 + * Maintained by: pv-drivers@vmware.com 6 + * 7 + */ 8 + 9 + #include "vmxnet3_int.h" 10 + #include "vmxnet3_xdp.h" 11 + 12 + static void 13 + vmxnet3_xdp_exchange_program(struct vmxnet3_adapter *adapter, 14 + struct bpf_prog *prog) 15 + { 16 + rcu_assign_pointer(adapter->xdp_bpf_prog, prog); 17 + } 18 + 19 + static inline struct vmxnet3_tx_queue * 20 + vmxnet3_xdp_get_tq(struct vmxnet3_adapter *adapter) 21 + { 22 + struct vmxnet3_tx_queue *tq; 23 + int tq_number; 24 + int cpu; 25 + 26 + tq_number = adapter->num_tx_queues; 27 + cpu = smp_processor_id(); 28 + if (likely(cpu < tq_number)) 29 + tq = &adapter->tx_queue[cpu]; 30 + else 31 + tq = &adapter->tx_queue[reciprocal_scale(cpu, tq_number)]; 32 + 33 + return tq; 34 + } 35 + 36 + static int 37 + vmxnet3_xdp_set(struct net_device *netdev, struct netdev_bpf *bpf, 38 + struct netlink_ext_ack *extack) 39 + { 40 + struct vmxnet3_adapter *adapter = netdev_priv(netdev); 41 + struct bpf_prog *new_bpf_prog = bpf->prog; 42 + struct bpf_prog *old_bpf_prog; 43 + bool need_update; 44 + bool running; 45 + int err; 46 + 47 + if (new_bpf_prog && netdev->mtu > VMXNET3_XDP_MAX_MTU) { 48 + NL_SET_ERR_MSG_FMT_MOD(extack, "MTU %u too large for XDP", 49 + netdev->mtu); 50 + return -EOPNOTSUPP; 51 + } 52 + 53 + if (adapter->netdev->features & NETIF_F_LRO) { 54 + NL_SET_ERR_MSG_MOD(extack, "LRO is not supported with XDP"); 55 + adapter->netdev->features &= ~NETIF_F_LRO; 56 + } 57 + 58 + old_bpf_prog = rcu_dereference(adapter->xdp_bpf_prog); 59 + if (!new_bpf_prog && !old_bpf_prog) 60 + return 0; 61 + 62 + running = netif_running(netdev); 63 + need_update = !!old_bpf_prog != !!new_bpf_prog; 64 + 65 + if (running && need_update) 66 + vmxnet3_quiesce_dev(adapter); 67 + 68 + vmxnet3_xdp_exchange_program(adapter, new_bpf_prog); 69 + if (old_bpf_prog) 70 + bpf_prog_put(old_bpf_prog); 71 + 72 + if (!running || !need_update) 73 + return 0; 74 + 75 + if (new_bpf_prog) 76 + xdp_features_set_redirect_target(netdev, false); 77 + else 78 + xdp_features_clear_redirect_target(netdev); 79 + 80 + vmxnet3_reset_dev(adapter); 81 + vmxnet3_rq_destroy_all(adapter); 82 + vmxnet3_adjust_rx_ring_size(adapter); 83 + err = vmxnet3_rq_create_all(adapter); 84 + if (err) { 85 + NL_SET_ERR_MSG_MOD(extack, 86 + "failed to re-create rx queues for XDP."); 87 + return -EOPNOTSUPP; 88 + } 89 + err = vmxnet3_activate_dev(adapter); 90 + if (err) { 91 + NL_SET_ERR_MSG_MOD(extack, 92 + "failed to activate device for XDP."); 93 + return -EOPNOTSUPP; 94 + } 95 + clear_bit(VMXNET3_STATE_BIT_RESETTING, &adapter->state); 96 + 97 + return 0; 98 + } 99 + 100 + /* This is the main xdp call used by kernel to set/unset eBPF program. */ 101 + int 102 + vmxnet3_xdp(struct net_device *netdev, struct netdev_bpf *bpf) 103 + { 104 + switch (bpf->command) { 105 + case XDP_SETUP_PROG: 106 + return vmxnet3_xdp_set(netdev, bpf, bpf->extack); 107 + default: 108 + return -EINVAL; 109 + } 110 + 111 + return 0; 112 + } 113 + 114 + static int 115 + vmxnet3_xdp_xmit_frame(struct vmxnet3_adapter *adapter, 116 + struct xdp_frame *xdpf, 117 + struct vmxnet3_tx_queue *tq, bool dma_map) 118 + { 119 + struct vmxnet3_tx_buf_info *tbi = NULL; 120 + union Vmxnet3_GenericDesc *gdesc; 121 + struct vmxnet3_tx_ctx ctx; 122 + int tx_num_deferred; 123 + struct page *page; 124 + u32 buf_size; 125 + u32 dw2; 126 + 127 + dw2 = (tq->tx_ring.gen ^ 0x1) << VMXNET3_TXD_GEN_SHIFT; 128 + dw2 |= xdpf->len; 129 + ctx.sop_txd = tq->tx_ring.base + tq->tx_ring.next2fill; 130 + gdesc = ctx.sop_txd; 131 + 132 + buf_size = xdpf->len; 133 + tbi = tq->buf_info + tq->tx_ring.next2fill; 134 + 135 + if (vmxnet3_cmd_ring_desc_avail(&tq->tx_ring) == 0) { 136 + tq->stats.tx_ring_full++; 137 + return -ENOSPC; 138 + } 139 + 140 + tbi->map_type = VMXNET3_MAP_XDP; 141 + if (dma_map) { /* ndo_xdp_xmit */ 142 + tbi->dma_addr = dma_map_single(&adapter->pdev->dev, 143 + xdpf->data, buf_size, 144 + DMA_TO_DEVICE); 145 + if (dma_mapping_error(&adapter->pdev->dev, tbi->dma_addr)) 146 + return -EFAULT; 147 + tbi->map_type |= VMXNET3_MAP_SINGLE; 148 + } else { /* XDP buffer from page pool */ 149 + page = virt_to_page(xdpf->data); 150 + tbi->dma_addr = page_pool_get_dma_addr(page) + 151 + VMXNET3_XDP_HEADROOM; 152 + dma_sync_single_for_device(&adapter->pdev->dev, 153 + tbi->dma_addr, buf_size, 154 + DMA_TO_DEVICE); 155 + } 156 + tbi->xdpf = xdpf; 157 + tbi->len = buf_size; 158 + 159 + gdesc = tq->tx_ring.base + tq->tx_ring.next2fill; 160 + WARN_ON_ONCE(gdesc->txd.gen == tq->tx_ring.gen); 161 + 162 + gdesc->txd.addr = cpu_to_le64(tbi->dma_addr); 163 + gdesc->dword[2] = cpu_to_le32(dw2); 164 + 165 + /* Setup the EOP desc */ 166 + gdesc->dword[3] = cpu_to_le32(VMXNET3_TXD_CQ | VMXNET3_TXD_EOP); 167 + 168 + gdesc->txd.om = 0; 169 + gdesc->txd.msscof = 0; 170 + gdesc->txd.hlen = 0; 171 + gdesc->txd.ti = 0; 172 + 173 + tx_num_deferred = le32_to_cpu(tq->shared->txNumDeferred); 174 + le32_add_cpu(&tq->shared->txNumDeferred, 1); 175 + tx_num_deferred++; 176 + 177 + vmxnet3_cmd_ring_adv_next2fill(&tq->tx_ring); 178 + 179 + /* set the last buf_info for the pkt */ 180 + tbi->sop_idx = ctx.sop_txd - tq->tx_ring.base; 181 + 182 + dma_wmb(); 183 + gdesc->dword[2] = cpu_to_le32(le32_to_cpu(gdesc->dword[2]) ^ 184 + VMXNET3_TXD_GEN); 185 + 186 + /* No need to handle the case when tx_num_deferred doesn't reach 187 + * threshold. Backend driver at hypervisor side will poll and reset 188 + * tq->shared->txNumDeferred to 0. 189 + */ 190 + if (tx_num_deferred >= le32_to_cpu(tq->shared->txThreshold)) { 191 + tq->shared->txNumDeferred = 0; 192 + VMXNET3_WRITE_BAR0_REG(adapter, 193 + VMXNET3_REG_TXPROD + tq->qid * 8, 194 + tq->tx_ring.next2fill); 195 + } 196 + 197 + return 0; 198 + } 199 + 200 + static int 201 + vmxnet3_xdp_xmit_back(struct vmxnet3_adapter *adapter, 202 + struct xdp_frame *xdpf) 203 + { 204 + struct vmxnet3_tx_queue *tq; 205 + struct netdev_queue *nq; 206 + int err; 207 + 208 + tq = vmxnet3_xdp_get_tq(adapter); 209 + if (tq->stopped) 210 + return -ENETDOWN; 211 + 212 + nq = netdev_get_tx_queue(adapter->netdev, tq->qid); 213 + 214 + __netif_tx_lock(nq, smp_processor_id()); 215 + err = vmxnet3_xdp_xmit_frame(adapter, xdpf, tq, false); 216 + __netif_tx_unlock(nq); 217 + 218 + return err; 219 + } 220 + 221 + /* ndo_xdp_xmit */ 222 + int 223 + vmxnet3_xdp_xmit(struct net_device *dev, 224 + int n, struct xdp_frame **frames, u32 flags) 225 + { 226 + struct vmxnet3_adapter *adapter = netdev_priv(dev); 227 + struct vmxnet3_tx_queue *tq; 228 + int i; 229 + 230 + if (unlikely(test_bit(VMXNET3_STATE_BIT_QUIESCED, &adapter->state))) 231 + return -ENETDOWN; 232 + if (unlikely(test_bit(VMXNET3_STATE_BIT_RESETTING, &adapter->state))) 233 + return -EINVAL; 234 + 235 + tq = vmxnet3_xdp_get_tq(adapter); 236 + if (tq->stopped) 237 + return -ENETDOWN; 238 + 239 + for (i = 0; i < n; i++) { 240 + if (vmxnet3_xdp_xmit_frame(adapter, frames[i], tq, true)) { 241 + tq->stats.xdp_xmit_err++; 242 + break; 243 + } 244 + } 245 + tq->stats.xdp_xmit += i; 246 + 247 + return i; 248 + } 249 + 250 + static int 251 + vmxnet3_run_xdp(struct vmxnet3_rx_queue *rq, struct xdp_buff *xdp, 252 + struct bpf_prog *prog) 253 + { 254 + struct xdp_frame *xdpf; 255 + struct page *page; 256 + int err; 257 + u32 act; 258 + 259 + rq->stats.xdp_packets++; 260 + act = bpf_prog_run_xdp(prog, xdp); 261 + page = virt_to_page(xdp->data_hard_start); 262 + 263 + switch (act) { 264 + case XDP_PASS: 265 + return act; 266 + case XDP_REDIRECT: 267 + err = xdp_do_redirect(rq->adapter->netdev, xdp, prog); 268 + if (!err) { 269 + rq->stats.xdp_redirects++; 270 + } else { 271 + rq->stats.xdp_drops++; 272 + page_pool_recycle_direct(rq->page_pool, page); 273 + } 274 + return act; 275 + case XDP_TX: 276 + xdpf = xdp_convert_buff_to_frame(xdp); 277 + if (unlikely(!xdpf || 278 + vmxnet3_xdp_xmit_back(rq->adapter, xdpf))) { 279 + rq->stats.xdp_drops++; 280 + page_pool_recycle_direct(rq->page_pool, page); 281 + } else { 282 + rq->stats.xdp_tx++; 283 + } 284 + return act; 285 + default: 286 + bpf_warn_invalid_xdp_action(rq->adapter->netdev, prog, act); 287 + fallthrough; 288 + case XDP_ABORTED: 289 + trace_xdp_exception(rq->adapter->netdev, prog, act); 290 + rq->stats.xdp_aborted++; 291 + break; 292 + case XDP_DROP: 293 + rq->stats.xdp_drops++; 294 + break; 295 + } 296 + 297 + page_pool_recycle_direct(rq->page_pool, page); 298 + 299 + return act; 300 + } 301 + 302 + static struct sk_buff * 303 + vmxnet3_build_skb(struct vmxnet3_rx_queue *rq, struct page *page, 304 + const struct xdp_buff *xdp) 305 + { 306 + struct sk_buff *skb; 307 + 308 + skb = build_skb(page_address(page), PAGE_SIZE); 309 + if (unlikely(!skb)) { 310 + page_pool_recycle_direct(rq->page_pool, page); 311 + rq->stats.rx_buf_alloc_failure++; 312 + return NULL; 313 + } 314 + 315 + /* bpf prog might change len and data position. */ 316 + skb_reserve(skb, xdp->data - xdp->data_hard_start); 317 + skb_put(skb, xdp->data_end - xdp->data); 318 + skb_mark_for_recycle(skb); 319 + 320 + return skb; 321 + } 322 + 323 + /* Handle packets from DataRing. */ 324 + int 325 + vmxnet3_process_xdp_small(struct vmxnet3_adapter *adapter, 326 + struct vmxnet3_rx_queue *rq, 327 + void *data, int len, 328 + struct sk_buff **skb_xdp_pass) 329 + { 330 + struct bpf_prog *xdp_prog; 331 + struct xdp_buff xdp; 332 + struct page *page; 333 + int act; 334 + 335 + page = page_pool_alloc_pages(rq->page_pool, GFP_ATOMIC); 336 + if (unlikely(!page)) { 337 + rq->stats.rx_buf_alloc_failure++; 338 + return XDP_DROP; 339 + } 340 + 341 + xdp_init_buff(&xdp, PAGE_SIZE, &rq->xdp_rxq); 342 + xdp_prepare_buff(&xdp, page_address(page), rq->page_pool->p.offset, 343 + len, false); 344 + xdp_buff_clear_frags_flag(&xdp); 345 + 346 + /* Must copy the data because it's at dataring. */ 347 + memcpy(xdp.data, data, len); 348 + 349 + xdp_prog = rcu_dereference(rq->adapter->xdp_bpf_prog); 350 + if (!xdp_prog) { 351 + act = XDP_PASS; 352 + goto out_skb; 353 + } 354 + act = vmxnet3_run_xdp(rq, &xdp, xdp_prog); 355 + if (act != XDP_PASS) 356 + return act; 357 + 358 + out_skb: 359 + *skb_xdp_pass = vmxnet3_build_skb(rq, page, &xdp); 360 + if (!*skb_xdp_pass) 361 + return XDP_DROP; 362 + 363 + /* No need to refill. */ 364 + return likely(*skb_xdp_pass) ? act : XDP_DROP; 365 + } 366 + 367 + int 368 + vmxnet3_process_xdp(struct vmxnet3_adapter *adapter, 369 + struct vmxnet3_rx_queue *rq, 370 + struct Vmxnet3_RxCompDesc *rcd, 371 + struct vmxnet3_rx_buf_info *rbi, 372 + struct Vmxnet3_RxDesc *rxd, 373 + struct sk_buff **skb_xdp_pass) 374 + { 375 + struct bpf_prog *xdp_prog; 376 + dma_addr_t new_dma_addr; 377 + struct xdp_buff xdp; 378 + struct page *page; 379 + void *new_data; 380 + int act; 381 + 382 + page = rbi->page; 383 + dma_sync_single_for_cpu(&adapter->pdev->dev, 384 + page_pool_get_dma_addr(page) + 385 + rq->page_pool->p.offset, rcd->len, 386 + page_pool_get_dma_dir(rq->page_pool)); 387 + 388 + xdp_init_buff(&xdp, rbi->len, &rq->xdp_rxq); 389 + xdp_prepare_buff(&xdp, page_address(page), rq->page_pool->p.offset, 390 + rcd->len, false); 391 + xdp_buff_clear_frags_flag(&xdp); 392 + 393 + xdp_prog = rcu_dereference(rq->adapter->xdp_bpf_prog); 394 + if (!xdp_prog) { 395 + act = XDP_PASS; 396 + goto out_skb; 397 + } 398 + act = vmxnet3_run_xdp(rq, &xdp, xdp_prog); 399 + 400 + if (act == XDP_PASS) { 401 + out_skb: 402 + *skb_xdp_pass = vmxnet3_build_skb(rq, page, &xdp); 403 + if (!*skb_xdp_pass) 404 + act = XDP_DROP; 405 + } 406 + 407 + new_data = vmxnet3_pp_get_buff(rq->page_pool, &new_dma_addr, 408 + GFP_ATOMIC); 409 + if (!new_data) { 410 + rq->stats.rx_buf_alloc_failure++; 411 + return XDP_DROP; 412 + } 413 + rbi->page = virt_to_page(new_data); 414 + rbi->dma_addr = new_dma_addr; 415 + rxd->addr = cpu_to_le64(rbi->dma_addr); 416 + rxd->len = rbi->len; 417 + 418 + return act; 419 + }
+47
drivers/net/vmxnet3/vmxnet3_xdp.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0-or-later 2 + * 3 + * Linux driver for VMware's vmxnet3 ethernet NIC. 4 + * Copyright (C) 2008-2023, VMware, Inc. All Rights Reserved. 5 + * Maintained by: pv-drivers@vmware.com 6 + * 7 + */ 8 + 9 + #ifndef _VMXNET3_XDP_H 10 + #define _VMXNET3_XDP_H 11 + 12 + #include <linux/filter.h> 13 + #include <linux/bpf_trace.h> 14 + #include <linux/netlink.h> 15 + 16 + #include "vmxnet3_int.h" 17 + 18 + #define VMXNET3_XDP_HEADROOM (XDP_PACKET_HEADROOM + NET_IP_ALIGN) 19 + #define VMXNET3_XDP_RX_TAILROOM SKB_DATA_ALIGN(sizeof(struct skb_shared_info)) 20 + #define VMXNET3_XDP_RX_OFFSET VMXNET3_XDP_HEADROOM 21 + #define VMXNET3_XDP_MAX_FRSIZE (PAGE_SIZE - VMXNET3_XDP_HEADROOM - \ 22 + VMXNET3_XDP_RX_TAILROOM) 23 + #define VMXNET3_XDP_MAX_MTU (VMXNET3_XDP_MAX_FRSIZE - ETH_HLEN - \ 24 + 2 * VLAN_HLEN - ETH_FCS_LEN) 25 + 26 + int vmxnet3_xdp(struct net_device *netdev, struct netdev_bpf *bpf); 27 + int vmxnet3_xdp_xmit(struct net_device *dev, int n, struct xdp_frame **frames, 28 + u32 flags); 29 + int vmxnet3_process_xdp(struct vmxnet3_adapter *adapter, 30 + struct vmxnet3_rx_queue *rq, 31 + struct Vmxnet3_RxCompDesc *rcd, 32 + struct vmxnet3_rx_buf_info *rbi, 33 + struct Vmxnet3_RxDesc *rxd, 34 + struct sk_buff **skb_xdp_pass); 35 + int vmxnet3_process_xdp_small(struct vmxnet3_adapter *adapter, 36 + struct vmxnet3_rx_queue *rq, 37 + void *data, int len, 38 + struct sk_buff **skb_xdp_pass); 39 + void *vmxnet3_pp_get_buff(struct page_pool *pp, dma_addr_t *dma_addr, 40 + gfp_t gfp_mask); 41 + 42 + static inline bool vmxnet3_xdp_enabled(struct vmxnet3_adapter *adapter) 43 + { 44 + return !!rcu_access_pointer(adapter->xdp_bpf_prog); 45 + } 46 + 47 + #endif