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