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);