On Thu, Apr 04, 2019 at 10:50:00AM -0700, David Ahern wrote: > From: David Ahern <dsah...@gmail.com> > > 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 <dsah...@gmail.com> 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; > }