Bug 268092 - ixgbe: if_ixv driver have mismatched Rx buffer size and rx_mbuf_sz
Summary: ixgbe: if_ixv driver have mismatched Rx buffer size and rx_mbuf_sz
Status: New
Alias: None
Product: Base System
Classification: Unclassified
Component: kern (show other bugs)
Version: 12.2-STABLE
Hardware: amd64 Any
: --- Affects Many People
Assignee: freebsd-net (Nobody)
URL:
Keywords: IntelNetworking
Depends on:
Blocks:
 
Reported: 2022-12-01 02:04 UTC by Kumara Babu
Modified: 2022-12-12 13:58 UTC (History)
3 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Kumara Babu 2022-12-01 02:04:53 UTC
If MTU of the if_ixv VF driver is configured between 1501 and 2030, and if a peer box have bigger MTU and sends a packet bigger than MTU into this guest, kernel could crashes. 

Here is my understanding :
There are 2 buffers involved for Rx process. One for the DMA(bufsz) and
another(rx_mbuf_sz) for sending that packet to netstack.

In if_ixv driver, bufsz is set to 4096 if MTU is more than the default
MTU: 1500. Whereas rx_mbuf_sz is set to 2048, for upto MTU 2030
(Calculation is based on frame size: 18). Because of this, for MTU upto
1500, both rx_mbuf_sz & bufsz is 2048. And for MTU above 2031,  both 
rx_mbuf_sz & bufsz is 4096. Whereas for MTU 1501 to 2030, rx_mbuf_sz 
will be 2048 and bufsz is 4096. 

So for MTU between 1501 and 2030, if the peer box have bigger MTU and 
sends a bigger packet, there is a mismatch between what's written to 
the Rx buffers and what's sent to netstack. And when that memory beyond
allocated 2048 is accessed, kernel crashes. 

Ideally, bufsz should be based on rx_mbuf_sz (This is calculated right
before configuring Rx settings). 

I could crash the box my setting MTU between 1501 and 2030 and sending sending 8k sized ping packet very consistently and with this below fix to match
bufsz & rx_mbuf_sz, could verify that no crash occurred. 


--- a/sys/dev/ixgbe/if_ixv.c
+++ b/sys/dev/ixgbe/if_ixv.c
@@ -1368,7 +1376,7 @@ ixv_initialize_receive_units(if_ctx_t ctx)
        struct ix_rx_queue *que = adapter->rx_queues;
        u32                bufsz, psrtype;
 
-       if (if_getmtu(ifp) > ETHERMTU)
+       if (adapter->rx_mbuf_sz > 2048)
                bufsz = 4096 >> IXGBE_SRRCTL_BSIZEPKT_SHIFT;
        else
                bufsz = 2048 >> IXGBE_SRRCTL_BSIZEPKT_SHIFT;