* [PATCH net-next 0/7] netpoll: Factor out functions from netpoll_send_udp() and add ipv6 selftest
@ 2025-06-27 17:55 Breno Leitao
2025-06-27 17:55 ` [PATCH net-next 1/7] netpoll: Improve code clarity with explicit struct size calculations Breno Leitao
` (6 more replies)
0 siblings, 7 replies; 10+ messages in thread
From: Breno Leitao @ 2025-06-27 17:55 UTC (permalink / raw)
To: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Simon Horman, Andrew Lunn, Shuah Khan
Cc: netdev, linux-kernel, linux-kselftest, Breno Leitao, gustavold
Refactors the netpoll UDP transmit path to improve code clarity,
maintainability, and protocol-layer encapsulation.
Function netpoll_send_udp() has more than 100 LoC, which is hard to
understand and review. After this patchset, it has only 32 LoC, which is
more manageable.
The series systematically moves the construction of protocol headers
(UDP, IPv4, IPv6, Ethernet) out of the core `netpoll_send_udp()`
function into dedicated static helpers:
- `push_udp()` for UDP header setup
- `push_ipv4()` and `push_ipv6()` for IP header setup
- `push_eth()` for Ethernet header setup
This results in a clean, layered abstraction that mirrors the protocol
stack, reduces code duplication, and improves readability.
Also, to make sure this is not breaking anything, add IPv6 selftest to
netconsole tests, which will exercise this code. This test would also pick
problems similiar to the one fixed by f599020702698 ("net: netpoll:
Initialize UDP checksum field before checksumming"), which was
embarrassin we didn't have a selftest catch it.
Anyway, there are **no functional changes** intended in this patchset.
Signed-off-by: Breno Leitao <leitao@debian.org>
---
Breno Leitao (7):
netpoll: Improve code clarity with explicit struct size calculations
netpoll: factor out UDP checksum calculation into helper
netpoll: factor out IPv6 header setup into push_ipv6() helper
netpoll: factor out IPv4 header setup into push_ipv4() helper
netpoll: factor out UDP header setup into push_udp() helper
netpoll: move Ethernet setup to push_eth() helper
selftests: net: Add IPv6 support to netconsole basic tests
net/core/netpoll.c | 196 +++++++++++++--------
.../selftests/drivers/net/lib/sh/lib_netcons.sh | 74 +++++++-
.../testing/selftests/drivers/net/netcons_basic.sh | 52 +++---
3 files changed, 216 insertions(+), 106 deletions(-)
---
base-commit: 8efa26fcbf8a7f783fd1ce7dd2a409e9b7758df0
change-id: 20250620-netpoll_untagle_ip-e37c799a6925
Best regards,
--
Breno Leitao <leitao@debian.org>
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH net-next 1/7] netpoll: Improve code clarity with explicit struct size calculations
2025-06-27 17:55 [PATCH net-next 0/7] netpoll: Factor out functions from netpoll_send_udp() and add ipv6 selftest Breno Leitao
@ 2025-06-27 17:55 ` Breno Leitao
2025-06-27 17:55 ` [PATCH net-next 2/7] netpoll: factor out UDP checksum calculation into helper Breno Leitao
` (5 subsequent siblings)
6 siblings, 0 replies; 10+ messages in thread
From: Breno Leitao @ 2025-06-27 17:55 UTC (permalink / raw)
To: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Simon Horman, Andrew Lunn, Shuah Khan
Cc: netdev, linux-kernel, linux-kselftest, Breno Leitao, gustavold
Replace pointer-dereference sizeof() operations with explicit struct names
for improved readability and maintainability. This change:
1. Replaces `sizeof(*udph)` with `sizeof(struct udphdr)`
2. Replaces `sizeof(*ip6h)` with `sizeof(struct ipv6hdr)`
3. Replaces `sizeof(*iph)` with `sizeof(struct iphdr)`
This will make it easy to move code in the upcoming patches.
No functional changes are introduced by this patch.
Signed-off-by: Breno Leitao <leitao@debian.org>
---
net/core/netpoll.c | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/net/core/netpoll.c b/net/core/netpoll.c
index 54f9d505895f6..ac0ae9630654a 100644
--- a/net/core/netpoll.c
+++ b/net/core/netpoll.c
@@ -402,11 +402,11 @@ int netpoll_send_udp(struct netpoll *np, const char *msg, int len)
if (!IS_ENABLED(CONFIG_PREEMPT_RT))
WARN_ON_ONCE(!irqs_disabled());
- udp_len = len + sizeof(*udph);
+ udp_len = len + sizeof(struct udphdr);
if (np->ipv6)
- ip_len = udp_len + sizeof(*ip6h);
+ ip_len = udp_len + sizeof(struct ipv6hdr);
else
- ip_len = udp_len + sizeof(*iph);
+ ip_len = udp_len + sizeof(struct iphdr);
total_len = ip_len + LL_RESERVED_SPACE(np->dev);
@@ -418,7 +418,7 @@ int netpoll_send_udp(struct netpoll *np, const char *msg, int len)
skb_copy_to_linear_data(skb, msg, len);
skb_put(skb, len);
- skb_push(skb, sizeof(*udph));
+ skb_push(skb, sizeof(struct udphdr));
skb_reset_transport_header(skb);
udph = udp_hdr(skb);
udph->source = htons(np->local_port);
@@ -434,7 +434,7 @@ int netpoll_send_udp(struct netpoll *np, const char *msg, int len)
if (udph->check == 0)
udph->check = CSUM_MANGLED_0;
- skb_push(skb, sizeof(*ip6h));
+ skb_push(skb, sizeof(struct ipv6hdr));
skb_reset_network_header(skb);
ip6h = ipv6_hdr(skb);
@@ -461,7 +461,7 @@ int netpoll_send_udp(struct netpoll *np, const char *msg, int len)
if (udph->check == 0)
udph->check = CSUM_MANGLED_0;
- skb_push(skb, sizeof(*iph));
+ skb_push(skb, sizeof(struct iphdr));
skb_reset_network_header(skb);
iph = ip_hdr(skb);
--
2.47.1
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH net-next 2/7] netpoll: factor out UDP checksum calculation into helper
2025-06-27 17:55 [PATCH net-next 0/7] netpoll: Factor out functions from netpoll_send_udp() and add ipv6 selftest Breno Leitao
2025-06-27 17:55 ` [PATCH net-next 1/7] netpoll: Improve code clarity with explicit struct size calculations Breno Leitao
@ 2025-06-27 17:55 ` Breno Leitao
2025-06-27 17:55 ` [PATCH net-next 3/7] netpoll: factor out IPv6 header setup into push_ipv6() helper Breno Leitao
` (4 subsequent siblings)
6 siblings, 0 replies; 10+ messages in thread
From: Breno Leitao @ 2025-06-27 17:55 UTC (permalink / raw)
To: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Simon Horman, Andrew Lunn, Shuah Khan
Cc: netdev, linux-kernel, linux-kselftest, Breno Leitao, gustavold
Extract UDP checksum calculation logic from netpoll_send_udp()
into a new static helper function netpoll_udp_checksum(). This
reduces code duplication and improves readability for both IPv4
and IPv6 cases.
No functional change intended.
Signed-off-by: Breno Leitao <leitao@debian.org>
---
net/core/netpoll.c | 41 ++++++++++++++++++++++++++---------------
1 file changed, 26 insertions(+), 15 deletions(-)
diff --git a/net/core/netpoll.c b/net/core/netpoll.c
index ac0ae9630654a..24e6ad2da8096 100644
--- a/net/core/netpoll.c
+++ b/net/core/netpoll.c
@@ -372,6 +372,31 @@ static netdev_tx_t __netpoll_send_skb(struct netpoll *np, struct sk_buff *skb)
return ret;
}
+static void netpoll_udp_checksum(struct netpoll *np, struct sk_buff *skb,
+ int len)
+{
+ struct udphdr *udph;
+ int udp_len;
+
+ udp_len = len + sizeof(struct udphdr);
+ 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;
+}
+
netdev_tx_t netpoll_send_skb(struct netpoll *np, struct sk_buff *skb)
{
unsigned long flags;
@@ -425,15 +450,8 @@ int netpoll_send_udp(struct netpoll *np, const char *msg, int len)
udph->dest = htons(np->remote_port);
udph->len = htons(udp_len);
- udph->check = 0;
+ netpoll_udp_checksum(np, skb, len);
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));
- if (udph->check == 0)
- udph->check = CSUM_MANGLED_0;
-
skb_push(skb, sizeof(struct ipv6hdr));
skb_reset_network_header(skb);
ip6h = ipv6_hdr(skb);
@@ -454,13 +472,6 @@ int netpoll_send_udp(struct netpoll *np, const char *msg, int len)
skb_reset_mac_header(skb);
skb->protocol = eth->h_proto = htons(ETH_P_IPV6);
} 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;
-
skb_push(skb, sizeof(struct iphdr));
skb_reset_network_header(skb);
iph = ip_hdr(skb);
--
2.47.1
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH net-next 3/7] netpoll: factor out IPv6 header setup into push_ipv6() helper
2025-06-27 17:55 [PATCH net-next 0/7] netpoll: Factor out functions from netpoll_send_udp() and add ipv6 selftest Breno Leitao
2025-06-27 17:55 ` [PATCH net-next 1/7] netpoll: Improve code clarity with explicit struct size calculations Breno Leitao
2025-06-27 17:55 ` [PATCH net-next 2/7] netpoll: factor out UDP checksum calculation into helper Breno Leitao
@ 2025-06-27 17:55 ` Breno Leitao
2025-06-27 17:55 ` [PATCH net-next 4/7] netpoll: factor out IPv4 header setup into push_ipv4() helper Breno Leitao
` (3 subsequent siblings)
6 siblings, 0 replies; 10+ messages in thread
From: Breno Leitao @ 2025-06-27 17:55 UTC (permalink / raw)
To: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Simon Horman, Andrew Lunn, Shuah Khan
Cc: netdev, linux-kernel, linux-kselftest, Breno Leitao, gustavold
Move IPv6 header construction from netpoll_send_udp() into a new
static helper function, push_ipv6(). This refactoring reduces code
duplication and improves readability in netpoll_send_udp().
Signed-off-by: Breno Leitao <leitao@debian.org>
---
net/core/netpoll.c | 49 +++++++++++++++++++++++++++++--------------------
1 file changed, 29 insertions(+), 20 deletions(-)
diff --git a/net/core/netpoll.c b/net/core/netpoll.c
index 24e6ad2da8096..247a73762fc2c 100644
--- a/net/core/netpoll.c
+++ b/net/core/netpoll.c
@@ -414,6 +414,33 @@ netdev_tx_t netpoll_send_skb(struct netpoll *np, struct sk_buff *skb)
}
EXPORT_SYMBOL(netpoll_send_skb);
+static void push_ipv6(struct netpoll *np, struct sk_buff *skb, int len)
+{
+ struct ipv6hdr *ip6h;
+ struct ethhdr *eth;
+
+ skb_push(skb, sizeof(struct ipv6hdr));
+ skb_reset_network_header(skb);
+ ip6h = ipv6_hdr(skb);
+
+ /* ip6h->version = 6; ip6h->priority = 0; */
+ *(unsigned char *)ip6h = 0x60;
+ ip6h->flow_lbl[0] = 0;
+ ip6h->flow_lbl[1] = 0;
+ ip6h->flow_lbl[2] = 0;
+
+ ip6h->payload_len = htons(sizeof(struct udphdr) + len);
+ ip6h->nexthdr = IPPROTO_UDP;
+ ip6h->hop_limit = 32;
+ 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 = htons(ETH_P_IPV6);
+ eth->h_proto = htons(ETH_P_IPV6);
+}
+
int netpoll_send_udp(struct netpoll *np, const char *msg, int len)
{
int total_len, ip_len, udp_len;
@@ -422,7 +449,6 @@ int netpoll_send_udp(struct netpoll *np, const char *msg, int len)
struct iphdr *iph;
struct ethhdr *eth;
static atomic_t ip_ident;
- struct ipv6hdr *ip6h;
if (!IS_ENABLED(CONFIG_PREEMPT_RT))
WARN_ON_ONCE(!irqs_disabled());
@@ -452,25 +478,8 @@ int netpoll_send_udp(struct netpoll *np, const char *msg, int len)
netpoll_udp_checksum(np, skb, len);
if (np->ipv6) {
- skb_push(skb, sizeof(struct ipv6hdr));
- skb_reset_network_header(skb);
- ip6h = ipv6_hdr(skb);
-
- /* ip6h->version = 6; ip6h->priority = 0; */
- *(unsigned char *)ip6h = 0x60;
- ip6h->flow_lbl[0] = 0;
- ip6h->flow_lbl[1] = 0;
- ip6h->flow_lbl[2] = 0;
-
- ip6h->payload_len = htons(sizeof(struct udphdr) + len);
- ip6h->nexthdr = IPPROTO_UDP;
- ip6h->hop_limit = 32;
- 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);
+ push_ipv6(np, skb, len);
+ eth = eth_hdr(skb);
} else {
skb_push(skb, sizeof(struct iphdr));
skb_reset_network_header(skb);
--
2.47.1
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH net-next 4/7] netpoll: factor out IPv4 header setup into push_ipv4() helper
2025-06-27 17:55 [PATCH net-next 0/7] netpoll: Factor out functions from netpoll_send_udp() and add ipv6 selftest Breno Leitao
` (2 preceding siblings ...)
2025-06-27 17:55 ` [PATCH net-next 3/7] netpoll: factor out IPv6 header setup into push_ipv6() helper Breno Leitao
@ 2025-06-27 17:55 ` Breno Leitao
2025-06-27 17:55 ` [PATCH net-next 5/7] netpoll: factor out UDP header setup into push_udp() helper Breno Leitao
` (2 subsequent siblings)
6 siblings, 0 replies; 10+ messages in thread
From: Breno Leitao @ 2025-06-27 17:55 UTC (permalink / raw)
To: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Simon Horman, Andrew Lunn, Shuah Khan
Cc: netdev, linux-kernel, linux-kselftest, Breno Leitao, gustavold
Move IPv4 header construction from netpoll_send_udp() into a new
static helper function push_ipv4(). This completes the refactoring
started with IPv6 header handling, creating symmetric helper functions
for both IP versions.
Changes include:
1. Extracting IPv4 header setup logic into push_ipv4()
2. Replacing inline IPv4 code with helper call
3. Moving eth assignment after helper calls for consistency
The refactoring reduces code duplication and improves maintainability
by isolating IP version-specific logic.
Signed-off-by: Breno Leitao <leitao@debian.org>
---
net/core/netpoll.c | 62 +++++++++++++++++++++++++++++++-----------------------
1 file changed, 36 insertions(+), 26 deletions(-)
diff --git a/net/core/netpoll.c b/net/core/netpoll.c
index 247a73762fc2c..ff64e94df5351 100644
--- a/net/core/netpoll.c
+++ b/net/core/netpoll.c
@@ -441,14 +441,44 @@ static void push_ipv6(struct netpoll *np, struct sk_buff *skb, int len)
eth->h_proto = htons(ETH_P_IPV6);
}
+static void push_ipv4(struct netpoll *np, struct sk_buff *skb, int len)
+{
+ static atomic_t ip_ident;
+ struct ethhdr *eth;
+ struct iphdr *iph;
+ int ip_len;
+
+ ip_len = len + sizeof(struct udphdr) + sizeof(struct iphdr);
+
+ skb_push(skb, sizeof(struct iphdr));
+ skb_reset_network_header(skb);
+ iph = ip_hdr(skb);
+
+ /* iph->version = 4; iph->ihl = 5; */
+ *(unsigned char *)iph = 0x45;
+ iph->tos = 0;
+ put_unaligned(htons(ip_len), &iph->tot_len);
+ iph->id = htons(atomic_inc_return(&ip_ident));
+ iph->frag_off = 0;
+ iph->ttl = 64;
+ iph->protocol = IPPROTO_UDP;
+ iph->check = 0;
+ put_unaligned(np->local_ip.ip, &iph->saddr);
+ put_unaligned(np->remote_ip.ip, &iph->daddr);
+ iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl);
+
+ eth = skb_push(skb, ETH_HLEN);
+ skb_reset_mac_header(skb);
+ skb->protocol = htons(ETH_P_IP);
+ eth->h_proto = htons(ETH_P_IP);
+}
+
int netpoll_send_udp(struct netpoll *np, const char *msg, int len)
{
int total_len, ip_len, udp_len;
struct sk_buff *skb;
struct udphdr *udph;
- struct iphdr *iph;
struct ethhdr *eth;
- static atomic_t ip_ident;
if (!IS_ENABLED(CONFIG_PREEMPT_RT))
WARN_ON_ONCE(!irqs_disabled());
@@ -477,32 +507,12 @@ int netpoll_send_udp(struct netpoll *np, const char *msg, int len)
udph->len = htons(udp_len);
netpoll_udp_checksum(np, skb, len);
- if (np->ipv6) {
+ if (np->ipv6)
push_ipv6(np, skb, len);
- eth = eth_hdr(skb);
- } else {
- skb_push(skb, sizeof(struct iphdr));
- skb_reset_network_header(skb);
- iph = ip_hdr(skb);
-
- /* iph->version = 4; iph->ihl = 5; */
- *(unsigned char *)iph = 0x45;
- iph->tos = 0;
- put_unaligned(htons(ip_len), &(iph->tot_len));
- iph->id = htons(atomic_inc_return(&ip_ident));
- iph->frag_off = 0;
- iph->ttl = 64;
- iph->protocol = IPPROTO_UDP;
- iph->check = 0;
- put_unaligned(np->local_ip.ip, &(iph->saddr));
- put_unaligned(np->remote_ip.ip, &(iph->daddr));
- iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl);
-
- eth = skb_push(skb, ETH_HLEN);
- skb_reset_mac_header(skb);
- skb->protocol = eth->h_proto = htons(ETH_P_IP);
- }
+ else
+ push_ipv4(np, skb, len);
+ eth = eth_hdr(skb);
ether_addr_copy(eth->h_source, np->dev->dev_addr);
ether_addr_copy(eth->h_dest, np->remote_mac);
--
2.47.1
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH net-next 5/7] netpoll: factor out UDP header setup into push_udp() helper
2025-06-27 17:55 [PATCH net-next 0/7] netpoll: Factor out functions from netpoll_send_udp() and add ipv6 selftest Breno Leitao
` (3 preceding siblings ...)
2025-06-27 17:55 ` [PATCH net-next 4/7] netpoll: factor out IPv4 header setup into push_ipv4() helper Breno Leitao
@ 2025-06-27 17:55 ` Breno Leitao
2025-06-27 17:55 ` [PATCH net-next 6/7] netpoll: move Ethernet setup to push_eth() helper Breno Leitao
2025-06-27 17:55 ` [PATCH net-next 7/7] selftests: net: Add IPv6 support to netconsole basic tests Breno Leitao
6 siblings, 0 replies; 10+ messages in thread
From: Breno Leitao @ 2025-06-27 17:55 UTC (permalink / raw)
To: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Simon Horman, Andrew Lunn, Shuah Khan
Cc: netdev, linux-kernel, linux-kselftest, Breno Leitao, gustavold
Move UDP header construction from netpoll_send_udp() into a new
static helper function push_udp(). This completes the protocol
layer refactoring by:
1. Creating a dedicated helper for UDP header assembly
2. Removing UDP-specific logic from the main send function
3. Establishing a consistent pattern with existing IPv4/IPv6 helpers:
- push_udp()
- push_ipv4()
- push_ipv6()
The change improves code organization and maintains the encapsulation
pattern established in previous refactorings.
Signed-off-by: Breno Leitao <leitao@debian.org>
---
net/core/netpoll.c | 28 +++++++++++++++++++---------
1 file changed, 19 insertions(+), 9 deletions(-)
diff --git a/net/core/netpoll.c b/net/core/netpoll.c
index ff64e94df5351..70035e27d91cc 100644
--- a/net/core/netpoll.c
+++ b/net/core/netpoll.c
@@ -473,11 +473,28 @@ static void push_ipv4(struct netpoll *np, struct sk_buff *skb, int len)
eth->h_proto = htons(ETH_P_IP);
}
+static void push_udp(struct netpoll *np, struct sk_buff *skb, int len)
+{
+ struct udphdr *udph;
+ int udp_len;
+
+ udp_len = len + sizeof(struct udphdr);
+
+ skb_push(skb, sizeof(struct udphdr));
+ skb_reset_transport_header(skb);
+
+ udph = udp_hdr(skb);
+ udph->source = htons(np->local_port);
+ udph->dest = htons(np->remote_port);
+ udph->len = htons(udp_len);
+
+ netpoll_udp_checksum(np, skb, len);
+}
+
int netpoll_send_udp(struct netpoll *np, const char *msg, int len)
{
int total_len, ip_len, udp_len;
struct sk_buff *skb;
- struct udphdr *udph;
struct ethhdr *eth;
if (!IS_ENABLED(CONFIG_PREEMPT_RT))
@@ -499,14 +516,7 @@ int netpoll_send_udp(struct netpoll *np, const char *msg, int len)
skb_copy_to_linear_data(skb, msg, len);
skb_put(skb, len);
- skb_push(skb, sizeof(struct udphdr));
- skb_reset_transport_header(skb);
- udph = udp_hdr(skb);
- udph->source = htons(np->local_port);
- udph->dest = htons(np->remote_port);
- udph->len = htons(udp_len);
-
- netpoll_udp_checksum(np, skb, len);
+ push_udp(np, skb, len);
if (np->ipv6)
push_ipv6(np, skb, len);
else
--
2.47.1
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH net-next 6/7] netpoll: move Ethernet setup to push_eth() helper
2025-06-27 17:55 [PATCH net-next 0/7] netpoll: Factor out functions from netpoll_send_udp() and add ipv6 selftest Breno Leitao
` (4 preceding siblings ...)
2025-06-27 17:55 ` [PATCH net-next 5/7] netpoll: factor out UDP header setup into push_udp() helper Breno Leitao
@ 2025-06-27 17:55 ` Breno Leitao
2025-07-02 0:53 ` Jakub Kicinski
2025-06-27 17:55 ` [PATCH net-next 7/7] selftests: net: Add IPv6 support to netconsole basic tests Breno Leitao
6 siblings, 1 reply; 10+ messages in thread
From: Breno Leitao @ 2025-06-27 17:55 UTC (permalink / raw)
To: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Simon Horman, Andrew Lunn, Shuah Khan
Cc: netdev, linux-kernel, linux-kselftest, Breno Leitao, gustavold
Refactor Ethernet header population into dedicated function, completing
the layered abstraction with:
- push_eth() for link layer
- push_udp() for transport
- push_ipv4()/push_ipv6() for network
Signed-off-by: Breno Leitao <leitao@debian.org>
---
net/core/netpoll.c | 16 ++++++++++------
1 file changed, 10 insertions(+), 6 deletions(-)
diff --git a/net/core/netpoll.c b/net/core/netpoll.c
index 70035e27d91cc..9ab3cf78a393c 100644
--- a/net/core/netpoll.c
+++ b/net/core/netpoll.c
@@ -491,11 +491,19 @@ static void push_udp(struct netpoll *np, struct sk_buff *skb, int len)
netpoll_udp_checksum(np, skb, len);
}
+static void push_eth(struct netpoll *np, struct sk_buff *skb)
+{
+ struct ethhdr *eth;
+
+ eth = eth_hdr(skb);
+ ether_addr_copy(eth->h_source, np->dev->dev_addr);
+ ether_addr_copy(eth->h_dest, np->remote_mac);
+}
+
int netpoll_send_udp(struct netpoll *np, const char *msg, int len)
{
int total_len, ip_len, udp_len;
struct sk_buff *skb;
- struct ethhdr *eth;
if (!IS_ENABLED(CONFIG_PREEMPT_RT))
WARN_ON_ONCE(!irqs_disabled());
@@ -521,11 +529,7 @@ int netpoll_send_udp(struct netpoll *np, const char *msg, int len)
push_ipv6(np, skb, len);
else
push_ipv4(np, skb, len);
-
- eth = eth_hdr(skb);
- ether_addr_copy(eth->h_source, np->dev->dev_addr);
- ether_addr_copy(eth->h_dest, np->remote_mac);
-
+ push_eth(np, skb);
skb->dev = np->dev;
return (int)netpoll_send_skb(np, skb);
--
2.47.1
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH net-next 7/7] selftests: net: Add IPv6 support to netconsole basic tests
2025-06-27 17:55 [PATCH net-next 0/7] netpoll: Factor out functions from netpoll_send_udp() and add ipv6 selftest Breno Leitao
` (5 preceding siblings ...)
2025-06-27 17:55 ` [PATCH net-next 6/7] netpoll: move Ethernet setup to push_eth() helper Breno Leitao
@ 2025-06-27 17:55 ` Breno Leitao
6 siblings, 0 replies; 10+ messages in thread
From: Breno Leitao @ 2025-06-27 17:55 UTC (permalink / raw)
To: David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Simon Horman, Andrew Lunn, Shuah Khan
Cc: netdev, linux-kernel, linux-kselftest, Breno Leitao, gustavold
Add IPv6 support to the netconsole basic functionality tests by:
- Introducing separate IPv4 and IPv6 address variables (SRCIP4/SRCIP6,
DSTIP4/DSTIP6) to replace the single SRCIP/DSTIP variables
- Adding select_ipv4_or_ipv6() function to choose protocol version
- Updating socat configuration to use UDP6-LISTEN for IPv6 tests
- Adding wait_for_port() wrapper to handle protocol-specific port waiting
- Expanding test matrix to run both basic and extended formats against
both IPv4 and IPv6 protocols
- Improving cleanup to kill any remaining socat processes
- Adding sleep delays for better IPv6 packet handling reliability
The test now validates netconsole functionality across both IP versions,
improving test coverage for dual-stack network environments.
This test would avoid the regression fixed by commit f59902070269 ("net:
netpoll: Initialize UDP checksum field before checksumming")
Signed-off-by: Breno Leitao <leitao@debian.org>
---
.../selftests/drivers/net/lib/sh/lib_netcons.sh | 74 ++++++++++++++++++++--
.../testing/selftests/drivers/net/netcons_basic.sh | 52 ++++++++-------
2 files changed, 96 insertions(+), 30 deletions(-)
diff --git a/tools/testing/selftests/drivers/net/lib/sh/lib_netcons.sh b/tools/testing/selftests/drivers/net/lib/sh/lib_netcons.sh
index 3fcf85a345969..60f968713cad7 100644
--- a/tools/testing/selftests/drivers/net/lib/sh/lib_netcons.sh
+++ b/tools/testing/selftests/drivers/net/lib/sh/lib_netcons.sh
@@ -11,9 +11,11 @@ set -euo pipefail
LIBDIR=$(dirname "$(readlink -e "${BASH_SOURCE[0]}")")
SRCIF="" # to be populated later
-SRCIP=192.0.2.1
+SRCIP4="192.0.2.1"
+SRCIP6="fc00::1"
DSTIF="" # to be populated later
-DSTIP=192.0.2.2
+DSTIP4="192.0.2.2"
+DSTIP6="fc00::2"
PORT="6666"
MSG="netconsole selftest"
@@ -80,7 +82,23 @@ function configure_ip() {
ip link set "${SRCIF}" up
}
+function select_ipv4_or_ipv6()
+{
+ local VERSION=${1}
+
+ if [[ "$VERSION" == "ipv6" ]]
+ then
+ DSTIP="${DSTIP6}"
+ SRCIP="${SRCIP6}"
+ else
+ DSTIP="${DSTIP4}"
+ SRCIP="${SRCIP4}"
+ fi
+}
+
function set_network() {
+ local IP_VERSION=${1:-"ipv4"}
+
# setup_ns function is coming from lib.sh
setup_ns NAMESPACE
@@ -91,6 +109,7 @@ function set_network() {
# Link both interfaces back to back
link_ifaces
+ select_ipv4_or_ipv6 "${IP_VERSION}"
configure_ip
}
@@ -119,6 +138,11 @@ function create_dynamic_target() {
fi
echo 1 > "${NETCONS_PATH}"/enabled
+
+ # This will make sure that the kernel was able to
+ # load the netconsole driver configuration. The console message
+ # gets more organized/sequential as well.
+ sleep 1
}
# Generate the command line argument for netconsole following:
@@ -179,9 +203,18 @@ function set_user_data() {
function listen_port_and_save_to() {
local OUTPUT=${1}
+ local IPVERSION=${2:-"ipv4"}
+
+ if [ "${IPVERSION}" == "ipv4" ]
+ then
+ SOCAT_MODE="UDP-LISTEN"
+ else
+ SOCAT_MODE="UDP6-LISTEN"
+ fi
+
# Just wait for 2 seconds
timeout 2 ip netns exec "${NAMESPACE}" \
- socat UDP-LISTEN:"${PORT}",fork "${OUTPUT}"
+ socat "${SOCAT_MODE}":"${PORT}",fork "${OUTPUT}"
}
# Only validate that the message arrived properly
@@ -263,8 +296,13 @@ function check_for_dependencies() {
exit "${ksft_skip}"
fi
- if ip addr list | grep -E "inet.*(${SRCIP}|${DSTIP})" 2> /dev/null; then
- echo "SKIP: IPs already in use. Skipping it" >&2
+ if ip addr list | grep -E "inet.*(${SRCIP4}|${DSTIP4})" 2> /dev/null; then
+ echo "SKIP: IPv4s already in use. Skipping it" >&2
+ exit "${ksft_skip}"
+ fi
+
+ if ip addr list | grep -E "inet.*(${SRCIP6}|${DSTIP6})" 2> /dev/null; then
+ echo "SKIP: IPv6s already in use. Skipping it" >&2
exit "${ksft_skip}"
fi
}
@@ -278,11 +316,13 @@ function check_for_taskset() {
# This is necessary if running multiple tests in a row
function pkill_socat() {
- PROCESS_NAME="socat UDP-LISTEN:6666,fork ${OUTPUT_FILE}"
+ PROCESS_NAME4="socat UDP-LISTEN:6666,fork ${OUTPUT_FILE}"
+ PROCESS_NAME6="socat UDP6-LISTEN:6666,fork ${OUTPUT_FILE}"
# socat runs under timeout(1), kill it if it is still alive
# do not fail if socat doesn't exist anymore
set +e
- pkill -f "${PROCESS_NAME}"
+ pkill -f "${PROCESS_NAME4}"
+ pkill -f "${PROCESS_NAME6}"
set -e
}
@@ -294,3 +334,23 @@ function check_netconsole_module() {
exit "${ksft_skip}"
fi
}
+
+# A wrapper to translate protocol version to udp version
+function wait_for_port() {
+ local NAMESPACE=${1}
+ local PORT=${2}
+ IP_VERSION=${3}
+
+ if [ "${IP_VERSION}" == "ipv6" ]
+ then
+ PROTOCOL="udp6"
+ else
+ PROTOCOL="udp"
+ fi
+
+ wait_local_port_listen "${NAMESPACE}" "${PORT}" "${PROTOCOL}"
+ # even after the port is open, let's wait 1 second before writing
+ # otherwise the packet could be missed, and the test will fail. Happens
+ # more frequently on IPv6
+ sleep 1
+}
diff --git a/tools/testing/selftests/drivers/net/netcons_basic.sh b/tools/testing/selftests/drivers/net/netcons_basic.sh
index 40a6ac6191b8b..c627993dc8605 100755
--- a/tools/testing/selftests/drivers/net/netcons_basic.sh
+++ b/tools/testing/selftests/drivers/net/netcons_basic.sh
@@ -36,30 +36,36 @@ trap cleanup EXIT
# Run the test twice, with different format modes
for FORMAT in "basic" "extended"
do
- echo "Running with target mode: ${FORMAT}"
- # Create one namespace and two interfaces
- set_network
- # Create a dynamic target for netconsole
- create_dynamic_target "${FORMAT}"
- # Only set userdata for extended format
- if [ "$FORMAT" == "extended" ]
- then
- # Set userdata "key" with the "value" value
- set_user_data
- fi
- # Listed for netconsole port inside the namespace and destination interface
- listen_port_and_save_to "${OUTPUT_FILE}" &
- # Wait for socat to start and listen to the port.
- wait_local_port_listen "${NAMESPACE}" "${PORT}" udp
- # Send the message
- echo "${MSG}: ${TARGET}" > /dev/kmsg
- # Wait until socat saves the file to disk
- busywait "${BUSYWAIT_TIMEOUT}" test -s "${OUTPUT_FILE}"
+ for IP_VERSION in "ipv6" "ipv4"
+ do
+ echo "Running with target mode: ${FORMAT} (${IP_VERSION})"
+ # Create one namespace and two interfaces
+ set_network "${IP_VERSION}"
+ # Create a dynamic target for netconsole
+ create_dynamic_target "${FORMAT}"
+ # Only set userdata for extended format
+ if [ "$FORMAT" == "extended" ]
+ then
+ # Set userdata "key" with the "value" value
+ set_user_data
+ fi
+ # Listed for netconsole port inside the namespace and destination interface
+ listen_port_and_save_to "${OUTPUT_FILE}" "${IP_VERSION}" &
+ # Wait for socat to start and listen to the port.
+ wait_for_port "${NAMESPACE}" "${PORT}" "${IP_VERSION}"
+ # Send the message
+ echo "${MSG}: ${TARGET}" > /dev/kmsg
+ # Wait until socat saves the file to disk
+ busywait "${BUSYWAIT_TIMEOUT}" test -s "${OUTPUT_FILE}"
- # Make sure the message was received in the dst part
- # and exit
- validate_result "${OUTPUT_FILE}" "${FORMAT}"
- cleanup
+ # Make sure the message was received in the dst part
+ # and exit
+ validate_result "${OUTPUT_FILE}" "${FORMAT}"
+ # kill socat in case it is still running
+ pkill_socat
+ cleanup
+ echo "${FORMAT} : ${IP_VERSION} : Test passed" >&2
+ done
done
trap - EXIT
--
2.47.1
^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [PATCH net-next 6/7] netpoll: move Ethernet setup to push_eth() helper
2025-06-27 17:55 ` [PATCH net-next 6/7] netpoll: move Ethernet setup to push_eth() helper Breno Leitao
@ 2025-07-02 0:53 ` Jakub Kicinski
2025-07-02 9:25 ` Breno Leitao
0 siblings, 1 reply; 10+ messages in thread
From: Jakub Kicinski @ 2025-07-02 0:53 UTC (permalink / raw)
To: Breno Leitao
Cc: David S. Miller, Eric Dumazet, Paolo Abeni, Simon Horman,
Andrew Lunn, Shuah Khan, netdev, linux-kernel, linux-kselftest,
gustavold
On Fri, 27 Jun 2025 10:55:52 -0700 Breno Leitao wrote:
> +static void push_eth(struct netpoll *np, struct sk_buff *skb)
> +{
> + struct ethhdr *eth;
> +
> + eth = eth_hdr(skb);
> + ether_addr_copy(eth->h_source, np->dev->dev_addr);
> + ether_addr_copy(eth->h_dest, np->remote_mac);
> +}
Can you move the pushing of the header and setting h_proto here?
if the goal of the series is to slice up the code per network layer
then its a bit odd for the IP layer handlers to be pushing the L2
header and setting its proto.
Just:
if (np->ipv6)
eth->h_proto = htons(ETH_P_IPV6);
else
eth->h_proto = htons(ETH_P_IP);
no?
Unless there's some complication here that I'm missing...
--
pw-bot: cr
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH net-next 6/7] netpoll: move Ethernet setup to push_eth() helper
2025-07-02 0:53 ` Jakub Kicinski
@ 2025-07-02 9:25 ` Breno Leitao
0 siblings, 0 replies; 10+ messages in thread
From: Breno Leitao @ 2025-07-02 9:25 UTC (permalink / raw)
To: Jakub Kicinski
Cc: David S. Miller, Eric Dumazet, Paolo Abeni, Simon Horman,
Andrew Lunn, Shuah Khan, netdev, linux-kernel, linux-kselftest,
gustavold
On Tue, Jul 01, 2025 at 05:53:25PM -0700, Jakub Kicinski wrote:
> On Fri, 27 Jun 2025 10:55:52 -0700 Breno Leitao wrote:
> > +static void push_eth(struct netpoll *np, struct sk_buff *skb)
> > +{
> > + struct ethhdr *eth;
> > +
> > + eth = eth_hdr(skb);
> > + ether_addr_copy(eth->h_source, np->dev->dev_addr);
> > + ether_addr_copy(eth->h_dest, np->remote_mac);
> > +}
>
> Can you move the pushing of the header and setting h_proto here?
>
> if the goal of the series is to slice up the code per network layer
> then its a bit odd for the IP layer handlers to be pushing the L2
> header and setting its proto.
>
> Just:
>
> if (np->ipv6)
> eth->h_proto = htons(ETH_P_IPV6);
> else
> eth->h_proto = htons(ETH_P_IP);
>
> no?
yes. We can do it. In fact, if we want to do even better, we can move
the can move the skb_push(skb, ETH_HLEN) and skb_reset_mac_header() here
as well. This will slice up the code even better.
The function will look like the following:
static void push_eth(struct netpoll *np, struct sk_buff *skb)
{
struct ethhdr *eth;
eth = skb_push(skb, ETH_HLEN);
skb_reset_mac_header(skb);
ether_addr_copy(eth->h_source, np->dev->dev_addr);
ether_addr_copy(eth->h_dest, np->remote_mac);
if (np->ipv6)
eth->h_proto = htons(ETH_P_IPV6);
else
eth->h_proto = htons(ETH_P_IP);
}
^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2025-07-02 9:25 UTC | newest]
Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-06-27 17:55 [PATCH net-next 0/7] netpoll: Factor out functions from netpoll_send_udp() and add ipv6 selftest Breno Leitao
2025-06-27 17:55 ` [PATCH net-next 1/7] netpoll: Improve code clarity with explicit struct size calculations Breno Leitao
2025-06-27 17:55 ` [PATCH net-next 2/7] netpoll: factor out UDP checksum calculation into helper Breno Leitao
2025-06-27 17:55 ` [PATCH net-next 3/7] netpoll: factor out IPv6 header setup into push_ipv6() helper Breno Leitao
2025-06-27 17:55 ` [PATCH net-next 4/7] netpoll: factor out IPv4 header setup into push_ipv4() helper Breno Leitao
2025-06-27 17:55 ` [PATCH net-next 5/7] netpoll: factor out UDP header setup into push_udp() helper Breno Leitao
2025-06-27 17:55 ` [PATCH net-next 6/7] netpoll: move Ethernet setup to push_eth() helper Breno Leitao
2025-07-02 0:53 ` Jakub Kicinski
2025-07-02 9:25 ` Breno Leitao
2025-06-27 17:55 ` [PATCH net-next 7/7] selftests: net: Add IPv6 support to netconsole basic tests Breno Leitao
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).