Skip to content

Commit

Permalink
sctp: use the pmtu from the icmp packet to update transport pathmtu
Browse files Browse the repository at this point in the history
Other than asoc pmtu sync from all transports, sctp_assoc_sync_pmtu
is also processing transport pmtu_pending by icmp packets. But it's
meaningless to use sctp_dst_mtu(t->dst) as new pmtu for a transport.

The right pmtu value should come from the icmp packet, and it would
be saved into transport->mtu_info in this patch and used later when
the pmtu sync happens in sctp_sendmsg_to_asoc or sctp_packet_config.

Besides, without this patch, as pmtu can only be updated correctly
when receiving a icmp packet and no place is holding sock lock, it
will take long time if the sock is busy with sending packets.

Note that it doesn't process transport->mtu_info in .release_cb(),
as there is no enough information for pmtu update, like for which
asoc or transport. It is not worth traversing all asocs to check
pmtu_pending. So unlike tcp, sctp does this in tx path, for which
mtu_info needs to be atomic_t.

Signed-off-by: Xin Long <[email protected]>
Acked-by: Marcelo Ricardo Leitner <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
  • Loading branch information
lxin authored and davem330 committed Oct 16, 2018
1 parent ec20a63 commit d805397
Show file tree
Hide file tree
Showing 4 changed files with 11 additions and 1 deletion.
2 changes: 2 additions & 0 deletions include/net/sctp/structs.h
Original file line number Diff line number Diff line change
Expand Up @@ -876,6 +876,8 @@ struct sctp_transport {
unsigned long sackdelay;
__u32 sackfreq;

atomic_t mtu_info;

/* When was the last time that we heard from this transport? We use
* this to pick new active and retran paths.
*/
Expand Down
3 changes: 2 additions & 1 deletion net/sctp/associola.c
Original file line number Diff line number Diff line change
Expand Up @@ -1450,7 +1450,8 @@ void sctp_assoc_sync_pmtu(struct sctp_association *asoc)
/* Get the lowest pmtu of all the transports. */
list_for_each_entry(t, &asoc->peer.transport_addr_list, transports) {
if (t->pmtu_pending && t->dst) {
sctp_transport_update_pmtu(t, sctp_dst_mtu(t->dst));
sctp_transport_update_pmtu(t,
atomic_read(&t->mtu_info));
t->pmtu_pending = 0;
}
if (!pmtu || (t->pathmtu < pmtu))
Expand Down
1 change: 1 addition & 0 deletions net/sctp/input.c
Original file line number Diff line number Diff line change
Expand Up @@ -395,6 +395,7 @@ void sctp_icmp_frag_needed(struct sock *sk, struct sctp_association *asoc,
return;

if (sock_owned_by_user(sk)) {
atomic_set(&t->mtu_info, pmtu);
asoc->pmtu_pending = 1;
t->pmtu_pending = 1;
return;
Expand Down
6 changes: 6 additions & 0 deletions net/sctp/output.c
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,12 @@ void sctp_packet_config(struct sctp_packet *packet, __u32 vtag,
sctp_assoc_sync_pmtu(asoc);
}

if (asoc->pmtu_pending) {
if (asoc->param_flags & SPP_PMTUD_ENABLE)
sctp_assoc_sync_pmtu(asoc);
asoc->pmtu_pending = 0;
}

/* If there a is a prepend chunk stick it on the list before
* any other chunks get appended.
*/
Expand Down

0 comments on commit d805397

Please sign in to comment.