ipv6: refactor ip6_finish_output2()
authorPavel Begunkov <asml.silence@gmail.com>
Thu, 28 Apr 2022 10:58:48 +0000 (11:58 +0100)
committerDavid S. Miller <davem@davemloft.net>
Sat, 30 Apr 2022 11:58:45 +0000 (12:58 +0100)
Throw neigh checks in ip6_finish_output2() under a single slow path if,
so we don't have the overhead in the hot path.

Signed-off-by: Pavel Begunkov <asml.silence@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
net/ipv6/ip6_output.c

index bda1d9f..afa5bd4 100644 (file)
@@ -119,19 +119,21 @@ static int ip6_finish_output2(struct net *net, struct sock *sk, struct sk_buff *
        rcu_read_lock_bh();
        nexthop = rt6_nexthop((struct rt6_info *)dst, daddr);
        neigh = __ipv6_neigh_lookup_noref(dev, nexthop);
-       if (unlikely(!neigh))
-               neigh = __neigh_create(&nd_tbl, nexthop, dev, false);
-       if (!IS_ERR(neigh)) {
-               sock_confirm_neigh(skb, neigh);
-               ret = neigh_output(neigh, skb, false);
-               rcu_read_unlock_bh();
-               return ret;
+
+       if (unlikely(IS_ERR_OR_NULL(neigh))) {
+               if (unlikely(!neigh))
+                       neigh = __neigh_create(&nd_tbl, nexthop, dev, false);
+               if (IS_ERR(neigh)) {
+                       rcu_read_unlock_bh();
+                       IP6_INC_STATS(net, idev, IPSTATS_MIB_OUTNOROUTES);
+                       kfree_skb_reason(skb, SKB_DROP_REASON_NEIGH_CREATEFAIL);
+                       return -EINVAL;
+               }
        }
+       sock_confirm_neigh(skb, neigh);
+       ret = neigh_output(neigh, skb, false);
        rcu_read_unlock_bh();
-
-       IP6_INC_STATS(net, idev, IPSTATS_MIB_OUTNOROUTES);
-       kfree_skb_reason(skb, SKB_DROP_REASON_NEIGH_CREATEFAIL);
-       return -EINVAL;
+       return ret;
 }
 
 static int