* [PATCH net-next 0/2] net: ntb_netdev: Preserve checksum offload across NTB
@ 2026-08-14 3:29 Koichiro Den
2026-08-14 3:29 ` [PATCH net-next 1/2] NTB: ntb_transport: Add per-payload client metadata Koichiro Den
2026-08-14 3:29 ` [PATCH net-next 2/2] net: ntb_netdev: Preserve CHECKSUM_PARTIAL across NTB Koichiro Den
0 siblings, 2 replies; 5+ messages in thread
From: Koichiro Den @ 2026-08-14 3:29 UTC (permalink / raw)
To: Jon Mason, Dave Jiang, Allen Hubbe, Andrew Lunn, David S. Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni
Cc: ntb, netdev, linux-kernel
ntb_netdev may be used on embedded systems, where CPU resources are
often limited. L4 checksum calculation can therefore become a bottleneck
even when traffic stays within a trusted PCIe fabric.
This small series carries CHECKSUM_PARTIAL state across the NTB link
using opaque per-payload metadata in ntb_transport. Existing peers
continue to use software checksumming. The feature remains disabled by
default and must be enabled explicitly for trusted links.
Best regards,
Koichiro
Koichiro Den (2):
NTB: ntb_transport: Add per-payload client metadata
net: ntb_netdev: Preserve CHECKSUM_PARTIAL across NTB
drivers/net/ntb_netdev.c | 78 +++++++++++++++++++++++++++++++++--
drivers/ntb/ntb_transport.c | 18 +++++---
include/linux/ntb_transport.h | 6 ++-
3 files changed, 91 insertions(+), 11 deletions(-)
base-commit: b3217bdb0091e52887e23896cd82483f7808914a
--
2.51.0
^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH net-next 1/2] NTB: ntb_transport: Add per-payload client metadata
2026-08-14 3:29 [PATCH net-next 0/2] net: ntb_netdev: Preserve checksum offload across NTB Koichiro Den
@ 2026-08-14 3:29 ` Koichiro Den
2026-08-15 3:29 ` sashiko-bot
2026-08-14 3:29 ` [PATCH net-next 2/2] net: ntb_netdev: Preserve CHECKSUM_PARTIAL across NTB Koichiro Den
1 sibling, 1 reply; 5+ messages in thread
From: Koichiro Den @ 2026-08-14 3:29 UTC (permalink / raw)
To: Jon Mason, Dave Jiang, Allen Hubbe, Andrew Lunn, David S. Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni
Cc: ntb, netdev, linux-kernel
ntb_transport currently carries only payload bytes, with no way for clients
to associate metadata with an individual payload.
The payload header has a 32-bit flags field, with only BIT(0) and BIT(1) in
use. Carry opaque client metadata in the upper 24 bits. Expose it through
the transmit enqueue interface and receive callback. Reject values that do
not fit. Keep the low byte for transport flags so future flags can continue
from BIT(2).
No protocol version bump is needed. Existing Linux version 4 peers ignore
the upper bits on receive and always transmit them as zero.
Adapt ntb_netdev to the new interfaces without using metadata.
Signed-off-by: Koichiro Den <den@valinux.co.jp>
---
drivers/net/ntb_netdev.c | 4 ++--
drivers/ntb/ntb_transport.c | 18 +++++++++++++-----
include/linux/ntb_transport.h | 6 ++++--
3 files changed, 19 insertions(+), 9 deletions(-)
diff --git a/drivers/net/ntb_netdev.c b/drivers/net/ntb_netdev.c
index 029a4a532a10..5c7fe6883cb9 100644
--- a/drivers/net/ntb_netdev.c
+++ b/drivers/net/ntb_netdev.c
@@ -123,7 +123,7 @@ static void ntb_netdev_event_handler(void *data, int link_is_up)
}
static void ntb_netdev_rx_handler(struct ntb_transport_qp *qp, void *qp_data,
- void *data, int len)
+ void *data, int len, unsigned int meta)
{
struct ntb_netdev_queue *q = qp_data;
struct ntb_netdev *dev = q->ntdev;
@@ -258,7 +258,7 @@ static netdev_tx_t ntb_netdev_start_xmit(struct sk_buff *skb,
ntb_netdev_maybe_stop_tx(ndev, q, tx_stop);
- rc = ntb_transport_tx_enqueue(q->qp, skb, skb->data, skb->len);
+ rc = ntb_transport_tx_enqueue(q->qp, skb, skb->data, skb->len, 0);
if (rc)
goto err;
diff --git a/drivers/ntb/ntb_transport.c b/drivers/ntb/ntb_transport.c
index f59f926d4bfa..ea97460c118a 100644
--- a/drivers/ntb/ntb_transport.c
+++ b/drivers/ntb/ntb_transport.c
@@ -167,7 +167,7 @@ struct ntb_transport_qp {
unsigned int tx_max_frame;
void (*rx_handler)(struct ntb_transport_qp *qp, void *qp_data,
- void *data, int len);
+ void *data, int len, unsigned int meta);
struct list_head rx_post_q;
struct list_head rx_pend_q;
struct list_head rx_free_q;
@@ -264,6 +264,10 @@ enum {
LINK_DOWN_FLAG = BIT(1),
};
+/* Reserve the low byte for transport flags. */
+#define DESC_META_SHIFT 8
+#define DESC_META_MASK (~0U << DESC_META_SHIFT)
+
struct ntb_payload_header {
unsigned int ver;
unsigned int len;
@@ -1435,6 +1439,7 @@ static void ntb_complete_rxc(struct ntb_transport_qp *qp)
struct ntb_queue_entry *entry;
void *cb_data;
unsigned int len;
+ unsigned int meta;
unsigned long irqflags;
spin_lock_irqsave(&qp->ntb_rx_q_lock, irqflags);
@@ -1450,13 +1455,14 @@ static void ntb_complete_rxc(struct ntb_transport_qp *qp)
cb_data = entry->cb_data;
len = entry->len;
+ meta = entry->flags >> DESC_META_SHIFT;
list_move_tail(&entry->entry, &qp->rx_free_q);
spin_unlock_irqrestore(&qp->ntb_rx_q_lock, irqflags);
if (qp->rx_handler && qp->client_ready)
- qp->rx_handler(qp, qp->cb_data, cb_data, len);
+ qp->rx_handler(qp, qp->cb_data, cb_data, len, meta);
spin_lock_irqsave(&qp->ntb_rx_q_lock, irqflags);
}
@@ -1647,6 +1653,7 @@ static int ntb_process_rxc(struct ntb_transport_qp *qp)
entry->rx_hdr = hdr;
entry->rx_index = qp->rx_index;
+ entry->flags = hdr->flags & DESC_META_MASK;
if (hdr->len > entry->len) {
dev_dbg(&qp->ndev->pdev->dev,
@@ -2332,6 +2339,7 @@ EXPORT_SYMBOL_GPL(ntb_transport_rx_enqueue);
* @cb: per buffer pointer for callback function to use
* @data: pointer to data buffer that will be sent
* @len: length of the data buffer
+ * @meta: client metadata to send with the buffer
*
* Enqueue a new transmit buffer onto the transport queue from which a NTB
* payload will be transmitted. This assumes that a lock is being held to
@@ -2340,12 +2348,12 @@ EXPORT_SYMBOL_GPL(ntb_transport_rx_enqueue);
* RETURNS: An appropriate -ERRNO error value on error, or zero for success.
*/
int ntb_transport_tx_enqueue(struct ntb_transport_qp *qp, void *cb, void *data,
- unsigned int len)
+ unsigned int len, unsigned int meta)
{
struct ntb_queue_entry *entry;
int rc;
- if (!qp || !len)
+ if (!qp || !len || meta > NTB_TRANSPORT_MAX_META)
return -EINVAL;
/* If the qp link is down already, just ignore. */
@@ -2361,7 +2369,7 @@ int ntb_transport_tx_enqueue(struct ntb_transport_qp *qp, void *cb, void *data,
entry->cb_data = cb;
entry->buf = data;
entry->len = len;
- entry->flags = 0;
+ entry->flags = meta << DESC_META_SHIFT;
entry->errors = 0;
entry->tx_index = 0;
diff --git a/include/linux/ntb_transport.h b/include/linux/ntb_transport.h
index 7243eb98a722..9e807542b6c4 100644
--- a/include/linux/ntb_transport.h
+++ b/include/linux/ntb_transport.h
@@ -50,6 +50,8 @@
struct ntb_transport_qp;
+#define NTB_TRANSPORT_MAX_META 0x00ffffffU
+
struct ntb_transport_client {
struct device_driver driver;
int (*probe)(struct device *client_dev);
@@ -63,7 +65,7 @@ void ntb_transport_unregister_client_dev(char *device_name);
struct ntb_queue_handlers {
void (*rx_handler)(struct ntb_transport_qp *qp, void *qp_data,
- void *data, int len);
+ void *data, int len, unsigned int meta);
void (*tx_handler)(struct ntb_transport_qp *qp, void *qp_data,
void *data, int len);
void (*event_handler)(void *data, int status);
@@ -78,7 +80,7 @@ void ntb_transport_free_queue(struct ntb_transport_qp *qp);
int ntb_transport_rx_enqueue(struct ntb_transport_qp *qp, void *cb, void *data,
unsigned int len);
int ntb_transport_tx_enqueue(struct ntb_transport_qp *qp, void *cb, void *data,
- unsigned int len);
+ unsigned int len, unsigned int meta);
void *ntb_transport_rx_remove(struct ntb_transport_qp *qp, unsigned int *len);
void ntb_transport_link_up(struct ntb_transport_qp *qp);
void ntb_transport_link_down(struct ntb_transport_qp *qp);
--
2.51.0
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH net-next 2/2] net: ntb_netdev: Preserve CHECKSUM_PARTIAL across NTB
2026-08-14 3:29 [PATCH net-next 0/2] net: ntb_netdev: Preserve checksum offload across NTB Koichiro Den
2026-08-14 3:29 ` [PATCH net-next 1/2] NTB: ntb_transport: Add per-payload client metadata Koichiro Den
@ 2026-08-14 3:29 ` Koichiro Den
2026-08-15 3:29 ` sashiko-bot
1 sibling, 1 reply; 5+ messages in thread
From: Koichiro Den @ 2026-08-14 3:29 UTC (permalink / raw)
To: Jon Mason, Dave Jiang, Allen Hubbe, Andrew Lunn, David S. Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni
Cc: ntb, netdev, linux-kernel
Calculating L4 checksums can limit ntb_netdev throughput especially on
embedded systems, where CPU resources are often limited. A trusted PCIe
fabric can avoid that work.
Carry CHECKSUM_PARTIAL with csum_start and csum_offset across the NTB link.
Advertise support in every frame and fall back to software until the peer
capability is seen. This preserves netdev checksum semantics and
interoperability with existing transport version 4 peers.
Leave the TX and RX checksum features disabled by default. Users can
just enable them explicitly for links they trust for lower CPU usage
and/or higher throughput.
Signed-off-by: Koichiro Den <den@valinux.co.jp>
---
drivers/net/ntb_netdev.c | 76 ++++++++++++++++++++++++++++++++++++++--
1 file changed, 73 insertions(+), 3 deletions(-)
diff --git a/drivers/net/ntb_netdev.c b/drivers/net/ntb_netdev.c
index 5c7fe6883cb9..b9a78ff695c8 100644
--- a/drivers/net/ntb_netdev.c
+++ b/drivers/net/ntb_netdev.c
@@ -4,6 +4,7 @@
*/
#include <linux/etherdevice.h>
#include <linux/ethtool.h>
+#include <linux/if_vlan.h>
#include <linux/module.h>
#include <linux/pci.h>
#include <linux/ntb.h>
@@ -29,6 +30,21 @@ static unsigned int tx_stop = 5;
#define NTB_NETDEV_MAX_QUEUES 64
#define NTB_NETDEV_DEFAULT_QUEUES 1
+/*
+ * Checksum metadata layout:
+ * bit 23 capability, advertised on every packet
+ * bit 22 per-packet CHECKSUM_PARTIAL flag
+ * bit 21..6 skb_checksum_start_offset() (16 bits)
+ * bit 5..0 skb->csum_offset (6 bits)
+ *
+ * Until the capability is observed, complete partial checksums in software.
+ * Six offset bits cover TCP/UDP. Larger offsets use software checksumming.
+ */
+#define NTB_NETDEV_META_CAP_CSUM BIT(23)
+#define NTB_NETDEV_META_CSUM BIT(22)
+#define NTB_NETDEV_META_CSUM_START_SHIFT 6
+#define NTB_NETDEV_META_CSUM_OFFSET_MASK GENMASK(5, 0)
+
struct ntb_netdev;
struct ntb_netdev_queue {
@@ -44,6 +60,7 @@ struct ntb_netdev {
struct net_device *ndev;
unsigned int num_queues;
struct ntb_netdev_queue *queues;
+ bool peer_csum;
};
#define NTB_TX_TIMEOUT_MS 1000
@@ -108,6 +125,8 @@ static void ntb_netdev_event_handler(void *data, int link_is_up)
struct net_device *ndev;
ndev = dev->ndev;
+ if (!link_is_up)
+ WRITE_ONCE(dev->peer_csum, false);
netdev_dbg(ndev, "Event %x, Link %x, qp %u\n", link_is_up,
ntb_transport_link_query(q->qp), q->qid);
@@ -151,8 +170,21 @@ static void ntb_netdev_rx_handler(struct ntb_transport_qp *qp, void *qp_data,
}
skb_put(skb, len);
+ if (meta & NTB_NETDEV_META_CAP_CSUM)
+ WRITE_ONCE(dev->peer_csum, true);
+
+ if (meta & NTB_NETDEV_META_CSUM) {
+ u16 csum_start = (meta >> NTB_NETDEV_META_CSUM_START_SHIFT) & U16_MAX;
+ u16 csum_offset = meta & NTB_NETDEV_META_CSUM_OFFSET_MASK;
+
+ if (!skb_partial_csum_set(skb, csum_start, csum_offset))
+ goto rx_drop;
+
+ if (!(ndev->features & NETIF_F_RXCSUM) &&
+ skb_checksum_help(skb))
+ goto rx_drop;
+ }
skb->protocol = eth_type_trans(skb, ndev);
- skb->ip_summed = CHECKSUM_NONE;
skb_record_rx_queue(skb, q->qid);
if (netif_rx(skb) == NET_RX_DROP) {
@@ -172,6 +204,14 @@ static void ntb_netdev_rx_handler(struct ntb_transport_qp *qp, void *qp_data,
ndev->stats.rx_errors++;
ndev->stats.rx_fifo_errors++;
}
+ return;
+
+rx_drop:
+ ndev->stats.rx_errors++;
+ ndev->stats.rx_dropped++;
+ dev_kfree_skb_any(skb);
+ skb = new_skb;
+ goto enqueue_again;
}
static int __ntb_netdev_maybe_stop_tx(struct net_device *netdev,
@@ -252,13 +292,24 @@ static netdev_tx_t ntb_netdev_start_xmit(struct sk_buff *skb,
struct ntb_netdev *dev = netdev_priv(ndev);
u16 qid = skb_get_queue_mapping(skb);
struct ntb_netdev_queue *q;
+ unsigned int meta = NTB_NETDEV_META_CAP_CSUM;
int rc;
q = &dev->queues[qid];
ntb_netdev_maybe_stop_tx(ndev, q, tx_stop);
- rc = ntb_transport_tx_enqueue(q->qp, skb, skb->data, skb->len, 0);
+ if (skb->ip_summed == CHECKSUM_PARTIAL) {
+ if (READ_ONCE(dev->peer_csum))
+ meta |= NTB_NETDEV_META_CSUM |
+ (skb_checksum_start_offset(skb) <<
+ NTB_NETDEV_META_CSUM_START_SHIFT) |
+ skb->csum_offset;
+ else if (skb_checksum_help(skb))
+ goto drop;
+ }
+
+ rc = ntb_transport_tx_enqueue(q->qp, skb, skb->data, skb->len, meta);
if (rc)
goto err;
@@ -267,12 +318,29 @@ static netdev_tx_t ntb_netdev_start_xmit(struct sk_buff *skb,
return NETDEV_TX_OK;
+drop:
+ dev_kfree_skb_any(skb);
+ ndev->stats.tx_dropped++;
+ ndev->stats.tx_errors++;
+ return NETDEV_TX_OK;
+
err:
ndev->stats.tx_dropped++;
ndev->stats.tx_errors++;
return NETDEV_TX_BUSY;
}
+static netdev_features_t ntb_netdev_features_check(struct sk_buff *skb,
+ struct net_device *ndev,
+ netdev_features_t features)
+{
+ if (skb->ip_summed == CHECKSUM_PARTIAL &&
+ skb->csum_offset > NTB_NETDEV_META_CSUM_OFFSET_MASK)
+ features &= ~NETIF_F_CSUM_MASK;
+
+ return vlan_features_check(skb, features);
+}
+
static void ntb_netdev_tx_timer(struct timer_list *t)
{
struct ntb_netdev_queue *q = timer_container_of(q, t, tx_timer);
@@ -423,6 +491,7 @@ static const struct net_device_ops ntb_netdev_ops = {
.ndo_open = ntb_netdev_open,
.ndo_stop = ntb_netdev_close,
.ndo_start_xmit = ntb_netdev_start_xmit,
+ .ndo_features_check = ntb_netdev_features_check,
.ndo_change_mtu = ntb_netdev_change_mtu,
.ndo_set_mac_address = eth_mac_addr,
};
@@ -642,7 +711,8 @@ static int ntb_netdev_probe(struct device *client_dev)
ndev->priv_flags |= IFF_LIVE_ADDR_CHANGE;
- ndev->hw_features = ndev->features;
+ /* Checksum bypass assumes a trusted NTB link, so keep it opt-in. */
+ ndev->hw_features = ndev->features | NETIF_F_HW_CSUM | NETIF_F_RXCSUM;
ndev->watchdog_timeo = msecs_to_jiffies(NTB_TX_TIMEOUT_MS);
eth_random_addr(ndev->perm_addr);
--
2.51.0
^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCH net-next 1/2] NTB: ntb_transport: Add per-payload client metadata
2026-08-14 3:29 ` [PATCH net-next 1/2] NTB: ntb_transport: Add per-payload client metadata Koichiro Den
@ 2026-08-15 3:29 ` sashiko-bot
0 siblings, 0 replies; 5+ messages in thread
From: sashiko-bot @ 2026-08-15 3:29 UTC (permalink / raw)
To: Koichiro Den; +Cc: ntb
Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider:
Pre-existing issues:
- [High] Oversized packets trigger a memory leak by passing NULL to the tx_handler, failing to free the SKB.
- [High] The RX descriptor polling path lacks a dma_rmb() barrier between checking the completion flag and reading the descriptor data.
- [High] The driver writes hardware descriptor fields using little-endian I/O accessors but reads them as native integers, breaking functionality on big-endian architectures.
--
--- Patch [1]: [PATCH net-next 1/2] NTB: ntb_transport: Add per-payload client metadata ---
commit 581d6bed46f9b62bccae9a18ddae3275987b5c5b
Author: Koichiro Den <den@valinux.co.jp>
NTB: ntb_transport: Add per-payload client metadata
This patch adds support for 24-bit per-payload client metadata in the NTB
transport payload header. It updates the transport enqueue and receive
handlers to pass this metadata without bumping the protocol version.
> diff --git a/drivers/ntb/ntb_transport.c b/drivers/ntb/ntb_transport.c
> index f59f926d4bfaa..ea97460c118ad 100644
> --- a/drivers/ntb/ntb_transport.c
> +++ b/drivers/ntb/ntb_transport.c
[ ... ]
> @@ -1647,6 +1653,7 @@ static int ntb_process_rxc(struct ntb_transport_qp *qp)
>
> entry->rx_hdr = hdr;
> entry->rx_index = qp->rx_index;
> + entry->flags = hdr->flags & DESC_META_MASK;
>
> if (hdr->len > entry->len) {
> dev_dbg(&qp->ndev->pdev->dev,
[Severity: High]
This is a pre-existing issue, but I noticed there may be a missing memory
barrier in ntb_process_rxc() when reading the descriptor.
The hardware writes the payload and the descriptor to host memory. The CPU
polls hdr->flags for DESC_DONE_FLAG, and then immediately reads fields like
hdr->ver and hdr->len.
Without a dma_rmb() after checking the flag, could weakly-ordered CPUs
speculatively fetch the descriptor fields or payload before the DMA transfer
actually commits to memory?
[Severity: High]
This isn't a bug introduced by this patch, but there appears to be an
endianness mismatch when reading these descriptor fields.
On the TX side, descriptor fields seem to be written using iowrite32(),
which implicitly performs a little-endian byte swap on big-endian CPUs.
However, in ntb_process_rxc(), they are accessed directly as native
integers (e.g., hdr->len). Won't this evaluate the little-endian bytes
incorrectly on big-endian architectures, causing version mismatches and
incorrect lengths?
[ ... ]
> @@ -2361,7 +2369,7 @@ int ntb_transport_tx_enqueue(struct ntb_transport_qp *qp, void *cb, void *data,
> entry->cb_data = cb;
> entry->buf = data;
> entry->len = len;
> - entry->flags = 0;
> + entry->flags = meta << DESC_META_SHIFT;
> entry->errors = 0;
> entry->tx_index = 0;
>
[Severity: High]
This is a pre-existing issue, but I noticed a potential memory leak during
TX when an oversized packet is enqueued.
If ntb_process_tx() detects a length overflow, it aborts transmission and
calls the transmit handler. However, it passes NULL instead of the original
buffer context to the handler:
ntb_process_tx()
if (qp->tx_handler)
qp->tx_handler(qp, qp->cb_data, NULL, -EIO);
Since ntb_netdev_tx_handler() explicitly checks if the skb is NULL and
returns immediately without freeing it, won't this leak the SKB if the
MTU check is bypassed or misconfigured?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260814032913.3558500-1-den@valinux.co.jp?part=1
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH net-next 2/2] net: ntb_netdev: Preserve CHECKSUM_PARTIAL across NTB
2026-08-14 3:29 ` [PATCH net-next 2/2] net: ntb_netdev: Preserve CHECKSUM_PARTIAL across NTB Koichiro Den
@ 2026-08-15 3:29 ` sashiko-bot
0 siblings, 0 replies; 5+ messages in thread
From: sashiko-bot @ 2026-08-15 3:29 UTC (permalink / raw)
To: Koichiro Den; +Cc: ntb
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [High] Race condition during link teardown leaves `peer_csum` flag incorrectly enabled for subsequent connections, leading to dropped packets.
--
--- Patch [2]: [PATCH net-next 2/2] net: ntb_netdev: Preserve CHECKSUM_PARTIAL across NTB ---
commit 361f3725205633c095fdcdcc524204c1da6ec87e
Author: Koichiro Den <den@valinux.co.jp>
Subject: net: ntb_netdev: Preserve CHECKSUM_PARTIAL across NTB
This commit introduces CHECKSUM_PARTIAL metadata across the NTB link to
improve throughput and reduce CPU usage on trusted PCIe fabrics. It
advertises checksum support in every frame and falls back to software
checksumming until the peer capability is observed. TX and RX checksum
features remain disabled by default.
> diff --git a/drivers/net/ntb_netdev.c b/drivers/net/ntb_netdev.c
> index 5c7fe6883cb93..b9a78ff695c87 100644
> --- a/drivers/net/ntb_netdev.c
> +++ b/drivers/net/ntb_netdev.c
[ ... ]
> @@ -108,6 +125,8 @@ static void ntb_netdev_event_handler(void *data, int link_is_up)
> struct net_device *ndev;
>
> ndev = dev->ndev;
> + if (!link_is_up)
> + WRITE_ONCE(dev->peer_csum, false);
>
> netdev_dbg(ndev, "Event %x, Link %x, qp %u\n", link_is_up,
> ntb_transport_link_query(q->qp), q->qid);
[ ... ]
> @@ -151,8 +170,21 @@ static void ntb_netdev_rx_handler(struct ntb_transport_qp *qp, void *qp_data,
> }
>
> skb_put(skb, len);
> + if (meta & NTB_NETDEV_META_CAP_CSUM)
> + WRITE_ONCE(dev->peer_csum, true);
[Severity: High]
Could a race condition occur during link teardown that leaves peer_csum
incorrectly enabled?
If the NTB link goes down, ntb_netdev_event_handler() clears dev->peer_csum.
However, if the RX tasklet is concurrently processing a straggler packet
sent before the link went down, ntb_netdev_rx_handler() will execute and
unconditionally set dev->peer_csum to true when it sees the capability bit.
When a new connection is established, dev->peer_csum would not be reset. If
the new peer is an older driver that does not support checksum offload, the
local driver might incorrectly skip software checksumming and send packets
with CHECKSUM_PARTIAL. Would this cause the older peer's networking stack to
see invalid checksums and silently drop the packets?
> +
> + if (meta & NTB_NETDEV_META_CSUM) {
> + u16 csum_start = (meta >> NTB_NETDEV_META_CSUM_START_SHIFT) & U16_MAX;
> + u16 csum_offset = meta & NTB_NETDEV_META_CSUM_OFFSET_MASK;
> +
> + if (!skb_partial_csum_set(skb, csum_start, csum_offset))
> + goto rx_drop;
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260814032913.3558500-1-den@valinux.co.jp?part=2
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2026-08-15 3:29 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-14 3:29 [PATCH net-next 0/2] net: ntb_netdev: Preserve checksum offload across NTB Koichiro Den
2026-08-14 3:29 ` [PATCH net-next 1/2] NTB: ntb_transport: Add per-payload client metadata Koichiro Den
2026-08-15 3:29 ` sashiko-bot
2026-08-14 3:29 ` [PATCH net-next 2/2] net: ntb_netdev: Preserve CHECKSUM_PARTIAL across NTB Koichiro Den
2026-08-15 3:29 ` sashiko-bot
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.