Commit 4422cc0d authored by David S. Miller's avatar David S. Miller

Merge branch 'sctp-refactor-MTU-handling'

Marcelo Ricardo Leitner says:

====================
sctp: refactor MTU handling

Currently MTU handling is spread over SCTP stack. There are multiple
places doing same/similar calculations and updating them is error prone
as one spot can easily be left out.

This patchset converges it into a more concise and consistent code. In
general, it moves MTU handling from functions with bigger objectives,
such as sctp_assoc_add_peer(), to specific functions.

It's also a preparation for the next patchset, which removes the
duplication between sctp_make_op_error_space and
sctp_make_op_error_fixed and relies on sctp_mtu_payload introduced here.

More details on each patch.
====================
Reviewed-by: default avatarXin Long <lucien.xin@gmail.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 5a643c86 38687b56
...@@ -254,11 +254,10 @@ enum { SCTP_ARBITRARY_COOKIE_ECHO_LEN = 200 }; ...@@ -254,11 +254,10 @@ enum { SCTP_ARBITRARY_COOKIE_ECHO_LEN = 200 };
#define SCTP_TSN_MAP_SIZE 4096 #define SCTP_TSN_MAP_SIZE 4096
/* We will not record more than this many duplicate TSNs between two /* We will not record more than this many duplicate TSNs between two
* SACKs. The minimum PMTU is 576. Remove all the headers and there * SACKs. The minimum PMTU is 512. Remove all the headers and there
* is enough room for 131 duplicate reports. Round down to the * is enough room for 117 duplicate reports. Round down to the
* nearest power of 2. * nearest power of 2.
*/ */
enum { SCTP_MIN_PMTU = 576 };
enum { SCTP_MAX_DUP_TSNS = 16 }; enum { SCTP_MAX_DUP_TSNS = 16 };
enum { SCTP_MAX_GABS = 16 }; enum { SCTP_MAX_GABS = 16 };
......
...@@ -428,32 +428,6 @@ static inline int sctp_list_single_entry(struct list_head *head) ...@@ -428,32 +428,6 @@ static inline int sctp_list_single_entry(struct list_head *head)
return (head->next != head) && (head->next == head->prev); return (head->next != head) && (head->next == head->prev);
} }
/* Break down data chunks at this point. */
static inline int sctp_frag_point(const struct sctp_association *asoc, int pmtu)
{
struct sctp_sock *sp = sctp_sk(asoc->base.sk);
struct sctp_af *af = sp->pf->af;
int frag = pmtu;
frag -= af->ip_options_len(asoc->base.sk);
frag -= af->net_header_len;
frag -= sizeof(struct sctphdr) + sctp_datachk_len(&asoc->stream);
if (asoc->user_frag)
frag = min_t(int, frag, asoc->user_frag);
frag = SCTP_TRUNC4(min_t(int, frag, SCTP_MAX_CHUNK_LEN -
sctp_datachk_len(&asoc->stream)));
return frag;
}
static inline void sctp_assoc_pending_pmtu(struct sctp_association *asoc)
{
sctp_assoc_sync_pmtu(asoc);
asoc->pmtu_pending = 0;
}
static inline bool sctp_chunk_pending(const struct sctp_chunk *chunk) static inline bool sctp_chunk_pending(const struct sctp_chunk *chunk)
{ {
return !list_empty(&chunk->list); return !list_empty(&chunk->list);
...@@ -607,17 +581,29 @@ static inline struct dst_entry *sctp_transport_dst_check(struct sctp_transport * ...@@ -607,17 +581,29 @@ static inline struct dst_entry *sctp_transport_dst_check(struct sctp_transport *
return t->dst; return t->dst;
} }
static inline bool sctp_transport_pmtu_check(struct sctp_transport *t) /* Calculate max payload size given a MTU, or the total overhead if
* given MTU is zero
*/
static inline __u32 sctp_mtu_payload(const struct sctp_sock *sp,
__u32 mtu, __u32 extra)
{ {
__u32 pmtu = max_t(size_t, SCTP_TRUNC4(dst_mtu(t->dst)), __u32 overhead = sizeof(struct sctphdr) + extra;
SCTP_DEFAULT_MINSEGMENT);
if (t->pathmtu == pmtu) if (sp)
return true; overhead += sp->pf->af->net_header_len;
else
overhead += sizeof(struct ipv6hdr);
t->pathmtu = pmtu; if (WARN_ON_ONCE(mtu && mtu <= overhead))
mtu = overhead;
return false; return mtu ? mtu - overhead : overhead;
}
static inline __u32 sctp_dst_mtu(const struct dst_entry *dst)
{
return SCTP_TRUNC4(max_t(__u32, dst_mtu(dst),
SCTP_DEFAULT_MINSEGMENT));
} }
#endif /* __net_sctp_h__ */ #endif /* __net_sctp_h__ */
...@@ -2097,6 +2097,8 @@ int sctp_assoc_update(struct sctp_association *old, ...@@ -2097,6 +2097,8 @@ int sctp_assoc_update(struct sctp_association *old,
__u32 sctp_association_get_next_tsn(struct sctp_association *); __u32 sctp_association_get_next_tsn(struct sctp_association *);
void sctp_assoc_update_frag_point(struct sctp_association *asoc);
void sctp_assoc_set_pmtu(struct sctp_association *asoc, __u32 pmtu);
void sctp_assoc_sync_pmtu(struct sctp_association *asoc); void sctp_assoc_sync_pmtu(struct sctp_association *asoc);
void sctp_assoc_rwnd_increase(struct sctp_association *, unsigned int); void sctp_assoc_rwnd_increase(struct sctp_association *, unsigned int);
void sctp_assoc_rwnd_decrease(struct sctp_association *, unsigned int); void sctp_assoc_rwnd_decrease(struct sctp_association *, unsigned int);
......
...@@ -652,33 +652,20 @@ struct sctp_transport *sctp_assoc_add_peer(struct sctp_association *asoc, ...@@ -652,33 +652,20 @@ struct sctp_transport *sctp_assoc_add_peer(struct sctp_association *asoc,
*/ */
peer->param_flags = asoc->param_flags; peer->param_flags = asoc->param_flags;
sctp_transport_route(peer, NULL, sp);
/* Initialize the pmtu of the transport. */ /* Initialize the pmtu of the transport. */
if (peer->param_flags & SPP_PMTUD_DISABLE) { sctp_transport_route(peer, NULL, sp);
if (asoc->pathmtu)
peer->pathmtu = asoc->pathmtu;
else
peer->pathmtu = SCTP_DEFAULT_MAXSEGMENT;
}
/* If this is the first transport addr on this association, /* If this is the first transport addr on this association,
* initialize the association PMTU to the peer's PMTU. * initialize the association PMTU to the peer's PMTU.
* If not and the current association PMTU is higher than the new * If not and the current association PMTU is higher than the new
* peer's PMTU, reset the association PMTU to the new peer's PMTU. * peer's PMTU, reset the association PMTU to the new peer's PMTU.
*/ */
if (asoc->pathmtu) sctp_assoc_set_pmtu(asoc, asoc->pathmtu ?
asoc->pathmtu = min_t(int, peer->pathmtu, asoc->pathmtu); min_t(int, peer->pathmtu, asoc->pathmtu) :
else peer->pathmtu);
asoc->pathmtu = peer->pathmtu;
pr_debug("%s: association:%p PMTU set to %d\n", __func__, asoc,
asoc->pathmtu);
peer->pmtu_pending = 0; peer->pmtu_pending = 0;
asoc->frag_point = sctp_frag_point(asoc, asoc->pathmtu);
/* The asoc->peer.port might not be meaningful yet, but /* The asoc->peer.port might not be meaningful yet, but
* initialize the packet structure anyway. * initialize the packet structure anyway.
*/ */
...@@ -1381,6 +1368,31 @@ sctp_assoc_choose_alter_transport(struct sctp_association *asoc, ...@@ -1381,6 +1368,31 @@ sctp_assoc_choose_alter_transport(struct sctp_association *asoc,
} }
} }
void sctp_assoc_update_frag_point(struct sctp_association *asoc)
{
int frag = sctp_mtu_payload(sctp_sk(asoc->base.sk), asoc->pathmtu,
sctp_datachk_len(&asoc->stream));
if (asoc->user_frag)
frag = min_t(int, frag, asoc->user_frag);
frag = min_t(int, frag, SCTP_MAX_CHUNK_LEN -
sctp_datachk_len(&asoc->stream));
asoc->frag_point = SCTP_TRUNC4(frag);
}
void sctp_assoc_set_pmtu(struct sctp_association *asoc, __u32 pmtu)
{
if (asoc->pathmtu != pmtu) {
asoc->pathmtu = pmtu;
sctp_assoc_update_frag_point(asoc);
}
pr_debug("%s: asoc:%p, pmtu:%d, frag_point:%d\n", __func__, asoc,
asoc->pathmtu, asoc->frag_point);
}
/* Update the association's pmtu and frag_point by going through all the /* Update the association's pmtu and frag_point by going through all the
* transports. This routine is called when a transport's PMTU has changed. * transports. This routine is called when a transport's PMTU has changed.
*/ */
...@@ -1393,24 +1405,16 @@ void sctp_assoc_sync_pmtu(struct sctp_association *asoc) ...@@ -1393,24 +1405,16 @@ void sctp_assoc_sync_pmtu(struct sctp_association *asoc)
return; return;
/* Get the lowest pmtu of all the transports. */ /* Get the lowest pmtu of all the transports. */
list_for_each_entry(t, &asoc->peer.transport_addr_list, list_for_each_entry(t, &asoc->peer.transport_addr_list, transports) {
transports) {
if (t->pmtu_pending && t->dst) { if (t->pmtu_pending && t->dst) {
sctp_transport_update_pmtu( sctp_transport_update_pmtu(t, sctp_dst_mtu(t->dst));
t, SCTP_TRUNC4(dst_mtu(t->dst)));
t->pmtu_pending = 0; t->pmtu_pending = 0;
} }
if (!pmtu || (t->pathmtu < pmtu)) if (!pmtu || (t->pathmtu < pmtu))
pmtu = t->pathmtu; pmtu = t->pathmtu;
} }
if (pmtu) { sctp_assoc_set_pmtu(asoc, pmtu);
asoc->pathmtu = pmtu;
asoc->frag_point = sctp_frag_point(asoc, pmtu);
}
pr_debug("%s: asoc:%p, pmtu:%d, frag_point:%d\n", __func__, asoc,
asoc->pathmtu, asoc->frag_point);
} }
/* Should we send a SACK to update our peer? */ /* Should we send a SACK to update our peer? */
......
...@@ -172,8 +172,6 @@ struct sctp_datamsg *sctp_datamsg_from_user(struct sctp_association *asoc, ...@@ -172,8 +172,6 @@ struct sctp_datamsg *sctp_datamsg_from_user(struct sctp_association *asoc,
struct list_head *pos, *temp; struct list_head *pos, *temp;
struct sctp_chunk *chunk; struct sctp_chunk *chunk;
struct sctp_datamsg *msg; struct sctp_datamsg *msg;
struct sctp_sock *sp;
struct sctp_af *af;
int err; int err;
msg = sctp_datamsg_new(GFP_KERNEL); msg = sctp_datamsg_new(GFP_KERNEL);
...@@ -192,12 +190,7 @@ struct sctp_datamsg *sctp_datamsg_from_user(struct sctp_association *asoc, ...@@ -192,12 +190,7 @@ struct sctp_datamsg *sctp_datamsg_from_user(struct sctp_association *asoc,
/* This is the biggest possible DATA chunk that can fit into /* This is the biggest possible DATA chunk that can fit into
* the packet * the packet
*/ */
sp = sctp_sk(asoc->base.sk); max_data = asoc->frag_point;
af = sp->pf->af;
max_data = asoc->pathmtu - af->net_header_len -
sizeof(struct sctphdr) - sctp_datachk_len(&asoc->stream) -
af->ip_options_len(asoc->base.sk);
max_data = SCTP_TRUNC4(max_data);
/* If the the peer requested that we authenticate DATA chunks /* If the the peer requested that we authenticate DATA chunks
* we need to account for bundling of the AUTH chunks along with * we need to account for bundling of the AUTH chunks along with
...@@ -222,9 +215,6 @@ struct sctp_datamsg *sctp_datamsg_from_user(struct sctp_association *asoc, ...@@ -222,9 +215,6 @@ struct sctp_datamsg *sctp_datamsg_from_user(struct sctp_association *asoc,
} }
} }
/* Check what's our max considering the above */
max_data = min_t(size_t, max_data, asoc->frag_point);
/* Set first_len and then account for possible bundles on first frag */ /* Set first_len and then account for possible bundles on first frag */
first_len = max_data; first_len = max_data;
......
...@@ -90,8 +90,8 @@ void sctp_packet_config(struct sctp_packet *packet, __u32 vtag, ...@@ -90,8 +90,8 @@ void sctp_packet_config(struct sctp_packet *packet, __u32 vtag,
{ {
struct sctp_transport *tp = packet->transport; struct sctp_transport *tp = packet->transport;
struct sctp_association *asoc = tp->asoc; struct sctp_association *asoc = tp->asoc;
struct sctp_sock *sp = NULL;
struct sock *sk; struct sock *sk;
size_t overhead = sizeof(struct ipv6hdr) + sizeof(struct sctphdr);
pr_debug("%s: packet:%p vtag:0x%x\n", __func__, packet, vtag); pr_debug("%s: packet:%p vtag:0x%x\n", __func__, packet, vtag);
packet->vtag = vtag; packet->vtag = vtag;
...@@ -102,28 +102,20 @@ void sctp_packet_config(struct sctp_packet *packet, __u32 vtag, ...@@ -102,28 +102,20 @@ void sctp_packet_config(struct sctp_packet *packet, __u32 vtag,
/* set packet max_size with pathmtu, then calculate overhead */ /* set packet max_size with pathmtu, then calculate overhead */
packet->max_size = tp->pathmtu; packet->max_size = tp->pathmtu;
if (asoc) { if (asoc) {
struct sctp_sock *sp = sctp_sk(asoc->base.sk); sk = asoc->base.sk;
struct sctp_af *af = sp->pf->af; sp = sctp_sk(sk);
overhead = af->net_header_len +
af->ip_options_len(asoc->base.sk);
overhead += sizeof(struct sctphdr);
packet->overhead = overhead;
packet->size = overhead;
} else {
packet->overhead = overhead;
packet->size = overhead;
return;
} }
packet->overhead = sctp_mtu_payload(sp, 0, 0);
packet->size = packet->overhead;
if (!asoc)
return;
/* update dst or transport pathmtu if in need */ /* update dst or transport pathmtu if in need */
sk = asoc->base.sk;
if (!sctp_transport_dst_check(tp)) { if (!sctp_transport_dst_check(tp)) {
sctp_transport_route(tp, NULL, sctp_sk(sk)); sctp_transport_route(tp, NULL, sp);
if (asoc->param_flags & SPP_PMTUD_ENABLE)
sctp_assoc_sync_pmtu(asoc);
} else if (!sctp_transport_pmtu_check(tp)) {
if (asoc->param_flags & SPP_PMTUD_ENABLE) if (asoc->param_flags & SPP_PMTUD_ENABLE)
sctp_assoc_sync_pmtu(asoc); sctp_assoc_sync_pmtu(asoc);
} }
......
...@@ -644,16 +644,15 @@ static int sctp_send_asconf_add_ip(struct sock *sk, ...@@ -644,16 +644,15 @@ static int sctp_send_asconf_add_ip(struct sock *sk,
list_for_each_entry(trans, list_for_each_entry(trans,
&asoc->peer.transport_addr_list, transports) { &asoc->peer.transport_addr_list, transports) {
/* Clear the source and route cache */
sctp_transport_dst_release(trans);
trans->cwnd = min(4*asoc->pathmtu, max_t(__u32, trans->cwnd = min(4*asoc->pathmtu, max_t(__u32,
2*asoc->pathmtu, 4380)); 2*asoc->pathmtu, 4380));
trans->ssthresh = asoc->peer.i.a_rwnd; trans->ssthresh = asoc->peer.i.a_rwnd;
trans->rto = asoc->rto_initial; trans->rto = asoc->rto_initial;
sctp_max_rto(asoc, trans); sctp_max_rto(asoc, trans);
trans->rtt = trans->srtt = trans->rttvar = 0; trans->rtt = trans->srtt = trans->rttvar = 0;
/* Clear the source and route cache */
sctp_transport_route(trans, NULL, sctp_transport_route(trans, NULL,
sctp_sk(asoc->base.sk)); sctp_sk(asoc->base.sk));
} }
} }
retval = sctp_send_asconf(asoc, chunk); retval = sctp_send_asconf(asoc, chunk);
...@@ -896,7 +895,6 @@ static int sctp_send_asconf_del_ip(struct sock *sk, ...@@ -896,7 +895,6 @@ static int sctp_send_asconf_del_ip(struct sock *sk,
*/ */
list_for_each_entry(transport, &asoc->peer.transport_addr_list, list_for_each_entry(transport, &asoc->peer.transport_addr_list,
transports) { transports) {
sctp_transport_dst_release(transport);
sctp_transport_route(transport, NULL, sctp_transport_route(transport, NULL,
sctp_sk(asoc->base.sk)); sctp_sk(asoc->base.sk));
} }
...@@ -1895,6 +1893,7 @@ static int sctp_sendmsg_to_asoc(struct sctp_association *asoc, ...@@ -1895,6 +1893,7 @@ static int sctp_sendmsg_to_asoc(struct sctp_association *asoc,
struct sctp_sndrcvinfo *sinfo) struct sctp_sndrcvinfo *sinfo)
{ {
struct sock *sk = asoc->base.sk; struct sock *sk = asoc->base.sk;
struct sctp_sock *sp = sctp_sk(sk);
struct net *net = sock_net(sk); struct net *net = sock_net(sk);
struct sctp_datamsg *datamsg; struct sctp_datamsg *datamsg;
bool wait_connect = false; bool wait_connect = false;
...@@ -1913,13 +1912,16 @@ static int sctp_sendmsg_to_asoc(struct sctp_association *asoc, ...@@ -1913,13 +1912,16 @@ static int sctp_sendmsg_to_asoc(struct sctp_association *asoc,
goto err; goto err;
} }
if (sctp_sk(sk)->disable_fragments && msg_len > asoc->frag_point) { if (sp->disable_fragments && msg_len > asoc->frag_point) {
err = -EMSGSIZE; err = -EMSGSIZE;
goto err; goto err;
} }
if (asoc->pmtu_pending) if (asoc->pmtu_pending) {
sctp_assoc_pending_pmtu(asoc); if (sp->param_flags & SPP_PMTUD_ENABLE)
sctp_assoc_sync_pmtu(asoc);
asoc->pmtu_pending = 0;
}
if (sctp_wspace(asoc) < msg_len) if (sctp_wspace(asoc) < msg_len)
sctp_prsctp_prune(asoc, sinfo, msg_len - sctp_wspace(asoc)); sctp_prsctp_prune(asoc, sinfo, msg_len - sctp_wspace(asoc));
...@@ -1936,7 +1938,7 @@ static int sctp_sendmsg_to_asoc(struct sctp_association *asoc, ...@@ -1936,7 +1938,7 @@ static int sctp_sendmsg_to_asoc(struct sctp_association *asoc,
if (err) if (err)
goto err; goto err;
if (sctp_sk(sk)->strm_interleave) { if (sp->strm_interleave) {
timeo = sock_sndtimeo(sk, 0); timeo = sock_sndtimeo(sk, 0);
err = sctp_wait_for_connect(asoc, &timeo); err = sctp_wait_for_connect(asoc, &timeo);
if (err) if (err)
...@@ -2539,7 +2541,7 @@ static int sctp_apply_peer_addr_params(struct sctp_paddrparams *params, ...@@ -2539,7 +2541,7 @@ static int sctp_apply_peer_addr_params(struct sctp_paddrparams *params,
trans->pathmtu = params->spp_pathmtu; trans->pathmtu = params->spp_pathmtu;
sctp_assoc_sync_pmtu(asoc); sctp_assoc_sync_pmtu(asoc);
} else if (asoc) { } else if (asoc) {
asoc->pathmtu = params->spp_pathmtu; sctp_assoc_set_pmtu(asoc, params->spp_pathmtu);
} else { } else {
sp->pathmtu = params->spp_pathmtu; sp->pathmtu = params->spp_pathmtu;
} }
...@@ -3209,7 +3211,6 @@ static int sctp_setsockopt_mappedv4(struct sock *sk, char __user *optval, unsign ...@@ -3209,7 +3211,6 @@ static int sctp_setsockopt_mappedv4(struct sock *sk, char __user *optval, unsign
static int sctp_setsockopt_maxseg(struct sock *sk, char __user *optval, unsigned int optlen) static int sctp_setsockopt_maxseg(struct sock *sk, char __user *optval, unsigned int optlen)
{ {
struct sctp_sock *sp = sctp_sk(sk); struct sctp_sock *sp = sctp_sk(sk);
struct sctp_af *af = sp->pf->af;
struct sctp_assoc_value params; struct sctp_assoc_value params;
struct sctp_association *asoc; struct sctp_association *asoc;
int val; int val;
...@@ -3231,30 +3232,24 @@ static int sctp_setsockopt_maxseg(struct sock *sk, char __user *optval, unsigned ...@@ -3231,30 +3232,24 @@ static int sctp_setsockopt_maxseg(struct sock *sk, char __user *optval, unsigned
return -EINVAL; return -EINVAL;
} }
asoc = sctp_id2assoc(sk, params.assoc_id);
if (val) { if (val) {
int min_len, max_len; int min_len, max_len;
__u16 datasize = asoc ? sctp_datachk_len(&asoc->stream) :
sizeof(struct sctp_data_chunk);
min_len = SCTP_DEFAULT_MINSEGMENT - af->net_header_len; min_len = sctp_mtu_payload(sp, SCTP_DEFAULT_MINSEGMENT,
min_len -= af->ip_options_len(sk); datasize);
min_len -= sizeof(struct sctphdr) + max_len = SCTP_MAX_CHUNK_LEN - datasize;
sizeof(struct sctp_data_chunk);
max_len = SCTP_MAX_CHUNK_LEN - sizeof(struct sctp_data_chunk);
if (val < min_len || val > max_len) if (val < min_len || val > max_len)
return -EINVAL; return -EINVAL;
} }
asoc = sctp_id2assoc(sk, params.assoc_id);
if (asoc) { if (asoc) {
if (val == 0) {
val = asoc->pathmtu - af->net_header_len;
val -= af->ip_options_len(sk);
val -= sizeof(struct sctphdr) +
sctp_datachk_len(&asoc->stream);
}
asoc->user_frag = val; asoc->user_frag = val;
asoc->frag_point = sctp_frag_point(asoc, asoc->pathmtu); sctp_assoc_update_frag_point(asoc);
} else { } else {
if (params.assoc_id && sctp_style(sk, UDP)) if (params.assoc_id && sctp_style(sk, UDP))
return -EINVAL; return -EINVAL;
......
...@@ -242,9 +242,18 @@ void sctp_transport_pmtu(struct sctp_transport *transport, struct sock *sk) ...@@ -242,9 +242,18 @@ void sctp_transport_pmtu(struct sctp_transport *transport, struct sock *sk)
&transport->fl, sk); &transport->fl, sk);
} }
if (transport->dst) { if (transport->param_flags & SPP_PMTUD_DISABLE) {
transport->pathmtu = SCTP_TRUNC4(dst_mtu(transport->dst)); struct sctp_association *asoc = transport->asoc;
} else
if (!transport->pathmtu && asoc && asoc->pathmtu)
transport->pathmtu = asoc->pathmtu;
if (transport->pathmtu)
return;
}
if (transport->dst)
transport->pathmtu = sctp_dst_mtu(transport->dst);
else
transport->pathmtu = SCTP_DEFAULT_MAXSEGMENT; transport->pathmtu = SCTP_DEFAULT_MAXSEGMENT;
} }
...@@ -290,6 +299,7 @@ void sctp_transport_route(struct sctp_transport *transport, ...@@ -290,6 +299,7 @@ void sctp_transport_route(struct sctp_transport *transport,
struct sctp_association *asoc = transport->asoc; struct sctp_association *asoc = transport->asoc;
struct sctp_af *af = transport->af_specific; struct sctp_af *af = transport->af_specific;
sctp_transport_dst_release(transport);
af->get_dst(transport, saddr, &transport->fl, sctp_opt2sk(opt)); af->get_dst(transport, saddr, &transport->fl, sctp_opt2sk(opt));
if (saddr) if (saddr)
...@@ -297,21 +307,14 @@ void sctp_transport_route(struct sctp_transport *transport, ...@@ -297,21 +307,14 @@ void sctp_transport_route(struct sctp_transport *transport,
else else
af->get_saddr(opt, transport, &transport->fl); af->get_saddr(opt, transport, &transport->fl);
if ((transport->param_flags & SPP_PMTUD_DISABLE) && transport->pathmtu) { sctp_transport_pmtu(transport, sctp_opt2sk(opt));
return;
}
if (transport->dst) {
transport->pathmtu = SCTP_TRUNC4(dst_mtu(transport->dst));
/* Initialize sk->sk_rcv_saddr, if the transport is the /* Initialize sk->sk_rcv_saddr, if the transport is the
* association's active path for getsockname(). * association's active path for getsockname().
*/ */
if (asoc && (!asoc->peer.primary_path || if (transport->dst && asoc &&
(transport == asoc->peer.active_path))) (!asoc->peer.primary_path || transport == asoc->peer.active_path))
opt->pf->to_sk_saddr(&transport->saddr, opt->pf->to_sk_saddr(&transport->saddr, asoc->base.sk);
asoc->base.sk);
} else
transport->pathmtu = SCTP_DEFAULT_MAXSEGMENT;
} }
/* Hold a reference to a transport. */ /* Hold a reference to a transport. */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment