Allow SCTP to use the hostcache.

This patch allows the MTU stored in the hostcache to be used as an
initial value for SCTP paths. When an ICMP PTB message is received,
store the MTU in the hostcache.

MFC after:	1 week
This commit is contained in:
Michael Tuexen 2017-04-29 19:20:50 +00:00
parent 2b223a01ef
commit 10e0318afa
4 changed files with 108 additions and 16 deletions

View File

@ -3933,6 +3933,7 @@ sctp_add_remote_addr(struct sctp_tcb *stcb, struct sockaddr *newaddr,
stcb->asoc.vrf_id,
stcb->sctp_ep->fibnum);
net->src_addr_selected = 0;
if (SCTP_ROUTE_HAS_VALID_IFN(&net->ro)) {
/* Get source address */
net->ro._s_addr = sctp_source_address_selection(stcb->sctp_ep,
@ -3942,18 +3943,18 @@ sctp_add_remote_addr(struct sctp_tcb *stcb, struct sockaddr *newaddr,
0,
stcb->asoc.vrf_id);
if (net->ro._s_addr != NULL) {
uint32_t imtu, rmtu, hcmtu;
net->src_addr_selected = 1;
/* Now get the interface MTU */
if (net->ro._s_addr->ifn_p != NULL) {
net->mtu = SCTP_GATHER_MTU_FROM_INTFC(net->ro._s_addr->ifn_p);
imtu = SCTP_GATHER_MTU_FROM_INTFC(net->ro._s_addr->ifn_p);
} else {
imtu = 0;
}
} else {
net->src_addr_selected = 0;
}
if (net->mtu > 0) {
uint32_t rmtu;
rmtu = SCTP_GATHER_MTU_FROM_ROUTE(net->ro._s_addr, &net->ro._l_addr.sa, net->ro.ro_rt);
hcmtu = sctp_hc_get_mtu(&net->ro._l_addr, stcb->sctp_ep->fibnum);
net->mtu = sctp_min_mtu(hcmtu, rmtu, imtu);
if (rmtu == 0) {
/*
* Start things off to match mtu of
@ -3961,17 +3962,8 @@ sctp_add_remote_addr(struct sctp_tcb *stcb, struct sockaddr *newaddr,
*/
SCTP_SET_MTU_OF_ROUTE(&net->ro._l_addr.sa,
net->ro.ro_rt, net->mtu);
} else {
/*
* we take the route mtu over the interface,
* since the route may be leading out the
* loopback, or a different interface.
*/
net->mtu = rmtu;
}
}
} else {
net->src_addr_selected = 0;
}
if (net->mtu == 0) {
switch (newaddr->sa_family) {

View File

@ -225,6 +225,11 @@ sctp_notify(struct sctp_inpcb *inp,
}
if (net->mtu > next_mtu) {
net->mtu = next_mtu;
if (net->port) {
sctp_hc_set_mtu(&net->ro._l_addr, inp->fibnum, next_mtu + sizeof(struct udphdr));
} else {
sctp_hc_set_mtu(&net->ro._l_addr, inp->fibnum, next_mtu);
}
}
/* Update the association MTU */
if (stcb->asoc.smallest_mtu > next_mtu) {

View File

@ -49,6 +49,9 @@ __FBSDID("$FreeBSD$");
#include <netinet/sctp_auth.h>
#include <netinet/sctp_asconf.h>
#include <netinet/sctp_bsd_addr.h>
#if defined(INET6) || defined(INET)
#include <netinet/tcp_var.h>
#endif
#include <netinet/udp.h>
#include <netinet/udp_var.h>
#include <sys/proc.h>
@ -7235,3 +7238,90 @@ sctp_over_udp_start(void)
#endif
return (0);
}
#if defined(INET6) || defined(INET)
/*
* sctp_min_mtu ()returns the minimum of all non-zero arguments.
* If all arguments are zero, zero is returned.
*/
uint32_t
sctp_min_mtu(uint32_t mtu1, uint32_t mtu2, uint32_t mtu3)
{
if (mtu1 > 0) {
if (mtu2 > 0) {
if (mtu3 > 0) {
return (min(mtu1, min(mtu2, mtu3)));
} else {
return (min(mtu1, mtu2));
}
} else {
if (mtu3 > 0) {
return (min(mtu1, mtu3));
} else {
return (mtu1);
}
}
} else {
if (mtu2 > 0) {
if (mtu3 > 0) {
return (min(mtu2, mtu3));
} else {
return (mtu2);
}
} else {
return (mtu3);
}
}
}
void
sctp_hc_set_mtu(union sctp_sockstore *addr, uint16_t fibnum, uint32_t mtu)
{
struct in_conninfo inc;
memset(&inc, 0, sizeof(struct in_conninfo));
inc.inc_fibnum = fibnum;
switch (addr->sa.sa_family) {
#ifdef INET
case AF_INET:
inc.inc_faddr = addr->sin.sin_addr;
break;
#endif
#ifdef INET6
case AF_INET6:
inc.inc_flags |= INC_ISIPV6;
inc.inc6_faddr = addr->sin6.sin6_addr;
break;
#endif
default:
return;
}
tcp_hc_updatemtu(&inc, (u_long)mtu);
}
uint32_t
sctp_hc_get_mtu(union sctp_sockstore *addr, uint16_t fibnum)
{
struct in_conninfo inc;
memset(&inc, 0, sizeof(struct in_conninfo));
inc.inc_fibnum = fibnum;
switch (addr->sa.sa_family) {
#ifdef INET
case AF_INET:
inc.inc_faddr = addr->sin.sin_addr;
break;
#endif
#ifdef INET6
case AF_INET6:
inc.inc_flags |= INC_ISIPV6;
inc.inc6_faddr = addr->sin6.sin6_addr;
break;
#endif
default:
return (0);
}
return ((uint32_t)tcp_hc_getmtu(&inc));
}
#endif

View File

@ -387,6 +387,11 @@ sctp_auditing(int, struct sctp_inpcb *, struct sctp_tcb *,
struct sctp_nets *);
void sctp_audit_log(uint8_t, uint8_t);
#endif
#if defined(INET6) || defined(INET)
uint32_t sctp_min_mtu(uint32_t, uint32_t, uint32_t);
void sctp_hc_set_mtu(union sctp_sockstore *, uint16_t, uint32_t);
uint32_t sctp_hc_get_mtu(union sctp_sockstore *, uint16_t);
#endif
#endif /* _KERNEL */
#endif