mirror of
https://github.com/opnsense/src.git
synced 2026-06-13 18:50:31 -04:00
sctp: improve sctp_pathmtu_adjustment()
Allow the resending of DATA chunks to be controlled by the caller, which allows retiring sctp_mtu_size_reset() in a separate commit. Also improve the computaion of the overhead and use 32-bit integers consistently. Thanks to Timo Voelker for pointing me to the code. MFC after: 3 days
This commit is contained in:
parent
b78860f96c
commit
2de2ae331b
5 changed files with 44 additions and 28 deletions
|
|
@ -5291,7 +5291,7 @@ sctp_common_input_processing(struct mbuf **mm, int iphlen, int offset, int lengt
|
|||
/* UDP encapsulation turned on. */
|
||||
net->mtu -= sizeof(struct udphdr);
|
||||
if (stcb->asoc.smallest_mtu > net->mtu) {
|
||||
sctp_pathmtu_adjustment(stcb, net->mtu);
|
||||
sctp_pathmtu_adjustment(stcb, net->mtu, true);
|
||||
}
|
||||
} else if (port == 0) {
|
||||
/* UDP encapsulation turned off. */
|
||||
|
|
@ -5331,7 +5331,7 @@ sctp_common_input_processing(struct mbuf **mm, int iphlen, int offset, int lengt
|
|||
/* UDP encapsulation turned on. */
|
||||
net->mtu -= sizeof(struct udphdr);
|
||||
if (stcb->asoc.smallest_mtu > net->mtu) {
|
||||
sctp_pathmtu_adjustment(stcb, net->mtu);
|
||||
sctp_pathmtu_adjustment(stcb, net->mtu, true);
|
||||
}
|
||||
} else if (port == 0) {
|
||||
/* UDP encapsulation turned off. */
|
||||
|
|
@ -5426,7 +5426,7 @@ sctp_common_input_processing(struct mbuf **mm, int iphlen, int offset, int lengt
|
|||
/* UDP encapsulation turned on. */
|
||||
net->mtu -= sizeof(struct udphdr);
|
||||
if (stcb->asoc.smallest_mtu > net->mtu) {
|
||||
sctp_pathmtu_adjustment(stcb, net->mtu);
|
||||
sctp_pathmtu_adjustment(stcb, net->mtu, true);
|
||||
}
|
||||
} else if (port == 0) {
|
||||
/* UDP encapsulation turned off. */
|
||||
|
|
|
|||
|
|
@ -4025,7 +4025,7 @@ sctp_add_remote_addr(struct sctp_tcb *stcb, struct sockaddr *newaddr,
|
|||
stcb->asoc.smallest_mtu = net->mtu;
|
||||
}
|
||||
if (stcb->asoc.smallest_mtu > net->mtu) {
|
||||
sctp_pathmtu_adjustment(stcb, net->mtu);
|
||||
sctp_pathmtu_adjustment(stcb, net->mtu, true);
|
||||
}
|
||||
#ifdef INET6
|
||||
if (newaddr->sa_family == AF_INET6) {
|
||||
|
|
|
|||
|
|
@ -104,35 +104,51 @@ VNET_SYSUNINIT(sctp, SI_SUB_PROTO_DOMAIN, SI_ORDER_FOURTH, sctp_finish, NULL);
|
|||
#endif
|
||||
|
||||
void
|
||||
sctp_pathmtu_adjustment(struct sctp_tcb *stcb, uint16_t nxtsz)
|
||||
sctp_pathmtu_adjustment(struct sctp_tcb *stcb, uint32_t mtu, bool resend)
|
||||
{
|
||||
struct sctp_association *asoc;
|
||||
struct sctp_tmit_chunk *chk;
|
||||
uint16_t overhead;
|
||||
uint32_t overhead;
|
||||
|
||||
/* Adjust that too */
|
||||
stcb->asoc.smallest_mtu = nxtsz;
|
||||
/* now off to subtract IP_DF flag if needed */
|
||||
overhead = IP_HDR_SIZE + sizeof(struct sctphdr);
|
||||
if (sctp_auth_is_required_chunk(SCTP_DATA, stcb->asoc.peer_auth_chunks)) {
|
||||
overhead += sctp_get_auth_chunk_len(stcb->asoc.peer_hmac_id);
|
||||
asoc = &stcb->asoc;
|
||||
KASSERT(mtu < asoc->smallest_mtu,
|
||||
("Currently only reducing association MTU %u supported (MTU %u)",
|
||||
asoc->smallest_mtu, mtu));
|
||||
asoc->smallest_mtu = mtu;
|
||||
if (stcb->sctp_ep->sctp_flags & SCTP_PCB_FLAGS_BOUND_V6) {
|
||||
overhead = SCTP_MIN_OVERHEAD;
|
||||
} else {
|
||||
overhead = SCTP_MIN_V4_OVERHEAD;
|
||||
}
|
||||
TAILQ_FOREACH(chk, &stcb->asoc.send_queue, sctp_next) {
|
||||
if ((chk->send_size + overhead) > nxtsz) {
|
||||
if (asoc->idata_supported) {
|
||||
if (sctp_auth_is_required_chunk(SCTP_IDATA, asoc->peer_auth_chunks)) {
|
||||
overhead += sctp_get_auth_chunk_len(asoc->peer_hmac_id);
|
||||
}
|
||||
} else {
|
||||
if (sctp_auth_is_required_chunk(SCTP_DATA, asoc->peer_auth_chunks)) {
|
||||
overhead += sctp_get_auth_chunk_len(asoc->peer_hmac_id);
|
||||
}
|
||||
}
|
||||
KASSERT(overhead % 4 == 0,
|
||||
("overhead (%u) not a multiple of 4", overhead));
|
||||
TAILQ_FOREACH(chk, &asoc->send_queue, sctp_next) {
|
||||
if (((uint32_t)chk->send_size + overhead) > mtu) {
|
||||
chk->flags |= CHUNK_FLAGS_FRAGMENT_OK;
|
||||
}
|
||||
}
|
||||
TAILQ_FOREACH(chk, &stcb->asoc.sent_queue, sctp_next) {
|
||||
if ((chk->send_size + overhead) > nxtsz) {
|
||||
/*
|
||||
* For this guy we also mark for immediate resend
|
||||
* since we sent to big of chunk
|
||||
*/
|
||||
TAILQ_FOREACH(chk, &asoc->sent_queue, sctp_next) {
|
||||
if (((uint32_t)chk->send_size + overhead) > mtu) {
|
||||
chk->flags |= CHUNK_FLAGS_FRAGMENT_OK;
|
||||
if (chk->sent < SCTP_DATAGRAM_RESEND) {
|
||||
if (resend && chk->sent < SCTP_DATAGRAM_RESEND) {
|
||||
/*
|
||||
* If requested, mark the chunk for
|
||||
* immediate resend, since we sent it being
|
||||
* too big.
|
||||
*/
|
||||
sctp_flight_size_decrease(chk);
|
||||
sctp_total_flight_decrease(stcb, chk);
|
||||
chk->sent = SCTP_DATAGRAM_RESEND;
|
||||
sctp_ucount_incr(stcb->asoc.sent_queue_retran_cnt);
|
||||
sctp_ucount_incr(asoc->sent_queue_retran_cnt);
|
||||
chk->rec.data.doing_fast_retransmit = 0;
|
||||
if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_FLIGHT_LOGGING_ENABLE) {
|
||||
sctp_misc_ints(SCTP_FLIGHT_LOG_DOWN_PMTU,
|
||||
|
|
@ -141,7 +157,7 @@ sctp_pathmtu_adjustment(struct sctp_tcb *stcb, uint16_t nxtsz)
|
|||
(uint32_t)(uintptr_t)chk->whoTo,
|
||||
chk->rec.data.tsn);
|
||||
}
|
||||
/* Clear any time so NO RTT is being done */
|
||||
/* Clear any time, so NO RTT is being done. */
|
||||
if (chk->do_rtt == 1) {
|
||||
chk->do_rtt = 0;
|
||||
chk->whoTo->rto_needed = 1;
|
||||
|
|
@ -229,7 +245,7 @@ sctp_notify(struct sctp_inpcb *inp,
|
|||
}
|
||||
/* Update the association MTU */
|
||||
if (stcb->asoc.smallest_mtu > next_mtu) {
|
||||
sctp_pathmtu_adjustment(stcb, next_mtu);
|
||||
sctp_pathmtu_adjustment(stcb, next_mtu, true);
|
||||
}
|
||||
/* Finally, start the PMTU timer if it was running before. */
|
||||
if (timer_stopped) {
|
||||
|
|
@ -5363,7 +5379,7 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
|
|||
break;
|
||||
}
|
||||
if (net->mtu < stcb->asoc.smallest_mtu) {
|
||||
sctp_pathmtu_adjustment(stcb, net->mtu);
|
||||
sctp_pathmtu_adjustment(stcb, net->mtu, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -5507,7 +5523,7 @@ sctp_setopt(struct socket *so, int optname, void *optval, size_t optsize,
|
|||
break;
|
||||
}
|
||||
if (net->mtu < stcb->asoc.smallest_mtu) {
|
||||
sctp_pathmtu_adjustment(stcb, net->mtu);
|
||||
sctp_pathmtu_adjustment(stcb, net->mtu, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -328,7 +328,7 @@ int sctp_ctloutput(struct socket *, struct sockopt *);
|
|||
void sctp_input_with_port(struct mbuf *, int, uint16_t);
|
||||
int sctp_input(struct mbuf **, int *, int);
|
||||
#endif
|
||||
void sctp_pathmtu_adjustment(struct sctp_tcb *, uint16_t);
|
||||
void sctp_pathmtu_adjustment(struct sctp_tcb *, uint32_t, bool);
|
||||
void sctp_drain(void);
|
||||
void sctp_init(void);
|
||||
void
|
||||
|
|
|
|||
|
|
@ -233,7 +233,7 @@ sctp6_notify(struct sctp_inpcb *inp,
|
|||
}
|
||||
/* Update the association MTU */
|
||||
if (stcb->asoc.smallest_mtu > next_mtu) {
|
||||
sctp_pathmtu_adjustment(stcb, next_mtu);
|
||||
sctp_pathmtu_adjustment(stcb, next_mtu, true);
|
||||
}
|
||||
/* Finally, start the PMTU timer if it was running before. */
|
||||
if (timer_stopped) {
|
||||
|
|
|
|||
Loading…
Reference in a new issue