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>

Split Close
Expand all
Collapse all
          --- old/usr/src/uts/common/inet/tunables.c
          +++ new/usr/src/uts/common/inet/tunables.c
↓ open down ↓ 13 lines elided ↑ open up ↑
  14   14   * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15   15   * If applicable, add the following below this CDDL HEADER, with the
  16   16   * fields enclosed by brackets "[]" replaced with your own identifying
  17   17   * information: Portions Copyright [yyyy] [name of copyright owner]
  18   18   *
  19   19   * CDDL HEADER END
  20   20   */
  21   21  /*
  22   22   * Copyright (c) 1991, 2010, Oracle and/or its affiliates. All rights reserved.
  23   23   * Copyright (c) 1990 Mentat Inc.
       24 + * Copyright (c) 2013 by Delphix. All rights reserved.
  24   25   */
  25   26  
  26   27  #include <inet/tunables.h>
  27   28  #include <sys/md5.h>
  28   29  #include <inet/common.h>
  29   30  #include <inet/ip.h>
  30   31  #include <inet/ip6.h>
  31   32  #include <netinet/icmp6.h>
  32   33  #include <inet/ip_stack.h>
  33   34  #include <inet/rawip_impl.h>
  34   35  #include <inet/tcp_stack.h>
  35   36  #include <inet/tcp_impl.h>
  36   37  #include <inet/udp_impl.h>
  37   38  #include <inet/sctp/sctp_stack.h>
  38   39  #include <inet/sctp/sctp_impl.h>
  39   40  #include <inet/tunables.h>
  40   41  
       42 +mod_prop_info_t *
       43 +mod_prop_lookup(mod_prop_info_t ptbl[], const char *prop_name, uint_t proto)
       44 +{
       45 +        mod_prop_info_t *pinfo;
       46 +
       47 +        /*
       48 +         * Walk the ptbl array looking for a property that has the requested
       49 +         * name and protocol number.  Note that we assume that all protocol
       50 +         * tables are terminated by an entry with a NULL property name.
       51 +         */
       52 +        for (pinfo = ptbl; pinfo->mpi_name != NULL; pinfo++) {
       53 +                if (strcmp(pinfo->mpi_name, prop_name) == 0 &&
       54 +                    pinfo->mpi_proto == proto)
       55 +                        return (pinfo);
       56 +        }
       57 +        return (NULL);
       58 +}
       59 +
  41   60  static int
  42   61  prop_perm2const(mod_prop_info_t *pinfo)
  43   62  {
  44   63          if (pinfo->mpi_setf == NULL)
  45   64                  return (MOD_PROP_PERM_READ);
  46   65          if (pinfo->mpi_getf == NULL)
  47   66                  return (MOD_PROP_PERM_WRITE);
  48   67          return (MOD_PROP_PERM_RW);
  49   68  }
  50   69  
  51   70  /*
  52   71   * Modifies the value of the property to default value or to the `pval'
  53   72   * specified by the user.
  54   73   */
  55   74  /* ARGSUSED */
  56   75  int
  57      -mod_set_boolean(void *cbarg, cred_t *cr, mod_prop_info_t *pinfo,
       76 +mod_set_boolean(netstack_t *stack, cred_t *cr, mod_prop_info_t *pinfo,
  58   77      const char *ifname, const void* pval, uint_t flags)
  59   78  {
  60      -        char            *end;
  61      -        unsigned long   new_value;
       79 +        char            *end;
       80 +        unsigned long   new_value;
  62   81  
  63   82          if (flags & MOD_PROP_DEFAULT) {
  64   83                  pinfo->prop_cur_bval = pinfo->prop_def_bval;
  65   84                  return (0);
  66   85          }
  67   86  
  68   87          if (ddi_strtoul(pval, &end, 10, &new_value) != 0 || *end != '\0')
  69   88                  return (EINVAL);
  70   89          if (new_value != B_TRUE && new_value != B_FALSE)
  71   90                  return (EINVAL);
  72   91          pinfo->prop_cur_bval = new_value;
  73   92          return (0);
  74   93  }
  75   94  
  76   95  /*
  77   96   * Retrieves property permission, default value, current value or possible
  78   97   * values for those properties whose value type is boolean_t.
  79   98   */
  80   99  /* ARGSUSED */
  81  100  int
  82      -mod_get_boolean(void *cbarg, mod_prop_info_t *pinfo, const char *ifname,
      101 +mod_get_boolean(netstack_t *stack, mod_prop_info_t *pinfo, const char *ifname,
  83  102      void *pval, uint_t psize, uint_t flags)
  84  103  {
  85  104          boolean_t       get_def = (flags & MOD_PROP_DEFAULT);
  86  105          boolean_t       get_perm = (flags & MOD_PROP_PERM);
  87  106          boolean_t       get_range = (flags & MOD_PROP_POSSIBLE);
  88  107          size_t          nbytes;
  89  108  
  90  109          bzero(pval, psize);
  91  110          if (get_perm)
  92  111                  nbytes = snprintf(pval, psize, "%u", prop_perm2const(pinfo));
↓ open down ↓ 28 lines elided ↑ open up ↑
 121  140          }
 122  141          return (0);
 123  142  }
 124  143  
 125  144  /*
 126  145   * Modifies the value of the property to default value or to the `pval'
 127  146   * specified by the user.
 128  147   */
 129  148  /* ARGSUSED */
 130  149  int
 131      -mod_set_uint32(void *cbarg, cred_t *cr, mod_prop_info_t *pinfo,
      150 +mod_set_uint32(netstack_t *stack, cred_t *cr, mod_prop_info_t *pinfo,
 132  151      const char *ifname, const void *pval, uint_t flags)
 133  152  {
 134  153          unsigned long   new_value;
 135  154          int             err;
 136  155  
 137  156          if ((err = mod_uint32_value(pval, pinfo, flags, &new_value)) != 0)
 138  157                  return (err);
 139  158          pinfo->prop_cur_uval = (uint32_t)new_value;
 140  159          return (0);
 141  160  }
 142  161  
 143  162  /*
 144  163   * Rounds up the value to make it multiple of 8.
 145  164   */
 146  165  /* ARGSUSED */
 147  166  int
 148      -mod_set_aligned(void *cbarg, cred_t *cr, mod_prop_info_t *pinfo,
      167 +mod_set_aligned(netstack_t *stack, cred_t *cr, mod_prop_info_t *pinfo,
 149  168      const char *ifname, const void* pval, uint_t flags)
 150  169  {
 151  170          int     err;
 152  171  
 153      -        if ((err = mod_set_uint32(cbarg, cr, pinfo, ifname, pval, flags)) != 0)
      172 +        if ((err = mod_set_uint32(stack, cr, pinfo, ifname, pval, flags)) != 0)
 154  173                  return (err);
 155  174  
 156  175          /* if required, align the value to multiple of 8 */
 157  176          if (pinfo->prop_cur_uval & 0x7) {
 158  177                  pinfo->prop_cur_uval &= ~0x7;
 159  178                  pinfo->prop_cur_uval += 0x8;
 160  179          }
 161  180  
 162  181          return (0);
 163  182  }
 164  183  
 165  184  /*
 166  185   * Retrieves property permission, default value, current value or possible
 167  186   * values for those properties whose value type is uint32_t.
 168  187   */
 169  188  /* ARGSUSED */
 170  189  int
 171      -mod_get_uint32(void *cbarg, mod_prop_info_t *pinfo, const char *ifname,
      190 +mod_get_uint32(netstack_t *stack, mod_prop_info_t *pinfo, const char *ifname,
 172  191      void *pval, uint_t psize, uint_t flags)
 173  192  {
 174  193          boolean_t       get_def = (flags & MOD_PROP_DEFAULT);
 175  194          boolean_t       get_perm = (flags & MOD_PROP_PERM);
 176  195          boolean_t       get_range = (flags & MOD_PROP_POSSIBLE);
 177  196          size_t          nbytes;
 178  197  
 179  198          bzero(pval, psize);
 180  199          if (get_perm)
 181  200                  nbytes = snprintf(pval, psize, "%u", prop_perm2const(pinfo));
↓ open down ↓ 3 lines elided ↑ open up ↑
 185  204          else if (get_def)
 186  205                  nbytes = snprintf(pval, psize, "%u", pinfo->prop_def_uval);
 187  206          else
 188  207                  nbytes = snprintf(pval, psize, "%u", pinfo->prop_cur_uval);
 189  208          if (nbytes >= psize)
 190  209                  return (ENOBUFS);
 191  210          return (0);
 192  211  }
 193  212  
 194  213  /*
      214 + * The range of the buffer size properties has a static lower bound configured
      215 + * in the property info structure of the property itself, and a dynamic upper
      216 + * bound.  The upper bound is the current value of the "max_buf" property
      217 + * in the appropriate protocol property table.
      218 + */
      219 +static void
      220 +mod_get_buf_prop_range(mod_prop_info_t ptbl[], mod_prop_info_t *pinfo,
      221 +    uint32_t *min, uint32_t *max)
      222 +{
      223 +        mod_prop_info_t *maxbuf_pinfo = mod_prop_lookup(ptbl, "max_buf",
      224 +            pinfo->mpi_proto);
      225 +
      226 +        *min = pinfo->prop_min_uval;
      227 +        *max = maxbuf_pinfo->prop_cur_uval;
      228 +}
      229 +
      230 +/*
      231 + * Modifies the value of the buffer size property to its default value or to
      232 + * the value specified by the user.  This is similar to mod_set_uint32() except
      233 + * that the value has a dynamically bounded range (see mod_get_buf_prop_range()
      234 + * for details).
      235 + */
      236 +/* ARGSUSED */
      237 +int
      238 +mod_set_buf_prop(mod_prop_info_t ptbl[], netstack_t *stack, cred_t *cr,
      239 +    mod_prop_info_t *pinfo, const char *ifname, const void *pval, uint_t flags)
      240 +{
      241 +        unsigned long   new_value;
      242 +        char            *end;
      243 +        uint32_t        min, max;
      244 +
      245 +        if (flags & MOD_PROP_DEFAULT) {
      246 +                pinfo->prop_cur_uval = pinfo->prop_def_uval;
      247 +                return (0);
      248 +        }
      249 +
      250 +        if (ddi_strtoul(pval, &end, 10, &new_value) != 0 || *end != '\0')
      251 +                return (EINVAL);
      252 +
      253 +        mod_get_buf_prop_range(ptbl, pinfo, &min, &max);
      254 +        if (new_value < min || new_value > max)
      255 +                return (ERANGE);
      256 +
      257 +        pinfo->prop_cur_uval = new_value;
      258 +        return (0);
      259 +}
      260 +
      261 +/*
      262 + * Retrieves property permissions, default value, current value, or possible
      263 + * values for buffer size properties.  While these properties have integer
      264 + * values, they have a dynamic range (see mod_get_buf_prop_range() for
      265 + * details).  As such, they need to be handled differently.
      266 + */
      267 +int
      268 +mod_get_buf_prop(mod_prop_info_t ptbl[], netstack_t *stack,
      269 +    mod_prop_info_t *pinfo, const char *ifname, void *pval, uint_t psize,
      270 +    uint_t flags)
      271 +{
      272 +        size_t nbytes;
      273 +        uint32_t min, max;
      274 +
      275 +        if (flags & MOD_PROP_POSSIBLE) {
      276 +                mod_get_buf_prop_range(ptbl, pinfo, &min, &max);
      277 +                nbytes = snprintf(pval, psize, "%u-%u", min, max);
      278 +                return (nbytes < psize ? 0 : ENOBUFS);
      279 +        }
      280 +        return (mod_get_uint32(stack, pinfo, ifname, pval, psize, flags));
      281 +}
      282 +
      283 +/*
 195  284   * Implements /sbin/ndd -get /dev/ip ?, for all the modules. Needed for
 196  285   * backward compatibility with /sbin/ndd.
 197  286   */
 198  287  /* ARGSUSED */
 199  288  int
 200      -mod_get_allprop(void *cbarg, mod_prop_info_t *pinfo, const char *ifname,
      289 +mod_get_allprop(netstack_t *stack, mod_prop_info_t *pinfo, const char *ifname,
 201  290      void *val, uint_t psize, uint_t flags)
 202  291  {
 203  292          char            *pval = val;
 204  293          mod_prop_info_t *ptbl, *prop;
 205      -        ip_stack_t      *ipst;
 206      -        tcp_stack_t     *tcps;
 207      -        sctp_stack_t    *sctps;
 208      -        udp_stack_t     *us;
 209      -        icmp_stack_t    *is;
 210  294          uint_t          size;
 211  295          size_t          nbytes = 0, tbytes = 0;
 212  296  
 213  297          bzero(pval, psize);
 214  298          size = psize;
 215  299  
 216  300          switch (pinfo->mpi_proto) {
 217  301          case MOD_PROTO_IP:
 218  302          case MOD_PROTO_IPV4:
 219  303          case MOD_PROTO_IPV6:
 220      -                ipst = (ip_stack_t *)cbarg;
 221      -                ptbl = ipst->ips_propinfo_tbl;
      304 +                ptbl = stack->netstack_ip->ips_propinfo_tbl;
 222  305                  break;
 223  306          case MOD_PROTO_RAWIP:
 224      -                is = (icmp_stack_t *)cbarg;
 225      -                ptbl = is->is_propinfo_tbl;
      307 +                ptbl = stack->netstack_icmp->is_propinfo_tbl;
 226  308                  break;
 227  309          case MOD_PROTO_TCP:
 228      -                tcps = (tcp_stack_t *)cbarg;
 229      -                ptbl = tcps->tcps_propinfo_tbl;
      310 +                ptbl = stack->netstack_tcp->tcps_propinfo_tbl;
 230  311                  break;
 231  312          case MOD_PROTO_UDP:
 232      -                us = (udp_stack_t *)cbarg;
 233      -                ptbl = us->us_propinfo_tbl;
      313 +                ptbl = stack->netstack_udp->us_propinfo_tbl;
 234  314                  break;
 235  315          case MOD_PROTO_SCTP:
 236      -                sctps = (sctp_stack_t *)cbarg;
 237      -                ptbl = sctps->sctps_propinfo_tbl;
      316 +                ptbl = stack->netstack_sctp->sctps_propinfo_tbl;
 238  317                  break;
 239  318          default:
 240  319                  return (EINVAL);
 241  320          }
 242  321  
 243  322          for (prop = ptbl; prop->mpi_name != NULL; prop++) {
 244  323                  if (prop->mpi_name[0] == '\0' ||
 245  324                      strcmp(prop->mpi_name, "?") == 0) {
 246  325                          continue;
 247  326                  }
↓ open down ↓ 9 lines elided ↑ open up ↑
 257  336          }
 258  337          return (0);
 259  338  }
 260  339  
 261  340  /*
 262  341   * Hold a lock while changing *_epriv_ports to prevent multiple
 263  342   * threads from changing it at the same time.
 264  343   */
 265  344  /* ARGSUSED */
 266  345  int
 267      -mod_set_extra_privports(void *cbarg, cred_t *cr, mod_prop_info_t *pinfo,
      346 +mod_set_extra_privports(netstack_t *stack, cred_t *cr, mod_prop_info_t *pinfo,
 268  347      const char *ifname, const void* val, uint_t flags)
 269  348  {
 270  349          uint_t          proto = pinfo->mpi_proto;
 271  350          tcp_stack_t     *tcps;
 272  351          sctp_stack_t    *sctps;
 273  352          udp_stack_t     *us;
 274  353          unsigned long   new_value;
 275  354          char            *end;
 276  355          kmutex_t        *lock;
 277  356          uint_t          i, nports;
↓ open down ↓ 8 lines elided ↑ open up ↑
 286  365                  }
 287  366  
 288  367                  if (new_value < pinfo->prop_min_uval ||
 289  368                      new_value > pinfo->prop_max_uval) {
 290  369                          return (ERANGE);
 291  370                  }
 292  371          }
 293  372  
 294  373          switch (proto) {
 295  374          case MOD_PROTO_TCP:
 296      -                tcps = (tcp_stack_t *)cbarg;
      375 +                tcps = stack->netstack_tcp;
 297  376                  lock = &tcps->tcps_epriv_port_lock;
 298  377                  ports = tcps->tcps_g_epriv_ports;
 299  378                  nports = tcps->tcps_g_num_epriv_ports;
 300  379                  break;
 301  380          case MOD_PROTO_UDP:
 302      -                us = (udp_stack_t *)cbarg;
      381 +                us = stack->netstack_udp;
 303  382                  lock = &us->us_epriv_port_lock;
 304  383                  ports = us->us_epriv_ports;
 305  384                  nports = us->us_num_epriv_ports;
 306  385                  break;
 307  386          case MOD_PROTO_SCTP:
 308      -                sctps = (sctp_stack_t *)cbarg;
      387 +                sctps = stack->netstack_sctp;
 309  388                  lock = &sctps->sctps_epriv_port_lock;
 310  389                  ports = sctps->sctps_g_epriv_ports;
 311  390                  nports = sctps->sctps_g_num_epriv_ports;
 312  391                  break;
 313  392          default:
 314  393                  return (ENOTSUP);
 315  394          }
 316  395  
 317  396          mutex_enter(lock);
 318  397  
↓ open down ↓ 56 lines elided ↑ open up ↑
 375  454  }
 376  455  
 377  456  /*
 378  457   * Note: No locks are held when inspecting *_epriv_ports
 379  458   * but instead the code relies on:
 380  459   * - the fact that the address of the array and its size never changes
 381  460   * - the atomic assignment of the elements of the array
 382  461   */
 383  462  /* ARGSUSED */
 384  463  int
 385      -mod_get_extra_privports(void *cbarg, mod_prop_info_t *pinfo, const char *ifname,
 386      -    void *val, uint_t psize, uint_t flags)
      464 +mod_get_extra_privports(netstack_t *stack, mod_prop_info_t *pinfo,
      465 +    const char *ifname, void *val, uint_t psize, uint_t flags)
 387  466  {
 388  467          uint_t          proto = pinfo->mpi_proto;
 389  468          tcp_stack_t     *tcps;
 390  469          sctp_stack_t    *sctps;
 391  470          udp_stack_t     *us;
 392  471          uint_t          i, nports, size;
 393  472          in_port_t       *ports;
 394  473          char            *pval = val;
 395  474          size_t          nbytes = 0, tbytes = 0;
 396  475          boolean_t       get_def = (flags & MOD_PROP_DEFAULT);
↓ open down ↓ 7 lines elided ↑ open up ↑
 404  483                  tbytes = snprintf(pval, psize, "%u,%u", ULP_DEF_EPRIV_PORT1,
 405  484                      ULP_DEF_EPRIV_PORT2);
 406  485                  goto ret;
 407  486          } else if (get_perm) {
 408  487                  tbytes = snprintf(pval, psize, "%u", MOD_PROP_PERM_RW);
 409  488                  goto ret;
 410  489          }
 411  490  
 412  491          switch (proto) {
 413  492          case MOD_PROTO_TCP:
 414      -                tcps = (tcp_stack_t *)cbarg;
      493 +                tcps = stack->netstack_tcp;
 415  494                  ports = tcps->tcps_g_epriv_ports;
 416  495                  nports = tcps->tcps_g_num_epriv_ports;
 417  496                  break;
 418  497          case MOD_PROTO_UDP:
 419      -                us = (udp_stack_t *)cbarg;
      498 +                us = stack->netstack_udp;
 420  499                  ports = us->us_epriv_ports;
 421  500                  nports = us->us_num_epriv_ports;
 422  501                  break;
 423  502          case MOD_PROTO_SCTP:
 424      -                sctps = (sctp_stack_t *)cbarg;
      503 +                sctps = stack->netstack_sctp;
 425  504                  ports = sctps->sctps_g_epriv_ports;
 426  505                  nports = sctps->sctps_g_num_epriv_ports;
 427  506                  break;
 428  507          default:
 429  508                  return (ENOTSUP);
 430  509          }
 431  510  
 432  511          if (get_range) {
 433  512                  tbytes = snprintf(pval, psize, "%u-%u", pinfo->prop_min_uval,
 434  513                      pinfo->prop_max_uval);
↓ open down ↓ 22 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX