diff mbox series

[RFC,net-next,v2,1/2] netpoll: support sending over raw IP interfaces

Message ID 20240321122003.20089-1-mark@yotsuba.nl (mailing list archive)
State RFC
Delegated to: Netdev Maintainers
Headers show
Series [RFC,net-next,v2,1/2] netpoll: support sending over raw IP interfaces | expand

Checks

Context Check Description
netdev/series_format success Single patches do not need cover letters
netdev/tree_selection success Clearly marked for net-next
netdev/ynl success Generated files up to date; no warnings/errors; no diff in generated;
netdev/fixes_present success Fixes tag not required for -next series
netdev/header_inline success No static functions without inline keyword in header files
netdev/build_32bit success Errors and warnings before: 942 this patch: 942
netdev/build_tools success No tools touched, skip
netdev/cc_maintainers warning 2 maintainers not CCed: corbet@lwn.net linux-doc@vger.kernel.org
netdev/build_clang success Errors and warnings before: 957 this patch: 957
netdev/verify_signedoff success Signed-off-by tag matches author and committer
netdev/deprecated_api success None detected
netdev/check_selftest success No net selftest shell script
netdev/verify_fixes success No Fixes tag
netdev/build_allmodconfig_warn success Errors and warnings before: 959 this patch: 959
netdev/checkpatch success total: 0 errors, 0 warnings, 0 checks, 37 lines checked
netdev/build_clang_rust success No Rust files in patch. Skipping build
netdev/kdoc success Errors and warnings before: 0 this patch: 0
netdev/source_inline success Was 0 now: 0

Commit Message

Mark March 21, 2024, 12:20 p.m. UTC
Currently, netpoll only supports interfaces with an ethernet-compatible
link layer. Certain interfaces like SLIP do not have a link layer
on the network interface level at all and expect raw IP packets,
and could benefit from being supported by netpoll.

This commit adds support for such interfaces by checking if a link layer
header is present using `dev_has_header()`. If that is not the case,
it simply skips adding the ethernet header, causing a raw IP packet to be
sent over the interface. This has been confirmed to add netconsole support
to at least SLIP and WireGuard interfaces.

Signed-off-by: Mark Cilissen <mark@yotsuba.nl>
---
v2:
- Use dev_has_header(netdev) to detect existence of link layer header
  instead of netdev->hard_header_len, restore prior skb allocation sizes
  by always using LL_RESERVED_SPACE() as before
- Add selftest for netconsole

v1: https://lore.kernel.org/netdev/20240313124613.51399-1-mark@yotsuba.nl/T/
---
 Documentation/networking/netconsole.rst |  3 ++-
 net/core/netpoll.c                      | 15 ++++++++-------
 2 files changed, 10 insertions(+), 8 deletions(-)
diff mbox series

Patch

diff --git a/Documentation/networking/netconsole.rst b/Documentation/networking/netconsole.rst
index d55c2a22ec7a..434ce0366027 100644
--- a/Documentation/networking/netconsole.rst
+++ b/Documentation/networking/netconsole.rst
@@ -327,4 +327,5 @@  enable the logging of even the most critical kernel bugs. It works
 from IRQ contexts as well, and does not enable interrupts while
 sending packets. Due to these unique needs, configuration cannot
 be more automatic, and some fundamental limitations will remain:
-only IP networks, UDP packets and ethernet devices are supported.
+only UDP packets over IP networks, over ethernet links if a
+hardware layer is required, are supported.
diff --git a/net/core/netpoll.c b/net/core/netpoll.c
index 543007f159f9..d12aa1b7d79e 100644
--- a/net/core/netpoll.c
+++ b/net/core/netpoll.c
@@ -458,9 +458,7 @@  void netpoll_send_udp(struct netpoll *np, const char *msg, int len)
 		ip6h->saddr = np->local_ip.in6;
 		ip6h->daddr = np->remote_ip.in6;
 
-		eth = skb_push(skb, ETH_HLEN);
-		skb_reset_mac_header(skb);
-		skb->protocol = eth->h_proto = htons(ETH_P_IPV6);
+		skb->protocol = htons(ETH_P_IPV6);
 	} else {
 		udph->check = 0;
 		udph->check = csum_tcpudp_magic(np->local_ip.ip,
@@ -487,14 +485,17 @@  void netpoll_send_udp(struct netpoll *np, const char *msg, int len)
 		put_unaligned(np->remote_ip.ip, &(iph->daddr));
 		iph->check    = ip_fast_csum((unsigned char *)iph, iph->ihl);
 
+		skb->protocol = htons(ETH_P_IP);
+	}
+
+	if (dev_has_header(np->dev)) {
 		eth = skb_push(skb, ETH_HLEN);
 		skb_reset_mac_header(skb);
-		skb->protocol = eth->h_proto = htons(ETH_P_IP);
+		eth->h_proto = skb->protocol;
+		ether_addr_copy(eth->h_source, np->dev->dev_addr);
+		ether_addr_copy(eth->h_dest, np->remote_mac);
 	}
 
-	ether_addr_copy(eth->h_source, np->dev->dev_addr);
-	ether_addr_copy(eth->h_dest, np->remote_mac);
-
 	skb->dev = np->dev;
 
 	netpoll_send_skb(np, skb);