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 * Copyright 2022 Garrett D'Amore
27 */
28 /* Copyright (c) 1990 Mentat Inc. */
29
30 #include <inet/ip.h>
31 #include <inet/tcp_impl.h>
32 #include <inet/cc.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
tcp_set_1948phrase(netstack_t * stack,cred_t * cr,mod_prop_info_t * pinfo,const char * ifname,const void * pr_val,uint_t flags)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
tcp_listener_conf_get(netstack_t * stack,mod_prop_info_t * pinfo,const char * ifname,void * val,uint_t psize,uint_t flags)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
tcp_listener_conf_add(netstack_t * stack,cred_t * cr,mod_prop_info_t * pinfo,const char * ifname,const void * pval,uint_t flags)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
tcp_listener_conf_del(netstack_t * stack,cred_t * cr,mod_prop_info_t * pinfo,const char * ifname,const void * pval,uint_t flags)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
tcp_set_buf_prop(netstack_t * stack,cred_t * cr,mod_prop_info_t * pinfo,const char * ifname,const void * pval,uint_t flags)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
tcp_get_buf_prop(netstack_t * stack,mod_prop_info_t * pinfo,const char * ifname,void * val,uint_t psize,uint_t flags)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
tcp_smallest_anon_set(netstack_t * stack,cred_t * cr,mod_prop_info_t * pinfo,const char * ifname,const void * pval,uint_t flags)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
tcp_largest_anon_set(netstack_t * stack,cred_t * cr,mod_prop_info_t * pinfo,const char * ifname,const void * pval,uint_t flags)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
tcp_set_cc_algorithm(netstack_t * stack,cred_t * cr,mod_prop_info_t * pinfo,const char * ifname,const void * pval,uint_t flags)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
tcp_copy_ccname(void * data,struct cc_algo * algo)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
tcp_get_cc_algorithm(netstack_t * stack,mod_prop_info_t * pinfo,const char * ifname,void * pval,uint_t psize,uint_t flags)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);
613