diff options
Diffstat (limited to 'sys/netinet/tcp_usrreq.c')
-rw-r--r-- | sys/netinet/tcp_usrreq.c | 113 |
1 files changed, 68 insertions, 45 deletions
diff --git a/sys/netinet/tcp_usrreq.c b/sys/netinet/tcp_usrreq.c index 76bc8aa..4b3150b 100644 --- a/sys/netinet/tcp_usrreq.c +++ b/sys/netinet/tcp_usrreq.c @@ -69,7 +69,6 @@ __FBSDID("$FreeBSD$"); #include <net/route.h> #include <net/vnet.h> -#include <netinet/cc.h> #include <netinet/in.h> #include <netinet/in_kdtrace.h> #include <netinet/in_pcb.h> @@ -85,11 +84,13 @@ __FBSDID("$FreeBSD$"); #ifdef TCP_RFC7413 #include <netinet/tcp_fastopen.h> #endif +#include <netinet/tcp.h> #include <netinet/tcp_fsm.h> #include <netinet/tcp_seq.h> #include <netinet/tcp_timer.h> #include <netinet/tcp_var.h> #include <netinet/tcpip.h> +#include <netinet/tcp_cc.h> #ifdef TCPPCAP #include <netinet/tcp_pcap.h> #endif @@ -1478,8 +1479,34 @@ tcp_default_ctloutput(struct socket *so, struct sockopt *sopt, struct inpcb *inp u_int ui; struct tcp_info ti; struct cc_algo *algo; - char buf[TCP_CA_NAME_MAX]; - + char *buf; + + /* + * For TCP_CCALGOOPT forward the control to CC module, for both + * SOPT_SET and SOPT_GET. + */ + switch (sopt->sopt_name) { + case TCP_CCALGOOPT: + INP_WUNLOCK(inp); + buf = malloc(sopt->sopt_valsize, M_TEMP, M_WAITOK | M_ZERO); + error = sooptcopyin(sopt, buf, sopt->sopt_valsize, + sopt->sopt_valsize); + if (error) { + free(buf, M_TEMP); + return (error); + } + INP_WLOCK_RECHECK(inp); + if (CC_ALGO(tp)->ctl_output != NULL) + error = CC_ALGO(tp)->ctl_output(tp->ccv, sopt, buf); + else + error = ENOENT; + INP_WUNLOCK(inp); + if (error == 0 && sopt->sopt_dir == SOPT_GET) + error = sooptcopyout(sopt, buf, sopt->sopt_valsize); + free(buf, M_TEMP); + return (error); + } + switch (sopt->sopt_dir) { case SOPT_SET: switch (sopt->sopt_name) { @@ -1573,50 +1600,47 @@ unlock_and_done: case TCP_CONGESTION: INP_WUNLOCK(inp); - bzero(buf, sizeof(buf)); - error = sooptcopyin(sopt, &buf, sizeof(buf), 1); - if (error) + buf = malloc(TCP_CA_NAME_MAX, M_TEMP, M_WAITOK|M_ZERO); + error = sooptcopyin(sopt, buf, TCP_CA_NAME_MAX, 1); + if (error) { + free(buf, M_TEMP); break; + } + CC_LIST_RLOCK(); + STAILQ_FOREACH(algo, &cc_list, entries) + if (strncmp(buf, algo->name, + TCP_CA_NAME_MAX) == 0) + break; + CC_LIST_RUNLOCK(); + free(buf, M_TEMP); + if (algo == NULL) { + error = EINVAL; + break; + } INP_WLOCK_RECHECK(inp); /* - * Return EINVAL if we can't find the requested cc algo. + * We hold a write lock over the tcb so it's safe to + * do these things without ordering concerns. */ - error = EINVAL; - CC_LIST_RLOCK(); - STAILQ_FOREACH(algo, &cc_list, entries) { - if (strncmp(buf, algo->name, TCP_CA_NAME_MAX) - == 0) { - /* We've found the requested algo. */ - error = 0; - /* - * We hold a write lock over the tcb - * so it's safe to do these things - * without ordering concerns. - */ - if (CC_ALGO(tp)->cb_destroy != NULL) - CC_ALGO(tp)->cb_destroy(tp->ccv); - CC_ALGO(tp) = algo; - /* - * If something goes pear shaped - * initialising the new algo, - * fall back to newreno (which - * does not require initialisation). - */ - if (algo->cb_init != NULL) - if (algo->cb_init(tp->ccv) > 0) { - CC_ALGO(tp) = &newreno_cc_algo; - /* - * The only reason init - * should fail is - * because of malloc. - */ - error = ENOMEM; - } - break; /* Break the STAILQ_FOREACH. */ - } + if (CC_ALGO(tp)->cb_destroy != NULL) + CC_ALGO(tp)->cb_destroy(tp->ccv); + CC_ALGO(tp) = algo; + /* + * If something goes pear shaped initialising the new + * algo, fall back to newreno (which does not + * require initialisation). + */ + if (algo->cb_init != NULL && + algo->cb_init(tp->ccv) != 0) { + CC_ALGO(tp) = &newreno_cc_algo; + /* + * The only reason init should fail is + * because of malloc. + */ + error = ENOMEM; } - CC_LIST_RUNLOCK(); - goto unlock_and_done; + INP_WUNLOCK(inp); + break; case TCP_KEEPIDLE: case TCP_KEEPINTVL: @@ -1762,10 +1786,9 @@ unlock_and_done: error = sooptcopyout(sopt, &ti, sizeof ti); break; case TCP_CONGESTION: - bzero(buf, sizeof(buf)); - strlcpy(buf, CC_ALGO(tp)->name, TCP_CA_NAME_MAX); INP_WUNLOCK(inp); - error = sooptcopyout(sopt, buf, TCP_CA_NAME_MAX); + error = sooptcopyout(sopt, CC_ALGO(tp)->name, + TCP_CA_NAME_MAX); break; case TCP_KEEPIDLE: case TCP_KEEPINTVL: |