Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0dec879f authored by Julian Anastasov's avatar Julian Anastasov Committed by David S. Miller
Browse files

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: default avatarYueHaibing <yuehaibing@huawei.com>
Fixes: 5110effe ("net: Do delayed neigh confirmation.")
Fixes: f2bb4bed ("ipv4: Cache output routes in fib_info nexthops.")
Signed-off-by: default avatarJulian Anastasov <ja@ssi.bg>
Acked-by: default avatarEric Dumazet <edumazet@google.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 63fca65d
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -889,6 +889,9 @@ static inline int ip_ufo_append_data(struct sock *sk,

		skb->csum = 0;

		if (flags & MSG_CONFIRM)
			skb_set_dst_pending_confirm(skb, 1);

		__skb_queue_tail(queue, skb);
	} else if (skb_is_gso(skb)) {
		goto append;
@@ -1089,6 +1092,9 @@ static int __ip_append_data(struct sock *sk,
			exthdrlen = 0;
			csummode = CHECKSUM_NONE;

			if ((flags & MSG_CONFIRM) && !skb_prev)
				skb_set_dst_pending_confirm(skb, 1);

			/*
			 * Put the packet on the pending queue.
			 */
+2 −1
Original line number Diff line number Diff line
@@ -848,7 +848,8 @@ static int ping_v4_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
	return err;

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)
		goto back_from_confirm;
	err = 0;
+5 −1
Original line number Diff line number Diff line
@@ -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);

	if (flags & MSG_CONFIRM)
		skb_set_dst_pending_confirm(skb, 1);

	skb->transport_header = skb->network_header;
	err = -EFAULT;
	if (memcpy_from_msg(iph, msg, length))
@@ -666,7 +669,8 @@ static int raw_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
	return len;

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)
		goto back_from_confirm;
	err = 0;
+2 −1
Original line number Diff line number Diff line
@@ -1101,7 +1101,8 @@ int udp_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
	return err;

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)
		goto back_from_confirm;
	err = 0;
+6 −0
Original line number Diff line number Diff line
@@ -1145,6 +1145,9 @@ static inline int ip6_ufo_append_data(struct sock *sk,
		skb->protocol = htons(ETH_P_IPV6);
		skb->csum = 0;

		if (flags & MSG_CONFIRM)
			skb_set_dst_pending_confirm(skb, 1);

		__skb_queue_tail(queue, skb);
	} else if (skb_is_gso(skb)) {
		goto append;
@@ -1517,6 +1520,9 @@ static int __ip6_append_data(struct sock *sk,
			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
			 */
Loading