Subject: Re: [PATCH net-next 11/18] ipv4: Add helpers for neigh lookup for nexthop

From: Ido Schimmel <[email-masked]>
Date: Fri, 5 Apr 2019 14:48:38 +0000

On Thu, Apr 04, 2019 at 10:50:00AM -0700, David Ahern wrote:
> From: David Ahern <[email-masked]>
> 
> A common them in the output path is looking up a neigh entry for a

s/them/theme/

> nexthop, either the gateway in an rtable or a fallback to the daddr
> in the skb:
> 
>         nexthop = (__force u32)rt_nexthop(rt, ip_hdr(skb)->daddr);
>         neigh = __ipv4_neigh_lookup_noref(dev, nexthop);
>         if (unlikely(!neigh))
>                 neigh = __neigh_create(&arp_tbl, &nexthop, dev, false);
> 
> To allow the nexthop to be an IPv6 address we need to consider the
> family of the nexthop and then call __ipv*_neigh_lookup_noref based
> on it.
> 
> To make this simpler, add a ip_neigh_gw4 helper similar to ip_neigh_gw6
> which handles:
> 
>         neigh = __ipv4_neigh_lookup_noref(dev, nexthop);
>         if (unlikely(!neigh))
>                 neigh = __neigh_create(&arp_tbl, &nexthop, dev, false);
> 
> And then add a second one, ip_neigh_for_gw, that calls either
> ip_neigh_gw4 or ip_neigh_gw6 based on the address family of the gateway.
> 
> Update the output paths in the VRF driver and core v4 code to use
> ip_neigh_for_gw simplifying the family based lookup and making both
> ready for a v6 nexthop.
> 
> ipv4_neigh_lookup has a different need - the potential to resolve a
> passed in address in addition to any gateway in the rtable or skb. Since
> this is a one-off, add ip_neigh_gw4 and ip_neigh_gw6 diectly. The
> difference between __neigh_create used by the helpers and neigh_create
> called by ipv4_neigh_lookup is taking a refcount, so add rcu_read_lock_bh
> and bump the refcnt on the neigh entry.
> 
> Signed-off-by: David Ahern <[email-masked]>

Looks good to me. A couple of nits below.

> @@ -572,13 +572,11 @@ static int vrf_finish_output(struct net *net, struct sock *sk, struct sk_buff *s
>  
>  	rcu_read_lock_bh();
>  
> -	nexthop = (__force u32)rt_nexthop(rt, ip_hdr(skb)->daddr);
> -	neigh = __ipv4_neigh_lookup_noref(dev, nexthop);
> -	if (unlikely(!neigh))
> -		neigh = __neigh_create(&arp_tbl, &nexthop, dev, false);
> +	neigh = ip_neigh_for_gw(rt, skb, &is_v6gw);
>  	if (!IS_ERR(neigh)) {
>  		sock_confirm_neigh(skb, neigh);
> -		ret = neigh_output(neigh, skb, false);
> +		/* if crossing protocols, can not used the cached header */

s/used/use/

> +		ret = neigh_output(neigh, skb, is_v6gw);
>  		rcu_read_unlock_bh();
>  		return ret;
>  	}

...

> @@ -218,16 +218,13 @@ static int ip_finish_output2(struct net *net, struct sock *sk, struct sk_buff *s
>  	}
>  
>  	rcu_read_lock_bh();
> -	nexthop = (__force u32) rt_nexthop(rt, ip_hdr(skb)->daddr);
> -	neigh = __ipv4_neigh_lookup_noref(dev, nexthop);
> -	if (unlikely(!neigh))
> -		neigh = __neigh_create(&arp_tbl, &nexthop, dev, false);
> +	neigh = ip_neigh_for_gw(rt, skb, &is_v6gw);
>  	if (!IS_ERR(neigh)) {
>  		int res;
>  
>  		sock_confirm_neigh(skb, neigh);
> -		res = neigh_output(neigh, skb, false);
> -
> +		/* if crossing protocols, can not used the cached header */

s/used/use/

> +		res = neigh_output(neigh, skb, is_v6gw);
>  		rcu_read_unlock_bh();
>  		return res;
>  	}