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

From: Yuya Kusakabe

Date: Sat Oct 10 2026 - 06:13:16 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.791 0.811 (+2.5%)
10 10 on the NIC's socket 6.118 7.394 (+20.9%)
16 10 + 6 on two sockets 3.305 10.205 (+208.8%)

End.DT4
queues cores before after
1 1 0.481 0.489 (+1.6%)
10 10 on the NIC's socket 4.328 4.588 (+6.0%)
16 10 + 6 on two sockets 3.351 7.153 (+113.5%)

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 more than half 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 f23330278922..60abd139dbe3 100644
--- a/net/ipv6/seg6_local.c
+++ b/net/ipv6/seg6_local.c
@@ -1099,7 +1099,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;
@@ -1325,7 +1325,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