summaryrefslogtreecommitdiffstats
path: root/sys/netinet
diff options
context:
space:
mode:
authorglebius <glebius@FreeBSD.org>2016-01-22 02:07:48 +0000
committerglebius <glebius@FreeBSD.org>2016-01-22 02:07:48 +0000
commit40ba1ae95a65027a63267d57c7b0fee6e030bbd2 (patch)
treedddc38b9e03f3559cc94d54c711282c48c319bd8 /sys/netinet
parent0840cf26409ce91dd72208f7439fe1b11f4204c8 (diff)
downloadFreeBSD-src-40ba1ae95a65027a63267d57c7b0fee6e030bbd2.zip
FreeBSD-src-40ba1ae95a65027a63267d57c7b0fee6e030bbd2.tar.gz
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
Diffstat (limited to 'sys/netinet')
-rw-r--r--sys/netinet/tcp.h1
-rw-r--r--sys/netinet/tcp_cc.h3
-rw-r--r--sys/netinet/tcp_usrreq.c28
3 files changed, 31 insertions, 1 deletions
diff --git a/sys/netinet/tcp.h b/sys/netinet/tcp.h
index bfc8073..4703810 100644
--- a/sys/netinet/tcp.h
+++ b/sys/netinet/tcp.h
@@ -165,6 +165,7 @@ struct tcphdr {
#define TCP_MD5SIG 16 /* use MD5 digests (RFC2385) */
#define TCP_INFO 32 /* retrieve tcp_info structure */
#define TCP_CONGESTION 64 /* get/set congestion control algorithm */
+#define TCP_CCALGOOPT 65 /* get/set cc algorithm specific options */
#define TCP_KEEPINIT 128 /* N, time to establish connection */
#define TCP_KEEPIDLE 256 /* L,N,X start keeplives after this period */
#define TCP_KEEPINTVL 512 /* L,N interval between keepalives */
diff --git a/sys/netinet/tcp_cc.h b/sys/netinet/tcp_cc.h
index 4a2b0c8..d90cd19 100644
--- a/sys/netinet/tcp_cc.h
+++ b/sys/netinet/tcp_cc.h
@@ -151,6 +151,9 @@ struct cc_algo {
/* Called for an additional ECN processing apart from RFC3168. */
void (*ecnpkt_handler)(struct cc_var *ccv);
+ /* Called for {get|set}sockopt() on a TCP socket with TCP_CCALGOOPT. */
+ int (*ctl_output)(struct cc_var *, struct sockopt *, void *);
+
STAILQ_ENTRY (cc_algo) entries;
};
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) {
OpenPOWER on IntegriCloud