mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-12 05:48:39 +08:00
net: use dst_confirm_neigh for UDP, RAW, ICMP, L2TP
When same struct dst_entry can be used for many different neighbours we can not use it for pending confirmations. The datagram protocols can use MSG_CONFIRM to confirm the neighbour. When used with MSG_PROBE we do not reach the code where neighbour is confirmed, so we have to do the same slow lookup by using the dst_confirm_neigh() helper. When MSG_PROBE is not used, ip_append_data/ip6_append_data will set the skb flag dst_pending_confirm. Reported-by: YueHaibing <yuehaibing@huawei.com> Fixes:5110effee8
("net: Do delayed neigh confirmation.") Fixes:f2bb4bedf3
("ipv4: Cache output routes in fib_info nexthops.") Signed-off-by: Julian Anastasov <ja@ssi.bg> Acked-by: Eric Dumazet <edumazet@google.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
63fca65d08
commit
0dec879f63
@ -889,6 +889,9 @@ static inline int ip_ufo_append_data(struct sock *sk,
|
|||||||
|
|
||||||
skb->csum = 0;
|
skb->csum = 0;
|
||||||
|
|
||||||
|
if (flags & MSG_CONFIRM)
|
||||||
|
skb_set_dst_pending_confirm(skb, 1);
|
||||||
|
|
||||||
__skb_queue_tail(queue, skb);
|
__skb_queue_tail(queue, skb);
|
||||||
} else if (skb_is_gso(skb)) {
|
} else if (skb_is_gso(skb)) {
|
||||||
goto append;
|
goto append;
|
||||||
@ -1089,6 +1092,9 @@ alloc_new_skb:
|
|||||||
exthdrlen = 0;
|
exthdrlen = 0;
|
||||||
csummode = CHECKSUM_NONE;
|
csummode = CHECKSUM_NONE;
|
||||||
|
|
||||||
|
if ((flags & MSG_CONFIRM) && !skb_prev)
|
||||||
|
skb_set_dst_pending_confirm(skb, 1);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Put the packet on the pending queue.
|
* Put the packet on the pending queue.
|
||||||
*/
|
*/
|
||||||
|
@ -848,7 +848,8 @@ out:
|
|||||||
return err;
|
return err;
|
||||||
|
|
||||||
do_confirm:
|
do_confirm:
|
||||||
dst_confirm(&rt->dst);
|
if (msg->msg_flags & MSG_PROBE)
|
||||||
|
dst_confirm_neigh(&rt->dst, &fl4.daddr);
|
||||||
if (!(msg->msg_flags & MSG_PROBE) || len)
|
if (!(msg->msg_flags & MSG_PROBE) || len)
|
||||||
goto back_from_confirm;
|
goto back_from_confirm;
|
||||||
err = 0;
|
err = 0;
|
||||||
|
@ -383,6 +383,9 @@ static int raw_send_hdrinc(struct sock *sk, struct flowi4 *fl4,
|
|||||||
|
|
||||||
sock_tx_timestamp(sk, sockc->tsflags, &skb_shinfo(skb)->tx_flags);
|
sock_tx_timestamp(sk, sockc->tsflags, &skb_shinfo(skb)->tx_flags);
|
||||||
|
|
||||||
|
if (flags & MSG_CONFIRM)
|
||||||
|
skb_set_dst_pending_confirm(skb, 1);
|
||||||
|
|
||||||
skb->transport_header = skb->network_header;
|
skb->transport_header = skb->network_header;
|
||||||
err = -EFAULT;
|
err = -EFAULT;
|
||||||
if (memcpy_from_msg(iph, msg, length))
|
if (memcpy_from_msg(iph, msg, length))
|
||||||
@ -666,7 +669,8 @@ out:
|
|||||||
return len;
|
return len;
|
||||||
|
|
||||||
do_confirm:
|
do_confirm:
|
||||||
dst_confirm(&rt->dst);
|
if (msg->msg_flags & MSG_PROBE)
|
||||||
|
dst_confirm_neigh(&rt->dst, &fl4.daddr);
|
||||||
if (!(msg->msg_flags & MSG_PROBE) || len)
|
if (!(msg->msg_flags & MSG_PROBE) || len)
|
||||||
goto back_from_confirm;
|
goto back_from_confirm;
|
||||||
err = 0;
|
err = 0;
|
||||||
|
@ -1101,7 +1101,8 @@ out:
|
|||||||
return err;
|
return err;
|
||||||
|
|
||||||
do_confirm:
|
do_confirm:
|
||||||
dst_confirm(&rt->dst);
|
if (msg->msg_flags & MSG_PROBE)
|
||||||
|
dst_confirm_neigh(&rt->dst, &fl4->daddr);
|
||||||
if (!(msg->msg_flags&MSG_PROBE) || len)
|
if (!(msg->msg_flags&MSG_PROBE) || len)
|
||||||
goto back_from_confirm;
|
goto back_from_confirm;
|
||||||
err = 0;
|
err = 0;
|
||||||
|
@ -1145,6 +1145,9 @@ static inline int ip6_ufo_append_data(struct sock *sk,
|
|||||||
skb->protocol = htons(ETH_P_IPV6);
|
skb->protocol = htons(ETH_P_IPV6);
|
||||||
skb->csum = 0;
|
skb->csum = 0;
|
||||||
|
|
||||||
|
if (flags & MSG_CONFIRM)
|
||||||
|
skb_set_dst_pending_confirm(skb, 1);
|
||||||
|
|
||||||
__skb_queue_tail(queue, skb);
|
__skb_queue_tail(queue, skb);
|
||||||
} else if (skb_is_gso(skb)) {
|
} else if (skb_is_gso(skb)) {
|
||||||
goto append;
|
goto append;
|
||||||
@ -1517,6 +1520,9 @@ alloc_new_skb:
|
|||||||
exthdrlen = 0;
|
exthdrlen = 0;
|
||||||
dst_exthdrlen = 0;
|
dst_exthdrlen = 0;
|
||||||
|
|
||||||
|
if ((flags & MSG_CONFIRM) && !skb_prev)
|
||||||
|
skb_set_dst_pending_confirm(skb, 1);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Put the packet on the pending queue
|
* Put the packet on the pending queue
|
||||||
*/
|
*/
|
||||||
|
@ -654,6 +654,9 @@ static int rawv6_send_hdrinc(struct sock *sk, struct msghdr *msg, int length,
|
|||||||
|
|
||||||
skb->ip_summed = CHECKSUM_NONE;
|
skb->ip_summed = CHECKSUM_NONE;
|
||||||
|
|
||||||
|
if (flags & MSG_CONFIRM)
|
||||||
|
skb_set_dst_pending_confirm(skb, 1);
|
||||||
|
|
||||||
skb->transport_header = skb->network_header;
|
skb->transport_header = skb->network_header;
|
||||||
err = memcpy_from_msg(iph, msg, length);
|
err = memcpy_from_msg(iph, msg, length);
|
||||||
if (err)
|
if (err)
|
||||||
@ -934,7 +937,8 @@ out:
|
|||||||
txopt_put(opt_to_free);
|
txopt_put(opt_to_free);
|
||||||
return err < 0 ? err : len;
|
return err < 0 ? err : len;
|
||||||
do_confirm:
|
do_confirm:
|
||||||
dst_confirm(dst);
|
if (msg->msg_flags & MSG_PROBE)
|
||||||
|
dst_confirm_neigh(dst, &fl6.daddr);
|
||||||
if (!(msg->msg_flags & MSG_PROBE) || len)
|
if (!(msg->msg_flags & MSG_PROBE) || len)
|
||||||
goto back_from_confirm;
|
goto back_from_confirm;
|
||||||
err = 0;
|
err = 0;
|
||||||
|
@ -1381,6 +1381,7 @@ static bool rt6_cache_allowed_for_pmtu(const struct rt6_info *rt)
|
|||||||
static void __ip6_rt_update_pmtu(struct dst_entry *dst, const struct sock *sk,
|
static void __ip6_rt_update_pmtu(struct dst_entry *dst, const struct sock *sk,
|
||||||
const struct ipv6hdr *iph, u32 mtu)
|
const struct ipv6hdr *iph, u32 mtu)
|
||||||
{
|
{
|
||||||
|
const struct in6_addr *daddr, *saddr;
|
||||||
struct rt6_info *rt6 = (struct rt6_info *)dst;
|
struct rt6_info *rt6 = (struct rt6_info *)dst;
|
||||||
|
|
||||||
if (rt6->rt6i_flags & RTF_LOCAL)
|
if (rt6->rt6i_flags & RTF_LOCAL)
|
||||||
@ -1389,26 +1390,26 @@ static void __ip6_rt_update_pmtu(struct dst_entry *dst, const struct sock *sk,
|
|||||||
if (dst_metric_locked(dst, RTAX_MTU))
|
if (dst_metric_locked(dst, RTAX_MTU))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
dst_confirm(dst);
|
if (iph) {
|
||||||
|
daddr = &iph->daddr;
|
||||||
|
saddr = &iph->saddr;
|
||||||
|
} else if (sk) {
|
||||||
|
daddr = &sk->sk_v6_daddr;
|
||||||
|
saddr = &inet6_sk(sk)->saddr;
|
||||||
|
} else {
|
||||||
|
daddr = NULL;
|
||||||
|
saddr = NULL;
|
||||||
|
}
|
||||||
|
dst_confirm_neigh(dst, daddr);
|
||||||
mtu = max_t(u32, mtu, IPV6_MIN_MTU);
|
mtu = max_t(u32, mtu, IPV6_MIN_MTU);
|
||||||
if (mtu >= dst_mtu(dst))
|
if (mtu >= dst_mtu(dst))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!rt6_cache_allowed_for_pmtu(rt6)) {
|
if (!rt6_cache_allowed_for_pmtu(rt6)) {
|
||||||
rt6_do_update_pmtu(rt6, mtu);
|
rt6_do_update_pmtu(rt6, mtu);
|
||||||
} else {
|
} else if (daddr) {
|
||||||
const struct in6_addr *daddr, *saddr;
|
|
||||||
struct rt6_info *nrt6;
|
struct rt6_info *nrt6;
|
||||||
|
|
||||||
if (iph) {
|
|
||||||
daddr = &iph->daddr;
|
|
||||||
saddr = &iph->saddr;
|
|
||||||
} else if (sk) {
|
|
||||||
daddr = &sk->sk_v6_daddr;
|
|
||||||
saddr = &inet6_sk(sk)->saddr;
|
|
||||||
} else {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
nrt6 = ip6_rt_cache_alloc(rt6, daddr, saddr);
|
nrt6 = ip6_rt_cache_alloc(rt6, daddr, saddr);
|
||||||
if (nrt6) {
|
if (nrt6) {
|
||||||
rt6_do_update_pmtu(nrt6, mtu);
|
rt6_do_update_pmtu(nrt6, mtu);
|
||||||
@ -2332,7 +2333,7 @@ static void rt6_do_redirect(struct dst_entry *dst, struct sock *sk, struct sk_bu
|
|||||||
* Look, redirects are sent only in response to data packets,
|
* Look, redirects are sent only in response to data packets,
|
||||||
* so that this nexthop apparently is reachable. --ANK
|
* so that this nexthop apparently is reachable. --ANK
|
||||||
*/
|
*/
|
||||||
dst_confirm(&rt->dst);
|
dst_confirm_neigh(&rt->dst, &ipv6_hdr(skb)->saddr);
|
||||||
|
|
||||||
neigh = __neigh_lookup(&nd_tbl, &msg->target, skb->dev, 1);
|
neigh = __neigh_lookup(&nd_tbl, &msg->target, skb->dev, 1);
|
||||||
if (!neigh)
|
if (!neigh)
|
||||||
|
@ -1308,7 +1308,8 @@ out:
|
|||||||
return err;
|
return err;
|
||||||
|
|
||||||
do_confirm:
|
do_confirm:
|
||||||
dst_confirm(dst);
|
if (msg->msg_flags & MSG_PROBE)
|
||||||
|
dst_confirm_neigh(dst, &fl6.daddr);
|
||||||
if (!(msg->msg_flags&MSG_PROBE) || len)
|
if (!(msg->msg_flags&MSG_PROBE) || len)
|
||||||
goto back_from_confirm;
|
goto back_from_confirm;
|
||||||
err = 0;
|
err = 0;
|
||||||
|
@ -658,7 +658,8 @@ out:
|
|||||||
return err < 0 ? err : len;
|
return err < 0 ? err : len;
|
||||||
|
|
||||||
do_confirm:
|
do_confirm:
|
||||||
dst_confirm(dst);
|
if (msg->msg_flags & MSG_PROBE)
|
||||||
|
dst_confirm_neigh(dst, &fl6.daddr);
|
||||||
if (!(msg->msg_flags & MSG_PROBE) || len)
|
if (!(msg->msg_flags & MSG_PROBE) || len)
|
||||||
goto back_from_confirm;
|
goto back_from_confirm;
|
||||||
err = 0;
|
err = 0;
|
||||||
|
Loading…
Reference in New Issue
Block a user