netpoll and netconsole were created together and their code has
been intermixed in net/core/netpoll.c for decades. The result is
that netpoll exposes two send-side interfaces:
* a generic "give me an sk_buff" path used by every stacked-device
driver (bonding, team, vlan, bridge, macvlan, dsa),
* a second path that takes raw bytes and builds a UDP/IP/Ethernet
packet -- exclusively for netconsole.
The packet builder, an skb pool allocator, and several
netconsole-specific helpers all live next to the generic plumbing even
though no other consumer ever touches them.
Worse, every netpoll user pays for that overlap: struct netpoll carries
an skb_pool and a refill work_struct that only netconsole's find_skb()
ever reads from, and net-core has to review unrelated changes (TTL, hop
limit, IP ID generation, source MAC selection, pool sizing) just because
they happen to be coded inside netpoll.
This is a waste of memory for something useless.
This series splits the netconsole-specific code out:
* netpoll_send_udp() and its private helpers (push_ipv6, push_ipv4,
push_eth, push_udp, netpoll_udp_checksum, find_skb) move into
drivers/net/netconsole.c, leaving netpoll with a single skb-only
send interface that is the same for every user.
The moves are one function per patch for reviewability; helpers are
temporarily EXPORT_SYMBOL_GPL'd while netpoll_send_udp() is still in
netpoll calling them, then those exports are dropped together once
netpoll_send_udp() itself moves.
The only new permanent export is zap_completion_queue(), needed because
find_skb() still drains the per-CPU TX completion queue before
allocating.
struct netpoll is unchanged in this series; making the pool itself
netconsole-private (and reclaiming the skb_pool / refill_wq fields for
the rest of netpoll's users) is the natural follow-up, once this patchset
lands.
Signed-off-by: Breno Leitao <leitao@debian.org>
---
Breno Leitao (8):
netpoll: expose UDP packet builder helpers for netconsole
netconsole: move netpoll_send_udp() from netpoll
netconsole: move push_ipv6() from netpoll
netconsole: move push_ipv4() from netpoll
netconsole: move push_eth() from netpoll
netconsole: move push_udp() from netpoll
netconsole: move netpoll_udp_checksum() from netpoll
netconsole: move find_skb() from netpoll
drivers/net/netconsole.c | 174 +++++++++++++++++++++++++++++++++++++++++++++
include/linux/netpoll.h | 2 +-
net/core/netpoll.c | 180 +----------------------------------------------
3 files changed, 178 insertions(+), 178 deletions(-)
---
base-commit: 6a4c4656b0d2d4056a1f0c35442db4e8a5cf8021
change-id: 20260508-netconsole_split-4f8402a9a9ff
Best regards,
--
Breno Leitao [off-list ref]
Move netpoll_send_udp() from net/core/netpoll.c into
drivers/net/netconsole.c as a static helper, drop EXPORT_SYMBOL(),
and remove the prototype from include/linux/netpoll.h.
netconsole was the only in-tree caller of this entry point. Every
other netpoll consumer (bonding, team, vlan, bridge, macvlan, dsa)
already builds its own sk_buff and hands it to netpoll_send_skb(),
so the netpoll send-side interface is now skb-only.
The helpers it depends on (find_skb(), push_ipv6(), push_ipv4(),
push_udp(), push_eth(), netpoll_udp_checksum()) were exposed in
the previous patches and stay in net/core/netpoll.c for now.
Subsequent patches move each of them into netconsole one at a time
and drop the corresponding EXPORT_SYMBOL_GPL.
Pull <linux/ip.h>, <linux/ipv6.h> and <linux/udp.h> into netconsole.c
so the moved code can name the header structures.
Signed-off-by: Breno Leitao <leitao@debian.org>
---
drivers/net/netconsole.c | 38 ++++++++++++++++++++++++++++++++++++++
include/linux/netpoll.h | 1 -
net/core/netpoll.c | 37 -------------------------------------
3 files changed, 38 insertions(+), 38 deletions(-)
Promote each from file-static to EXPORT_SYMBOL_GPL and forward-
declare them in include/linux/netpoll.h so netconsole can call
them once netpoll_send_udp() moves out.
These exports are kept until the end of the series, when
al of them move into netconsole.
No functional change.
Signed-off-by: Breno Leitao <leitao@debian.org>
---
include/linux/netpoll.h | 6 ++++++
net/core/netpoll.c | 20 +++++++++++++-------
2 files changed, 19 insertions(+), 7 deletions(-)
push_ipv6() builds the IPv6 header for netconsole's UDP packets.
Its only caller, netpoll_send_udp(), now lives in netconsole, so
the helper can move there as a file-static function. Drop its
EXPORT_SYMBOL_GPL and remove the prototype from
include/linux/netpoll.h.
Signed-off-by: Breno Leitao <leitao@debian.org>
---
drivers/net/netconsole.c | 23 +++++++++++++++++++++++
include/linux/netpoll.h | 1 -
net/core/netpoll.c | 24 ------------------------
3 files changed, 23 insertions(+), 25 deletions(-)
push_ipv4() builds the IPv4 header for netconsole's UDP packets.
Move it into drivers/net/netconsole.c as a file-static helper; drop
its EXPORT_SYMBOL_GPL and remove the prototype from
include/linux/netpoll.h.
put_unaligned() is no longer used in net/core/netpoll.c, so drop
the now-stale <linux/unaligned.h> include from there. Pull it into
netconsole.c so the moved code keeps building.
Signed-off-by: Breno Leitao <leitao@debian.org>
---
drivers/net/netconsole.c | 28 ++++++++++++++++++++++++++++
include/linux/netpoll.h | 1 -
net/core/netpoll.c | 29 -----------------------------
3 files changed, 28 insertions(+), 30 deletions(-)
push_eth() builds the Ethernet header for netconsole's UDP packets.
Move it into drivers/net/netconsole.c as a file-static helper; drop
its EXPORT_SYMBOL_GPL and remove the prototype from
include/linux/netpoll.h.
Signed-off-by: Breno Leitao <leitao@debian.org>
---
drivers/net/netconsole.c | 14 ++++++++++++++
include/linux/netpoll.h | 1 -
net/core/netpoll.c | 15 ---------------
3 files changed, 14 insertions(+), 16 deletions(-)
push_udp() builds the UDP header (and triggers the checksum) for
netconsole's UDP packets. Move it into drivers/net/netconsole.c as
a file-static helper; drop its EXPORT_SYMBOL_GPL and remove the
prototype from include/linux/netpoll.h.
push_udp() was the last udp_hdr() consumer in net/core/netpoll.c,
so swap <net/udp.h> for <linux/udp.h> there: MAX_SKB_SIZE still
needs struct udphdr.
Signed-off-by: Breno Leitao <leitao@debian.org>
---
drivers/net/netconsole.c | 18 ++++++++++++++++++
include/linux/netpoll.h | 1 -
net/core/netpoll.c | 21 +--------------------
3 files changed, 19 insertions(+), 21 deletions(-)
netpoll_udp_checksum() computes the UDP checksum for netconsole's
packets. Move it into drivers/net/netconsole.c as a file-static
helper; drop its EXPORT_SYMBOL_GPL and remove the prototype from
include/linux/netpoll.h.
This was the last csum_ipv6_magic() consumer in
net/core/netpoll.c, so drop the now-stale <net/ip6_checksum.h>
include there. Pull it into netconsole.c so the moved code keeps
building.
Signed-off-by: Breno Leitao <leitao@debian.org>
---
drivers/net/netconsole.c | 26 ++++++++++++++++++++++++++
include/linux/netpoll.h | 1 -
net/core/netpoll.c | 27 ---------------------------
3 files changed, 26 insertions(+), 28 deletions(-)
@@ -1652,6 +1653,31 @@ static struct notifier_block netconsole_netdev_notifier = {.notifier_call=netconsole_netdev_event,};+staticvoidnetpoll_udp_checksum(structnetpoll*np,structsk_buff*skb,+intlen)+{+structudphdr*udph;+intudp_len;++udp_len=len+sizeof(structudphdr);+udph=udp_hdr(skb);++/* check needs to be set, since it will be consumed in csum_partial */+udph->check=0;+if(np->ipv6)+udph->check=csum_ipv6_magic(&np->local_ip.in6,+&np->remote_ip.in6,+udp_len,IPPROTO_UDP,+csum_partial(udph,udp_len,0));+else+udph->check=csum_tcpudp_magic(np->local_ip.ip,+np->remote_ip.ip,+udp_len,IPPROTO_UDP,+csum_partial(udph,udp_len,0));+if(udph->check==0)+udph->check=CSUM_MANGLED_0;+}+staticvoidpush_udp(structnetpoll*np,structsk_buff*skb,intlen){structudphdr*udph;
@@ -369,32 +368,6 @@ static netdev_tx_t __netpoll_send_skb(struct netpoll *np, struct sk_buff *skb)returnret;}-voidnetpoll_udp_checksum(structnetpoll*np,structsk_buff*skb,-intlen)-{-structudphdr*udph;-intudp_len;--udp_len=len+sizeof(structudphdr);-udph=udp_hdr(skb);--/* check needs to be set, since it will be consumed in csum_partial */-udph->check=0;-if(np->ipv6)-udph->check=csum_ipv6_magic(&np->local_ip.in6,-&np->remote_ip.in6,-udp_len,IPPROTO_UDP,-csum_partial(udph,udp_len,0));-else-udph->check=csum_tcpudp_magic(np->local_ip.ip,-np->remote_ip.ip,-udp_len,IPPROTO_UDP,-csum_partial(udph,udp_len,0));-if(udph->check==0)-udph->check=CSUM_MANGLED_0;-}-EXPORT_SYMBOL_GPL(netpoll_udp_checksum);-netdev_tx_tnetpoll_send_skb(structnetpoll*np,structsk_buff*skb){unsignedlongflags;
find_skb() is the netconsole-specific entry into the netpoll skb
pool: every other netpoll consumer (bonding, team, vlan, bridge,
macvlan, dsa) builds its own sk_buff and never touches the pool.
With netpoll_send_udp() (its only caller) now living in netconsole,
find_skb() can join it.
Move find_skb() into drivers/net/netconsole.c as a file-static
helper, drop EXPORT_SYMBOL_GPL(find_skb) and remove its prototype
from include/linux/netpoll.h.
find_skb() calls zap_completion_queue() to drain TX completions
before allocating. zap_completion_queue() also has a second caller
inside netpoll itself (netpoll_poll_dev() runs it after each poll
to free completed skbs), so it stays in net/core/netpoll.c.
Promote it from file-static to EXPORT_SYMBOL_GPL with a forward
declaration in include/linux/netpoll.h, and drop its old
file-static forward declaration.
The skb pool's lifecycle (np->skb_pool, np->refill_wq, refill_skbs(),
refill_skbs_work_handler(), skb_pool_flush()) stays in netpoll: it
is initialised in __netpoll_setup() and torn down in
__netpoll_cleanup(), both of which remain netpoll's responsibility.
The refill work queued via schedule_work(&np->refill_wq) from the
moved find_skb() runs refill_skbs_work_handler() in netpoll without
any further plumbing.
Signed-off-by: Breno Leitao <leitao@debian.org>
---
drivers/net/netconsole.c | 27 +++++++++++++++++++++++++++
include/linux/netpoll.h | 2 +-
net/core/netpoll.c | 33 ++-------------------------------
3 files changed, 30 insertions(+), 32 deletions(-)