From a1e3038e6879c24a6f2fa064fc09facb25ecd981 Mon Sep 17 00:00:00 2001 From: glebius Date: Thu, 21 Jan 2016 22:34:51 +0000 Subject: - Rename cc.h to more meaningful tcp_cc.h. - Declare it a kernel only include, which it already is. - Don't include tcp.h implicitly from tcp_cc.h --- sys/netinet/tcp_usrreq.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'sys/netinet/tcp_usrreq.c') diff --git a/sys/netinet/tcp_usrreq.c b/sys/netinet/tcp_usrreq.c index 76bc8aa..c084f92 100644 --- a/sys/netinet/tcp_usrreq.c +++ b/sys/netinet/tcp_usrreq.c @@ -69,7 +69,6 @@ __FBSDID("$FreeBSD$"); #include #include -#include #include #include #include @@ -85,11 +84,13 @@ __FBSDID("$FreeBSD$"); #ifdef TCP_RFC7413 #include #endif +#include #include #include #include #include #include +#include #ifdef TCPPCAP #include #endif -- cgit v1.1 From f6d6671576bc39e8b20cd8b2f036fa6ad8d08dde Mon Sep 17 00:00:00 2001 From: glebius Date: Thu, 21 Jan 2016 22:53:12 +0000 Subject: Refactor TCP_CONGESTION setsockopt handling: - Use M_TEMP instead of stack variable. - Unroll error handling, removing several levels of indentation. --- sys/netinet/tcp_usrreq.c | 82 +++++++++++++++++++++++------------------------- 1 file changed, 39 insertions(+), 43 deletions(-) (limited to 'sys/netinet/tcp_usrreq.c') diff --git a/sys/netinet/tcp_usrreq.c b/sys/netinet/tcp_usrreq.c index c084f92..29e92b2 100644 --- a/sys/netinet/tcp_usrreq.c +++ b/sys/netinet/tcp_usrreq.c @@ -1479,7 +1479,7 @@ 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; switch (sopt->sopt_dir) { case SOPT_SET: @@ -1574,50 +1574,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: @@ -1763,10 +1760,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: -- cgit v1.1 From 40ba1ae95a65027a63267d57c7b0fee6e030bbd2 Mon Sep 17 00:00:00 2001 From: glebius Date: Fri, 22 Jan 2016 02:07:48 +0000 Subject: Provide new socket option TCP_CCALGOOPT, which stands for TCP congestion control algorithm options. The argument is variable length and is opaque to TCP, forwarded directly to the algorithm's ctl_output method. Provide new includes directory netinet/cc, where algorithm specific headers can be installed. The new API doesn't yet have any in tree consumers. The original code written by lstewart. Reviewed by: rrs, emax Sponsored by: Netflix Differential Revision: https://reviews.freebsd.org/D711 --- sys/netinet/tcp_usrreq.c | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) (limited to 'sys/netinet/tcp_usrreq.c') diff --git a/sys/netinet/tcp_usrreq.c b/sys/netinet/tcp_usrreq.c index 29e92b2..4b3150b 100644 --- a/sys/netinet/tcp_usrreq.c +++ b/sys/netinet/tcp_usrreq.c @@ -1480,7 +1480,33 @@ tcp_default_ctloutput(struct socket *so, struct sockopt *sopt, struct inpcb *inp struct tcp_info ti; struct cc_algo *algo; 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) { -- cgit v1.1