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

tsnep: Fix mapping for zero copy XDP_TX action

For XDP_TX action xdp_buff is converted to xdp_frame. The conversion is
done by xdp_convert_buff_to_frame(). The memory type of the resulting
xdp_frame depends on the memory type of the xdp_buff. For page pool
based xdp_buff it produces xdp_frame with memory type
MEM_TYPE_PAGE_POOL. For zero copy XSK pool based xdp_buff it produces
xdp_frame with memory type MEM_TYPE_PAGE_ORDER0.

tsnep_xdp_xmit_back() is not prepared for that and uses always the page
pool buffer type TSNEP_TX_TYPE_XDP_TX. This leads to invalid mappings
and the transmission of undefined data.

Improve tsnep_xdp_xmit_back() to use the generic buffer type
TSNEP_TX_TYPE_XDP_NDO for zero copy XDP_TX.

Fixes: 3fc2333933fd ("tsnep: Add XDP socket zero-copy RX support")
Signed-off-by: Gerhard Engleder <gerhard@engleder-embedded.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Gerhard Engleder and committed by
David S. Miller
d7f5fb33 010e03db

+12 -4
+12 -4
drivers/net/ethernet/engleder/tsnep_main.c
··· 719 719 720 720 static bool tsnep_xdp_xmit_back(struct tsnep_adapter *adapter, 721 721 struct xdp_buff *xdp, 722 - struct netdev_queue *tx_nq, struct tsnep_tx *tx) 722 + struct netdev_queue *tx_nq, struct tsnep_tx *tx, 723 + bool zc) 723 724 { 724 725 struct xdp_frame *xdpf = xdp_convert_buff_to_frame(xdp); 725 726 bool xmit; 727 + u32 type; 726 728 727 729 if (unlikely(!xdpf)) 728 730 return false; 729 731 732 + /* no page pool for zero copy */ 733 + if (zc) 734 + type = TSNEP_TX_TYPE_XDP_NDO; 735 + else 736 + type = TSNEP_TX_TYPE_XDP_TX; 737 + 730 738 __netif_tx_lock(tx_nq, smp_processor_id()); 731 739 732 - xmit = tsnep_xdp_xmit_frame_ring(xdpf, tx, TSNEP_TX_TYPE_XDP_TX); 740 + xmit = tsnep_xdp_xmit_frame_ring(xdpf, tx, type); 733 741 734 742 /* Avoid transmit queue timeout since we share it with the slow path */ 735 743 if (xmit) ··· 1281 1273 case XDP_PASS: 1282 1274 return false; 1283 1275 case XDP_TX: 1284 - if (!tsnep_xdp_xmit_back(rx->adapter, xdp, tx_nq, tx)) 1276 + if (!tsnep_xdp_xmit_back(rx->adapter, xdp, tx_nq, tx, false)) 1285 1277 goto out_failure; 1286 1278 *status |= TSNEP_XDP_TX; 1287 1279 return true; ··· 1331 1323 case XDP_PASS: 1332 1324 return false; 1333 1325 case XDP_TX: 1334 - if (!tsnep_xdp_xmit_back(rx->adapter, xdp, tx_nq, tx)) 1326 + if (!tsnep_xdp_xmit_back(rx->adapter, xdp, tx_nq, tx, true)) 1335 1327 goto out_failure; 1336 1328 *status |= TSNEP_XDP_TX; 1337 1329 return true;