Commit 3ad96554 authored by Jakub Kicinski's avatar Jakub Kicinski
Browse files

Merge branch 'net-ipv4-allow-directed-broadcast-routes-to-use-dst-hint'

Oscar Maes says:

====================
net: ipv4: allow directed broadcast routes to use dst hint

Currently, ip_extract_route_hint uses RTN_BROADCAST to decide
whether to use the route dst hint mechanism.

This check is too strict, as it prevents directed broadcast
routes from using the hint, resulting in poor performance
during bursts of directed broadcast traffic.

This series fixes this, and adds a new selftest to ensure
this does not regress.

Link to v2: https://lore.kernel.org/20250814140309.3742-1-oscmaes92@gmail.com
====================

Link: https://patch.msgid.link/20250819174642.5148-1-oscmaes92@gmail.com


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parents 7f052126 bd0d9e75
Loading
Loading
Loading
Loading
+7 −4
Original line number Diff line number Diff line
@@ -587,9 +587,13 @@ static void ip_sublist_rcv_finish(struct list_head *head)
}

static struct sk_buff *ip_extract_route_hint(const struct net *net,
					     struct sk_buff *skb, int rt_type)
					     struct sk_buff *skb)
{
	if (fib4_has_custom_rules(net) || rt_type == RTN_BROADCAST ||
	const struct iphdr *iph = ip_hdr(skb);

	if (fib4_has_custom_rules(net) ||
	    ipv4_is_lbcast(iph->daddr) ||
	    ipv4_is_zeronet(iph->daddr) ||
	    IPCB(skb)->flags & IPSKB_MULTIPATH)
		return NULL;

@@ -618,8 +622,7 @@ static void ip_list_rcv_finish(struct net *net, struct list_head *head)

		dst = skb_dst(skb);
		if (curr_dst != dst) {
			hint = ip_extract_route_hint(net, skb,
						     dst_rtable(dst)->rt_type);
			hint = ip_extract_route_hint(net, skb);

			/* dispatch old sublist */
			if (!list_empty(&sublist))
+1 −1
Original line number Diff line number Diff line
@@ -2210,7 +2210,7 @@ ip_route_use_hint(struct sk_buff *skb, __be32 daddr, __be32 saddr,
		goto martian_source;
	}

	if (rt->rt_type != RTN_LOCAL)
	if (!(rt->rt_flags & RTCF_LOCAL))
		goto skip_validate_source;

	reason = fib_validate_source_reason(skb, saddr, daddr, dscp, 0, dev,
+1 −0
Original line number Diff line number Diff line
@@ -117,6 +117,7 @@ TEST_GEN_FILES += tfo
TEST_PROGS += tfo_passive.sh
TEST_PROGS += broadcast_pmtu.sh
TEST_PROGS += ipv6_force_forwarding.sh
TEST_PROGS += route_hint.sh

# YNL files, must be before "include ..lib.mk"
YNL_GEN_FILES := busy_poller netlink-dumps
+79 −0
Original line number Diff line number Diff line
#!/bin/bash
# SPDX-License-Identifier: GPL-2.0

# This test ensures directed broadcast routes use dst hint mechanism

source lib.sh

CLIENT_IP4="192.168.0.1"
SERVER_IP4="192.168.0.2"
BROADCAST_ADDRESS="192.168.0.255"

setup() {
	setup_ns CLIENT_NS SERVER_NS

	ip -net "${SERVER_NS}" link add link1 type veth peer name link0 netns "${CLIENT_NS}"

	ip -net "${CLIENT_NS}" link set link0 up
	ip -net "${CLIENT_NS}" addr add "${CLIENT_IP4}/24" dev link0

	ip -net "${SERVER_NS}" link set link1 up
	ip -net "${SERVER_NS}" addr add "${SERVER_IP4}/24" dev link1

	ip netns exec "${CLIENT_NS}" ethtool -K link0 tcp-segmentation-offload off
	ip netns exec "${SERVER_NS}" sh -c "echo 500000000 > /sys/class/net/link1/gro_flush_timeout"
	ip netns exec "${SERVER_NS}" sh -c "echo 1 > /sys/class/net/link1/napi_defer_hard_irqs"
	ip netns exec "${SERVER_NS}" ethtool -K link1 generic-receive-offload on
}

cleanup() {
	ip -net "${SERVER_NS}" link del link1
	cleanup_ns "${CLIENT_NS}" "${SERVER_NS}"
}

directed_bcast_hint_test()
{
	local rc=0

	echo "Testing for directed broadcast route hint"

	orig_in_brd=$(ip netns exec "${SERVER_NS}" lnstat -j -i1 -c1 | jq '.in_brd')
	ip netns exec "${CLIENT_NS}" mausezahn link0 -a own -b bcast -A "${CLIENT_IP4}" \
		-B "${BROADCAST_ADDRESS}" -c1 -t tcp "sp=1-100,dp=1234,s=1,a=0" -p 5 -q
	sleep 1
	new_in_brd=$(ip netns exec "${SERVER_NS}" lnstat -j -i1 -c1 | jq '.in_brd')

	res=$(echo "${new_in_brd} - ${orig_in_brd}" | bc)

	if [ "${res}" -lt 100 ]; then
		echo "[ OK ]"
		rc="${ksft_pass}"
	else
		echo "[FAIL] expected in_brd to be under 100, got ${res}"
		rc="${ksft_fail}"
	fi

	return "${rc}"
}

if [ ! -x "$(command -v mausezahn)" ]; then
	echo "SKIP: Could not run test without mausezahn tool"
	exit "${ksft_skip}"
fi

if [ ! -x "$(command -v jq)" ]; then
	echo "SKIP: Could not run test without jq tool"
	exit "${ksft_skip}"
fi

if [ ! -x "$(command -v bc)" ]; then
	echo "SKIP: Could not run test without bc tool"
	exit "${ksft_skip}"
fi

trap cleanup EXIT

setup

directed_bcast_hint_test
exit $?