[PATCH net-next 2/2] seg6: skip the route refcount in seg6local IPv4 lookups

From: Yuya Kusakabe

Date: Mon Oct 05 2026 - 01:34:39 EST


ip_route_input() looks the input route up with ip_route_input_noref()
and then forces a reference on it, which is dropped again when the
packet is transmitted. End.DX4 and End.DT4 call it from the RCU
read-side section of the receive path, either directly from the
seg6local input handler or from a netfilter okfn, and hand the skb to
dst_input() before leaving that section.

Use ip_route_input_noref(), as ip_rcv_finish() does.

Throughput at 0.5% packet loss of 82-byte IPv4-in-IPv6 UDP packets
(no SRH), spread by RSS on an ixgbe 82599ES across two 10-core Xeon
E5-2650 v3, offered by TRex over 10 runs of 10 s, in Mpps:

End.DX4
queues cores before after
1 1 0.816 0.837 (+2.6%)
10 10 on the NIC's socket 6.534 7.621 (+16.6%)
16 10 + 6 on two sockets 3.369 10.208 (+203.0%)

End.DT4
queues cores before after
1 1 0.497 0.501 (+0.8%)
10 10 on the NIC's socket 4.410 4.679 (+6.1%)
16 10 + 6 on two sockets 3.259 7.431 (+128.0%)

Every CPU takes and drops a reference on the same input route, the
one cached on the nexthop. At 16 queues that cache line bounces
between the sockets, and skb_dst_force() and dst_release() together
take about 60% of the cycles for End.DX4 and over 40% for End.DT4.

Assisted-by: LLM
Signed-off-by: Yuya Kusakabe <yuya.kusakabe@xxxxxxxxx>
---
net/ipv6/seg6_local.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/net/ipv6/seg6_local.c b/net/ipv6/seg6_local.c
index 4bde3669d0dd..1dfe20b365b7 100644
--- a/net/ipv6/seg6_local.c
+++ b/net/ipv6/seg6_local.c
@@ -1079,7 +1079,7 @@ static int input_action_end_dx4_finish(struct net *net, struct sock *sk,

skb_dst_drop(skb);

- reason = ip_route_input(skb, nhaddr, iph->saddr, 0, skb->dev);
+ reason = ip_route_input_noref(skb, nhaddr, iph->saddr, 0, skb->dev);
if (reason) {
kfree_skb_reason(skb, reason);
return -EINVAL;
@@ -1305,7 +1305,7 @@ static int input_action_end_dt4(struct sk_buff *skb,

iph = ip_hdr(skb);

- reason = ip_route_input(skb, iph->daddr, iph->saddr, 0, skb->dev);
+ reason = ip_route_input_noref(skb, iph->daddr, iph->saddr, 0, skb->dev);
if (unlikely(reason))
goto drop;


--
2.50.1