1 /*
   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 /*
  22  * Copyright (c) 1991, 2010, Oracle and/or its affiliates. All rights reserved.
  23  * Copyright 2016 Joyent, Inc.
  24  * Copyright 2013 Nexenta Systems, Inc.  All rights reserved.
  25  * Copyright (c) 2012, 2017 by Delphix. All rights reserved.
  26  */
  27 /* Copyright (c) 1990 Mentat Inc. */
  28 
  29 #include <inet/ip.h>
  30 #include <inet/tcp_impl.h>
  31 #include <inet/cc.h>
  32 #include <sys/multidata.h>
  33 #include <sys/sunddi.h>
  34 
  35 /* Max size IP datagram is 64k - 1 */
  36 #define TCP_MSS_MAX_IPV4 (IP_MAXPACKET - (sizeof (ipha_t) + sizeof (tcpha_t)))
  37 #define TCP_MSS_MAX_IPV6 (IP_MAXPACKET - (sizeof (ip6_t) + sizeof (tcpha_t)))
  38 
  39 /* Max of the above */
  40 #define TCP_MSS_MAX             TCP_MSS_MAX_IPV4
  41 
  42 typedef struct {
  43         char *ccn_buf;
  44         uint_t ccn_bufsize;
  45         uint_t ccn_bytes;
  46 } tcp_copy_ccname_t;
  47 
  48 /*
  49  * Set the RFC 1948 pass phrase
  50  */
  51 /* ARGSUSED */
  52 static int
  53 tcp_set_1948phrase(netstack_t *stack,  cred_t *cr, mod_prop_info_t *pinfo,
  54     const char *ifname, const void* pr_val, uint_t flags)
  55 {
  56         if (flags & MOD_PROP_DEFAULT)
  57                 return (ENOTSUP);
  58 
  59         /*
  60          * Basically, value contains a new pass phrase.  Pass it along!
  61          */
  62         tcp_iss_key_init((uint8_t *)pr_val, strlen(pr_val),
  63             stack->netstack_tcp);
  64         return (0);
  65 }
  66 
  67 /*
  68  * returns the current list of listener limit configuration.
  69  */
  70 /* ARGSUSED */
  71 static int
  72 tcp_listener_conf_get(netstack_t *stack, mod_prop_info_t *pinfo,
  73     const char *ifname, void *val, uint_t psize, uint_t flags)
  74 {
  75         tcp_stack_t     *tcps = stack->netstack_tcp;
  76         tcp_listener_t  *tl;
  77         char            *pval = val;
  78         size_t          nbytes = 0, tbytes = 0;
  79         uint_t          size;
  80         int             err = 0;
  81 
  82         bzero(pval, psize);
  83         size = psize;
  84 
  85         if (flags & (MOD_PROP_DEFAULT|MOD_PROP_PERM|MOD_PROP_POSSIBLE))
  86                 return (0);
  87 
  88         mutex_enter(&tcps->tcps_listener_conf_lock);
  89         for (tl = list_head(&tcps->tcps_listener_conf); tl != NULL;
  90             tl = list_next(&tcps->tcps_listener_conf, tl)) {
  91                 if (psize == size)
  92                         nbytes = snprintf(pval, size, "%d:%d",  tl->tl_port,
  93                             tl->tl_ratio);
  94                 else
  95                         nbytes = snprintf(pval, size, ",%d:%d",  tl->tl_port,
  96                             tl->tl_ratio);
  97                 size -= nbytes;
  98                 pval += nbytes;
  99                 tbytes += nbytes;
 100                 if (tbytes >= psize) {
 101                         /* Buffer overflow, stop copying information */
 102                         err = ENOBUFS;
 103                         break;
 104                 }
 105         }
 106 
 107         mutex_exit(&tcps->tcps_listener_conf_lock);
 108         return (err);
 109 }
 110 
 111 /*
 112  * add a new listener limit configuration.
 113  */
 114 /* ARGSUSED */
 115 static int
 116 tcp_listener_conf_add(netstack_t *stack, cred_t *cr, mod_prop_info_t *pinfo,
 117     const char *ifname, const void* pval, uint_t flags)
 118 {
 119         tcp_listener_t  *new_tl;
 120         tcp_listener_t  *tl;
 121         long            lport;
 122         long            ratio;
 123         char            *colon;
 124         tcp_stack_t     *tcps = stack->netstack_tcp;
 125 
 126         if (flags & MOD_PROP_DEFAULT)
 127                 return (ENOTSUP);
 128 
 129         if (ddi_strtol(pval, &colon, 10, &lport) != 0 || lport <= 0 ||
 130             lport > USHRT_MAX || *colon != ':') {
 131                 return (EINVAL);
 132         }
 133         if (ddi_strtol(colon + 1, NULL, 10, &ratio) != 0 || ratio <= 0)
 134                 return (EINVAL);
 135 
 136         mutex_enter(&tcps->tcps_listener_conf_lock);
 137         for (tl = list_head(&tcps->tcps_listener_conf); tl != NULL;
 138             tl = list_next(&tcps->tcps_listener_conf, tl)) {
 139                 /* There is an existing entry, so update its ratio value. */
 140                 if (tl->tl_port == lport) {
 141                         tl->tl_ratio = ratio;
 142                         mutex_exit(&tcps->tcps_listener_conf_lock);
 143                         return (0);
 144                 }
 145         }
 146 
 147         if ((new_tl = kmem_alloc(sizeof (tcp_listener_t), KM_NOSLEEP)) ==
 148             NULL) {
 149                 mutex_exit(&tcps->tcps_listener_conf_lock);
 150                 return (ENOMEM);
 151         }
 152 
 153         new_tl->tl_port = lport;
 154         new_tl->tl_ratio = ratio;
 155         list_insert_tail(&tcps->tcps_listener_conf, new_tl);
 156         mutex_exit(&tcps->tcps_listener_conf_lock);
 157         return (0);
 158 }
 159 
 160 /*
 161  * remove a listener limit configuration.
 162  */
 163 /* ARGSUSED */
 164 static int
 165 tcp_listener_conf_del(netstack_t *stack, cred_t *cr, mod_prop_info_t *pinfo,
 166     const char *ifname, const void* pval, uint_t flags)
 167 {
 168         tcp_listener_t  *tl;
 169         long            lport;
 170         tcp_stack_t     *tcps = stack->netstack_tcp;
 171 
 172         if (flags & MOD_PROP_DEFAULT)
 173                 return (ENOTSUP);
 174 
 175         if (ddi_strtol(pval, NULL, 10, &lport) != 0 || lport <= 0 ||
 176             lport > USHRT_MAX) {
 177                 return (EINVAL);
 178         }
 179         mutex_enter(&tcps->tcps_listener_conf_lock);
 180         for (tl = list_head(&tcps->tcps_listener_conf); tl != NULL;
 181             tl = list_next(&tcps->tcps_listener_conf, tl)) {
 182                 if (tl->tl_port == lport) {
 183                         list_remove(&tcps->tcps_listener_conf, tl);
 184                         mutex_exit(&tcps->tcps_listener_conf_lock);
 185                         kmem_free(tl, sizeof (tcp_listener_t));
 186                         return (0);
 187                 }
 188         }
 189         mutex_exit(&tcps->tcps_listener_conf_lock);
 190         return (ESRCH);
 191 }
 192 
 193 static int
 194 tcp_set_buf_prop(netstack_t *stack, cred_t *cr, mod_prop_info_t *pinfo,
 195     const char *ifname, const void *pval, uint_t flags)
 196 {
 197         return (mod_set_buf_prop(stack->netstack_tcp->tcps_propinfo_tbl, stack,
 198             cr, pinfo, ifname, pval, flags));
 199 }
 200 
 201 static int
 202 tcp_get_buf_prop(netstack_t *stack, mod_prop_info_t *pinfo, const char *ifname,
 203     void *val, uint_t psize, uint_t flags)
 204 {
 205         return (mod_get_buf_prop(stack->netstack_tcp->tcps_propinfo_tbl, stack,
 206             pinfo, ifname, val, psize, flags));
 207 }
 208 
 209 /*
 210  * Special checkers for smallest/largest anonymous port so they don't
 211  * ever happen to be (largest < smallest).
 212  */
 213 /* ARGSUSED */
 214 static int
 215 tcp_smallest_anon_set(netstack_t *stack, cred_t *cr, mod_prop_info_t *pinfo,
 216     const char *ifname, const void *pval, uint_t flags)
 217 {
 218         unsigned long new_value;
 219         tcp_stack_t *tcps = stack->netstack_tcp;
 220         int err;
 221 
 222         if ((err = mod_uint32_value(pval, pinfo, flags, &new_value)) != 0)
 223                 return (err);
 224         /* mod_uint32_value() + pinfo guarantees we're in TCP port range. */
 225         if ((uint32_t)new_value > tcps->tcps_largest_anon_port)
 226                 return (ERANGE);
 227         pinfo->prop_cur_uval = (uint32_t)new_value;
 228         return (0);
 229 }
 230 
 231 /* ARGSUSED */
 232 static int
 233 tcp_largest_anon_set(netstack_t *stack, cred_t *cr, mod_prop_info_t *pinfo,
 234     const char *ifname, const void *pval, uint_t flags)
 235 {
 236         unsigned long new_value;
 237         tcp_stack_t *tcps = stack->netstack_tcp;
 238         int err;
 239 
 240         if ((err = mod_uint32_value(pval, pinfo, flags, &new_value)) != 0)
 241                 return (err);
 242         /* mod_uint32_value() + pinfo guarantees we're in TCP port range. */
 243         if ((uint32_t)new_value < tcps->tcps_smallest_anon_port)
 244                 return (ERANGE);
 245         pinfo->prop_cur_uval = (uint32_t)new_value;
 246         return (0);
 247 }
 248 
 249 /* ARGSUSED */
 250 static int
 251 tcp_set_cc_algorithm(netstack_t *stack, cred_t *cr, mod_prop_info_t *pinfo,
 252     const char *ifname, const void *pval, uint_t flags)
 253 {
 254         tcp_stack_t *tcps = stack->netstack_tcp;
 255         char *name = (flags & MOD_PROP_DEFAULT) ?
 256             CC_DEFAULT_ALGO_NAME : (char *)pval;
 257         struct cc_algo *algo = cc_load_algo(name);
 258 
 259         if (algo == NULL) {
 260                 return (EINVAL);
 261         }
 262 
 263         tcps->tcps_default_cc_algo = algo;
 264 
 265         return (0);
 266 }
 267 
 268 static int
 269 tcp_copy_ccname(void *data, struct cc_algo *algo)
 270 {
 271         tcp_copy_ccname_t *cd = data;
 272         char *sep = cd->ccn_bytes > 0 ? "," : "";
 273         size_t avail = 0;
 274 
 275         if (cd->ccn_bytes < cd->ccn_bufsize) {
 276                 avail = cd->ccn_bufsize - cd->ccn_bytes;
 277         }
 278 
 279         cd->ccn_bytes += snprintf(cd->ccn_buf + cd->ccn_bytes, avail,
 280             "%s%s", sep, algo->name);
 281 
 282         return (cd->ccn_bytes >= cd->ccn_bufsize ? ENOBUFS : 0);
 283 }
 284 
 285 /* ARGSUSED */
 286 static int
 287 tcp_get_cc_algorithm(netstack_t *stack, mod_prop_info_t *pinfo,
 288     const char *ifname, void *pval, uint_t psize, uint_t flags)
 289 {
 290         size_t nbytes;
 291 
 292         if (flags & MOD_PROP_POSSIBLE) {
 293                 tcp_copy_ccname_t cd = { pval, psize, 0 };
 294                 return (cc_walk_algos(tcp_copy_ccname, &cd));
 295         } else if (flags & MOD_PROP_PERM) {
 296                 nbytes = snprintf(pval, psize, "%u", MOD_PROP_PERM_RW);
 297         } else if (flags & MOD_PROP_DEFAULT) {
 298                 nbytes = snprintf(pval, psize, "%s", CC_DEFAULT_ALGO_NAME);
 299         } else {
 300                 nbytes = snprintf(pval, psize, "%s",
 301                     stack->netstack_tcp->tcps_default_cc_algo->name);
 302         }
 303         if (nbytes >= psize)
 304                 return (ENOBUFS);
 305         return (0);
 306 }
 307 
 308 /*
 309  * All of these are alterable, within the min/max values given, at run time.
 310  *
 311  * Note: All those tunables which do not start with "_" are Committed and
 312  * therefore are public. See PSARC 2010/080.
 313  */
 314 mod_prop_info_t tcp_propinfo_tbl[] = {
 315         /* tunable - 0 */
 316         { "_time_wait_interval", MOD_PROTO_TCP,
 317             mod_set_uint32, mod_get_uint32,
 318             {1*SECONDS, TCP_TIME_WAIT_MAX, 1*MINUTES}, {1*MINUTES} },
 319 
 320         { "_conn_req_max_q", MOD_PROTO_TCP,
 321             mod_set_uint32, mod_get_uint32,
 322             {1, UINT32_MAX, 128}, {128} },
 323 
 324         { "_conn_req_max_q0", MOD_PROTO_TCP,
 325             mod_set_uint32, mod_get_uint32,
 326             {0, UINT32_MAX, 1024}, {1024} },
 327 
 328         { "_conn_req_min", MOD_PROTO_TCP,
 329             mod_set_uint32, mod_get_uint32,
 330             {1, 1024, 1}, {1} },
 331 
 332         { "_conn_grace_period", MOD_PROTO_TCP,
 333             mod_set_uint32, mod_get_uint32,
 334             {0*MS, 20*SECONDS, 0*MS}, {0*MS} },
 335 
 336         { "_cwnd_max", MOD_PROTO_TCP,
 337             mod_set_uint32, mod_get_uint32,
 338             {128, ULP_MAX_BUF, 1024*1024}, {1024*1024} },
 339 
 340         { "_debug", MOD_PROTO_TCP,
 341             mod_set_uint32, mod_get_uint32,
 342             {0, 10, 0}, {0} },
 343 
 344         { "smallest_nonpriv_port", MOD_PROTO_TCP,
 345             mod_set_uint32, mod_get_uint32,
 346             {1024, (32*1024), 1024}, {1024} },
 347 
 348         { "_ip_abort_cinterval", MOD_PROTO_TCP,
 349             mod_set_uint32, mod_get_uint32,
 350             {1*SECONDS, UINT32_MAX, 3*MINUTES}, {3*MINUTES} },
 351 
 352         { "_ip_abort_linterval", MOD_PROTO_TCP,
 353             mod_set_uint32, mod_get_uint32,
 354             {1*SECONDS, UINT32_MAX, 3*MINUTES}, {3*MINUTES} },
 355 
 356         /* tunable - 10 */
 357         { "_ip_abort_interval", MOD_PROTO_TCP,
 358             mod_set_uint32, mod_get_uint32,
 359             {500*MS, UINT32_MAX, 5*MINUTES}, {5*MINUTES} },
 360 
 361         { "_ip_notify_cinterval", MOD_PROTO_TCP,
 362             mod_set_uint32, mod_get_uint32,
 363             {1*SECONDS, UINT32_MAX, 10*SECONDS},
 364             {10*SECONDS} },
 365 
 366         { "_ip_notify_interval", MOD_PROTO_TCP,
 367             mod_set_uint32, mod_get_uint32,
 368             {500*MS, UINT32_MAX, 10*SECONDS}, {10*SECONDS} },
 369 
 370         { "_ipv4_ttl", MOD_PROTO_TCP,
 371             mod_set_uint32, mod_get_uint32,
 372             {1, 255, 64}, {64} },
 373 
 374         { "_keepalive_interval", MOD_PROTO_TCP,
 375             mod_set_uint32, mod_get_uint32,
 376             {1*SECONDS, 10*DAYS, 2*HOURS}, {2*HOURS} },
 377 
 378         { "_maxpsz_multiplier", MOD_PROTO_TCP,
 379             mod_set_uint32, mod_get_uint32,
 380             {0, 100, 10}, {10} },
 381 
 382         { "_mss_def_ipv4", MOD_PROTO_TCP,
 383             mod_set_uint32, mod_get_uint32,
 384             {1, TCP_MSS_MAX_IPV4, 536}, {536} },
 385 
 386         { "_mss_max_ipv4", MOD_PROTO_TCP,
 387             mod_set_uint32, mod_get_uint32,
 388             {1, TCP_MSS_MAX_IPV4, TCP_MSS_MAX_IPV4},
 389             {TCP_MSS_MAX_IPV4} },
 390 
 391         { "_mss_min", MOD_PROTO_TCP,
 392             mod_set_uint32, mod_get_uint32,
 393             {1, TCP_MSS_MAX, 108}, {108} },
 394 
 395         { "_naglim_def", MOD_PROTO_TCP,
 396             mod_set_uint32, mod_get_uint32,
 397             {1, (64*1024)-1, (4*1024)-1}, {(4*1024)-1} },
 398 
 399         /* tunable - 20 */
 400         { "_rexmit_interval_initial", MOD_PROTO_TCP,
 401             mod_set_uint32, mod_get_uint32,
 402             {1*MS, 20*SECONDS, 1*SECONDS}, {1*SECONDS} },
 403 
 404         { "_rexmit_interval_max", MOD_PROTO_TCP,
 405             mod_set_uint32, mod_get_uint32,
 406             {1*MS, 2*HOURS, 60*SECONDS}, {60*SECONDS} },
 407 
 408         { "_rexmit_interval_min", MOD_PROTO_TCP,
 409             mod_set_uint32, mod_get_uint32,
 410             {1*MS, 2*HOURS, 400*MS}, {400*MS} },
 411 
 412         { "_deferred_ack_interval", MOD_PROTO_TCP,
 413             mod_set_uint32, mod_get_uint32,
 414             {1*MS, 1*MINUTES, 100*MS}, {100*MS} },
 415 
 416         { "_snd_lowat_fraction", MOD_PROTO_TCP,
 417             mod_set_uint32, mod_get_uint32,
 418             {0, 16, 10}, {10} },
 419 
 420         { "_dupack_fast_retransmit", MOD_PROTO_TCP,
 421             mod_set_uint32, mod_get_uint32,
 422             {1, 10000, 3}, {3} },
 423 
 424         { "_ignore_path_mtu", MOD_PROTO_TCP,
 425             mod_set_boolean, mod_get_boolean,
 426             {B_FALSE}, {B_FALSE} },
 427 
 428         { "smallest_anon_port", MOD_PROTO_TCP,
 429             tcp_smallest_anon_set, mod_get_uint32,
 430             {1024, ULP_MAX_PORT, 32*1024}, {32*1024} },
 431 
 432         { "largest_anon_port", MOD_PROTO_TCP,
 433             tcp_largest_anon_set, mod_get_uint32,
 434             {1024, ULP_MAX_PORT, ULP_MAX_PORT},
 435             {ULP_MAX_PORT} },
 436 
 437         { "send_buf", MOD_PROTO_TCP,
 438             tcp_set_buf_prop, tcp_get_buf_prop,
 439             {TCP_XMIT_LOWATER, ULP_MAX_BUF, TCP_XMIT_HIWATER},
 440             {TCP_XMIT_HIWATER} },
 441 
 442         /* tunable - 30 */
 443         { "_xmit_lowat", MOD_PROTO_TCP,
 444             mod_set_uint32, mod_get_uint32,
 445             {TCP_XMIT_LOWATER, ULP_MAX_BUF, TCP_XMIT_LOWATER},
 446             {TCP_XMIT_LOWATER} },
 447 
 448         { "recv_buf", MOD_PROTO_TCP,
 449             tcp_set_buf_prop, tcp_get_buf_prop,
 450             {TCP_RECV_LOWATER, ULP_MAX_BUF, TCP_RECV_HIWATER},
 451             {TCP_RECV_HIWATER} },
 452 
 453         { "_recv_hiwat_minmss", MOD_PROTO_TCP,
 454             mod_set_uint32, mod_get_uint32,
 455             {1, 65536, 4}, {4} },
 456 
 457         { "_fin_wait_2_flush_interval", MOD_PROTO_TCP,
 458             mod_set_uint32, mod_get_uint32,
 459             {1*SECONDS, 2*HOURS, 60*SECONDS},
 460             {60*SECONDS} },
 461 
 462         { "max_buf", MOD_PROTO_TCP,
 463             mod_set_uint32, mod_get_uint32,
 464             {8192, ULP_MAX_BUF, 1024*1024}, {1024*1024} },
 465 
 466         { "_strong_iss", MOD_PROTO_TCP,
 467             mod_set_uint32, mod_get_uint32,
 468             {0, 2, 2}, {2} },
 469 
 470         { "_rtt_updates", MOD_PROTO_TCP,
 471             mod_set_uint32, mod_get_uint32,
 472             {0, 65536, 20}, {20} },
 473 
 474         { "_wscale_always", MOD_PROTO_TCP,
 475             mod_set_boolean, mod_get_boolean,
 476             {B_TRUE}, {B_TRUE} },
 477 
 478         { "_tstamp_always", MOD_PROTO_TCP,
 479             mod_set_boolean, mod_get_boolean,
 480             {B_FALSE}, {B_FALSE} },
 481 
 482         { "_tstamp_if_wscale", MOD_PROTO_TCP,
 483             mod_set_boolean, mod_get_boolean,
 484             {B_TRUE}, {B_TRUE} },
 485 
 486         /* tunable - 40 */
 487         { "_rexmit_interval_extra", MOD_PROTO_TCP,
 488             mod_set_uint32, mod_get_uint32,
 489             {0*MS, 2*HOURS, 0*MS}, {0*MS} },
 490 
 491         { "_deferred_acks_max", MOD_PROTO_TCP,
 492             mod_set_uint32, mod_get_uint32,
 493             {0, 16, 2}, {2} },
 494 
 495         { "_slow_start_after_idle", MOD_PROTO_TCP,
 496             mod_set_uint32, mod_get_uint32,
 497             {0, 16384, 0}, {0} },
 498 
 499         { "_slow_start_initial", MOD_PROTO_TCP,
 500             mod_set_uint32, mod_get_uint32,
 501             {0, 16, 0}, {0} },
 502 
 503         { "sack", MOD_PROTO_TCP,
 504             mod_set_uint32, mod_get_uint32,
 505             {0, 2, 2}, {2} },
 506 
 507         { "_ipv6_hoplimit", MOD_PROTO_TCP,
 508             mod_set_uint32, mod_get_uint32,
 509             {0, IPV6_MAX_HOPS, IPV6_DEFAULT_HOPS},
 510             {IPV6_DEFAULT_HOPS} },
 511 
 512         { "_mss_def_ipv6", MOD_PROTO_TCP,
 513             mod_set_uint32, mod_get_uint32,
 514             {1, TCP_MSS_MAX_IPV6, 1220}, {1220} },
 515 
 516         { "_mss_max_ipv6", MOD_PROTO_TCP,
 517             mod_set_uint32, mod_get_uint32,
 518             {1, TCP_MSS_MAX_IPV6, TCP_MSS_MAX_IPV6},
 519             {TCP_MSS_MAX_IPV6} },
 520 
 521         { "_rev_src_routes", MOD_PROTO_TCP,
 522             mod_set_boolean, mod_get_boolean,
 523             {B_FALSE}, {B_FALSE} },
 524 
 525         { "_local_dack_interval", MOD_PROTO_TCP,
 526             mod_set_uint32, mod_get_uint32,
 527             {10*MS, 500*MS, 50*MS}, {50*MS} },
 528 
 529         /* tunable - 50 */
 530         { "_local_dacks_max", MOD_PROTO_TCP,
 531             mod_set_uint32, mod_get_uint32,
 532             {0, 16, 8}, {8} },
 533 
 534         { "ecn", MOD_PROTO_TCP,
 535             mod_set_uint32, mod_get_uint32,
 536             {0, 2, 1}, {1} },
 537 
 538         { "_rst_sent_rate_enabled", MOD_PROTO_TCP,
 539             mod_set_boolean, mod_get_boolean,
 540             {B_TRUE}, {B_TRUE} },
 541 
 542         { "_rst_sent_rate", MOD_PROTO_TCP,
 543             mod_set_uint32, mod_get_uint32,
 544             {0, UINT32_MAX, 40}, {40} },
 545 
 546         { "_push_timer_interval", MOD_PROTO_TCP,
 547             mod_set_uint32, mod_get_uint32,
 548             {0, 100*MS, 50*MS}, {50*MS} },
 549 
 550         { "_use_smss_as_mss_opt", MOD_PROTO_TCP,
 551             mod_set_boolean, mod_get_boolean,
 552             {B_FALSE}, {B_FALSE} },
 553 
 554         { "_keepalive_abort_interval", MOD_PROTO_TCP,
 555             mod_set_uint32, mod_get_uint32,
 556             {0, UINT32_MAX, 8*MINUTES}, {8*MINUTES} },
 557 
 558         /*
 559          * tcp_wroff_xtra is the extra space in front of TCP/IP header for link
 560          * layer header.  It has to be a multiple of 8.
 561          */
 562         { "_wroff_xtra", MOD_PROTO_TCP,
 563             mod_set_aligned, mod_get_uint32,
 564             {0, 256, 32}, {32} },
 565 
 566         { "_dev_flow_ctl", MOD_PROTO_TCP,
 567             mod_set_boolean, mod_get_boolean,
 568             {B_FALSE}, {B_FALSE} },
 569 
 570         { "_reass_timeout", MOD_PROTO_TCP,
 571             mod_set_uint32, mod_get_uint32,
 572             {0, UINT32_MAX, 100*SECONDS}, {100*SECONDS} },
 573 
 574         /* tunable - 60 */
 575         { "extra_priv_ports", MOD_PROTO_TCP,
 576             mod_set_extra_privports, mod_get_extra_privports,
 577             {1, ULP_MAX_PORT, 0}, {0} },
 578 
 579         { "_1948_phrase", MOD_PROTO_TCP,
 580             tcp_set_1948phrase, NULL, {0}, {0} },
 581 
 582         { "_listener_limit_conf", MOD_PROTO_TCP,
 583             NULL, tcp_listener_conf_get, {0}, {0} },
 584 
 585         { "_listener_limit_conf_add", MOD_PROTO_TCP,
 586             tcp_listener_conf_add, NULL, {0}, {0} },
 587 
 588         { "_listener_limit_conf_del", MOD_PROTO_TCP,
 589             tcp_listener_conf_del, NULL, {0}, {0} },
 590 
 591         { "_iss_incr", MOD_PROTO_TCP,
 592             mod_set_uint32, mod_get_uint32,
 593             {1, ISS_INCR, ISS_INCR},
 594             {ISS_INCR} },
 595 
 596         { "congestion_control", MOD_PROTO_TCP,
 597             tcp_set_cc_algorithm, tcp_get_cc_algorithm, {0}, {0} },
 598 
 599         /* RFC 3465 - TCP Congestion Control with Appropriate Byte Counting */
 600         { "_abc", MOD_PROTO_TCP,
 601             mod_set_boolean, mod_get_boolean, {B_TRUE}, {B_TRUE} },
 602 
 603         /* "L" value from RFC 3465 */
 604         { "_abc_l_var", MOD_PROTO_TCP,
 605             mod_set_uint32, mod_get_uint32, {1, UINT32_MAX, 2}, {2} },
 606 
 607         { "?", MOD_PROTO_TCP, NULL, mod_get_allprop, {0}, {0} },
 608 
 609         { NULL, 0, NULL, NULL, {0}, {0} }
 610 };
 611 
 612 int tcp_propinfo_count = A_CNT(tcp_propinfo_tbl);