Print this page
11554 Want TCP_CONGESTION socket option
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
*** 19,29 ****
* 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 (c) 2016 by Delphix. All rights reserved.
*/
#include <sys/types.h>
#include <sys/stream.h>
--- 19,29 ----
* CDDL HEADER END
*/
/*
* Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2011 Nexenta Systems, Inc. All rights reserved.
! * Copyright 2019 Joyent, Inc.
* Copyright (c) 2016 by Delphix. All rights reserved.
*/
#include <sys/types.h>
#include <sys/stream.h>
*** 32,41 ****
--- 32,42 ----
#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,148 ****
--- 140,152 ----
{ 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,440 ****
--- 435,451 ----
*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,861 ****
--- 863,907 ----
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