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
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);
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);
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);
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);
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
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);
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
linux-kselftest-mirror@lists.linaro.org