forked from luck/tmp_suning_uos_patched
neighbor: Add skip_cache argument to neigh_output
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>
This commit is contained in:
parent
717a8f5b29
commit
0353f28231
|
@ -370,7 +370,7 @@ static int vrf_finish_output6(struct net *net, struct sock *sk,
|
||||||
neigh = __neigh_create(&nd_tbl, nexthop, dst->dev, false);
|
neigh = __neigh_create(&nd_tbl, nexthop, dst->dev, false);
|
||||||
if (!IS_ERR(neigh)) {
|
if (!IS_ERR(neigh)) {
|
||||||
sock_confirm_neigh(skb, neigh);
|
sock_confirm_neigh(skb, neigh);
|
||||||
ret = neigh_output(neigh, skb);
|
ret = neigh_output(neigh, skb, false);
|
||||||
rcu_read_unlock_bh();
|
rcu_read_unlock_bh();
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -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);
|
neigh = __neigh_create(&arp_tbl, &nexthop, dev, false);
|
||||||
if (!IS_ERR(neigh)) {
|
if (!IS_ERR(neigh)) {
|
||||||
sock_confirm_neigh(skb, neigh);
|
sock_confirm_neigh(skb, neigh);
|
||||||
ret = neigh_output(neigh, skb);
|
ret = neigh_output(neigh, skb, false);
|
||||||
rcu_read_unlock_bh();
|
rcu_read_unlock_bh();
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
|
@ -498,11 +498,12 @@ static inline int neigh_hh_output(const struct hh_cache *hh, struct sk_buff *skb
|
||||||
return dev_queue_xmit(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;
|
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);
|
return neigh_hh_output(hh, skb);
|
||||||
else
|
else
|
||||||
return n->output(n, skb);
|
return n->output(n, skb);
|
||||||
|
|
|
@ -226,7 +226,7 @@ static int ip_finish_output2(struct net *net, struct sock *sk, struct sk_buff *s
|
||||||
int res;
|
int res;
|
||||||
|
|
||||||
sock_confirm_neigh(skb, neigh);
|
sock_confirm_neigh(skb, neigh);
|
||||||
res = neigh_output(neigh, skb);
|
res = neigh_output(neigh, skb, false);
|
||||||
|
|
||||||
rcu_read_unlock_bh();
|
rcu_read_unlock_bh();
|
||||||
return res;
|
return res;
|
||||||
|
|
|
@ -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);
|
neigh = __neigh_create(&nd_tbl, nexthop, dst->dev, false);
|
||||||
if (!IS_ERR(neigh)) {
|
if (!IS_ERR(neigh)) {
|
||||||
sock_confirm_neigh(skb, neigh);
|
sock_confirm_neigh(skb, neigh);
|
||||||
ret = neigh_output(neigh, skb);
|
ret = neigh_output(neigh, skb, false);
|
||||||
rcu_read_unlock_bh();
|
rcu_read_unlock_bh();
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user