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
42typedef 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 */
52static int
53tcp_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 */
71static int
72tcp_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 */
115static int
116tcp_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 */
164static int
165tcp_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
193static int
194tcp_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
201static int
202tcp_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 */
214static int
215tcp_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 */
232static int
233tcp_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 */
250static int
251tcp_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
268static int
269tcp_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 */
286static int
287tcp_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 */
314mod_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
612int tcp_propinfo_count = A_CNT(tcp_propinfo_tbl);
613