]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
net: ipv4: allow directed broadcast routes to use dst hint
authorOscar Maes <oscmaes92@gmail.com>
Tue, 19 Aug 2025 17:46:41 +0000 (19:46 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 13 Nov 2025 20:34:15 +0000 (15:34 -0500)
[ Upstream commit 1b8c5fa0cb35efd08f07f700e6d78a541ebabe26 ]

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.

Fix this in ip_extract_route_hint and modify ip_route_use_hint
to preserve the intended behaviour.

Signed-off-by: Oscar Maes <oscmaes92@gmail.com>
Reviewed-by: David Ahern <dsahern@kernel.org>
Link: https://patch.msgid.link/20250819174642.5148-2-oscmaes92@gmail.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
net/ipv4/ip_input.c
net/ipv4/route.c

index b6e7d4921309741193a8c096aeb278255ec56794..7b092ba6f5779f4141689164281a27e6bafeba65 100644 (file)
@@ -582,9 +582,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;
 
@@ -614,8 +618,7 @@ static void ip_list_rcv_finish(struct net *net, struct sock *sk,
 
                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))
index 7d04df4fc66084b2a5fbff421574abe8751a2db3..96a01eb33653f86c01eaf5fc3ce1b357b835ee76 100644 (file)
@@ -2187,7 +2187,7 @@ int ip_route_use_hint(struct sk_buff *skb, __be32 daddr, __be32 saddr,
        if (ipv4_is_loopback(saddr) && !IN_DEV_NET_ROUTE_LOCALNET(in_dev, net))
                goto martian_source;
 
-       if (rt->rt_type != RTN_LOCAL)
+       if (!(rt->rt_flags & RTCF_LOCAL))
                goto skip_validate_source;
 
        tos &= INET_DSCP_MASK;