Skip to content

Commit

Permalink
neighbor: Add skip_cache argument to neigh_output
Browse files Browse the repository at this point in the history
A later patch allows an IPv6 gateway with an IPv4 route. The neighbor
entry will exist in the v6 ndisc table and the cached header will contain
the ipv6 protocol which is wrong for an IPv4 packet. For an IPv4 packet to
use the v6 neighbor entry, neigh_output needs to skip the cached header
and just use the output callback for the neigh entry.

A future patchset can look at expanding the hh_cache to handle 2
protocols. For now, IPv6 gateways with an IPv4 route will take the
extra overhead of generating the header.

Signed-off-by: David Ahern <dsahern@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
David Ahern authored and David S. Miller committed Apr 8, 2019
1 parent 717a8f5 commit 0353f28
Show file tree
Hide file tree
Showing 4 changed files with 7 additions and 6 deletions.
4 changes: 2 additions & 2 deletions drivers/net/vrf.c
Original file line number Diff line number Diff line change
Expand Up @@ -370,7 +370,7 @@ static int vrf_finish_output6(struct net *net, struct sock *sk,
neigh = __neigh_create(&nd_tbl, nexthop, dst->dev, false);
if (!IS_ERR(neigh)) {
sock_confirm_neigh(skb, neigh);
ret = neigh_output(neigh, skb);
ret = neigh_output(neigh, skb, false);
rcu_read_unlock_bh();
return ret;
}
Expand Down Expand Up @@ -578,7 +578,7 @@ static int vrf_finish_output(struct net *net, struct sock *sk, struct sk_buff *s
neigh = __neigh_create(&arp_tbl, &nexthop, dev, false);
if (!IS_ERR(neigh)) {
sock_confirm_neigh(skb, neigh);
ret = neigh_output(neigh, skb);
ret = neigh_output(neigh, skb, false);
rcu_read_unlock_bh();
return ret;
}
Expand Down
5 changes: 3 additions & 2 deletions include/net/neighbour.h
Original file line number Diff line number Diff line change
Expand Up @@ -498,11 +498,12 @@ static inline int neigh_hh_output(const struct hh_cache *hh, struct sk_buff *skb
return dev_queue_xmit(skb);
}

static inline int neigh_output(struct neighbour *n, struct sk_buff *skb)
static inline int neigh_output(struct neighbour *n, struct sk_buff *skb,
bool skip_cache)
{
const struct hh_cache *hh = &n->hh;

if ((n->nud_state & NUD_CONNECTED) && hh->hh_len)
if ((n->nud_state & NUD_CONNECTED) && hh->hh_len && !skip_cache)
return neigh_hh_output(hh, skb);
else
return n->output(n, skb);
Expand Down
2 changes: 1 addition & 1 deletion net/ipv4/ip_output.c
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,7 @@ static int ip_finish_output2(struct net *net, struct sock *sk, struct sk_buff *s
int res;

sock_confirm_neigh(skb, neigh);
res = neigh_output(neigh, skb);
res = neigh_output(neigh, skb, false);

rcu_read_unlock_bh();
return res;
Expand Down
2 changes: 1 addition & 1 deletion net/ipv6/ip6_output.c
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ static int ip6_finish_output2(struct net *net, struct sock *sk, struct sk_buff *
neigh = __neigh_create(&nd_tbl, nexthop, dst->dev, false);
if (!IS_ERR(neigh)) {
sock_confirm_neigh(skb, neigh);
ret = neigh_output(neigh, skb);
ret = neigh_output(neigh, skb, false);
rcu_read_unlock_bh();
return ret;
}
Expand Down

0 comments on commit 0353f28

Please sign in to comment.