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

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

sctp: add dst_pending_confirm flag



Add new transport flag to allow sockets to confirm neighbour.
When same struct dst_entry can be used for many different
neighbours we can not use it for pending confirmations.
The flag is propagated from transport to every packet.
It is reset when cached dst is reset.

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>
Acked-by: default avatarNeil Horman <nhorman@tuxdriver.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 4ff06203
Loading
Loading
Loading
Loading
+2 −4
Original line number Diff line number Diff line
@@ -593,10 +593,8 @@ static inline void sctp_v4_map_v6(union sctp_addr *addr)
 */
static inline struct dst_entry *sctp_transport_dst_check(struct sctp_transport *t)
{
	if (t->dst && !dst_check(t->dst, t->dst_cookie)) {
		dst_release(t->dst);
		t->dst = NULL;
	}
	if (t->dst && !dst_check(t->dst, t->dst_cookie))
		sctp_transport_dst_release(t);

	return t->dst;
}
+4 −0
Original line number Diff line number Diff line
@@ -804,6 +804,8 @@ struct sctp_transport {

	__u32 burst_limited;	/* Holds old cwnd when max.burst is applied */

	__u32 dst_pending_confirm;	/* need to confirm neighbour */

	/* Destination */
	struct dst_entry *dst;
	/* Source address. */
@@ -950,6 +952,8 @@ unsigned long sctp_transport_timeout(struct sctp_transport *);
void sctp_transport_reset(struct sctp_transport *);
void sctp_transport_update_pmtu(struct sock *, struct sctp_transport *, u32);
void sctp_transport_immediate_rtx(struct sctp_transport *);
void sctp_transport_dst_release(struct sctp_transport *t);
void sctp_transport_dst_confirm(struct sctp_transport *t);


/* This is the structure we use to queue packets as they come into
+1 −2
Original line number Diff line number Diff line
@@ -832,8 +832,7 @@ void sctp_assoc_control_transport(struct sctp_association *asoc,
		if (transport->state != SCTP_UNCONFIRMED)
			transport->state = SCTP_INACTIVE;
		else {
			dst_release(transport->dst);
			transport->dst = NULL;
			sctp_transport_dst_release(transport);
			ulp_notify = false;
		}

+9 −1
Original line number Diff line number Diff line
@@ -546,6 +546,7 @@ int sctp_packet_transmit(struct sctp_packet *packet, gfp_t gfp)
	struct sctp_association *asoc = tp->asoc;
	struct sctp_chunk *chunk, *tmp;
	int pkt_count, gso = 0;
	int confirm;
	struct dst_entry *dst;
	struct sk_buff *head;
	struct sctphdr *sh;
@@ -624,7 +625,14 @@ int sctp_packet_transmit(struct sctp_packet *packet, gfp_t gfp)
			asoc->peer.last_sent_to = tp;
	}
	head->ignore_df = packet->ipfragok;
	tp->af_specific->sctp_xmit(head, tp);
	confirm = tp->dst_pending_confirm;
	if (confirm)
		skb_set_dst_pending_confirm(head, 1);
	/* neighbour should be confirmed on successful transmission or
	 * positive error
	 */
	if (tp->af_specific->sctp_xmit(head, tp) >= 0 && confirm)
		tp->dst_pending_confirm = 0;

out:
	list_for_each_entry_safe(chunk, tmp, &packet->chunk_list, list) {
+1 −1
Original line number Diff line number Diff line
@@ -1654,7 +1654,7 @@ static void sctp_check_transmitted(struct sctp_outq *q,

		if (forward_progress) {
			if (transport->dst)
				dst_confirm(transport->dst);
				sctp_transport_dst_confirm(transport);
		}
	}

Loading