Print this page
11554 Want TCP_CONGESTION socket option
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
@@ -19,11 +19,11 @@
* CDDL HEADER END
*/
/*
* Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2011 Nexenta Systems, Inc. All rights reserved.
- * Copyright 2016 Joyent, Inc.
+ * Copyright 2019 Joyent, Inc.
* Copyright (c) 2016 by Delphix. All rights reserved.
*/
#include <sys/types.h>
#include <sys/stream.h>
@@ -32,10 +32,11 @@
#include <sys/socket.h>
#include <sys/xti_xtiopt.h>
#include <sys/xti_inet.h>
#include <sys/policy.h>
+#include <inet/cc.h>
#include <inet/common.h>
#include <netinet/ip6.h>
#include <inet/ip.h>
#include <netinet/in.h>
@@ -139,10 +140,13 @@
{ TCP_RTO_MAX, IPPROTO_TCP, OA_RW, OA_RW, OP_NP, 0, sizeof (uint32_t), 0 },
{ TCP_LINGER2, IPPROTO_TCP, OA_RW, OA_RW, OP_NP, 0, sizeof (int), 0 },
+{ TCP_CONGESTION, IPPROTO_TCP, OA_RW, OA_RW, OP_NP,
+ OP_VARLEN, CC_ALGO_NAME_MAX, 0 },
+
{ IP_OPTIONS, IPPROTO_IP, OA_RW, OA_RW, OP_NP,
(OP_VARLEN|OP_NODEFAULT),
IP_MAX_OPT_LENGTH + IP_ADDR_LEN, -1 /* not initialized */ },
{ T_IP_OPTIONS, IPPROTO_IP, OA_RW, OA_RW, OP_NP,
(OP_VARLEN|OP_NODEFAULT),
@@ -431,10 +435,17 @@
*i1 = tcp->tcp_ka_rinterval / 1000;
return (sizeof (int));
case TCP_KEEPALIVE_ABORT_THRESHOLD:
*i1 = tcp->tcp_ka_abort_thres;
return (sizeof (int));
+ case TCP_CONGESTION: {
+ size_t len = strlcpy((char *)ptr, CC_ALGO(tcp)->name,
+ CC_ALGO_NAME_MAX);
+ if (len >= CC_ALGO_NAME_MAX)
+ return (-1);
+ return (len + 1);
+ }
case TCP_CORK:
*i1 = tcp->tcp_cork;
return (sizeof (int));
case TCP_RTO_INITIAL:
*i1 = tcp->tcp_rto_initial;
@@ -852,10 +863,45 @@
tcp->tcp_ka_abort_thres = *i1;
tcp->tcp_ka_cnt = 0;
tcp->tcp_ka_rinterval = 0;
}
break;
+ case TCP_CONGESTION: {
+ struct cc_algo *algo;
+
+ if (checkonly) {
+ break;
+ }
+
+ /*
+ * Make sure the string is NUL-terminated. Some
+ * consumers pass only the number of characters
+ * in the string, and don't include the NUL
+ * terminator, so we set it for them.
+ */
+ if (inlen < CC_ALGO_NAME_MAX) {
+ invalp[inlen] = '\0';
+ }
+ invalp[CC_ALGO_NAME_MAX - 1] = '\0';
+
+ if ((algo = cc_load_algo((char *)invalp)) == NULL) {
+ return (ENOENT);
+ }
+
+ if (CC_ALGO(tcp)->cb_destroy != NULL) {
+ CC_ALGO(tcp)->cb_destroy(&tcp->tcp_ccv);
+ }
+
+ CC_DATA(tcp) = NULL;
+ CC_ALGO(tcp) = algo;
+
+ if (CC_ALGO(tcp)->cb_init != NULL) {
+ VERIFY0(CC_ALGO(tcp)->cb_init(&tcp->tcp_ccv));
+ }
+
+ break;
+ }
case TCP_CORK:
if (!checkonly) {
/*
* if tcp->tcp_cork was set and is now
* being unset, we have to make sure that