Allow the setting of the MTU for future paths using an SCTP socket option.
This functionality was missing. MFC after: 1 week
This commit is contained in:
parent
91fcd6f57c
commit
28a6adde1d
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=325370
@ -4273,12 +4273,8 @@ sctp_lowlevel_chunk_output(struct sctp_inpcb *inp,
|
||||
/* free tempy routes */
|
||||
RO_RTFREE(ro);
|
||||
} else {
|
||||
/*
|
||||
* PMTU check versus smallest asoc MTU goes
|
||||
* here
|
||||
*/
|
||||
if ((ro->ro_rt != NULL) &&
|
||||
(net->ro._s_addr)) {
|
||||
if ((ro->ro_rt != NULL) && (net->ro._s_addr) &&
|
||||
((net->dest_state & SCTP_ADDR_NO_PMTUD) == 0)) {
|
||||
uint32_t mtu;
|
||||
|
||||
mtu = SCTP_GATHER_MTU_FROM_ROUTE(net->ro._s_addr, &net->ro._l_addr.sa, ro->ro_rt);
|
||||
@ -4635,8 +4631,8 @@ sctp_lowlevel_chunk_output(struct sctp_inpcb *inp,
|
||||
}
|
||||
net->src_addr_selected = 0;
|
||||
}
|
||||
if ((ro->ro_rt != NULL) &&
|
||||
(net->ro._s_addr)) {
|
||||
if ((ro->ro_rt != NULL) && (net->ro._s_addr) &&
|
||||
((net->dest_state & SCTP_ADDR_NO_PMTUD) == 0)) {
|
||||
uint32_t mtu;
|
||||
|
||||
mtu = SCTP_GATHER_MTU_FROM_ROUTE(net->ro._s_addr, &net->ro._l_addr.sa, ro->ro_rt);
|
||||
|
@ -2577,6 +2577,7 @@ sctp_inpcb_alloc(struct socket *so, uint32_t vrf_id)
|
||||
/* number of streams to pre-open on a association */
|
||||
m->pre_open_stream_count = SCTP_BASE_SYSCTL(sctp_nr_outgoing_streams_default);
|
||||
|
||||
m->default_mtu = 0;
|
||||
/* Add adaptation cookie */
|
||||
m->adaptation_layer_indicator = 0;
|
||||
m->adaptation_layer_indicator_provided = 0;
|
||||
@ -3942,7 +3943,28 @@ sctp_add_remote_addr(struct sctp_tcb *stcb, struct sockaddr *newaddr,
|
||||
net,
|
||||
0,
|
||||
stcb->asoc.vrf_id);
|
||||
if (net->ro._s_addr != NULL) {
|
||||
if (stcb->asoc.default_mtu > 0) {
|
||||
net->mtu = stcb->asoc.default_mtu;
|
||||
switch (net->ro._l_addr.sa.sa_family) {
|
||||
#ifdef INET
|
||||
case AF_INET:
|
||||
net->mtu += SCTP_MIN_V4_OVERHEAD;
|
||||
break;
|
||||
#endif
|
||||
#ifdef INET6
|
||||
case AF_INET6:
|
||||
net->mtu += SCTP_MIN_OVERHEAD;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
break;
|
||||
}
|
||||
#if defined(INET) || defined(INET6)
|
||||
if (net->port) {
|
||||
net->mtu += (uint32_t)sizeof(struct udphdr);
|
||||
}
|
||||
#endif
|
||||
} else if (net->ro._s_addr != NULL) {
|
||||
uint32_t imtu, rmtu, hcmtu;
|
||||
|
||||
net->src_addr_selected = 1;
|
||||
@ -3966,19 +3988,42 @@ sctp_add_remote_addr(struct sctp_tcb *stcb, struct sockaddr *newaddr,
|
||||
}
|
||||
}
|
||||
if (net->mtu == 0) {
|
||||
switch (newaddr->sa_family) {
|
||||
if (stcb->asoc.default_mtu > 0) {
|
||||
net->mtu = stcb->asoc.default_mtu;
|
||||
switch (net->ro._l_addr.sa.sa_family) {
|
||||
#ifdef INET
|
||||
case AF_INET:
|
||||
net->mtu = SCTP_DEFAULT_MTU;
|
||||
break;
|
||||
case AF_INET:
|
||||
net->mtu += SCTP_MIN_V4_OVERHEAD;
|
||||
break;
|
||||
#endif
|
||||
#ifdef INET6
|
||||
case AF_INET6:
|
||||
net->mtu = 1280;
|
||||
break;
|
||||
case AF_INET6:
|
||||
net->mtu += SCTP_MIN_OVERHEAD;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
#if defined(INET) || defined(INET6)
|
||||
if (net->port) {
|
||||
net->mtu += (uint32_t)sizeof(struct udphdr);
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
switch (newaddr->sa_family) {
|
||||
#ifdef INET
|
||||
case AF_INET:
|
||||
net->mtu = SCTP_DEFAULT_MTU;
|
||||
break;
|
||||
#endif
|
||||
#ifdef INET6
|
||||
case AF_INET6:
|
||||
net->mtu = 1280;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
#if defined(INET) || defined(INET6)
|
||||
|
@ -287,6 +287,7 @@ struct sctp_pcb {
|
||||
sctp_auth_chklist_t *local_auth_chunks;
|
||||
sctp_hmaclist_t *local_hmacs;
|
||||
uint16_t default_keyid;
|
||||
uint32_t default_mtu;
|
||||
|
||||
/* various thresholds */
|
||||
/* Max times I will init at a guy */
|
||||
|
@ -1098,6 +1098,7 @@ struct sctp_association {
|
||||
uint32_t chunks_on_out_queue; /* total chunks floating around,
|
||||
* locked by send socket buffer */
|
||||
uint32_t peers_adaptation;
|
||||
uint32_t default_mtu;
|
||||
uint16_t peer_hmac_id; /* peer HMAC id to send */
|
||||
|
||||
/*
|
||||
|
@ -202,6 +202,10 @@ sctp_notify(struct sctp_inpcb *inp,
|
||||
#endif
|
||||
/* no need to unlock here, since the TCB is gone */
|
||||
} else if (icmp_code == ICMP_UNREACH_NEEDFRAG) {
|
||||
if ((net->dest_state & SCTP_ADDR_NO_PMTUD) == 0) {
|
||||
SCTP_TCB_UNLOCK(stcb);
|
||||
return;
|
||||
}
|
||||
/* Find the next (smaller) MTU */
|
||||
if (next_mtu == 0) {
|
||||
/*
|
||||
@ -2447,7 +2451,7 @@ sctp_getopt(struct socket *so, int optname, void *optval, size_t *optsize,
|
||||
* value
|
||||
*/
|
||||
paddrp->spp_pathmaxrxt = stcb->asoc.def_net_failure;
|
||||
paddrp->spp_pathmtu = 0;
|
||||
paddrp->spp_pathmtu = stcb->asoc.default_mtu;
|
||||
if (stcb->asoc.default_dscp & 0x01) {
|
||||
paddrp->spp_dscp = stcb->asoc.default_dscp & 0xfc;
|
||||
paddrp->spp_flags |= SPP_DSCP;
|
||||
@ -2494,8 +2498,7 @@ sctp_getopt(struct socket *so, int optname, void *optval, size_t *optsize,
|
||||
paddrp->spp_flags |= SPP_IPV6_FLOWLABEL;
|
||||
}
|
||||
#endif
|
||||
/* can't return this */
|
||||
paddrp->spp_pathmtu = 0;
|
||||
paddrp->spp_pathmtu = inp->sctp_ep.default_mtu;
|
||||
|
||||
if (sctp_is_feature_off(inp, SCTP_PCB_FLAGS_DONOT_HEARTBEAT)) {
|
||||
paddrp->spp_flags |= SPP_HB_ENABLE;
|
||||
@ -5479,6 +5482,7 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
|
||||
sctp_pathmtu_adjustment(stcb, net->mtu);
|
||||
}
|
||||
}
|
||||
stcb->asoc.default_mtu = paddrp->spp_pathmtu;
|
||||
sctp_stcb_feature_on(inp, stcb, SCTP_PCB_FLAGS_DO_NOT_PMTUD);
|
||||
}
|
||||
if (paddrp->spp_flags & SPP_PMTUD_ENABLE) {
|
||||
@ -5488,6 +5492,7 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
|
||||
}
|
||||
net->dest_state &= ~SCTP_ADDR_NO_PMTUD;
|
||||
}
|
||||
stcb->asoc.default_mtu = 0;
|
||||
sctp_stcb_feature_off(inp, stcb, SCTP_PCB_FLAGS_DO_NOT_PMTUD);
|
||||
}
|
||||
if (paddrp->spp_flags & SPP_DSCP) {
|
||||
@ -5544,8 +5549,12 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
|
||||
sctp_feature_on(inp, SCTP_PCB_FLAGS_DONOT_HEARTBEAT);
|
||||
}
|
||||
if (paddrp->spp_flags & SPP_PMTUD_ENABLE) {
|
||||
inp->sctp_ep.default_mtu = 0;
|
||||
sctp_feature_off(inp, SCTP_PCB_FLAGS_DO_NOT_PMTUD);
|
||||
} else if (paddrp->spp_flags & SPP_PMTUD_DISABLE) {
|
||||
if (paddrp->spp_pathmtu >= SCTP_SMALLEST_PMTU) {
|
||||
inp->sctp_ep.default_mtu = paddrp->spp_pathmtu;
|
||||
}
|
||||
sctp_feature_on(inp, SCTP_PCB_FLAGS_DO_NOT_PMTUD);
|
||||
}
|
||||
if (paddrp->spp_flags & SPP_DSCP) {
|
||||
|
@ -1042,6 +1042,7 @@ sctp_init_asoc(struct sctp_inpcb *inp, struct sctp_tcb *stcb,
|
||||
asoc->initial_init_rto_max = inp->sctp_ep.initial_init_rto_max;
|
||||
asoc->initial_rto = inp->sctp_ep.initial_rto;
|
||||
|
||||
asoc->default_mtu = inp->sctp_ep.default_mtu;
|
||||
asoc->max_init_times = inp->sctp_ep.max_init_times;
|
||||
asoc->max_send_times = inp->sctp_ep.max_send_times;
|
||||
asoc->def_net_failure = inp->sctp_ep.def_net_failure;
|
||||
|
@ -229,6 +229,10 @@ sctp6_notify(struct sctp_inpcb *inp,
|
||||
}
|
||||
break;
|
||||
case ICMP6_PACKET_TOO_BIG:
|
||||
if ((net->dest_state & SCTP_ADDR_NO_PMTUD) == 0) {
|
||||
SCTP_TCB_UNLOCK(stcb);
|
||||
break;
|
||||
}
|
||||
if (SCTP_OS_TIMER_PENDING(&net->pmtu_timer.timer)) {
|
||||
timer_stopped = 1;
|
||||
sctp_timer_stop(SCTP_TIMER_TYPE_PATHMTURAISE, inp, stcb, net,
|
||||
|
Loading…
Reference in New Issue
Block a user