Print this page
3942 inject sanity into ipadm tcp buffer size properties
3943 _snd_lowat_fraction tcp tunable has no effect
Reviewed by: Adam Leventhal <ahl@delphix.com>
Reviewed by: Peng Dai <peng.dai@delphix.com>

*** 19,28 **** --- 19,29 ---- * CDDL HEADER END */ /* * Copyright (c) 1991, 2010, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 1990 Mentat Inc. + * Copyright (c) 2013 by Delphix. All rights reserved. */ #include <inet/tunables.h> #include <sys/md5.h> #include <inet/common.h>
*** 36,45 **** --- 37,64 ---- #include <inet/udp_impl.h> #include <inet/sctp/sctp_stack.h> #include <inet/sctp/sctp_impl.h> #include <inet/tunables.h> + mod_prop_info_t * + mod_prop_lookup(mod_prop_info_t ptbl[], const char *prop_name, uint_t proto) + { + mod_prop_info_t *pinfo; + + /* + * Walk the ptbl array looking for a property that has the requested + * name and protocol number. Note that we assume that all protocol + * tables are terminated by an entry with a NULL property name. + */ + for (pinfo = ptbl; pinfo->mpi_name != NULL; pinfo++) { + if (strcmp(pinfo->mpi_name, prop_name) == 0 && + pinfo->mpi_proto == proto) + return (pinfo); + } + return (NULL); + } + static int prop_perm2const(mod_prop_info_t *pinfo) { if (pinfo->mpi_setf == NULL) return (MOD_PROP_PERM_READ);
*** 52,62 **** * Modifies the value of the property to default value or to the `pval' * specified by the user. */ /* ARGSUSED */ int ! mod_set_boolean(void *cbarg, cred_t *cr, mod_prop_info_t *pinfo, const char *ifname, const void* pval, uint_t flags) { char *end; unsigned long new_value; --- 71,81 ---- * Modifies the value of the property to default value or to the `pval' * specified by the user. */ /* ARGSUSED */ int ! mod_set_boolean(netstack_t *stack, cred_t *cr, mod_prop_info_t *pinfo, const char *ifname, const void* pval, uint_t flags) { char *end; unsigned long new_value;
*** 77,87 **** * Retrieves property permission, default value, current value or possible * values for those properties whose value type is boolean_t. */ /* ARGSUSED */ int ! mod_get_boolean(void *cbarg, mod_prop_info_t *pinfo, const char *ifname, void *pval, uint_t psize, uint_t flags) { boolean_t get_def = (flags & MOD_PROP_DEFAULT); boolean_t get_perm = (flags & MOD_PROP_PERM); boolean_t get_range = (flags & MOD_PROP_POSSIBLE); --- 96,106 ---- * Retrieves property permission, default value, current value or possible * values for those properties whose value type is boolean_t. */ /* ARGSUSED */ int ! mod_get_boolean(netstack_t *stack, mod_prop_info_t *pinfo, const char *ifname, void *pval, uint_t psize, uint_t flags) { boolean_t get_def = (flags & MOD_PROP_DEFAULT); boolean_t get_perm = (flags & MOD_PROP_PERM); boolean_t get_range = (flags & MOD_PROP_POSSIBLE);
*** 126,136 **** * Modifies the value of the property to default value or to the `pval' * specified by the user. */ /* ARGSUSED */ int ! mod_set_uint32(void *cbarg, cred_t *cr, mod_prop_info_t *pinfo, const char *ifname, const void *pval, uint_t flags) { unsigned long new_value; int err; --- 145,155 ---- * Modifies the value of the property to default value or to the `pval' * specified by the user. */ /* ARGSUSED */ int ! mod_set_uint32(netstack_t *stack, cred_t *cr, mod_prop_info_t *pinfo, const char *ifname, const void *pval, uint_t flags) { unsigned long new_value; int err;
*** 143,158 **** /* * Rounds up the value to make it multiple of 8. */ /* ARGSUSED */ int ! mod_set_aligned(void *cbarg, cred_t *cr, mod_prop_info_t *pinfo, const char *ifname, const void* pval, uint_t flags) { int err; ! if ((err = mod_set_uint32(cbarg, cr, pinfo, ifname, pval, flags)) != 0) return (err); /* if required, align the value to multiple of 8 */ if (pinfo->prop_cur_uval & 0x7) { pinfo->prop_cur_uval &= ~0x7; --- 162,177 ---- /* * Rounds up the value to make it multiple of 8. */ /* ARGSUSED */ int ! mod_set_aligned(netstack_t *stack, cred_t *cr, mod_prop_info_t *pinfo, const char *ifname, const void* pval, uint_t flags) { int err; ! if ((err = mod_set_uint32(stack, cr, pinfo, ifname, pval, flags)) != 0) return (err); /* if required, align the value to multiple of 8 */ if (pinfo->prop_cur_uval & 0x7) { pinfo->prop_cur_uval &= ~0x7;
*** 166,176 **** * Retrieves property permission, default value, current value or possible * values for those properties whose value type is uint32_t. */ /* ARGSUSED */ int ! mod_get_uint32(void *cbarg, mod_prop_info_t *pinfo, const char *ifname, void *pval, uint_t psize, uint_t flags) { boolean_t get_def = (flags & MOD_PROP_DEFAULT); boolean_t get_perm = (flags & MOD_PROP_PERM); boolean_t get_range = (flags & MOD_PROP_POSSIBLE); --- 185,195 ---- * Retrieves property permission, default value, current value or possible * values for those properties whose value type is uint32_t. */ /* ARGSUSED */ int ! mod_get_uint32(netstack_t *stack, mod_prop_info_t *pinfo, const char *ifname, void *pval, uint_t psize, uint_t flags) { boolean_t get_def = (flags & MOD_PROP_DEFAULT); boolean_t get_perm = (flags & MOD_PROP_PERM); boolean_t get_range = (flags & MOD_PROP_POSSIBLE);
*** 190,214 **** return (ENOBUFS); return (0); } /* * Implements /sbin/ndd -get /dev/ip ?, for all the modules. Needed for * backward compatibility with /sbin/ndd. */ /* ARGSUSED */ int ! mod_get_allprop(void *cbarg, mod_prop_info_t *pinfo, const char *ifname, void *val, uint_t psize, uint_t flags) { char *pval = val; mod_prop_info_t *ptbl, *prop; - ip_stack_t *ipst; - tcp_stack_t *tcps; - sctp_stack_t *sctps; - udp_stack_t *us; - icmp_stack_t *is; uint_t size; size_t nbytes = 0, tbytes = 0; bzero(pval, psize); size = psize; --- 209,298 ---- return (ENOBUFS); return (0); } /* + * The range of the buffer size properties has a static lower bound configured + * in the property info structure of the property itself, and a dynamic upper + * bound. The upper bound is the current value of the "max_buf" property + * in the appropriate protocol property table. + */ + static void + mod_get_buf_prop_range(mod_prop_info_t ptbl[], mod_prop_info_t *pinfo, + uint32_t *min, uint32_t *max) + { + mod_prop_info_t *maxbuf_pinfo = mod_prop_lookup(ptbl, "max_buf", + pinfo->mpi_proto); + + *min = pinfo->prop_min_uval; + *max = maxbuf_pinfo->prop_cur_uval; + } + + /* + * Modifies the value of the buffer size property to its default value or to + * the value specified by the user. This is similar to mod_set_uint32() except + * that the value has a dynamically bounded range (see mod_get_buf_prop_range() + * for details). + */ + /* ARGSUSED */ + int + mod_set_buf_prop(mod_prop_info_t ptbl[], netstack_t *stack, cred_t *cr, + mod_prop_info_t *pinfo, const char *ifname, const void *pval, uint_t flags) + { + unsigned long new_value; + char *end; + uint32_t min, max; + + if (flags & MOD_PROP_DEFAULT) { + pinfo->prop_cur_uval = pinfo->prop_def_uval; + return (0); + } + + if (ddi_strtoul(pval, &end, 10, &new_value) != 0 || *end != '\0') + return (EINVAL); + + mod_get_buf_prop_range(ptbl, pinfo, &min, &max); + if (new_value < min || new_value > max) + return (ERANGE); + + pinfo->prop_cur_uval = new_value; + return (0); + } + + /* + * Retrieves property permissions, default value, current value, or possible + * values for buffer size properties. While these properties have integer + * values, they have a dynamic range (see mod_get_buf_prop_range() for + * details). As such, they need to be handled differently. + */ + int + mod_get_buf_prop(mod_prop_info_t ptbl[], netstack_t *stack, + mod_prop_info_t *pinfo, const char *ifname, void *pval, uint_t psize, + uint_t flags) + { + size_t nbytes; + uint32_t min, max; + + if (flags & MOD_PROP_POSSIBLE) { + mod_get_buf_prop_range(ptbl, pinfo, &min, &max); + nbytes = snprintf(pval, psize, "%u-%u", min, max); + return (nbytes < psize ? 0 : ENOBUFS); + } + return (mod_get_uint32(stack, pinfo, ifname, pval, psize, flags)); + } + + /* * Implements /sbin/ndd -get /dev/ip ?, for all the modules. Needed for * backward compatibility with /sbin/ndd. */ /* ARGSUSED */ int ! mod_get_allprop(netstack_t *stack, mod_prop_info_t *pinfo, const char *ifname, void *val, uint_t psize, uint_t flags) { char *pval = val; mod_prop_info_t *ptbl, *prop; uint_t size; size_t nbytes = 0, tbytes = 0; bzero(pval, psize); size = psize;
*** 215,242 **** switch (pinfo->mpi_proto) { case MOD_PROTO_IP: case MOD_PROTO_IPV4: case MOD_PROTO_IPV6: ! ipst = (ip_stack_t *)cbarg; ! ptbl = ipst->ips_propinfo_tbl; break; case MOD_PROTO_RAWIP: ! is = (icmp_stack_t *)cbarg; ! ptbl = is->is_propinfo_tbl; break; case MOD_PROTO_TCP: ! tcps = (tcp_stack_t *)cbarg; ! ptbl = tcps->tcps_propinfo_tbl; break; case MOD_PROTO_UDP: ! us = (udp_stack_t *)cbarg; ! ptbl = us->us_propinfo_tbl; break; case MOD_PROTO_SCTP: ! sctps = (sctp_stack_t *)cbarg; ! ptbl = sctps->sctps_propinfo_tbl; break; default: return (EINVAL); } --- 299,321 ---- switch (pinfo->mpi_proto) { case MOD_PROTO_IP: case MOD_PROTO_IPV4: case MOD_PROTO_IPV6: ! ptbl = stack->netstack_ip->ips_propinfo_tbl; break; case MOD_PROTO_RAWIP: ! ptbl = stack->netstack_icmp->is_propinfo_tbl; break; case MOD_PROTO_TCP: ! ptbl = stack->netstack_tcp->tcps_propinfo_tbl; break; case MOD_PROTO_UDP: ! ptbl = stack->netstack_udp->us_propinfo_tbl; break; case MOD_PROTO_SCTP: ! ptbl = stack->netstack_sctp->sctps_propinfo_tbl; break; default: return (EINVAL); }
*** 262,272 **** * Hold a lock while changing *_epriv_ports to prevent multiple * threads from changing it at the same time. */ /* ARGSUSED */ int ! mod_set_extra_privports(void *cbarg, cred_t *cr, mod_prop_info_t *pinfo, const char *ifname, const void* val, uint_t flags) { uint_t proto = pinfo->mpi_proto; tcp_stack_t *tcps; sctp_stack_t *sctps; --- 341,351 ---- * Hold a lock while changing *_epriv_ports to prevent multiple * threads from changing it at the same time. */ /* ARGSUSED */ int ! mod_set_extra_privports(netstack_t *stack, cred_t *cr, mod_prop_info_t *pinfo, const char *ifname, const void* val, uint_t flags) { uint_t proto = pinfo->mpi_proto; tcp_stack_t *tcps; sctp_stack_t *sctps;
*** 291,313 **** } } switch (proto) { case MOD_PROTO_TCP: ! tcps = (tcp_stack_t *)cbarg; lock = &tcps->tcps_epriv_port_lock; ports = tcps->tcps_g_epriv_ports; nports = tcps->tcps_g_num_epriv_ports; break; case MOD_PROTO_UDP: ! us = (udp_stack_t *)cbarg; lock = &us->us_epriv_port_lock; ports = us->us_epriv_ports; nports = us->us_num_epriv_ports; break; case MOD_PROTO_SCTP: ! sctps = (sctp_stack_t *)cbarg; lock = &sctps->sctps_epriv_port_lock; ports = sctps->sctps_g_epriv_ports; nports = sctps->sctps_g_num_epriv_ports; break; default: --- 370,392 ---- } } switch (proto) { case MOD_PROTO_TCP: ! tcps = stack->netstack_tcp; lock = &tcps->tcps_epriv_port_lock; ports = tcps->tcps_g_epriv_ports; nports = tcps->tcps_g_num_epriv_ports; break; case MOD_PROTO_UDP: ! us = stack->netstack_udp; lock = &us->us_epriv_port_lock; ports = us->us_epriv_ports; nports = us->us_num_epriv_ports; break; case MOD_PROTO_SCTP: ! sctps = stack->netstack_sctp; lock = &sctps->sctps_epriv_port_lock; ports = sctps->sctps_g_epriv_ports; nports = sctps->sctps_g_num_epriv_ports; break; default:
*** 380,391 **** * - the fact that the address of the array and its size never changes * - the atomic assignment of the elements of the array */ /* ARGSUSED */ int ! mod_get_extra_privports(void *cbarg, mod_prop_info_t *pinfo, const char *ifname, ! void *val, uint_t psize, uint_t flags) { uint_t proto = pinfo->mpi_proto; tcp_stack_t *tcps; sctp_stack_t *sctps; udp_stack_t *us; --- 459,470 ---- * - the fact that the address of the array and its size never changes * - the atomic assignment of the elements of the array */ /* ARGSUSED */ int ! mod_get_extra_privports(netstack_t *stack, mod_prop_info_t *pinfo, ! const char *ifname, void *val, uint_t psize, uint_t flags) { uint_t proto = pinfo->mpi_proto; tcp_stack_t *tcps; sctp_stack_t *sctps; udp_stack_t *us;
*** 409,429 **** goto ret; } switch (proto) { case MOD_PROTO_TCP: ! tcps = (tcp_stack_t *)cbarg; ports = tcps->tcps_g_epriv_ports; nports = tcps->tcps_g_num_epriv_ports; break; case MOD_PROTO_UDP: ! us = (udp_stack_t *)cbarg; ports = us->us_epriv_ports; nports = us->us_num_epriv_ports; break; case MOD_PROTO_SCTP: ! sctps = (sctp_stack_t *)cbarg; ports = sctps->sctps_g_epriv_ports; nports = sctps->sctps_g_num_epriv_ports; break; default: return (ENOTSUP); --- 488,508 ---- goto ret; } switch (proto) { case MOD_PROTO_TCP: ! tcps = stack->netstack_tcp; ports = tcps->tcps_g_epriv_ports; nports = tcps->tcps_g_num_epriv_ports; break; case MOD_PROTO_UDP: ! us = stack->netstack_udp; ports = us->us_epriv_ports; nports = us->us_num_epriv_ports; break; case MOD_PROTO_SCTP: ! sctps = stack->netstack_sctp; ports = sctps->sctps_g_epriv_ports; nports = sctps->sctps_g_num_epriv_ports; break; default: return (ENOTSUP);