* [PATCH] net: lwip: handle chained pbufs in transmit path
@ 2026-07-15 8:42 Weijie Gao
2026-07-16 7:56 ` Jerome Forissier
0 siblings, 1 reply; 5+ messages in thread
From: Weijie Gao @ 2026-07-15 8:42 UTC (permalink / raw)
To: u-boot
Cc: GSS_MTK_Uboot_upstream, Tom Rini, Jerome Forissier,
Andrew Goodbody, Tim Harvey, Ilias Apalodimas, Weijie Gao
LwIP may pass a packet to the netif linkoutput callback as a chain
of pbufs. In this case, p->len only describes the length of the
first pbuf, while p->tot_len describes the length of the whole
packet.
The current transmit path only sends the first pbuf. This can
truncate packets whose headers have already been generated for the
full packet length, resulting in malformed frames on the wire.
For example, the IP header may record a larger total length than the
actual Ethernet frame length.
Assemble chained pbufs into one aligned contiguous buffer before
passing the packet to the Ethernet driver.
Fixes: 98ad145db61a (net: lwip: add DHCP support and dhcp commmand)
Signed-off-by: Weijie Gao <weijie.gao@mediatek.com>
---
net/lwip/net-lwip.c | 45 ++++++++++++++++++++++++++++++++-------------
1 file changed, 32 insertions(+), 13 deletions(-)
diff --git a/net/lwip/net-lwip.c b/net/lwip/net-lwip.c
index cfe5a6a640d..8f8f9d69020 100644
--- a/net/lwip/net-lwip.c
+++ b/net/lwip/net-lwip.c
@@ -40,28 +40,47 @@ char *pxelinux_configfile;
static err_t net_lwip_tx(struct netif *netif, struct pbuf *p)
{
struct udevice *udev = netif->state;
- void *pp = NULL;
+ bool pp_allocated = false;
+ u32 plen;
+ void *pp;
int err;
- if (CONFIG_IS_ENABLED(LWIP_DEBUG_RXTX)) {
- printf("net_lwip_tx: %u bytes, udev %s\n", p->len, udev->name);
- print_hex_dump("net_lwip_tx: ", 0, 16, 1, p->payload, p->len,
- true);
- }
-
- if ((unsigned long)p->payload % PKTALIGN) {
+ if ((unsigned long)p->payload % PKTALIGN || p->len != p->tot_len) {
/*
* Some net drivers have strict alignment requirements and may
* fail or output invalid data if the packet is not aligned.
+ *
+ * A packet may also be stored in multiple chained pbufs. In
+ * this case, assemble the fragments into one contiguous packet
+ * buffer before passing it to the Ethernet driver.
*/
- pp = memalign(PKTALIGN, p->len);
+
+ pp = memalign(PKTALIGN, p->tot_len);
if (!pp)
- return ERR_ABRT;
- memcpy(pp, p->payload, p->len);
+ return ERR_MEM;
+
+ pp_allocated = true;
+
+ plen = pbuf_copy_partial(p, pp, p->tot_len, 0);
+ if (plen != p->tot_len) {
+ free(pp);
+ return ERR_BUF;
+ }
+ } else {
+ pp = p->payload;
+ plen = p->len;
+ }
+
+ if (CONFIG_IS_ENABLED(LWIP_DEBUG_RXTX)) {
+ printf("net_lwip_tx: %u bytes, udev %s\n", plen, udev->name);
+ print_hex_dump("net_lwip_tx: ", 0, 16, 1, pp, plen, true);
}
- err = eth_get_ops(udev)->send(udev, pp ? pp : p->payload, p->len);
- free(pp);
+ err = eth_get_ops(udev)->send(udev, pp, plen);
+
+ if (pp_allocated)
+ free(pp);
+
if (err) {
debug("send error %d\n", err);
return ERR_ABRT;
--
2.45.2
^ permalink raw reply related [flat|nested] 5+ messages in thread* Re: [PATCH] net: lwip: handle chained pbufs in transmit path
2026-07-15 8:42 [PATCH] net: lwip: handle chained pbufs in transmit path Weijie Gao
@ 2026-07-16 7:56 ` Jerome Forissier
2026-07-16 8:00 ` Jerome Forissier
0 siblings, 1 reply; 5+ messages in thread
From: Jerome Forissier @ 2026-07-16 7:56 UTC (permalink / raw)
To: Weijie Gao, u-boot
Cc: GSS_MTK_Uboot_upstream, Tom Rini, Andrew Goodbody, Tim Harvey,
Ilias Apalodimas, nd
On 15/07/2026 10:42, Weijie Gao wrote:
> LwIP may pass a packet to the netif linkoutput callback as a chain
> of pbufs. In this case, p->len only describes the length of the
> first pbuf, while p->tot_len describes the length of the whole
> packet.
>
> The current transmit path only sends the first pbuf. This can
> truncate packets whose headers have already been generated for the
> full packet length, resulting in malformed frames on the wire.
> For example, the IP header may record a larger total length than the
> actual Ethernet frame length.
>
> Assemble chained pbufs into one aligned contiguous buffer before
> passing the packet to the Ethernet driver.
>
> Fixes: 98ad145db61a (net: lwip: add DHCP support and dhcp commmand)
> Signed-off-by: Weijie Gao <weijie.gao@mediatek.com>
Good catch! That was a big oversight :-/ thanks for the fix.
Reviewed-by: Jerome Forissier <jerome.forissier@arm.com>
--
Jerome
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH] net: lwip: handle chained pbufs in transmit path
2026-07-16 7:56 ` Jerome Forissier
@ 2026-07-16 8:00 ` Jerome Forissier
0 siblings, 0 replies; 5+ messages in thread
From: Jerome Forissier @ 2026-07-16 8:00 UTC (permalink / raw)
To: Weijie Gao, u-boot
Cc: GSS_MTK_Uboot_upstream, Tom Rini, Andrew Goodbody, Tim Harvey,
Ilias Apalodimas, nd
On 16/07/2026 09:56, Jerome Forissier wrote:
> On 15/07/2026 10:42, Weijie Gao wrote:
>> LwIP may pass a packet to the netif linkoutput callback as a chain
>> of pbufs. In this case, p->len only describes the length of the
>> first pbuf, while p->tot_len describes the length of the whole
>> packet.
>>
>> The current transmit path only sends the first pbuf. This can
>> truncate packets whose headers have already been generated for the
>> full packet length, resulting in malformed frames on the wire.
>> For example, the IP header may record a larger total length than the
>> actual Ethernet frame length.
>>
>> Assemble chained pbufs into one aligned contiguous buffer before
>> passing the packet to the Ethernet driver.
>>
>> Fixes: 98ad145db61a (net: lwip: add DHCP support and dhcp commmand)
>> Signed-off-by: Weijie Gao <weijie.gao@mediatek.com>
>
> Good catch! That was a big oversight :-/ thanks for the fix.
>
> Reviewed-by: Jerome Forissier <jerome.forissier@arm.com>
>
...and applied to u-boot-net/for-master.
--
Jerome
^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH] net: lwip: handle chained pbufs in transmit path
@ 2026-07-27 8:02 Weijie Gao
2026-07-27 8:06 ` Weijie Gao
0 siblings, 1 reply; 5+ messages in thread
From: Weijie Gao @ 2026-07-27 8:02 UTC (permalink / raw)
To: u-boot
Cc: GSS_MTK_Uboot_upstream, Tom Rini, Vignesh R, Takahiro Kuwano,
Marek Vasut, Tudor Ambarus, Jeffrey Yu, Christoph Reiter,
Miquel Raynal, Shiji Yang, Bernhard Messerklinger,
Vaishnav Achath, Prasad Kummari, Weijie Gao
LwIP may pass a packet to the netif linkoutput callback as a chain
of pbufs. In this case, p->len only describes the length of the
first pbuf, while p->tot_len describes the length of the whole
packet.
The current transmit path only sends the first pbuf. This can
truncate packets whose headers have already been generated for the
full packet length, resulting in malformed frames on the wire.
For example, the IP header may record a larger total length than the
actual Ethernet frame length.
Assemble chained pbufs into one aligned contiguous buffer before
passing the packet to the Ethernet driver.
Fixes: 98ad145db61a (net: lwip: add DHCP support and dhcp commmand)
Signed-off-by: Weijie Gao <weijie.gao@mediatek.com>
---
net/lwip/net-lwip.c | 45 ++++++++++++++++++++++++++++++++-------------
1 file changed, 32 insertions(+), 13 deletions(-)
diff --git a/net/lwip/net-lwip.c b/net/lwip/net-lwip.c
index cfe5a6a640d..8f8f9d69020 100644
--- a/net/lwip/net-lwip.c
+++ b/net/lwip/net-lwip.c
@@ -40,28 +40,47 @@ char *pxelinux_configfile;
static err_t net_lwip_tx(struct netif *netif, struct pbuf *p)
{
struct udevice *udev = netif->state;
- void *pp = NULL;
+ bool pp_allocated = false;
+ u32 plen;
+ void *pp;
int err;
- if (CONFIG_IS_ENABLED(LWIP_DEBUG_RXTX)) {
- printf("net_lwip_tx: %u bytes, udev %s\n", p->len, udev->name);
- print_hex_dump("net_lwip_tx: ", 0, 16, 1, p->payload, p->len,
- true);
- }
-
- if ((unsigned long)p->payload % PKTALIGN) {
+ if ((unsigned long)p->payload % PKTALIGN || p->len != p->tot_len) {
/*
* Some net drivers have strict alignment requirements and may
* fail or output invalid data if the packet is not aligned.
+ *
+ * A packet may also be stored in multiple chained pbufs. In
+ * this case, assemble the fragments into one contiguous packet
+ * buffer before passing it to the Ethernet driver.
*/
- pp = memalign(PKTALIGN, p->len);
+
+ pp = memalign(PKTALIGN, p->tot_len);
if (!pp)
- return ERR_ABRT;
- memcpy(pp, p->payload, p->len);
+ return ERR_MEM;
+
+ pp_allocated = true;
+
+ plen = pbuf_copy_partial(p, pp, p->tot_len, 0);
+ if (plen != p->tot_len) {
+ free(pp);
+ return ERR_BUF;
+ }
+ } else {
+ pp = p->payload;
+ plen = p->len;
+ }
+
+ if (CONFIG_IS_ENABLED(LWIP_DEBUG_RXTX)) {
+ printf("net_lwip_tx: %u bytes, udev %s\n", plen, udev->name);
+ print_hex_dump("net_lwip_tx: ", 0, 16, 1, pp, plen, true);
}
- err = eth_get_ops(udev)->send(udev, pp ? pp : p->payload, p->len);
- free(pp);
+ err = eth_get_ops(udev)->send(udev, pp, plen);
+
+ if (pp_allocated)
+ free(pp);
+
if (err) {
debug("send error %d\n", err);
return ERR_ABRT;
--
2.45.2
^ permalink raw reply related [flat|nested] 5+ messages in thread* Re: [PATCH] net: lwip: handle chained pbufs in transmit path
2026-07-27 8:02 Weijie Gao
@ 2026-07-27 8:06 ` Weijie Gao
0 siblings, 0 replies; 5+ messages in thread
From: Weijie Gao @ 2026-07-27 8:06 UTC (permalink / raw)
To: u-boot
Cc: GSS_MTK_Uboot_upstream, Tom Rini, Vignesh R, Takahiro Kuwano,
Marek Vasut, Tudor Ambarus, Jeffrey Yu, Christoph Reiter,
Miquel Raynal, Shiji Yang, Bernhard Messerklinger,
Vaishnav Achath, Prasad Kummari
On Mon, 2026-07-27 at 16:02 +0800, Weijie Gao wrote:
> LwIP may pass a packet to the netif linkoutput callback as a chain
> of pbufs. In this case, p->len only describes the length of the
> first pbuf, while p->tot_len describes the length of the whole
> packet.
>
> The current transmit path only sends the first pbuf. This can
> truncate packets whose headers have already been generated for the
> full packet length, resulting in malformed frames on the wire.
> For example, the IP header may record a larger total length than the
> actual Ethernet frame length.
>
> Assemble chained pbufs into one aligned contiguous buffer before
> passing the packet to the Ethernet driver.
>
> Fixes: 98ad145db61a (net: lwip: add DHCP support and dhcp commmand)
> Signed-off-by: Weijie Gao <weijie.gao@mediatek.com>
> ---
> net/lwip/net-lwip.c | 45 ++++++++++++++++++++++++++++++++-----------
> --
> 1 file changed, 32 insertions(+), 13 deletions(-)
>
Sorry, I sent this patch by mistake. Please ignore it.
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2026-07-27 8:21 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-15 8:42 [PATCH] net: lwip: handle chained pbufs in transmit path Weijie Gao
2026-07-16 7:56 ` Jerome Forissier
2026-07-16 8:00 ` Jerome Forissier
-- strict thread matches above, loose matches on Subject: below --
2026-07-27 8:02 Weijie Gao
2026-07-27 8:06 ` Weijie Gao
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox