Print this page
    
OS-277 add ZONE column to dlstat output
    
      
        | Split | 
	Close | 
      
      | Expand all | 
      | Collapse all | 
    
    
          --- old/usr/src/cmd/dlstat/dlstat.c
          +++ new/usr/src/cmd/dlstat/dlstat.c
   1    1  /*
   2    2   * CDDL HEADER START
   3    3   *
   4    4   * The contents of this file are subject to the terms of the
   5    5   * Common Development and Distribution License (the "License").
   6    6   * You may not use this file except in compliance with the License.
   7    7   *
   8    8   * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9    9   * or http://www.opensolaris.org/os/licensing.
  10   10   * See the License for the specific language governing permissions
  11   11   * and limitations under the License.
  12   12   *
  13   13   * When distributing Covered Code, include this CDDL HEADER in each
  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 2010 Sun Microsystems, Inc.  All rights reserved.
  23   23   * Use is subject to license terms.
  24   24   */
  25   25  
  26   26  #include <stdio.h>
  27   27  #include <ctype.h>
  28   28  #include <locale.h>
  29   29  #include <signal.h>
  30   30  #include <stdarg.h>
  31   31  #include <stdlib.h>
  32   32  #include <fcntl.h>
  33   33  #include <string.h>
  34   34  #include <stropts.h>
  35   35  #include <sys/stat.h>
  36   36  #include <errno.h>
  37   37  #include <strings.h>
  38   38  #include <getopt.h>
  39   39  #include <unistd.h>
  40   40  #include <priv.h>
  41   41  #include <termios.h>
  42   42  #include <pwd.h>
  43   43  #include <auth_attr.h>
  44   44  #include <auth_list.h>
  45   45  #include <libintl.h>
  46   46  #include <libdevinfo.h>
  47   47  #include <libdlpi.h>
  48   48  #include <libdladm.h>
  49   49  #include <libdllink.h>
  50   50  #include <libdlstat.h>
  51   51  #include <libdlaggr.h>
  52   52  #include <libinetutil.h>
  53   53  #include <bsm/adt.h>
  54   54  #include <bsm/adt_event.h>
  
    | 
      ↓ open down ↓ | 
    54 lines elided | 
    
      ↑ open up ↑ | 
  
  55   55  #include <stddef.h>
  56   56  #include <ofmt.h>
  57   57  
  58   58  typedef struct link_chain_s {
  59   59          datalink_id_t           lc_linkid;
  60   60          boolean_t               lc_visited;
  61   61          dladm_stat_chain_t      *lc_statchain[DLADM_STAT_NUM_STATS];
  62   62          struct link_chain_s     *lc_next;
  63   63  } link_chain_t;
  64   64  
  65      -typedef void *  (*stats2str_t)(const char *, void *,
       65 +typedef void *  (*stats2str_t)(const char *, const char *, void *,
  66   66                      char, boolean_t);
  67   67  
  68   68  typedef struct show_state {
  69   69          link_chain_t    *ls_linkchain;
  70   70          boolean_t       ls_stattype[DLADM_STAT_NUM_STATS];
  71   71          stats2str_t     ls_stats2str[DLADM_STAT_NUM_STATS];
  72   72          ofmt_handle_t   ls_ofmt;
  73   73          char            ls_unit;
  74   74          boolean_t       ls_parsable;
  75   75  } show_state_t;
  76   76  
  77   77  typedef struct show_history_state_s {
  78   78          boolean_t       hs_plot;
  79   79          boolean_t       hs_parsable;
  80   80          boolean_t       hs_printheader;
  81   81          boolean_t       hs_first;
  82   82          boolean_t       hs_showall;
  83   83          ofmt_handle_t   hs_ofmt;
  84   84  } show_history_state_t;
  85   85  
  86   86  /*
  87   87   * callback functions for printing output and error diagnostics.
  88   88   */
  89   89  static ofmt_cb_t print_default_cb;
  90   90  
  91   91  static void dlstat_ofmt_check(ofmt_status_t, boolean_t, ofmt_handle_t);
  92   92  
  93   93  typedef void cmdfunc_t(int, char **, const char *);
  94   94  
  95   95  static cmdfunc_t do_show, do_show_history, do_show_phys, do_show_link;
  96   96  static cmdfunc_t do_show_aggr;
  97   97  
  98   98  static void     die(const char *, ...);
  99   99  static void     die_optdup(int);
 100  100  static void     die_opterr(int, int, const char *);
 101  101  static void     die_dlerr(dladm_status_t, const char *, ...);
 102  102  static void     warn(const char *, ...);
 103  103  
 104  104  typedef struct  cmd {
 105  105          char            *c_name;
 106  106          cmdfunc_t       *c_fn;
 107  107          const char      *c_usage;
 108  108  } cmd_t;
 109  109  
 110  110  static cmd_t    cmds[] = {
 111  111          { "",           do_show,
 112  112              "dlstat [-r | -t] [-i <interval>] [link]\n"
 113  113              "       dlstat [-a | -A] [-i <interval>] [-p] [ -o field[,...]]\n"
 114  114              "              [-u R|K|M|G|T|P] [link]"},
 115  115          { "show-phys", do_show_phys,
 116  116              "dlstat show-phys [-r | -t] [-i interval] [-a]\n"
 117  117              "                 [-p] [ -o field[,...]] [-u R|K|M|G|T|P] "
 118  118              "[link]"},
 119  119          { "show-link", do_show_link,
 120  120              "dlstat show-link [-r [-F] | -t] [-i interval] [-a]\n"
 121  121              "                 [-p] [ -o field[,...]] [-u R|K|M|G|T|P] "
 122  122              "[link]\n"
 123  123              "       dlstat show-link -h [-a] [-d] [-F <format>]\n"
 124  124              "                 [-s <DD/MM/YYYY,HH:MM:SS>] "
 125  125              "[-e <DD/MM/YYYY,HH:MM:SS>]\n"
 126  126              "                 -f <logfile> [<link>]" },
 127  127          { "show-aggr", do_show_aggr,
 128  128              "dlstat show-aggr [-r | -t] [-i interval] [-p]\n"
 129  129              "                 [ -o field[,...]] [-u R|K|M|G|T|P] "
 130  130              " [link]" }
 131  131  };
 132  132  
 133  133  #define MAXSTATLEN 15
  
    | 
      ↓ open down ↓ | 
    58 lines elided | 
    
      ↑ open up ↑ | 
  
 134  134  
 135  135  /*
 136  136   * dlstat : total stat fields
 137  137   */
 138  138  typedef struct total_fields_buf_s {
 139  139          char t_linkname[MAXLINKNAMELEN];
 140  140          char t_ipackets[MAXSTATLEN];
 141  141          char t_rbytes[MAXSTATLEN];
 142  142          char t_opackets[MAXSTATLEN];
 143  143          char t_obytes[MAXSTATLEN];
      144 +        char t_zone[ZONENAME_MAX];
 144  145  } total_fields_buf_t;
 145  146  
 146  147  static ofmt_field_t total_s_fields[] = {
 147  148  { "LINK",       15,
 148  149      offsetof(total_fields_buf_t, t_linkname),   print_default_cb},
 149  150  { "IPKTS",      8,
 150  151      offsetof(total_fields_buf_t, t_ipackets),   print_default_cb},
 151  152  { "RBYTES",     8,
 152  153      offsetof(total_fields_buf_t, t_rbytes),     print_default_cb},
 153  154  { "OPKTS",      8,
 154  155      offsetof(total_fields_buf_t, t_opackets),   print_default_cb},
 155  156  { "OBYTES",     8,
 156  157      offsetof(total_fields_buf_t, t_obytes),     print_default_cb},
      158 +{ "ZONE",       20,
      159 +    offsetof(total_fields_buf_t, t_zone),       print_default_cb},
 157  160  { NULL,         0,      0,              NULL}};
 158  161  
 159  162  /*
 160  163   * dlstat show-phys: both Rx and Tx stat fields
 161  164   */
 162  165  typedef struct ring_fields_buf_s {
 163  166          char r_linkname[MAXLINKNAMELEN];
 164  167          char r_type[MAXSTATLEN];
 165  168          char r_id[MAXSTATLEN];
 166  169          char r_index[MAXSTATLEN];
 167  170          char r_packets[MAXSTATLEN];
 168  171          char r_bytes[MAXSTATLEN];
 169  172  } ring_fields_buf_t;
 170  173  
 171  174  static ofmt_field_t ring_s_fields[] = {
 172  175  { "LINK",       15,
 173  176      offsetof(ring_fields_buf_t, r_linkname),    print_default_cb},
 174  177  { "TYPE",       5,
 175  178      offsetof(ring_fields_buf_t, r_type),        print_default_cb},
 176  179  { "ID",         7,
 177  180      offsetof(ring_fields_buf_t, r_id),          print_default_cb},
 178  181  { "INDEX",      6,
 179  182      offsetof(ring_fields_buf_t, r_index),       print_default_cb},
 180  183  { "PKTS",       8,
 181  184      offsetof(ring_fields_buf_t, r_packets),     print_default_cb},
 182  185  { "BYTES",      8,
 183  186      offsetof(ring_fields_buf_t, r_bytes),       print_default_cb},
 184  187  { NULL,         0,              0,              NULL}};
 185  188  
 186  189  /*
 187  190   * dlstat show-phys -r: Rx Ring stat fields
 188  191   */
 189  192  typedef struct rx_ring_fields_buf_s {
 190  193          char rr_linkname[MAXLINKNAMELEN];
 191  194          char rr_type[MAXSTATLEN];
 192  195          char rr_id[MAXSTATLEN];
 193  196          char rr_index[MAXSTATLEN];
 194  197          char rr_ipackets[MAXSTATLEN];
 195  198          char rr_rbytes[MAXSTATLEN];
 196  199  } rx_ring_fields_buf_t;
 197  200  
 198  201  static ofmt_field_t rx_ring_s_fields[] = {
 199  202  { "LINK",       15,
 200  203      offsetof(rx_ring_fields_buf_t, rr_linkname),        print_default_cb},
 201  204  { "TYPE",       5,
 202  205      offsetof(rx_ring_fields_buf_t, rr_type),            print_default_cb},
 203  206  { "ID",         7,
 204  207      offsetof(rx_ring_fields_buf_t, rr_id),              print_default_cb},
 205  208  { "INDEX",      6,
 206  209      offsetof(rx_ring_fields_buf_t, rr_index),           print_default_cb},
 207  210  { "IPKTS",      8,
 208  211      offsetof(rx_ring_fields_buf_t, rr_ipackets),        print_default_cb},
 209  212  { "RBYTES",     8,
 210  213      offsetof(rx_ring_fields_buf_t, rr_rbytes),          print_default_cb},
 211  214  { NULL,         0,              0,              NULL}};
 212  215  
 213  216  /*
 214  217   * dlstat show-phys -t: Tx Ring stat fields
 215  218   */
 216  219  typedef struct tx_ring_fields_buf_s {
 217  220          char tr_linkname[MAXLINKNAMELEN];
 218  221          char tr_type[MAXSTATLEN];
 219  222          char tr_id[MAXSTATLEN];
 220  223          char tr_index[MAXSTATLEN];
 221  224          char tr_opackets[MAXSTATLEN];
 222  225          char tr_obytes[MAXSTATLEN];
 223  226  } tx_ring_fields_buf_t;
 224  227  
 225  228  static ofmt_field_t tx_ring_s_fields[] = {
 226  229  { "LINK",       15,
 227  230      offsetof(tx_ring_fields_buf_t, tr_linkname),        print_default_cb},
 228  231  { "TYPE",       5,
 229  232      offsetof(tx_ring_fields_buf_t, tr_type),            print_default_cb},
 230  233  { "ID",         7,
 231  234      offsetof(tx_ring_fields_buf_t, tr_id),              print_default_cb},
 232  235  { "INDEX",      6,
 233  236      offsetof(tx_ring_fields_buf_t, tr_index),           print_default_cb},
 234  237  { "OPKTS",      8,
 235  238      offsetof(tx_ring_fields_buf_t, tr_opackets),        print_default_cb},
 236  239  { "OBYTES",     8,
 237  240      offsetof(tx_ring_fields_buf_t, tr_obytes),          print_default_cb},
 238  241  { NULL,         0,              0,              NULL}};
 239  242  
 240  243  /*
 241  244   * dlstat show-link: both Rx and Tx lane fields
 242  245   */
 243  246  typedef struct lane_fields_buf_s {
 244  247          char l_linkname[MAXLINKNAMELEN];
 245  248          char l_type[MAXSTATLEN];
 246  249          char l_id[MAXSTATLEN];
 247  250          char l_index[MAXSTATLEN];
 248  251          char l_packets[MAXSTATLEN];
 249  252          char l_bytes[MAXSTATLEN];
 250  253  } lane_fields_buf_t;
 251  254  
 252  255  static ofmt_field_t lane_s_fields[] = {
 253  256  { "LINK",       15,
 254  257      offsetof(lane_fields_buf_t, l_linkname),    print_default_cb},
 255  258  { "TYPE",       5,
 256  259      offsetof(lane_fields_buf_t, l_type),        print_default_cb},
 257  260  { "ID",         7,
 258  261      offsetof(lane_fields_buf_t, l_id),          print_default_cb},
 259  262  { "INDEX",      6,
 260  263      offsetof(lane_fields_buf_t, l_index),       print_default_cb},
 261  264  { "PKTS",       8,
 262  265      offsetof(lane_fields_buf_t, l_packets),     print_default_cb},
 263  266  { "BYTES",      8,
 264  267      offsetof(lane_fields_buf_t, l_bytes),       print_default_cb},
 265  268  { NULL,         0,              0,              NULL}};
 266  269  
 267  270  /*
 268  271   * dlstat show-link -r, dlstat -r: Rx Lane stat fields
 269  272   */
 270  273  typedef struct rx_lane_fields_buf_s {
 271  274          char rl_linkname[MAXLINKNAMELEN];
 272  275          char rl_type[MAXSTATLEN];
 273  276          char rl_id[MAXSTATLEN];
 274  277          char rl_index[MAXSTATLEN];
 275  278          char rl_ipackets[MAXSTATLEN];
 276  279          char rl_rbytes[MAXSTATLEN];
 277  280          char rl_intrs[MAXSTATLEN];
 278  281          char rl_polls[MAXSTATLEN];
 279  282          char rl_sdrops[MAXSTATLEN];
 280  283          char rl_chl10[MAXSTATLEN];
 281  284          char rl_ch10_50[MAXSTATLEN];
 282  285          char rl_chg50[MAXSTATLEN];
 283  286  } rx_lane_fields_buf_t;
 284  287  
 285  288  static ofmt_field_t rx_lane_s_fields[] = {
 286  289  { "LINK",       10,
 287  290      offsetof(rx_lane_fields_buf_t, rl_linkname),        print_default_cb},
 288  291  { "TYPE",       5,
 289  292      offsetof(rx_lane_fields_buf_t, rl_type),            print_default_cb},
 290  293  { "ID",         7,
 291  294      offsetof(rx_lane_fields_buf_t, rl_id),              print_default_cb},
 292  295  { "INDEX",      6,
 293  296      offsetof(rx_lane_fields_buf_t, rl_index),           print_default_cb},
 294  297  { "IPKTS",      8,
 295  298      offsetof(rx_lane_fields_buf_t, rl_ipackets),        print_default_cb},
 296  299  { "RBYTES",     8,
 297  300      offsetof(rx_lane_fields_buf_t, rl_rbytes),          print_default_cb},
 298  301  { "INTRS",      8,
 299  302      offsetof(rx_lane_fields_buf_t, rl_intrs),           print_default_cb},
 300  303  { "POLLS",      8,
 301  304      offsetof(rx_lane_fields_buf_t, rl_polls),           print_default_cb},
 302  305  { "SDROPS",     8,
 303  306      offsetof(rx_lane_fields_buf_t, rl_sdrops),          print_default_cb},
 304  307  { "CH<10",      8,
 305  308      offsetof(rx_lane_fields_buf_t, rl_chl10),           print_default_cb},
 306  309  { "CH10-50",    8,
 307  310      offsetof(rx_lane_fields_buf_t, rl_ch10_50),         print_default_cb},
 308  311  { "CH>50",      8,
 309  312      offsetof(rx_lane_fields_buf_t, rl_chg50),           print_default_cb},
 310  313  { NULL,         0,              0,              NULL}};
 311  314  
 312  315  /*
 313  316   * dlstat show-link -r -F: Rx fanout stat fields
 314  317   */
 315  318  typedef struct rx_fanout_lane_fields_buf_s {
 316  319          char rfl_linkname[MAXLINKNAMELEN];
 317  320          char rfl_type[MAXSTATLEN];
 318  321          char rfl_id[MAXSTATLEN];
 319  322          char rfl_index[MAXSTATLEN];
 320  323          char rfl_fout[MAXSTATLEN];
 321  324          char rfl_ipackets[MAXSTATLEN];
 322  325          char rfl_rbytes[MAXSTATLEN];
 323  326  } rx_fanout_lane_fields_buf_t;
 324  327  
 325  328  static ofmt_field_t rx_fanout_lane_s_fields[] = {
 326  329  { "LINK",       15,
 327  330      offsetof(rx_fanout_lane_fields_buf_t, rfl_linkname), print_default_cb},
 328  331  { "TYPE",       5,
 329  332      offsetof(rx_fanout_lane_fields_buf_t, rfl_type),    print_default_cb},
 330  333  { "ID",         7,
 331  334      offsetof(rx_fanout_lane_fields_buf_t, rfl_id),      print_default_cb},
 332  335  { "INDEX",      6,
 333  336      offsetof(rx_fanout_lane_fields_buf_t, rfl_index),   print_default_cb},
 334  337  { "FOUT",       6,
 335  338      offsetof(rx_fanout_lane_fields_buf_t, rfl_fout),    print_default_cb},
 336  339  { "IPKTS",      8,
 337  340      offsetof(rx_fanout_lane_fields_buf_t, rfl_ipackets), print_default_cb},
 338  341  { "RBYTES",     8,
 339  342      offsetof(rx_fanout_lane_fields_buf_t, rfl_rbytes),  print_default_cb},
 340  343  { NULL,         0,              0,              NULL}};
 341  344  
 342  345  /*
 343  346   * dlstat show-link -t: Tx Lane stat fields
 344  347   */
 345  348  typedef struct tx_lane_fields_buf_s {
 346  349          char tl_linkname[MAXLINKNAMELEN];
 347  350          char tl_index[MAXSTATLEN];
 348  351          char tl_type[MAXSTATLEN];
 349  352          char tl_id[MAXSTATLEN];
 350  353          char tl_opackets[MAXSTATLEN];
 351  354          char tl_obytes[MAXSTATLEN];
 352  355          char tl_blockcnt[MAXSTATLEN];
 353  356          char tl_unblockcnt[MAXSTATLEN];
 354  357          char tl_sdrops[MAXSTATLEN];
 355  358  } tx_lane_fields_buf_t;
 356  359  
 357  360  static ofmt_field_t tx_lane_s_fields[] = {
 358  361  { "LINK",       15,
 359  362      offsetof(tx_lane_fields_buf_t, tl_linkname),        print_default_cb},
 360  363  { "TYPE",       5,
 361  364      offsetof(tx_lane_fields_buf_t, tl_type),            print_default_cb},
 362  365  { "ID",         7,
 363  366      offsetof(tx_lane_fields_buf_t, tl_id),              print_default_cb},
 364  367  { "INDEX",      6,
 365  368      offsetof(tx_lane_fields_buf_t, tl_index),           print_default_cb},
 366  369  { "OPKTS",      8,
 367  370      offsetof(tx_lane_fields_buf_t, tl_opackets),        print_default_cb},
 368  371  { "OBYTES",     8,
 369  372      offsetof(tx_lane_fields_buf_t, tl_obytes),          print_default_cb},
 370  373  { "BLKCNT",     8,
 371  374      offsetof(tx_lane_fields_buf_t, tl_blockcnt),        print_default_cb},
 372  375  { "UBLKCNT",    8,
 373  376      offsetof(tx_lane_fields_buf_t, tl_unblockcnt),      print_default_cb},
 374  377  { "SDROPS",     8,
 375  378      offsetof(tx_lane_fields_buf_t, tl_sdrops),          print_default_cb},
 376  379  { NULL,         0,              0,              NULL}};
 377  380  
 378  381  /*
 379  382   * dlstat show-aggr: aggr port stat fields
 380  383   */
 381  384  typedef struct aggr_port_fields_buf_s {
 382  385          char ap_linkname[MAXLINKNAMELEN];
 383  386          char ap_portname[MAXLINKNAMELEN];
 384  387          char ap_ipackets[MAXSTATLEN];
 385  388          char ap_rbytes[MAXSTATLEN];
 386  389          char ap_opackets[MAXSTATLEN];
 387  390          char ap_obytes[MAXSTATLEN];
 388  391  } aggr_port_fields_buf_t;
 389  392  
 390  393  static ofmt_field_t aggr_port_s_fields[] = {
 391  394  { "LINK",       15,
 392  395      offsetof(aggr_port_fields_buf_t, ap_linkname),      print_default_cb},
 393  396  { "PORT",       15,
 394  397      offsetof(aggr_port_fields_buf_t, ap_portname),      print_default_cb},
 395  398  { "IPKTS",      8,
 396  399      offsetof(aggr_port_fields_buf_t, ap_ipackets),      print_default_cb},
 397  400  { "RBYTES",     8,
 398  401      offsetof(aggr_port_fields_buf_t, ap_rbytes),        print_default_cb},
 399  402  { "OPKTS",      8,
 400  403      offsetof(aggr_port_fields_buf_t, ap_opackets),      print_default_cb},
 401  404  { "OBYTES",     8,
 402  405      offsetof(aggr_port_fields_buf_t, ap_obytes),        print_default_cb},
 403  406  { NULL,         0,              0,              NULL}};
 404  407  
 405  408  /*
 406  409   * structures for 'dlstat show-link -h'
 407  410   */
 408  411  typedef struct  history_fields_buf_s {
 409  412          char    h_link[12];
 410  413          char    h_duration[10];
 411  414          char    h_ipackets[9];
 412  415          char    h_rbytes[10];
 413  416          char    h_opackets[9];
 414  417          char    h_obytes[10];
 415  418          char    h_bandwidth[14];
 416  419  } history_fields_buf_t;
 417  420  
 418  421  static ofmt_field_t history_fields[] = {
 419  422  { "LINK",       13,
 420  423          offsetof(history_fields_buf_t, h_link), print_default_cb},
 421  424  { "DURATION",   11,
 422  425          offsetof(history_fields_buf_t, h_duration), print_default_cb},
 423  426  { "IPKTS",      10,
 424  427          offsetof(history_fields_buf_t, h_ipackets), print_default_cb},
 425  428  { "RBYTES",     11,
 426  429          offsetof(history_fields_buf_t, h_rbytes), print_default_cb},
 427  430  { "OPKTS",      10,
 428  431          offsetof(history_fields_buf_t, h_opackets), print_default_cb},
 429  432  { "OBYTES",     11,
 430  433          offsetof(history_fields_buf_t, h_obytes), print_default_cb},
 431  434  { "BANDWIDTH",  15,
 432  435          offsetof(history_fields_buf_t, h_bandwidth), print_default_cb},
 433  436  { NULL,         0, 0, NULL}};
 434  437  
 435  438  /*
 436  439   * structures for 'dlstat show-link -h link'
 437  440   */
 438  441  typedef struct  history_l_fields_buf_s {
 439  442          char    hl_link[12];
 440  443          char    hl_stime[13];
 441  444          char    hl_etime[13];
 442  445          char    hl_rbytes[8];
 443  446          char    hl_obytes[8];
 444  447          char    hl_bandwidth[14];
 445  448  } history_l_fields_buf_t;
 446  449  
 447  450  static ofmt_field_t history_l_fields[] = {
 448  451  /* name,        field width,    offset */
 449  452  { "LINK",       13,
 450  453          offsetof(history_l_fields_buf_t, hl_link), print_default_cb},
 451  454  { "START",      14,
 452  455          offsetof(history_l_fields_buf_t, hl_stime), print_default_cb},
 453  456  { "END",        14,
 454  457          offsetof(history_l_fields_buf_t, hl_etime), print_default_cb},
 455  458  { "RBYTES",     9,
 456  459          offsetof(history_l_fields_buf_t, hl_rbytes), print_default_cb},
 457  460  { "OBYTES",     9,
 458  461          offsetof(history_l_fields_buf_t, hl_obytes), print_default_cb},
 459  462  { "BANDWIDTH",  15,
 460  463          offsetof(history_l_fields_buf_t, hl_bandwidth), print_default_cb},
 461  464  { NULL,         0, 0, NULL}}
 462  465  ;
 463  466  
 464  467  static char *progname;
 465  468  
 466  469  /*
 467  470   * Handle to libdladm.  Opened in main() before the sub-command
 468  471   * specific function is called.
 469  472   */
 470  473  static dladm_handle_t handle = NULL;
 471  474  
 472  475  static void
 473  476  usage(void)
 474  477  {
 475  478          int     i;
 476  479          cmd_t   *cmdp;
 477  480  
 478  481          (void) fprintf(stderr, gettext("usage: "));
 479  482          for (i = 0; i < sizeof (cmds) / sizeof (cmds[0]); i++) {
 480  483                  cmdp = &cmds[i];
 481  484                  if (cmdp->c_usage != NULL)
 482  485                          (void) fprintf(stderr, "%s\n", gettext(cmdp->c_usage));
 483  486          }
 484  487  
 485  488          /* close dladm handle if it was opened */
 486  489          if (handle != NULL)
 487  490                  dladm_close(handle);
 488  491  
 489  492          exit(1);
 490  493  }
 491  494  
 492  495  int
 493  496  main(int argc, char *argv[])
 494  497  {
 495  498          int             i;
 496  499          cmd_t           *cmdp;
 497  500          dladm_status_t  status;
 498  501  
 499  502          (void) setlocale(LC_ALL, "");
 500  503  #if !defined(TEXT_DOMAIN)
 501  504  #define TEXT_DOMAIN "SYS_TEST"
 502  505  #endif
 503  506          (void) textdomain(TEXT_DOMAIN);
 504  507  
 505  508          progname = argv[0];
 506  509  
 507  510          /* Open the libdladm handle */
 508  511          if ((status = dladm_open(&handle)) != DLADM_STATUS_OK)
 509  512                  die_dlerr(status, "could not open /dev/dld");
 510  513  
 511  514          if (argc == 1) {
 512  515                  do_show(argc - 1, NULL, cmds[0].c_usage);
 513  516                  goto done;
 514  517          }
 515  518  
 516  519          for (i = 0; i < sizeof (cmds) / sizeof (cmds[0]); i++) {
 517  520                  cmdp = &cmds[i];
 518  521                  if (strcmp(argv[1], cmdp->c_name) == 0) {
 519  522                          cmdp->c_fn(argc - 1, &argv[1], cmdp->c_usage);
 520  523                          goto done;
 521  524                  }
 522  525          }
 523  526  
 524  527          do_show(argc, &argv[0], cmds[0].c_usage);
 525  528  
 526  529  done:
 527  530          dladm_close(handle);
 528  531          return (0);
 529  532  }
 530  533  
 531  534  /*ARGSUSED*/
 532  535  static int
 533  536  show_history_date(dladm_usage_t *history, void *arg)
 534  537  {
 535  538          show_history_state_t    *state = arg;
 536  539          time_t                  stime;
 537  540          char                    timebuf[20];
 538  541          dladm_status_t          status;
 539  542          uint32_t                flags;
 540  543  
 541  544          /*
 542  545           * Only show history information for existing links unless '-a'
 543  546           * is specified.
 544  547           */
 545  548          if (!state->hs_showall) {
 546  549                  if ((status = dladm_name2info(handle, history->du_name,
 547  550                      NULL, &flags, NULL, NULL)) != DLADM_STATUS_OK) {
 548  551                          return (status);
 549  552                  }
 550  553                  if ((flags & DLADM_OPT_ACTIVE) == 0)
 551  554                          return (DLADM_STATUS_LINKINVAL);
 552  555          }
 553  556  
 554  557          stime = history->du_stime;
 555  558          (void) strftime(timebuf, sizeof (timebuf), "%m/%d/%Y",
 556  559              localtime(&stime));
 557  560          (void) printf("%s\n", timebuf);
 558  561  
 559  562          return (DLADM_STATUS_OK);
 560  563  }
 561  564  
 562  565  static int
 563  566  show_history_time(dladm_usage_t *history, void *arg)
 564  567  {
 565  568          show_history_state_t    *state = arg;
 566  569          char                    buf[DLADM_STRSIZE];
 567  570          history_l_fields_buf_t  ubuf;
 568  571          time_t                  time;
 569  572          double                  bw;
 570  573          dladm_status_t          status;
 571  574          uint32_t                flags;
 572  575  
 573  576          /*
 574  577           * Only show history information for existing links unless '-a'
 575  578           * is specified.
 576  579           */
 577  580          if (!state->hs_showall) {
 578  581                  if ((status = dladm_name2info(handle, history->du_name,
 579  582                      NULL, &flags, NULL, NULL)) != DLADM_STATUS_OK) {
 580  583                          return (status);
 581  584                  }
 582  585                  if ((flags & DLADM_OPT_ACTIVE) == 0)
 583  586                          return (DLADM_STATUS_LINKINVAL);
 584  587          }
 585  588  
 586  589          if (state->hs_plot) {
 587  590                  if (!state->hs_printheader) {
 588  591                          if (state->hs_first) {
 589  592                                  (void) printf("# Time");
 590  593                                  state->hs_first = B_FALSE;
 591  594                          }
 592  595                          (void) printf(" %s", history->du_name);
 593  596                          if (history->du_last) {
 594  597                                  (void) printf("\n");
 595  598                                  state->hs_first = B_TRUE;
 596  599                                  state->hs_printheader = B_TRUE;
 597  600                          }
 598  601                  } else {
 599  602                          if (state->hs_first) {
 600  603                                  time = history->du_etime;
 601  604                                  (void) strftime(buf, sizeof (buf), "%T",
 602  605                                      localtime(&time));
 603  606                                  state->hs_first = B_FALSE;
 604  607                                  (void) printf("%s", buf);
 605  608                          }
 606  609                          bw = (double)history->du_bandwidth/1000;
 607  610                          (void) printf(" %.2f", bw);
 608  611                          if (history->du_last) {
 609  612                                  (void) printf("\n");
 610  613                                  state->hs_first = B_TRUE;
 611  614                          }
 612  615                  }
 613  616                  return (DLADM_STATUS_OK);
 614  617          }
 615  618  
 616  619          bzero(&ubuf, sizeof (ubuf));
 617  620  
 618  621          (void) snprintf(ubuf.hl_link, sizeof (ubuf.hl_link), "%s",
 619  622              history->du_name);
 620  623          time = history->du_stime;
 621  624          (void) strftime(buf, sizeof (buf), "%T", localtime(&time));
 622  625          (void) snprintf(ubuf.hl_stime, sizeof (ubuf.hl_stime), "%s",
 623  626              buf);
 624  627          time = history->du_etime;
 625  628          (void) strftime(buf, sizeof (buf), "%T", localtime(&time));
 626  629          (void) snprintf(ubuf.hl_etime, sizeof (ubuf.hl_etime), "%s",
 627  630              buf);
 628  631          (void) snprintf(ubuf.hl_rbytes, sizeof (ubuf.hl_rbytes),
 629  632              "%llu", history->du_rbytes);
 630  633          (void) snprintf(ubuf.hl_obytes, sizeof (ubuf.hl_obytes),
 631  634              "%llu", history->du_obytes);
 632  635          (void) snprintf(ubuf.hl_bandwidth, sizeof (ubuf.hl_bandwidth),
 633  636              "%s Mbps", dladm_bw2str(history->du_bandwidth, buf));
 634  637  
 635  638          ofmt_print(state->hs_ofmt, &ubuf);
 636  639          return (DLADM_STATUS_OK);
 637  640  }
 638  641  
 639  642  static int
 640  643  show_history_res(dladm_usage_t *history, void *arg)
 641  644  {
 642  645          show_history_state_t    *state = arg;
 643  646          char                    buf[DLADM_STRSIZE];
 644  647          history_fields_buf_t    ubuf;
 645  648          dladm_status_t          status;
 646  649          uint32_t                flags;
 647  650  
 648  651          /*
 649  652           * Only show history information for existing links unless '-a'
 650  653           * is specified.
 651  654           */
 652  655          if (!state->hs_showall) {
 653  656                  if ((status = dladm_name2info(handle, history->du_name,
 654  657                      NULL, &flags, NULL, NULL)) != DLADM_STATUS_OK) {
 655  658                          return (status);
 656  659                  }
 657  660                  if ((flags & DLADM_OPT_ACTIVE) == 0)
 658  661                          return (DLADM_STATUS_LINKINVAL);
 659  662          }
 660  663  
 661  664          bzero(&ubuf, sizeof (ubuf));
 662  665  
 663  666          (void) snprintf(ubuf.h_link, sizeof (ubuf.h_link), "%s",
 664  667              history->du_name);
 665  668          (void) snprintf(ubuf.h_duration, sizeof (ubuf.h_duration),
 666  669              "%llu", history->du_duration);
 667  670          (void) snprintf(ubuf.h_ipackets, sizeof (ubuf.h_ipackets),
 668  671              "%llu", history->du_ipackets);
 669  672          (void) snprintf(ubuf.h_rbytes, sizeof (ubuf.h_rbytes),
 670  673              "%llu", history->du_rbytes);
 671  674          (void) snprintf(ubuf.h_opackets, sizeof (ubuf.h_opackets),
 672  675              "%llu", history->du_opackets);
 673  676          (void) snprintf(ubuf.h_obytes, sizeof (ubuf.h_obytes),
 674  677              "%llu", history->du_obytes);
 675  678          (void) snprintf(ubuf.h_bandwidth, sizeof (ubuf.h_bandwidth),
 676  679              "%s Mbps", dladm_bw2str(history->du_bandwidth, buf));
 677  680  
 678  681          ofmt_print(state->hs_ofmt, &ubuf);
 679  682  
 680  683          return (DLADM_STATUS_OK);
 681  684  }
 682  685  
 683  686  static boolean_t
 684  687  valid_formatspec(char *formatspec_str)
 685  688  {
 686  689          return (strcmp(formatspec_str, "gnuplot") == 0);
 687  690  }
 688  691  
 689  692  /*ARGSUSED*/
 690  693  static void
 691  694  do_show_history(int argc, char *argv[], const char *use)
 692  695  {
 693  696          char                    *file = NULL;
 694  697          int                     opt;
 695  698          dladm_status_t          status;
 696  699          boolean_t               d_arg = B_FALSE;
 697  700          char                    *stime = NULL;
 698  701          char                    *etime = NULL;
 699  702          char                    *resource = NULL;
 700  703          show_history_state_t    state;
 701  704          boolean_t               o_arg = B_FALSE;
 702  705          boolean_t               F_arg = B_FALSE;
 703  706          char                    *fields_str = NULL;
 704  707          char                    *formatspec_str = NULL;
 705  708          char                    *all_l_fields =
 706  709              "link,start,end,rbytes,obytes,bandwidth";
 707  710          ofmt_handle_t           ofmt;
 708  711          ofmt_status_t           oferr;
 709  712          uint_t                  ofmtflags = 0;
 710  713  
 711  714          bzero(&state, sizeof (show_history_state_t));
 712  715          state.hs_parsable = B_FALSE;
 713  716          state.hs_printheader = B_FALSE;
 714  717          state.hs_plot = B_FALSE;
 715  718          state.hs_first = B_TRUE;
 716  719  
 717  720          while ((opt = getopt(argc, argv, "das:e:o:f:F:")) != -1) {
 718  721                  switch (opt) {
 719  722                  case 'd':
 720  723                          d_arg = B_TRUE;
 721  724                          break;
 722  725                  case 'a':
 723  726                          state.hs_showall = B_TRUE;
 724  727                          break;
 725  728                  case 'f':
 726  729                          file = optarg;
 727  730                          break;
 728  731                  case 's':
 729  732                          stime = optarg;
 730  733                          break;
 731  734                  case 'e':
 732  735                          etime = optarg;
 733  736                          break;
 734  737                  case 'o':
 735  738                          o_arg = B_TRUE;
 736  739                          fields_str = optarg;
 737  740                          break;
 738  741                  case 'F':
 739  742                          state.hs_plot = F_arg = B_TRUE;
 740  743                          formatspec_str = optarg;
 741  744                          break;
 742  745                  default:
 743  746                          die_opterr(optopt, opt, use);
 744  747                          break;
 745  748                  }
 746  749          }
 747  750  
 748  751          if (file == NULL)
 749  752                  die("show-link -h requires a file");
 750  753  
 751  754          if (optind == (argc-1)) {
 752  755                  uint32_t        flags;
 753  756  
 754  757                  resource = argv[optind];
 755  758                  if (!state.hs_showall &&
 756  759                      (((status = dladm_name2info(handle, resource, NULL, &flags,
 757  760                      NULL, NULL)) != DLADM_STATUS_OK) ||
 758  761                      ((flags & DLADM_OPT_ACTIVE) == 0))) {
 759  762                          die("invalid link: '%s'", resource);
 760  763                  }
 761  764          }
 762  765  
 763  766          if (F_arg && d_arg)
 764  767                  die("incompatible -d and -F options");
 765  768  
 766  769          if (F_arg && !valid_formatspec(formatspec_str))
 767  770                  die("Format specifier %s not supported", formatspec_str);
 768  771  
 769  772          if (state.hs_parsable)
 770  773                  ofmtflags |= OFMT_PARSABLE;
 771  774  
 772  775          if (resource == NULL && stime == NULL && etime == NULL) {
 773  776                  oferr = ofmt_open(fields_str, history_fields, ofmtflags, 0,
 774  777                      &ofmt);
 775  778          } else {
 776  779                  if (!o_arg || (o_arg && strcasecmp(fields_str, "all") == 0))
 777  780                          fields_str = all_l_fields;
 778  781                  oferr = ofmt_open(fields_str, history_l_fields, ofmtflags, 0,
 779  782                      &ofmt);
 780  783  
 781  784          }
 782  785          dlstat_ofmt_check(oferr, state.hs_parsable, ofmt);
 783  786          state.hs_ofmt = ofmt;
 784  787  
 785  788          if (d_arg) {
 786  789                  /* Print log dates */
 787  790                  status = dladm_usage_dates(show_history_date,
 788  791                      DLADM_LOGTYPE_LINK, file, resource, &state);
 789  792          } else if (resource == NULL && stime == NULL && etime == NULL &&
 790  793              !F_arg) {
 791  794                  /* Print summary */
 792  795                  status = dladm_usage_summary(show_history_res,
 793  796                      DLADM_LOGTYPE_LINK, file, &state);
 794  797          } else if (resource != NULL) {
 795  798                  /* Print log entries for named resource */
 796  799                  status = dladm_walk_usage_res(show_history_time,
 797  800                      DLADM_LOGTYPE_LINK, file, resource, stime, etime, &state);
 798  801          } else {
 799  802                  /* Print time and information for each link */
 800  803                  status = dladm_walk_usage_time(show_history_time,
 801  804                      DLADM_LOGTYPE_LINK, file, stime, etime, &state);
 802  805          }
 803  806  
 804  807          if (status != DLADM_STATUS_OK)
 805  808                  die_dlerr(status, "show-link -h");
 806  809          ofmt_close(ofmt);
 807  810  }
 808  811  
 809  812  boolean_t
 810  813  dlstat_unit(char *oarg, char *unit)
 811  814  {
 812  815          if ((strcmp(oarg, "R") == 0) || (strcmp(oarg, "K") == 0) ||
 813  816              (strcmp(oarg, "M") == 0) || (strcmp(oarg, "G") == 0) ||
 814  817              (strcmp(oarg, "T") == 0) || (strcmp(oarg, "P") == 0)) {
 815  818                  *unit = oarg[0];
 816  819                  return (B_TRUE);
 817  820          }
 818  821  
 819  822          return (B_FALSE);
 820  823  }
 821  824  
 822  825  void
 823  826  map_to_units(char *buf, uint_t bufsize, double num, char unit,
 824  827      boolean_t parsable)
 825  828  {
 826  829          if (parsable) {
 827  830                  (void) snprintf(buf, bufsize, "%.0lf", num);
 828  831                  return;
 829  832          }
 830  833  
 831  834          if (unit == '\0') {
 832  835                  int index;
 833  836  
 834  837                  for (index = 0; (int)(num/1000) != 0; index++, num /= 1000)
 835  838                          ;
 836  839  
 837  840                  switch (index) {
 838  841                          case 0:
 839  842                                  unit = '\0';
 840  843                                  break;
 841  844                          case 1:
 842  845                                  unit = 'K';
 843  846                                  break;
 844  847                          case 2:
 845  848                                  unit = 'M';
 846  849                                  break;
 847  850                          case 3:
 848  851                                  unit = 'G';
 849  852                                  break;
 850  853                          case 4:
 851  854                                  unit = 'T';
 852  855                                  break;
 853  856                          case 5:
 854  857                                  /* Largest unit supported */
 855  858                          default:
 856  859                                  unit = 'P';
 857  860                                  break;
 858  861                  }
 859  862          } else  {
 860  863                  switch (unit) {
 861  864                          case 'R':
 862  865                                  /* Already raw numbers */
 863  866                                  unit = '\0';
 864  867                                  break;
 865  868                          case 'K':
 866  869                                  num /= 1000;
 867  870                                  break;
 868  871                          case 'M':
 869  872                                  num /= (1000*1000);
 870  873                                  break;
 871  874                          case 'G':
 872  875                                  num /= (1000*1000*1000);
 873  876                                  break;
 874  877                          case 'T':
 875  878                                  num /= (1000.0*1000.0*1000.0*1000.0);
 876  879                                  break;
 877  880                          case 'P':
 878  881                                  /* Largest unit supported */
 879  882                          default:
 880  883                                  num /= (1000.0*1000.0*1000.0*1000.0*1000.0);
 881  884                                  break;
 882  885                  }
 883  886          }
 884  887  
 885  888          if (unit == '\0')
 886  889                  (void) snprintf(buf, bufsize, " %7.0lf%c", num, unit);
 887  890          else
 888  891                  (void) snprintf(buf, bufsize, " %6.2lf%c", num, unit);
 889  892  }
 890  893  
 891  894  link_chain_t *
 892  895  get_link_prev_stat(datalink_id_t linkid, void *arg)
 893  896  {
 894  897          show_state_t    *state = (show_state_t *)arg;
 895  898          link_chain_t    *link_curr = NULL;
 896  899  
 897  900          /* Scan prev linkid list and look for entry matching this entry */
 898  901          for (link_curr = state->ls_linkchain; link_curr;
 899  902              link_curr = link_curr->lc_next) {
 900  903                  if (link_curr->lc_linkid == linkid)
 901  904                          break;
 902  905          }
 903  906                                  /* New link, add it */
 904  907          if (link_curr == NULL) {
 905  908                  link_curr = (link_chain_t *)malloc(sizeof (link_chain_t));
 906  909                  if (link_curr == NULL)
 907  910                          goto done;
 908  911                  link_curr->lc_linkid = linkid;
 909  912                  bzero(&link_curr->lc_statchain,
 910  913                      sizeof (link_curr->lc_statchain));
 911  914                  link_curr->lc_next = state->ls_linkchain;
 912  915                  state->ls_linkchain = link_curr;
 913  916          }
 914  917  done:
 915  918          return (link_curr);
 916  919  }
 917  920  
 918  921  /*
 919  922   * Number of links may change while dlstat with -i is executing.
 920  923   * Free memory allocated for links that are no longer there.
 921  924   * Prepare for next iteration by marking visited = false for existing stat
 922  925   * entries.
 923  926   */
 924  927  static void
 925  928  cleanup_removed_links(show_state_t *state)
 926  929  {
 927  930          link_chain_t    *lcurr;
 928  931          link_chain_t    *lprev;
 929  932          link_chain_t    *tofree;
 930  933          int             i;
 931  934  
 932  935          /* Delete all nodes from the list that have lc_visited marked false */
 933  936          lcurr = state->ls_linkchain;
 934  937          while (lcurr != NULL) {
 935  938                  if (lcurr->lc_visited) {
 936  939                          lcurr->lc_visited = B_FALSE;
 937  940                          lprev = lcurr;
 938  941                          lcurr = lcurr->lc_next;
 939  942                          continue;
 940  943                  }
 941  944                                  /* Is it head of the list? */
 942  945                  if (lcurr == state->ls_linkchain)
 943  946                          state->ls_linkchain = lcurr->lc_next;
 944  947                  else
 945  948                          lprev->lc_next = lcurr->lc_next;
 946  949                                  /* lprev remains the same */
 947  950                  tofree = lcurr;
 948  951                  lcurr = lcurr->lc_next;
 949  952  
  
    | 
      ↓ open down ↓ | 
    783 lines elided | 
    
      ↑ open up ↑ | 
  
 950  953                                  /* Free stats memory for the removed link */
 951  954                  for (i = 0; i < DLADM_STAT_NUM_STATS; i++) {
 952  955                          if (state->ls_stattype[i])
 953  956                                  dladm_link_stat_free(tofree->lc_statchain[i]);
 954  957                  }
 955  958                  free(tofree);
 956  959          }
 957  960  }
 958  961  
 959  962  void *
 960      -print_total_stats(const char *linkname, void *statentry, char unit,
 961      -    boolean_t parsable)
      963 +print_total_stats(const char *linkname, const char *zonename, void *statentry,
      964 +    char unit, boolean_t parsable)
 962  965  {
 963  966          total_stat_entry_t      *sentry = statentry;
 964  967          total_stat_t            *link_stats = &sentry->tse_stats;
 965  968          total_fields_buf_t      *buf;
 966  969  
 967  970          buf = malloc(sizeof (total_fields_buf_t));
 968  971          if (buf == NULL)
 969  972                  goto done;
 970  973  
 971  974          (void) snprintf(buf->t_linkname, sizeof (buf->t_linkname), "%s",
 972  975              linkname);
      976 +        (void) snprintf(buf->t_zone, sizeof (buf->t_zone), "%s", zonename);
 973  977  
 974  978          map_to_units(buf->t_ipackets, sizeof (buf->t_ipackets),
 975  979              link_stats->ts_ipackets, unit, parsable);
 976  980  
 977  981          map_to_units(buf->t_rbytes, sizeof (buf->t_rbytes),
 978  982              link_stats->ts_rbytes, unit, parsable);
 979  983  
 980  984          map_to_units(buf->t_opackets, sizeof (buf->t_opackets),
 981  985              link_stats->ts_opackets, unit, parsable);
 982  986  
 983  987          map_to_units(buf->t_obytes, sizeof (buf->t_obytes),
 984  988              link_stats->ts_obytes, unit, parsable);
 985  989  
 986  990  done:
 987  991          return (buf);
 988  992  }
 989  993  
 990  994  void *
 991      -print_rx_generic_ring_stats(const char *linkname, void *statentry, char unit,
 992      -    boolean_t parsable)
      995 +print_rx_generic_ring_stats(const char *linkname, const char *zonename, 
      996 +    void *statentry, char unit, boolean_t parsable)
 993  997  {
 994  998          ring_stat_entry_t       *sentry = statentry;
 995  999          ring_stat_t             *link_stats = &sentry->re_stats;
 996 1000          ring_fields_buf_t       *buf;
 997 1001  
 998 1002          buf = malloc(sizeof (ring_fields_buf_t));
 999 1003          if (buf == NULL)
1000 1004                  goto done;
1001 1005  
1002 1006          (void) snprintf(buf->r_linkname, sizeof (buf->r_linkname), "%s",
1003 1007              linkname);
1004 1008  
1005 1009          (void) snprintf(buf->r_type, sizeof (buf->r_type), "rx");
1006 1010  
1007 1011          if (sentry->re_index == DLSTAT_INVALID_ENTRY) {
1008 1012                  (void) snprintf(buf->r_index, sizeof (buf->r_index), "--");
1009 1013          } else {
1010 1014                  (void) snprintf(buf->r_index, sizeof (buf->r_index),
1011 1015                      "%llu", sentry->re_index);
1012 1016          }
1013 1017  
1014 1018          map_to_units(buf->r_packets, sizeof (buf->r_packets),
  
    | 
      ↓ open down ↓ | 
    12 lines elided | 
    
      ↑ open up ↑ | 
  
1015 1019              link_stats->r_packets, unit, parsable);
1016 1020  
1017 1021          map_to_units(buf->r_bytes, sizeof (buf->r_bytes),
1018 1022              link_stats->r_bytes, unit, parsable);
1019 1023  
1020 1024  done:
1021 1025          return (buf);
1022 1026  }
1023 1027  
1024 1028  void *
1025      -print_tx_generic_ring_stats(const char *linkname, void *statentry, char unit,
1026      -    boolean_t parsable)
     1029 +print_tx_generic_ring_stats(const char *linkname, const char *zonename,
     1030 +    void *statentry, char unit, boolean_t parsable)
1027 1031  {
1028 1032          ring_stat_entry_t       *sentry = statentry;
1029 1033          ring_stat_t             *link_stats = &sentry->re_stats;
1030 1034          ring_fields_buf_t       *buf;
1031 1035  
1032 1036          buf = malloc(sizeof (ring_fields_buf_t));
1033 1037          if (buf == NULL)
1034 1038                  goto done;
1035 1039  
1036 1040          (void) snprintf(buf->r_linkname, sizeof (buf->r_linkname), "%s",
1037 1041              linkname);
1038 1042  
1039 1043          (void) snprintf(buf->r_type, sizeof (buf->r_type), "tx");
1040 1044  
1041 1045          if (sentry->re_index == DLSTAT_INVALID_ENTRY) {
1042 1046                  (void) snprintf(buf->r_index, sizeof (buf->r_index), "--");
1043 1047          } else {
1044 1048                  (void) snprintf(buf->r_index, sizeof (buf->r_index),
1045 1049                      "%llu", sentry->re_index);
1046 1050          }
1047 1051  
1048 1052          map_to_units(buf->r_packets, sizeof (buf->r_packets),
  
    | 
      ↓ open down ↓ | 
    12 lines elided | 
    
      ↑ open up ↑ | 
  
1049 1053              link_stats->r_packets, unit, parsable);
1050 1054  
1051 1055          map_to_units(buf->r_bytes, sizeof (buf->r_bytes),
1052 1056              link_stats->r_bytes, unit, parsable);
1053 1057  
1054 1058  done:
1055 1059          return (buf);
1056 1060  }
1057 1061  
1058 1062  void *
1059      -print_rx_ring_stats(const char *linkname, void *statentry, char unit,
1060      -    boolean_t parsable)
     1063 +print_rx_ring_stats(const char *linkname, const char *zonename, void *statentry,
     1064 +    char unit, boolean_t parsable)
1061 1065  {
1062 1066          ring_stat_entry_t       *sentry = statentry;
1063 1067          ring_stat_t             *link_stats = &sentry->re_stats;
1064 1068          rx_ring_fields_buf_t    *buf;
1065 1069  
1066 1070          buf = malloc(sizeof (rx_ring_fields_buf_t));
1067 1071          if (buf == NULL)
1068 1072                  goto done;
1069 1073  
1070 1074          (void) snprintf(buf->rr_linkname, sizeof (buf->rr_linkname), "%s",
1071 1075              linkname);
1072 1076  
1073 1077          (void) snprintf(buf->rr_type, sizeof (buf->rr_type), "rx");
1074 1078  
1075 1079          if (sentry->re_index == DLSTAT_INVALID_ENTRY) {
1076 1080                  (void) snprintf(buf->rr_index, sizeof (buf->rr_index), "--");
1077 1081          } else {
1078 1082                  (void) snprintf(buf->rr_index, sizeof (buf->rr_index),
1079 1083                      "%llu", sentry->re_index);
1080 1084          }
1081 1085  
1082 1086          map_to_units(buf->rr_ipackets, sizeof (buf->rr_ipackets),
  
    | 
      ↓ open down ↓ | 
    12 lines elided | 
    
      ↑ open up ↑ | 
  
1083 1087              link_stats->r_packets, unit, parsable);
1084 1088  
1085 1089          map_to_units(buf->rr_rbytes, sizeof (buf->rr_rbytes),
1086 1090              link_stats->r_bytes, unit, parsable);
1087 1091  
1088 1092  done:
1089 1093          return (buf);
1090 1094  }
1091 1095  
1092 1096  void *
1093      -print_tx_ring_stats(const char *linkname, void *statentry, char unit,
1094      -    boolean_t parsable)
     1097 +print_tx_ring_stats(const char *linkname, const char *zonename, void *statentry,
     1098 +    char unit, boolean_t parsable)
1095 1099  {
1096 1100          ring_stat_entry_t       *sentry = statentry;
1097 1101          ring_stat_t             *link_stats = &sentry->re_stats;
1098 1102          tx_ring_fields_buf_t    *buf;
1099 1103  
1100 1104          buf = malloc(sizeof (tx_ring_fields_buf_t));
1101 1105          if (buf == NULL)
1102 1106                  goto done;
1103 1107  
1104 1108          (void) snprintf(buf->tr_linkname, sizeof (buf->tr_linkname), "%s",
1105 1109              linkname);
1106 1110  
1107 1111          (void) snprintf(buf->tr_type, sizeof (buf->tr_type), "tx");
1108 1112  
1109 1113          if (sentry->re_index == DLSTAT_INVALID_ENTRY) {
1110 1114                  (void) snprintf(buf->tr_index, sizeof (buf->tr_index), "--");
1111 1115          } else {
1112 1116                  (void) snprintf(buf->tr_index, sizeof (buf->tr_index),
1113 1117                      "%llu", sentry->re_index);
1114 1118          }
1115 1119  
1116 1120          map_to_units(buf->tr_opackets, sizeof (buf->tr_opackets),
  
    | 
      ↓ open down ↓ | 
    12 lines elided | 
    
      ↑ open up ↑ | 
  
1117 1121              link_stats->r_packets, unit, parsable);
1118 1122  
1119 1123          map_to_units(buf->tr_obytes, sizeof (buf->tr_obytes),
1120 1124              link_stats->r_bytes, unit, parsable);
1121 1125  
1122 1126  done:
1123 1127          return (buf);
1124 1128  }
1125 1129  
1126 1130  void *
1127      -print_rx_generic_lane_stats(const char *linkname, void *statentry, char unit,
1128      -    boolean_t parsable)
     1131 +print_rx_generic_lane_stats(const char *linkname, const char *zonename,
     1132 +    void *statentry, char unit, boolean_t parsable)
1129 1133  {
1130 1134          rx_lane_stat_entry_t    *sentry = statentry;
1131 1135          rx_lane_stat_t          *link_stats = &sentry->rle_stats;
1132 1136          lane_fields_buf_t       *buf;
1133 1137  
1134 1138          if (sentry->rle_id == L_DFNCT)
1135 1139                  return (NULL);
1136 1140  
1137 1141          buf = malloc(sizeof (lane_fields_buf_t));
1138 1142          if (buf == NULL)
1139 1143                  goto done;
1140 1144  
1141 1145          (void) snprintf(buf->l_linkname, sizeof (buf->l_linkname), "%s",
1142 1146              linkname);
1143 1147  
1144 1148          (void) snprintf(buf->l_type, sizeof (buf->l_type), "rx");
1145 1149  
1146 1150          if (sentry->rle_id == L_HWLANE)
1147 1151                  (void) snprintf(buf->l_id, sizeof (buf->l_id), "hw");
1148 1152          else if (sentry->rle_id == L_SWLANE)
1149 1153                  (void) snprintf(buf->l_id, sizeof (buf->l_id), "sw");
1150 1154          else if (sentry->rle_id == L_LOCAL)
1151 1155                  (void) snprintf(buf->l_id, sizeof (buf->l_id), "local");
1152 1156          else if (sentry->rle_id == L_BCAST)
1153 1157                  (void) snprintf(buf->l_id, sizeof (buf->l_id), "bcast");
1154 1158          else
1155 1159                  (void) snprintf(buf->l_id, sizeof (buf->l_id), "--");
1156 1160  
1157 1161          if (sentry->rle_index == DLSTAT_INVALID_ENTRY) {
1158 1162                  (void) snprintf(buf->l_index, sizeof (buf->l_index), "--");
1159 1163          } else {
1160 1164                  (void) snprintf(buf->l_index, sizeof (buf->l_index),
1161 1165                      "%llu", sentry->rle_index);
1162 1166          }
1163 1167  
1164 1168          map_to_units(buf->l_packets, sizeof (buf->l_packets),
  
    | 
      ↓ open down ↓ | 
    26 lines elided | 
    
      ↑ open up ↑ | 
  
1165 1169              link_stats->rl_ipackets, unit, parsable);
1166 1170  
1167 1171          map_to_units(buf->l_bytes, sizeof (buf->l_bytes),
1168 1172              link_stats->rl_rbytes, unit, parsable);
1169 1173  
1170 1174  done:
1171 1175          return (buf);
1172 1176  }
1173 1177  
1174 1178  void *
1175      -print_tx_generic_lane_stats(const char *linkname, void *statentry, char unit,
1176      -    boolean_t parsable)
     1179 +print_tx_generic_lane_stats(const char *linkname, const char *zonename,
     1180 +    void *statentry, char unit, boolean_t parsable)
1177 1181  {
1178 1182          tx_lane_stat_entry_t    *sentry = statentry;
1179 1183          tx_lane_stat_t          *link_stats = &sentry->tle_stats;
1180 1184          lane_fields_buf_t       *buf;
1181 1185  
1182 1186          if (sentry->tle_id == L_DFNCT)
1183 1187                  return (NULL);
1184 1188  
1185 1189          buf = malloc(sizeof (lane_fields_buf_t));
1186 1190          if (buf == NULL)
1187 1191                  goto done;
1188 1192  
1189 1193          (void) snprintf(buf->l_linkname, sizeof (buf->l_linkname), "%s",
1190 1194              linkname);
1191 1195  
1192 1196          (void) snprintf(buf->l_type, sizeof (buf->l_type), "tx");
1193 1197  
1194 1198          if (sentry->tle_id == L_HWLANE)
1195 1199                  (void) snprintf(buf->l_id, sizeof (buf->l_id), "hw");
1196 1200          else if (sentry->tle_id == L_SWLANE)
1197 1201                  (void) snprintf(buf->l_id, sizeof (buf->l_id), "sw");
1198 1202          else if (sentry->tle_id == L_BCAST)
1199 1203                  (void) snprintf(buf->l_id, sizeof (buf->l_id), "bcast");
1200 1204          else
1201 1205                  (void) snprintf(buf->l_id, sizeof (buf->l_id), "--");
1202 1206  
1203 1207          if (sentry->tle_index == DLSTAT_INVALID_ENTRY) {
1204 1208                  (void) snprintf(buf->l_index, sizeof (buf->l_index), "--");
1205 1209          } else {
1206 1210                  (void) snprintf(buf->l_index, sizeof (buf->l_index),
1207 1211                      "%llu", sentry->tle_index);
1208 1212          }
1209 1213          map_to_units(buf->l_packets, sizeof (buf->l_packets),
  
    | 
      ↓ open down ↓ | 
    23 lines elided | 
    
      ↑ open up ↑ | 
  
1210 1214              link_stats->tl_opackets, unit, parsable);
1211 1215  
1212 1216          map_to_units(buf->l_bytes, sizeof (buf->l_bytes),
1213 1217              link_stats->tl_obytes, unit, parsable);
1214 1218  
1215 1219  done:
1216 1220          return (buf);
1217 1221  }
1218 1222  
1219 1223  void *
1220      -print_rx_lane_stats(const char *linkname, void *statentry, char unit,
1221      -    boolean_t parsable)
     1224 +print_rx_lane_stats(const char *linkname, const char *zonename, void *statentry,
     1225 +    char unit, boolean_t parsable)
1222 1226  {
1223 1227          rx_lane_stat_entry_t    *sentry = statentry;
1224 1228          rx_lane_stat_t          *link_stats = &sentry->rle_stats;
1225 1229          rx_lane_fields_buf_t    *buf;
1226 1230  
1227 1231          if (sentry->rle_id == L_DFNCT)
1228 1232                  return (NULL);
1229 1233  
1230 1234          buf = malloc(sizeof (rx_lane_fields_buf_t));
1231 1235          if (buf == NULL)
1232 1236                  goto done;
1233 1237  
1234 1238          (void) snprintf(buf->rl_linkname, sizeof (buf->rl_linkname), "%s",
1235 1239              linkname);
1236 1240  
1237 1241          (void) snprintf(buf->rl_type, sizeof (buf->rl_type), "rx");
1238 1242  
1239 1243          if (sentry->rle_id == L_HWLANE)
1240 1244                  (void) snprintf(buf->rl_id, sizeof (buf->rl_id), "hw");
1241 1245          else if (sentry->rle_id == L_SWLANE)
1242 1246                  (void) snprintf(buf->rl_id, sizeof (buf->rl_id), "sw");
1243 1247          else if (sentry->rle_id == L_LOCAL)
1244 1248                  (void) snprintf(buf->rl_id, sizeof (buf->rl_id), "local");
1245 1249          else if (sentry->rle_id == L_BCAST)
1246 1250                  (void) snprintf(buf->rl_id, sizeof (buf->rl_id), "bcast");
1247 1251          else
1248 1252                  (void) snprintf(buf->rl_id, sizeof (buf->rl_id), "--");
1249 1253  
1250 1254          if (sentry->rle_index == DLSTAT_INVALID_ENTRY) {
1251 1255                  (void) snprintf(buf->rl_index, sizeof (buf->rl_index), "--");
1252 1256          } else {
1253 1257                  (void) snprintf(buf->rl_index, sizeof (buf->rl_index),
1254 1258                      "%llu", sentry->rle_index);
1255 1259          }
1256 1260  
1257 1261          map_to_units(buf->rl_ipackets, sizeof (buf->rl_ipackets),
1258 1262              link_stats->rl_ipackets, unit, parsable);
1259 1263  
1260 1264          map_to_units(buf->rl_rbytes, sizeof (buf->rl_rbytes),
1261 1265              link_stats->rl_rbytes, unit, parsable);
1262 1266  
1263 1267          map_to_units(buf->rl_intrs, sizeof (buf->rl_intrs),
1264 1268              link_stats->rl_intrs, unit, parsable);
1265 1269  
1266 1270          map_to_units(buf->rl_polls, sizeof (buf->rl_polls),
1267 1271              link_stats->rl_polls, unit, parsable);
1268 1272  
1269 1273          map_to_units(buf->rl_sdrops, sizeof (buf->rl_sdrops),
1270 1274              link_stats->rl_sdrops, unit, parsable);
1271 1275  
1272 1276          map_to_units(buf->rl_chl10, sizeof (buf->rl_chl10),
1273 1277              link_stats->rl_chl10, unit, parsable);
1274 1278  
1275 1279          map_to_units(buf->rl_ch10_50, sizeof (buf->rl_ch10_50),
  
    | 
      ↓ open down ↓ | 
    44 lines elided | 
    
      ↑ open up ↑ | 
  
1276 1280              link_stats->rl_ch10_50, unit, parsable);
1277 1281  
1278 1282          map_to_units(buf->rl_chg50, sizeof (buf->rl_chg50),
1279 1283              link_stats->rl_chg50, unit, parsable);
1280 1284  
1281 1285  done:
1282 1286          return (buf);
1283 1287  }
1284 1288  
1285 1289  void *
1286      -print_tx_lane_stats(const char *linkname, void *statentry, char unit,
1287      -    boolean_t parsable)
1288      -{
     1290 +print_tx_lane_stats(const char *linkname, const char *zonename, void *statentry,
     1291 +    char unit, boolean_t parsable) {
1289 1292          tx_lane_stat_entry_t    *sentry = statentry;
1290 1293          tx_lane_stat_t          *link_stats = &sentry->tle_stats;
1291 1294          tx_lane_fields_buf_t    *buf = NULL;
1292 1295  
1293 1296          if (sentry->tle_id == L_DFNCT)
1294 1297                  return (NULL);
1295 1298  
1296 1299          buf = malloc(sizeof (tx_lane_fields_buf_t));
1297 1300          if (buf == NULL)
1298 1301                  goto done;
1299 1302  
1300 1303          (void) snprintf(buf->tl_linkname, sizeof (buf->tl_linkname), "%s",
1301 1304              linkname);
1302 1305  
1303 1306          (void) snprintf(buf->tl_type, sizeof (buf->tl_type), "tx");
1304 1307  
1305 1308          if (sentry->tle_id == L_HWLANE)
1306 1309                  (void) snprintf(buf->tl_id, sizeof (buf->tl_id), "hw");
1307 1310          else if (sentry->tle_id == L_SWLANE)
1308 1311                  (void) snprintf(buf->tl_id, sizeof (buf->tl_id), "sw");
1309 1312          else if (sentry->tle_id == L_BCAST)
1310 1313                  (void) snprintf(buf->tl_id, sizeof (buf->tl_id), "bcast");
1311 1314          else
1312 1315                  (void) snprintf(buf->tl_id, sizeof (buf->tl_id), "--");
1313 1316  
1314 1317          if (sentry->tle_index == DLSTAT_INVALID_ENTRY) {
1315 1318                  (void) snprintf(buf->tl_index, sizeof (buf->tl_index), "--");
1316 1319          } else {
1317 1320                  (void) snprintf(buf->tl_index, sizeof (buf->tl_index),
1318 1321                      "%llu", sentry->tle_index);
1319 1322          }
1320 1323  
1321 1324          map_to_units(buf->tl_opackets, sizeof (buf->tl_opackets),
1322 1325              link_stats->tl_opackets, unit, parsable);
1323 1326  
1324 1327          map_to_units(buf->tl_obytes, sizeof (buf->tl_obytes),
1325 1328              link_stats->tl_obytes, unit, parsable);
1326 1329  
1327 1330          map_to_units(buf->tl_blockcnt, sizeof (buf->tl_blockcnt),
1328 1331              link_stats->tl_blockcnt, unit, parsable);
1329 1332  
1330 1333          map_to_units(buf->tl_unblockcnt, sizeof (buf->tl_unblockcnt),
  
    | 
      ↓ open down ↓ | 
    32 lines elided | 
    
      ↑ open up ↑ | 
  
1331 1334              link_stats->tl_unblockcnt, unit, parsable);
1332 1335  
1333 1336          map_to_units(buf->tl_sdrops, sizeof (buf->tl_sdrops),
1334 1337              link_stats->tl_sdrops, unit, parsable);
1335 1338  
1336 1339  done:
1337 1340          return (buf);
1338 1341  }
1339 1342  
1340 1343  void *
1341      -print_fanout_stats(const char *linkname, void *statentry, char unit,
1342      -    boolean_t parsable)
     1344 +print_fanout_stats(const char *linkname, const char *zonename, void *statentry,
     1345 +    char unit, boolean_t parsable)
1343 1346  {
1344 1347          fanout_stat_entry_t             *sentry = statentry;
1345 1348          fanout_stat_t                   *link_stats = &sentry->fe_stats;
1346 1349          rx_fanout_lane_fields_buf_t     *buf;
1347 1350  
1348 1351          buf = malloc(sizeof (rx_fanout_lane_fields_buf_t));
1349 1352          if (buf == NULL)
1350 1353                  goto done;
1351 1354  
1352 1355          (void) snprintf(buf->rfl_linkname, sizeof (buf->rfl_linkname), "%s",
1353 1356              linkname);
1354 1357  
1355 1358          (void) snprintf(buf->rfl_type, sizeof (buf->rfl_type), "rx");
1356 1359  
1357 1360          if (sentry->fe_id == L_HWLANE)
1358 1361                  (void) snprintf(buf->rfl_id, sizeof (buf->rfl_id), "hw");
1359 1362          else if (sentry->fe_id == L_SWLANE)
1360 1363                  (void) snprintf(buf->rfl_id, sizeof (buf->rfl_id), "sw");
1361 1364          else if (sentry->fe_id == L_LCLSWLANE)
1362 1365                  (void) snprintf(buf->rfl_id, sizeof (buf->rfl_id), "lcl/sw");
1363 1366          else if (sentry->fe_id == L_LOCAL)
1364 1367                  (void) snprintf(buf->rfl_id, sizeof (buf->rfl_id), "local");
1365 1368          else if (sentry->fe_id == L_BCAST)
1366 1369                  (void) snprintf(buf->rfl_id, sizeof (buf->rfl_id), "bcast");
1367 1370          else
1368 1371                  (void) snprintf(buf->rfl_id, sizeof (buf->rfl_id), "--");
1369 1372  
1370 1373          if (sentry->fe_index == DLSTAT_INVALID_ENTRY) {
1371 1374                  (void) snprintf(buf->rfl_index, sizeof (buf->rfl_index), "--");
1372 1375          } else {
1373 1376                  (void) snprintf(buf->rfl_index, sizeof (buf->rfl_index),
1374 1377                      "%llu", sentry->fe_index);
1375 1378          }
1376 1379  
1377 1380          if (sentry->fe_foutindex == DLSTAT_INVALID_ENTRY)
1378 1381                  (void) snprintf(buf->rfl_fout, sizeof (buf->rfl_fout), "--");
1379 1382          else {
1380 1383                  (void) snprintf(buf->rfl_fout, sizeof (buf->rfl_fout), "%llu",
1381 1384                      sentry->fe_foutindex);
1382 1385          }
1383 1386  
1384 1387          map_to_units(buf->rfl_ipackets, sizeof (buf->rfl_ipackets),
  
    | 
      ↓ open down ↓ | 
    32 lines elided | 
    
      ↑ open up ↑ | 
  
1385 1388              link_stats->f_ipackets, unit, parsable);
1386 1389  
1387 1390          map_to_units(buf->rfl_rbytes, sizeof (buf->rfl_rbytes),
1388 1391              link_stats->f_rbytes, unit, parsable);
1389 1392  
1390 1393  done:
1391 1394          return (buf);
1392 1395  }
1393 1396  
1394 1397  void *
1395      -print_aggr_port_stats(const char *linkname, void *statentry, char unit,
1396      -    boolean_t parsable)
     1398 +print_aggr_port_stats(const char *linkname, const char *zonename,
     1399 +    void *statentry, char unit, boolean_t parsable)
1397 1400  {
1398 1401          aggr_port_stat_entry_t  *sentry = statentry;
1399 1402          aggr_port_stat_t        *link_stats = &sentry->ape_stats;
1400 1403          aggr_port_fields_buf_t  *buf;
1401 1404          char                    portname[MAXLINKNAMELEN];
1402 1405  
1403 1406          buf = malloc(sizeof (aggr_port_fields_buf_t));
1404 1407          if (buf == NULL)
1405 1408                  goto done;
1406 1409  
1407 1410          (void) snprintf(buf->ap_linkname, sizeof (buf->ap_linkname), "%s",
1408 1411              linkname);
1409 1412  
1410 1413          if (dladm_datalink_id2info(handle, sentry->ape_portlinkid, NULL,
1411 1414              NULL, NULL, portname, DLPI_LINKNAME_MAX)
1412 1415              != DLADM_STATUS_OK) {
1413 1416                  (void) snprintf(buf->ap_portname,
1414 1417                      sizeof (buf->ap_portname), "--");
1415 1418          } else {
1416 1419                  (void) snprintf(buf->ap_portname,
1417 1420                      sizeof (buf->ap_portname), "%s", portname);
1418 1421          }
1419 1422  
1420 1423          map_to_units(buf->ap_ipackets, sizeof (buf->ap_ipackets),
1421 1424              link_stats->ap_ipackets, unit, parsable);
1422 1425  
1423 1426          map_to_units(buf->ap_rbytes, sizeof (buf->ap_rbytes),
1424 1427              link_stats->ap_rbytes, unit, parsable);
1425 1428  
1426 1429          map_to_units(buf->ap_opackets, sizeof (buf->ap_opackets),
1427 1430              link_stats->ap_opackets, unit, parsable);
1428 1431  
1429 1432          map_to_units(buf->ap_obytes, sizeof (buf->ap_obytes),
1430 1433              link_stats->ap_obytes, unit, parsable);
1431 1434  
1432 1435  done:
1433 1436          return (buf);
1434 1437  }
1435 1438  
1436 1439  dladm_stat_chain_t *
1437 1440  query_link_stats(dladm_handle_t dh, datalink_id_t linkid, void *arg,
1438 1441      dladm_stat_type_t stattype)
1439 1442  {
1440 1443          link_chain_t            *link_node;
1441 1444          dladm_stat_chain_t      *curr_stat;
1442 1445          dladm_stat_chain_t      *prev_stat = NULL;
1443 1446          dladm_stat_chain_t      *diff_stat = NULL;
1444 1447  
1445 1448          /*  Get prev iteration stat for this link */
1446 1449          link_node = get_link_prev_stat(linkid, arg);
1447 1450          if (link_node == NULL)
1448 1451                  goto done;
1449 1452  
1450 1453          link_node->lc_visited = B_TRUE;
1451 1454          prev_stat = link_node->lc_statchain[stattype];
1452 1455  
1453 1456          /* Query library for current stats */
1454 1457          curr_stat = dladm_link_stat_query(dh, linkid, stattype);
1455 1458          if (curr_stat == NULL)
1456 1459                  goto done;
1457 1460  
1458 1461          /* current stats - prev iteration stats */
1459 1462          diff_stat = dladm_link_stat_diffchain(curr_stat, prev_stat, stattype);
1460 1463  
1461 1464          /* Free prev stats */
1462 1465          dladm_link_stat_free(prev_stat);
  
    | 
      ↓ open down ↓ | 
    56 lines elided | 
    
      ↑ open up ↑ | 
  
1463 1466  
1464 1467          /* Prev <- curr stats */
1465 1468          link_node->lc_statchain[stattype] = curr_stat;
1466 1469  
1467 1470  done:
1468 1471          return (diff_stat);
1469 1472  }
1470 1473  
1471 1474  void
1472 1475  walk_dlstat_stats(show_state_t *state, const char *linkname,
1473      -    dladm_stat_type_t stattype, dladm_stat_chain_t *diff_stat)
     1476 +    const char *zonename, dladm_stat_type_t stattype,
     1477 +    dladm_stat_chain_t *diff_stat)
1474 1478  {
1475 1479          dladm_stat_chain_t  *curr;
1476 1480  
1477 1481          /* Unpack invidual stat entry and call library consumer's callback */
1478 1482          for (curr = diff_stat; curr != NULL; curr = curr->dc_next) {
1479 1483                  void    *fields_buf;
1480 1484  
1481 1485                  /* Format the raw numbers for printing */
1482 1486                  fields_buf = state->ls_stats2str[stattype](linkname,
1483      -                    curr->dc_statentry, state->ls_unit, state->ls_parsable);
     1487 +                    zonename, curr->dc_statentry, state->ls_unit,
     1488 +                    state->ls_parsable);
1484 1489                  /* Print the stats */
1485 1490                  if (fields_buf != NULL)
1486 1491                          ofmt_print(state->ls_ofmt, fields_buf);
1487 1492                  free(fields_buf);
1488 1493          }
1489 1494  }
1490 1495  
1491 1496  static int
1492 1497  show_queried_stats(dladm_handle_t dh, datalink_id_t linkid, void *arg)
1493 1498  {
1494 1499          show_state_t            *state = arg;
1495 1500          int                     i;
1496 1501          dladm_stat_chain_t      *diff_stat;
1497 1502          char                    linkname[DLPI_LINKNAME_MAX];
     1503 +        char                    zonename[DLADM_PROP_VAL_MAX + 1];
     1504 +        char                    *valptr[1];
     1505 +        uint_t                  valcnt = 1;
1498 1506  
1499 1507          if (dladm_datalink_id2info(dh, linkid, NULL, NULL, NULL, linkname,
1500 1508              DLPI_LINKNAME_MAX) != DLADM_STATUS_OK) {
1501 1509                  goto done;
1502 1510          }
1503 1511  
     1512 +        valptr[0] = zonename;
     1513 +        if (dladm_get_linkprop(handle, linkid, DLADM_PROP_VAL_CURRENT, "zone",
     1514 +            (char **)valptr, &valcnt) != 0)
     1515 +                zonename[0] = '\0';
     1516 +
1504 1517          for (i = 0; i < DLADM_STAT_NUM_STATS; i++) {
1505 1518                  if (state->ls_stattype[i]) {
1506 1519                          /*
1507 1520                           * Query library for stats
1508 1521                           * Stats are returned as chain of raw numbers
1509 1522                           */
1510 1523                          diff_stat = query_link_stats(handle, linkid, arg, i);
1511      -                        walk_dlstat_stats(state, linkname, i, diff_stat);
     1524 +                        walk_dlstat_stats(state, linkname, zonename, i,
     1525 +                            diff_stat);
1512 1526                          dladm_link_stat_free(diff_stat);
1513 1527                  }
1514 1528          }
1515 1529  done:
1516 1530          return (DLADM_WALK_CONTINUE);
1517 1531  }
1518 1532  
1519 1533  void
1520 1534  show_link_stats(datalink_id_t linkid, show_state_t state, uint32_t interval)
1521 1535  {
1522 1536          for (;;) {
1523 1537                  if (linkid == DATALINK_ALL_LINKID) {
1524 1538                          (void) dladm_walk_datalink_id(show_queried_stats,
1525 1539                              handle, &state, DATALINK_CLASS_ALL,
1526 1540                              DATALINK_ANY_MEDIATYPE, DLADM_OPT_ACTIVE);
1527 1541                  } else {
1528 1542                          (void) show_queried_stats(handle, linkid, &state);
1529 1543                  }
1530 1544  
1531 1545                  if (interval == 0)
1532 1546                          break;
1533 1547  
1534 1548                  cleanup_removed_links(&state);
1535 1549                  (void) sleep(interval);
1536 1550          }
1537 1551  }
1538 1552  
1539 1553  void
1540 1554  print_all_stats(dladm_handle_t dh, datalink_id_t linkid,
1541 1555      dladm_stat_chain_t *stat_chain)
1542 1556  {
1543 1557          dladm_stat_chain_t      *curr;
1544 1558          name_value_stat_entry_t *stat_entry;
1545 1559          name_value_stat_t       *curr_stat;
1546 1560          boolean_t               stat_printed = B_FALSE;
1547 1561          char                    linkname[MAXLINKNAMELEN];
1548 1562          char                    prev_linkname[MAXLINKNAMELEN];
1549 1563  
1550 1564          if (dladm_datalink_id2info(dh, linkid, NULL, NULL, NULL, linkname,
1551 1565              DLPI_LINKNAME_MAX) != DLADM_STATUS_OK)
1552 1566                  return;
1553 1567  
1554 1568          for (curr = stat_chain; curr != NULL; curr = curr->dc_next) {
1555 1569                  stat_entry = curr->dc_statentry;
1556 1570                  /*
1557 1571                   * Print header
1558 1572                   * If link name is already printed in previous iteration,
1559 1573                   * don't print again
1560 1574                   */
1561 1575                  if (strcmp(prev_linkname, linkname) != 0)
1562 1576                          printf("%s \n", linkname);
1563 1577                  printf("  %s \n", stat_entry->nve_header);
1564 1578  
1565 1579                  /* Print stat fields */
1566 1580                  for (curr_stat = stat_entry->nve_stats; curr_stat != NULL;
1567 1581                      curr_stat = curr_stat->nv_nextstat) {
1568 1582                          printf("\t%15s", curr_stat->nv_statname);
1569 1583                          printf("\t\t%15llu\n", curr_stat->nv_statval);
1570 1584                  }
1571 1585  
1572 1586                  strncpy(prev_linkname, linkname, MAXLINKNAMELEN);
1573 1587                  stat_printed = B_TRUE;
1574 1588          }
1575 1589          if (stat_printed)
1576 1590                  printf("---------------------------------------------------\n");
1577 1591  }
1578 1592  
1579 1593  static int
1580 1594  dump_queried_stats(dladm_handle_t dh, datalink_id_t linkid, void *arg)
1581 1595  {
1582 1596          boolean_t               *stattype = arg;
1583 1597          int                     i;
1584 1598          dladm_stat_chain_t      *stat_chain;
1585 1599  
1586 1600          for (i = 0; i < DLADM_STAT_NUM_STATS; i++) {
1587 1601                  if (stattype[i]) {
1588 1602                          stat_chain = dladm_link_stat_query_all(dh, linkid, i);
1589 1603                          print_all_stats(dh, linkid, stat_chain);
1590 1604                          dladm_link_stat_query_all_free(stat_chain);
1591 1605                  }
1592 1606          }
1593 1607  done:
1594 1608          return (DLADM_WALK_CONTINUE);
1595 1609  }
1596 1610  
1597 1611  void
1598 1612  dump_all_link_stats(datalink_id_t linkid, boolean_t *stattype)
1599 1613  {
1600 1614          if (linkid == DATALINK_ALL_LINKID) {
1601 1615                  (void) dladm_walk_datalink_id(dump_queried_stats,
1602 1616                      handle, stattype, DATALINK_CLASS_ALL,
1603 1617                      DATALINK_ANY_MEDIATYPE, DLADM_OPT_ACTIVE);
1604 1618          } else {
1605 1619                  (void) dump_queried_stats(handle, linkid, stattype);
1606 1620          }
1607 1621  }
1608 1622  
1609 1623  static void
1610 1624  do_show(int argc, char *argv[], const char *use)
1611 1625  {
1612 1626          int                     option;
1613 1627          boolean_t               r_arg = B_FALSE;
1614 1628          boolean_t               t_arg = B_FALSE;
1615 1629          boolean_t               i_arg = B_FALSE;
1616 1630          boolean_t               p_arg = B_FALSE;
1617 1631          boolean_t               o_arg = B_FALSE;
1618 1632          boolean_t               u_arg = B_FALSE;
1619 1633          boolean_t               a_arg = B_FALSE;
1620 1634          boolean_t               A_arg = B_FALSE;
  
    | 
      ↓ open down ↓ | 
    99 lines elided | 
    
      ↑ open up ↑ | 
  
1621 1635          uint32_t                flags = DLADM_OPT_ACTIVE;
1622 1636          datalink_id_t           linkid = DATALINK_ALL_LINKID;
1623 1637          uint32_t                interval = 0;
1624 1638          char                    unit = '\0';
1625 1639          show_state_t            state;
1626 1640          dladm_status_t          status;
1627 1641          char                    *fields_str = NULL;
1628 1642          char                    *o_fields_str = NULL;
1629 1643  
1630 1644          char                    *total_stat_fields =
1631      -            "link,ipkts,rbytes,opkts,obytes";
     1645 +            "link,ipkts,rbytes,opkts,obytes,zone";
1632 1646          char                    *rx_total_stat_fields =
1633 1647              "link,ipkts,rbytes,intrs,polls,ch<10,ch10-50,ch>50";
1634 1648          char                    *tx_total_stat_fields =
1635 1649              "link,opkts,obytes,blkcnt,ublkcnt";
1636 1650  
1637 1651          ofmt_handle_t           ofmt;
1638 1652          ofmt_status_t           oferr;
1639 1653          uint_t                  ofmtflags = OFMT_RIGHTJUST;
1640 1654          ofmt_field_t            *oftemplate;
1641 1655  
1642 1656          bzero(&state, sizeof (state));
1643 1657          opterr = 0;
1644 1658          while ((option = getopt_long(argc, argv, ":rtaApi:o:u:",
1645 1659              NULL, NULL)) != -1) {
1646 1660                  switch (option) {
1647 1661                  case 'r':
1648 1662                          if (r_arg)
1649 1663                                  die_optdup(option);
1650 1664  
1651 1665                          r_arg = B_TRUE;
1652 1666                          break;
1653 1667                  case 't':
1654 1668                          if (t_arg)
1655 1669                                  die_optdup(option);
1656 1670  
1657 1671                          t_arg = B_TRUE;
1658 1672                          break;
1659 1673                  case 'a':
1660 1674                          if (a_arg)
1661 1675                                  die_optdup(option);
1662 1676  
1663 1677                          a_arg = B_TRUE;
1664 1678                          break;
1665 1679                  case 'A':
1666 1680                          if (A_arg)
1667 1681                                  die_optdup(option);
1668 1682  
1669 1683                          A_arg = B_TRUE;
1670 1684                          break;
1671 1685                  case 'i':
1672 1686                          if (i_arg)
1673 1687                                  die_optdup(option);
1674 1688  
1675 1689                          i_arg = B_TRUE;
1676 1690                          if (!dladm_str2interval(optarg, &interval))
1677 1691                                  die("invalid interval value '%s'", optarg);
1678 1692                          break;
1679 1693                  case 'p':
1680 1694                          if (p_arg)
1681 1695                                  die_optdup(option);
1682 1696  
1683 1697                          p_arg = B_TRUE;
1684 1698                          break;
1685 1699                  case 'o':
1686 1700                          o_arg = B_TRUE;
1687 1701                          o_fields_str = optarg;
1688 1702                          break;
1689 1703                  case 'u':
1690 1704                          if (u_arg)
1691 1705                                  die_optdup(option);
1692 1706  
1693 1707                          u_arg = B_TRUE;
1694 1708                          if (!dlstat_unit(optarg, &unit))
1695 1709                                  die("invalid unit value '%s',"
1696 1710                                      "unit must be R|K|M|G|T|P", optarg);
1697 1711                          break;
1698 1712                  default:
1699 1713                          die_opterr(optopt, option, use);
1700 1714                          break;
1701 1715                  }
1702 1716          }
1703 1717  
1704 1718          if (r_arg && t_arg)
1705 1719                  die("the options -t and -r are not compatible");
1706 1720  
1707 1721          if (u_arg && p_arg)
1708 1722                  die("the options -u and -p are not compatible");
1709 1723  
1710 1724          if (p_arg && !o_arg)
1711 1725                  die("-p requires -o");
1712 1726  
1713 1727          if (p_arg && strcasecmp(o_fields_str, "all") == 0)
1714 1728                  die("\"-o all\" is invalid with -p");
1715 1729  
1716 1730          if (a_arg && A_arg)
1717 1731                  die("the options -a and -A are not compatible");
1718 1732  
1719 1733          if (a_arg &&
1720 1734              (p_arg || o_arg || u_arg || i_arg)) {
1721 1735                  die("the option -a is not compatible with "
1722 1736                      "-p, -o, -u, -i");
1723 1737          }
1724 1738  
1725 1739          if (A_arg &&
1726 1740              (r_arg || t_arg || p_arg || o_arg || u_arg || i_arg)) {
1727 1741                  die("the option -A is not compatible with "
1728 1742                      "-r, -t, -p, -o, -u, -i");
1729 1743          }
1730 1744  
1731 1745          /* get link name (optional last argument) */
1732 1746          if (optind == (argc-1)) {
1733 1747                  if (strlen(argv[optind]) >= MAXLINKNAMELEN)
1734 1748                          die("link name too long");
1735 1749  
1736 1750                  if ((status = dladm_name2info(handle, argv[optind], &linkid,
1737 1751                      NULL, NULL, NULL)) != DLADM_STATUS_OK) {
1738 1752                          die_dlerr(status, "link %s is not valid", argv[optind]);
1739 1753                  }
1740 1754          } else if (optind != argc) {
1741 1755                  if (argc != 0)
1742 1756                          usage();
1743 1757          }
1744 1758  
1745 1759          if (a_arg) {
1746 1760                  boolean_t       stattype[DLADM_STAT_NUM_STATS];
1747 1761  
1748 1762                  bzero(&stattype, sizeof (stattype));
1749 1763                  if (r_arg) {
1750 1764                          stattype[DLADM_STAT_RX_LANE_TOTAL] = B_TRUE;
1751 1765                  } else if (t_arg) {
1752 1766                          stattype[DLADM_STAT_TX_LANE_TOTAL] = B_TRUE;
1753 1767                  } else {                /* Display both Rx and Tx lanes */
1754 1768                          stattype[DLADM_STAT_TOTAL] = B_TRUE;
1755 1769                  }
1756 1770  
1757 1771                  dump_all_link_stats(linkid, stattype);
1758 1772                  return;
1759 1773          }
1760 1774  
1761 1775          if (A_arg) {
1762 1776                  boolean_t       stattype[DLADM_STAT_NUM_STATS];
1763 1777                  int             i;
1764 1778  
1765 1779                  for (i = 0; i < DLADM_STAT_NUM_STATS; i++)
1766 1780                          stattype[i] = B_TRUE;
1767 1781  
1768 1782                  dump_all_link_stats(linkid, stattype);
1769 1783                  return;
1770 1784          }
1771 1785  
1772 1786          state.ls_unit = unit;
1773 1787          state.ls_parsable = p_arg;
1774 1788  
1775 1789          if (state.ls_parsable)
1776 1790                  ofmtflags |= OFMT_PARSABLE;
1777 1791  
1778 1792          if (r_arg) {
1779 1793                  fields_str = rx_total_stat_fields;
1780 1794                  oftemplate = rx_lane_s_fields;
1781 1795                  state.ls_stattype[DLADM_STAT_RX_LANE_TOTAL] = B_TRUE;
1782 1796                  state.ls_stats2str[DLADM_STAT_RX_LANE_TOTAL] =
1783 1797                      print_rx_lane_stats;
1784 1798          } else if (t_arg) {
1785 1799                  fields_str = tx_total_stat_fields;
1786 1800                  oftemplate = tx_lane_s_fields;
1787 1801                  state.ls_stattype[DLADM_STAT_TX_LANE_TOTAL] = B_TRUE;
1788 1802                  state.ls_stats2str[DLADM_STAT_TX_LANE_TOTAL] =
1789 1803                      print_tx_lane_stats;
1790 1804          } else {                /* Display both Rx and Tx lanes total */
1791 1805                  fields_str = total_stat_fields;
1792 1806                  oftemplate = total_s_fields;
1793 1807                  state.ls_stattype[DLADM_STAT_TOTAL] = B_TRUE;
1794 1808                  state.ls_stats2str[DLADM_STAT_TOTAL] = print_total_stats;
1795 1809          }
1796 1810  
1797 1811          if (o_arg) {
1798 1812                  fields_str = (strcasecmp(o_fields_str, "all") == 0) ?
1799 1813                      fields_str : o_fields_str;
1800 1814          }
1801 1815  
1802 1816          oferr = ofmt_open(fields_str, oftemplate, ofmtflags, 0, &ofmt);
1803 1817          dlstat_ofmt_check(oferr, state.ls_parsable, ofmt);
1804 1818          state.ls_ofmt = ofmt;
1805 1819  
1806 1820          show_link_stats(linkid, state, interval);
1807 1821  
1808 1822          ofmt_close(ofmt);
1809 1823  }
1810 1824  
1811 1825  static void
1812 1826  do_show_phys(int argc, char *argv[], const char *use)
1813 1827  {
1814 1828          int                     option;
1815 1829          boolean_t               r_arg = B_FALSE;
1816 1830          boolean_t               t_arg = B_FALSE;
1817 1831          boolean_t               i_arg = B_FALSE;
1818 1832          boolean_t               p_arg = B_FALSE;
1819 1833          boolean_t               o_arg = B_FALSE;
1820 1834          boolean_t               u_arg = B_FALSE;
1821 1835          boolean_t               a_arg = B_FALSE;
1822 1836          uint32_t                flags = DLADM_OPT_ACTIVE;
1823 1837          datalink_id_t           linkid = DATALINK_ALL_LINKID;
1824 1838          char                    linkname[MAXLINKNAMELEN];
1825 1839          uint32_t                interval = 0;
1826 1840          char                    unit = '\0';
1827 1841          show_state_t            state;
1828 1842          dladm_status_t          status;
1829 1843          char                    *fields_str = NULL;
1830 1844          char                    *o_fields_str = NULL;
1831 1845          char                    *ring_stat_fields =
1832 1846              "link,type,index,pkts,bytes";
1833 1847          char                    *rx_ring_stat_fields =
1834 1848              "link,type,index,ipkts,rbytes";
1835 1849          char                    *tx_ring_stat_fields =
1836 1850              "link,type,index,opkts,obytes";
1837 1851  
1838 1852          ofmt_handle_t           ofmt;
1839 1853          ofmt_status_t           oferr;
1840 1854          uint_t                  ofmtflags = OFMT_RIGHTJUST;
1841 1855          ofmt_field_t            *oftemplate;
1842 1856  
1843 1857          bzero(&state, sizeof (state));
1844 1858          opterr = 0;
1845 1859          while ((option = getopt_long(argc, argv, ":rtapi:o:u:",
1846 1860              NULL, NULL)) != -1) {
1847 1861                  switch (option) {
1848 1862                  case 'r':
1849 1863                          if (r_arg)
1850 1864                                  die_optdup(option);
1851 1865  
1852 1866                          r_arg = B_TRUE;
1853 1867                          break;
1854 1868                  case 't':
1855 1869                          if (t_arg)
1856 1870                                  die_optdup(option);
1857 1871  
1858 1872                          t_arg = B_TRUE;
1859 1873                          break;
1860 1874                  case 'a':
1861 1875                          if (a_arg)
1862 1876                                  die_optdup(option);
1863 1877  
1864 1878                          a_arg = B_TRUE;
1865 1879                          break;
1866 1880                  case 'i':
1867 1881                          if (i_arg)
1868 1882                                  die_optdup(option);
1869 1883  
1870 1884                          i_arg = B_TRUE;
1871 1885                          if (!dladm_str2interval(optarg, &interval))
1872 1886                                  die("invalid interval value '%s'", optarg);
1873 1887                          break;
1874 1888                  case 'p':
1875 1889                          if (p_arg)
1876 1890                                  die_optdup(option);
1877 1891  
1878 1892                          p_arg = B_TRUE;
1879 1893                          break;
1880 1894                  case 'o':
1881 1895                          o_arg = B_TRUE;
1882 1896                          o_fields_str = optarg;
1883 1897                          break;
1884 1898                  case 'u':
1885 1899                          if (u_arg)
1886 1900                                  die_optdup(option);
1887 1901  
1888 1902                          u_arg = B_TRUE;
1889 1903                          if (!dlstat_unit(optarg, &unit))
1890 1904                                  die("invalid unit value '%s',"
1891 1905                                      "unit must be R|K|M|G|T|P", optarg);
1892 1906                          break;
1893 1907                  default:
1894 1908                          die_opterr(optopt, option, use);
1895 1909                          break;
1896 1910                  }
1897 1911          }
1898 1912  
1899 1913          if (r_arg && t_arg)
1900 1914                  die("the options -t and -r are not compatible");
1901 1915  
1902 1916          if (u_arg && p_arg)
1903 1917                  die("the options -u and -p are not compatible");
1904 1918  
1905 1919          if (p_arg && !o_arg)
1906 1920                  die("-p requires -o");
1907 1921  
1908 1922          if (p_arg && strcasecmp(o_fields_str, "all") == 0)
1909 1923                  die("\"-o all\" is invalid with -p");
1910 1924  
1911 1925          if (a_arg &&
1912 1926              (p_arg || o_arg || u_arg || i_arg)) {
1913 1927                  die("the option -a is not compatible with "
1914 1928                      "-p, -o, -u, -i");
1915 1929          }
1916 1930  
1917 1931  
1918 1932          /* get link name (optional last argument) */
1919 1933          if (optind == (argc-1)) {
1920 1934                  if (strlen(argv[optind]) >= MAXLINKNAMELEN)
1921 1935                          die("link name too long");
1922 1936  
1923 1937                  if ((status = dladm_name2info(handle, argv[optind], &linkid,
1924 1938                      NULL, NULL, NULL)) != DLADM_STATUS_OK) {
1925 1939                          die_dlerr(status, "link %s is not valid", argv[optind]);
1926 1940                  }
1927 1941          } else if (optind != argc) {
1928 1942                  usage();
1929 1943          }
1930 1944  
1931 1945          if (a_arg) {
1932 1946                  boolean_t       stattype[DLADM_STAT_NUM_STATS];
1933 1947  
1934 1948                  bzero(&stattype, sizeof (stattype));
1935 1949  
1936 1950                  if (r_arg) {
1937 1951                          stattype[DLADM_STAT_RX_RING] = B_TRUE;
1938 1952                  } else if (t_arg) {
1939 1953                          stattype[DLADM_STAT_TX_RING] = B_TRUE;
1940 1954                  } else {                /* Display both Rx and Tx lanes */
1941 1955                          stattype[DLADM_STAT_RX_RING] = B_TRUE;
1942 1956                          stattype[DLADM_STAT_TX_RING] = B_TRUE;
1943 1957                  }
1944 1958  
1945 1959                  dump_all_link_stats(linkid, stattype);
1946 1960                  return;
1947 1961          }
1948 1962  
1949 1963          state.ls_unit = unit;
1950 1964          state.ls_parsable = p_arg;
1951 1965  
1952 1966          if (state.ls_parsable)
1953 1967                  ofmtflags |= OFMT_PARSABLE;
1954 1968  
1955 1969          if (r_arg) {
1956 1970                  fields_str = rx_ring_stat_fields;
1957 1971                  oftemplate = rx_ring_s_fields;
1958 1972                  state.ls_stattype[DLADM_STAT_RX_RING] = B_TRUE;
1959 1973                  state.ls_stats2str[DLADM_STAT_RX_RING] = print_rx_ring_stats;
1960 1974          } else if (t_arg) {
1961 1975                  fields_str = tx_ring_stat_fields;
1962 1976                  oftemplate = tx_ring_s_fields;
1963 1977                  state.ls_stattype[DLADM_STAT_TX_RING] = B_TRUE;
1964 1978                  state.ls_stats2str[DLADM_STAT_TX_RING] = print_tx_ring_stats;
1965 1979          } else {                /* Display both Rx and Tx lanes */
1966 1980                  fields_str = ring_stat_fields;
1967 1981                  oftemplate = ring_s_fields;
1968 1982                  state.ls_stattype[DLADM_STAT_RX_RING] = B_TRUE;
1969 1983                  state.ls_stattype[DLADM_STAT_TX_RING] = B_TRUE;
1970 1984                  state.ls_stats2str[DLADM_STAT_RX_RING] =
1971 1985                      print_rx_generic_ring_stats;
1972 1986                  state.ls_stats2str[DLADM_STAT_TX_RING] =
1973 1987                      print_tx_generic_ring_stats;
1974 1988          }
1975 1989  
1976 1990          if (o_arg) {
1977 1991                  fields_str = (strcasecmp(o_fields_str, "all") == 0) ?
1978 1992                      fields_str : o_fields_str;
1979 1993          }
1980 1994  
1981 1995          oferr = ofmt_open(fields_str, oftemplate, ofmtflags, 0, &ofmt);
1982 1996          dlstat_ofmt_check(oferr, state.ls_parsable, ofmt);
1983 1997          state.ls_ofmt = ofmt;
1984 1998  
1985 1999          show_link_stats(linkid, state, interval);
1986 2000  
1987 2001          ofmt_close(ofmt);
1988 2002  }
1989 2003  
1990 2004  static void
1991 2005  do_show_link(int argc, char *argv[], const char *use)
1992 2006  {
1993 2007          int                     option;
1994 2008          boolean_t               r_arg = B_FALSE;
1995 2009          boolean_t               F_arg = B_FALSE;
1996 2010          boolean_t               t_arg = B_FALSE;
1997 2011          boolean_t               i_arg = B_FALSE;
1998 2012          boolean_t               p_arg = B_FALSE;
1999 2013          boolean_t               o_arg = B_FALSE;
2000 2014          boolean_t               u_arg = B_FALSE;
2001 2015          boolean_t               a_arg = B_FALSE;
2002 2016          uint32_t                flags = DLADM_OPT_ACTIVE;
2003 2017          datalink_id_t           linkid = DATALINK_ALL_LINKID;
2004 2018          uint32_t                interval = 0;
2005 2019          char                    unit = '\0';
2006 2020          show_state_t            state;
2007 2021          dladm_status_t          status;
2008 2022          char                    *fields_str = NULL;
2009 2023          char                    *o_fields_str = NULL;
2010 2024  
2011 2025          char                    *lane_stat_fields =
2012 2026              "link,type,id,index,pkts,bytes";
2013 2027          char                    *rx_lane_stat_fields =
2014 2028              "link,type,id,index,ipkts,rbytes,intrs,polls,ch<10,ch10-50,ch>50";
2015 2029          char                    *tx_lane_stat_fields =
2016 2030              "link,type,id,index,opkts,obytes,blkcnt,ublkcnt";
2017 2031          char                    *rx_fanout_stat_fields =
2018 2032              "link,id,index,fout,ipkts,rbytes";
2019 2033  
2020 2034          ofmt_handle_t           ofmt;
2021 2035          ofmt_status_t           oferr;
2022 2036          uint_t                  ofmtflags = OFMT_RIGHTJUST;
2023 2037          ofmt_field_t            *oftemplate;
2024 2038  
2025 2039          bzero(&state, sizeof (state));
2026 2040          opterr = 0;
2027 2041          while ((option = getopt_long(argc, argv, ":hrtFapi:o:u:",
2028 2042              NULL, NULL)) != -1) {
2029 2043                  switch (option) {
2030 2044                  case 'h':
2031 2045                          if (r_arg || F_arg || t_arg || i_arg || p_arg ||
2032 2046                              o_arg || u_arg || a_arg) {
2033 2047                                  die("the option -h is not compatible with "
2034 2048                                      "-r, -F, -t, -i, -p, -o, -u, -a");
2035 2049                          }
2036 2050                          do_show_history(argc, &argv[0], use);
2037 2051                          return;
2038 2052                  case 'r':
2039 2053                          if (r_arg)
2040 2054                                  die_optdup(option);
2041 2055  
2042 2056                          r_arg = B_TRUE;
2043 2057                          break;
2044 2058                  case 'F':
2045 2059                          if (F_arg)
2046 2060                                  die_optdup(option);
2047 2061  
2048 2062                          F_arg = B_TRUE;
2049 2063                          break;
2050 2064                  case 't':
2051 2065                          if (t_arg)
2052 2066                                  die_optdup(option);
2053 2067  
2054 2068                          t_arg = B_TRUE;
2055 2069                          break;
2056 2070                  case 'a':
2057 2071                          if (a_arg)
2058 2072                                  die_optdup(option);
2059 2073  
2060 2074                          a_arg = B_TRUE;
2061 2075                          break;
2062 2076                  case 'i':
2063 2077                          if (i_arg)
2064 2078                                  die_optdup(option);
2065 2079  
2066 2080                          i_arg = B_TRUE;
2067 2081                          if (!dladm_str2interval(optarg, &interval))
2068 2082                                  die("invalid interval value '%s'", optarg);
2069 2083                          break;
2070 2084                  case 'p':
2071 2085                          if (p_arg)
2072 2086                                  die_optdup(option);
2073 2087  
2074 2088                          p_arg = B_TRUE;
2075 2089                          break;
2076 2090                  case 'o':
2077 2091                          o_arg = B_TRUE;
2078 2092                          o_fields_str = optarg;
2079 2093                          break;
2080 2094                  case 'u':
2081 2095                          if (u_arg)
2082 2096                                  die_optdup(option);
2083 2097  
2084 2098                          u_arg = B_TRUE;
2085 2099                          if (!dlstat_unit(optarg, &unit))
2086 2100                                  die("invalid unit value '%s',"
2087 2101                                      "unit must be R|K|M|G|T|P", optarg);
2088 2102                          break;
2089 2103                  default:
2090 2104                          die_opterr(optopt, option, use);
2091 2105                          break;
2092 2106                  }
2093 2107          }
2094 2108  
2095 2109          if (r_arg && t_arg)
2096 2110                  die("the options -t and -r are not compatible");
2097 2111  
2098 2112          if (u_arg && p_arg)
2099 2113                  die("the options -u and -p are not compatible");
2100 2114  
2101 2115          if (F_arg && !r_arg)
2102 2116                  die("-F must be used with -r");
2103 2117  
2104 2118          if (p_arg && !o_arg)
2105 2119                  die("-p requires -o");
2106 2120  
2107 2121          if (p_arg && strcasecmp(o_fields_str, "all") == 0)
2108 2122                  die("\"-o all\" is invalid with -p");
2109 2123  
2110 2124          if (a_arg &&
2111 2125              (p_arg || o_arg || u_arg || i_arg)) {
2112 2126                  die("the option -a is not compatible with "
2113 2127                      "-p, -o, -u, -i");
2114 2128          }
2115 2129  
2116 2130          /* get link name (optional last argument) */
2117 2131          if (optind == (argc-1)) {
2118 2132                  if (strlen(argv[optind]) >= MAXLINKNAMELEN)
2119 2133                          die("link name too long");
2120 2134  
2121 2135                  if ((status = dladm_name2info(handle, argv[optind], &linkid,
2122 2136                      NULL, NULL, NULL)) != DLADM_STATUS_OK) {
2123 2137                          die_dlerr(status, "link %s is not valid", argv[optind]);
2124 2138                  }
2125 2139          } else if (optind != argc) {
2126 2140                  usage();
2127 2141          }
2128 2142  
2129 2143          if (a_arg) {
2130 2144                  boolean_t       stattype[DLADM_STAT_NUM_STATS];
2131 2145  
2132 2146                  bzero(&stattype, sizeof (stattype));
2133 2147  
2134 2148                  if (r_arg) {
2135 2149                          if (F_arg) {
2136 2150                                  stattype[DLADM_STAT_RX_LANE_FOUT] = B_TRUE;
2137 2151                          } else {
2138 2152                                  stattype[DLADM_STAT_RX_LANE] = B_TRUE;
2139 2153                          }
2140 2154                  } else if (t_arg) {
2141 2155                          stattype[DLADM_STAT_TX_LANE] = B_TRUE;
2142 2156                  } else {                /* Display both Rx and Tx lanes */
2143 2157                          stattype[DLADM_STAT_RX_LANE] = B_TRUE;
2144 2158                          stattype[DLADM_STAT_TX_LANE] = B_TRUE;
2145 2159                  }
2146 2160  
2147 2161                  dump_all_link_stats(linkid, stattype);
2148 2162                  return;
2149 2163          }
2150 2164  
2151 2165          state.ls_unit = unit;
2152 2166          state.ls_parsable = p_arg;
2153 2167  
2154 2168          if (state.ls_parsable)
2155 2169                  ofmtflags |= OFMT_PARSABLE;
2156 2170  
2157 2171          if (r_arg) {
2158 2172                  if (F_arg) {
2159 2173                          fields_str = rx_fanout_stat_fields;
2160 2174                          oftemplate = rx_fanout_lane_s_fields;
2161 2175                          state.ls_stattype[DLADM_STAT_RX_LANE_FOUT] = B_TRUE;
2162 2176                          state.ls_stats2str[DLADM_STAT_RX_LANE_FOUT] =
2163 2177                              print_fanout_stats;
2164 2178                  } else {
2165 2179                          fields_str = rx_lane_stat_fields;
2166 2180                          oftemplate = rx_lane_s_fields;
2167 2181                          state.ls_stattype[DLADM_STAT_RX_LANE] = B_TRUE;
2168 2182                          state.ls_stats2str[DLADM_STAT_RX_LANE] =
2169 2183                              print_rx_lane_stats;
2170 2184                  }
2171 2185          } else if (t_arg) {
2172 2186                  fields_str = tx_lane_stat_fields;
2173 2187                  oftemplate = tx_lane_s_fields;
2174 2188                  state.ls_stattype[DLADM_STAT_TX_LANE] = B_TRUE;
2175 2189                  state.ls_stats2str[DLADM_STAT_TX_LANE] = print_tx_lane_stats;
2176 2190          } else {                /* Display both Rx and Tx lanes */
2177 2191                  fields_str = lane_stat_fields;
2178 2192                  oftemplate = lane_s_fields;
2179 2193                  state.ls_stattype[DLADM_STAT_RX_LANE] = B_TRUE;
2180 2194                  state.ls_stattype[DLADM_STAT_TX_LANE] = B_TRUE;
2181 2195                  state.ls_stats2str[DLADM_STAT_RX_LANE] =
2182 2196                      print_rx_generic_lane_stats;
2183 2197                  state.ls_stats2str[DLADM_STAT_TX_LANE] =
2184 2198                      print_tx_generic_lane_stats;
2185 2199          }
2186 2200          if (o_arg) {
2187 2201                  fields_str = (strcasecmp(o_fields_str, "all") == 0) ?
2188 2202                      fields_str : o_fields_str;
2189 2203          }
2190 2204  
2191 2205          oferr = ofmt_open(fields_str, oftemplate, ofmtflags, 0, &ofmt);
2192 2206          dlstat_ofmt_check(oferr, state.ls_parsable, ofmt);
2193 2207  
2194 2208          state.ls_ofmt = ofmt;
2195 2209  
2196 2210          show_link_stats(linkid, state, interval);
2197 2211  
2198 2212          ofmt_close(ofmt);
2199 2213  }
2200 2214  
2201 2215  static void
2202 2216  do_show_aggr(int argc, char *argv[], const char *use)
2203 2217  {
2204 2218          int                     option;
2205 2219          boolean_t               r_arg = B_FALSE;
2206 2220          boolean_t               t_arg = B_FALSE;
2207 2221          boolean_t               i_arg = B_FALSE;
2208 2222          boolean_t               p_arg = B_FALSE;
2209 2223          boolean_t               o_arg = B_FALSE;
2210 2224          boolean_t               u_arg = B_FALSE;
2211 2225          uint32_t                flags = DLADM_OPT_ACTIVE;
2212 2226          datalink_id_t           linkid = DATALINK_ALL_LINKID;
2213 2227          uint32_t                interval = 0;
2214 2228          char                    unit = '\0';
2215 2229          show_state_t            state;
2216 2230          dladm_status_t          status;
2217 2231          char                    *fields_str = NULL;
2218 2232          char                    *o_fields_str = NULL;
2219 2233  
2220 2234          char                    *aggr_stat_fields =
2221 2235              "link,port,ipkts,rbytes,opkts,obytes";
2222 2236          char                    *rx_aggr_stat_fields = "link,port,ipkts,rbytes";
2223 2237          char                    *tx_aggr_stat_fields = "link,port,opkts,obytes";
2224 2238  
2225 2239          ofmt_handle_t           ofmt;
2226 2240          ofmt_status_t           oferr;
2227 2241          uint_t                  ofmtflags = OFMT_RIGHTJUST;
2228 2242          ofmt_field_t            *oftemplate;
2229 2243  
2230 2244          bzero(&state, sizeof (state));
2231 2245          opterr = 0;
2232 2246          while ((option = getopt_long(argc, argv, ":rtpi:o:u:",
2233 2247              NULL, NULL)) != -1) {
2234 2248                  switch (option) {
2235 2249                  case 'r':
2236 2250                          if (r_arg)
2237 2251                                  die_optdup(option);
2238 2252  
2239 2253                          r_arg = B_TRUE;
2240 2254                          break;
2241 2255                  case 't':
2242 2256                          if (t_arg)
2243 2257                                  die_optdup(option);
2244 2258  
2245 2259                          t_arg = B_TRUE;
2246 2260                          break;
2247 2261                  case 'i':
2248 2262                          if (i_arg)
2249 2263                                  die_optdup(option);
2250 2264  
2251 2265                          i_arg = B_TRUE;
2252 2266                          if (!dladm_str2interval(optarg, &interval))
2253 2267                                  die("invalid interval value '%s'", optarg);
2254 2268                          break;
2255 2269                  case 'p':
2256 2270                          if (p_arg)
2257 2271                                  die_optdup(option);
2258 2272  
2259 2273                          p_arg = B_TRUE;
2260 2274                          break;
2261 2275                  case 'o':
2262 2276                          o_arg = B_TRUE;
2263 2277                          o_fields_str = optarg;
2264 2278                          break;
2265 2279                  case 'u':
2266 2280                          if (u_arg)
2267 2281                                  die_optdup(option);
2268 2282  
2269 2283                          u_arg = B_TRUE;
2270 2284                          if (!dlstat_unit(optarg, &unit))
2271 2285                                  die("invalid unit value '%s',"
2272 2286                                      "unit must be R|K|M|G|T|P", optarg);
2273 2287                          break;
2274 2288                  default:
2275 2289                          die_opterr(optopt, option, use);
2276 2290                          break;
2277 2291                  }
2278 2292          }
2279 2293  
2280 2294          if (r_arg && t_arg)
2281 2295                  die("the options -t and -r are not compatible");
2282 2296  
2283 2297          if (u_arg && p_arg)
2284 2298                  die("the options -u and -p are not compatible");
2285 2299  
2286 2300          if (p_arg && !o_arg)
2287 2301                  die("-p requires -o");
2288 2302  
2289 2303          if (p_arg && strcasecmp(o_fields_str, "all") == 0)
2290 2304                  die("\"-o all\" is invalid with -p");
2291 2305  
2292 2306  
2293 2307          /* get link name (optional last argument) */
2294 2308          if (optind == (argc-1)) {
2295 2309                  if (strlen(argv[optind]) >= MAXLINKNAMELEN)
2296 2310                          die("link name too long");
2297 2311  
2298 2312                  if ((status = dladm_name2info(handle, argv[optind], &linkid,
2299 2313                      NULL, NULL, NULL)) != DLADM_STATUS_OK) {
2300 2314                          die_dlerr(status, "link %s is not valid", argv[optind]);
2301 2315                  }
2302 2316          } else if (optind != argc) {
2303 2317                  usage();
2304 2318          }
2305 2319  
2306 2320          state.ls_unit = unit;
2307 2321          state.ls_parsable = p_arg;
2308 2322  
2309 2323          if (state.ls_parsable)
2310 2324                  ofmtflags |= OFMT_PARSABLE;
2311 2325  
2312 2326          oftemplate = aggr_port_s_fields;
2313 2327          state.ls_stattype[DLADM_STAT_AGGR_PORT] = B_TRUE;
2314 2328          state.ls_stats2str[DLADM_STAT_AGGR_PORT] = print_aggr_port_stats;
2315 2329  
2316 2330          if (r_arg)
2317 2331                  fields_str = rx_aggr_stat_fields;
2318 2332          else if (t_arg)
2319 2333                  fields_str = tx_aggr_stat_fields;
2320 2334          else
2321 2335                  fields_str = aggr_stat_fields;
2322 2336  
2323 2337          if (o_arg) {
2324 2338                  fields_str = (strcasecmp(o_fields_str, "all") == 0) ?
2325 2339                      fields_str : o_fields_str;
2326 2340          }
2327 2341  
2328 2342          oferr = ofmt_open(fields_str, oftemplate, ofmtflags, 0, &ofmt);
2329 2343          dlstat_ofmt_check(oferr, state.ls_parsable, ofmt);
2330 2344          state.ls_ofmt = ofmt;
2331 2345  
2332 2346          show_link_stats(linkid, state, interval);
2333 2347  
2334 2348          ofmt_close(ofmt);
2335 2349  }
2336 2350  
2337 2351  /* PRINTFLIKE1 */
2338 2352  static void
2339 2353  warn(const char *format, ...)
2340 2354  {
2341 2355          va_list alist;
2342 2356  
2343 2357          format = gettext(format);
2344 2358          (void) fprintf(stderr, "%s: warning: ", progname);
2345 2359  
2346 2360          va_start(alist, format);
2347 2361          (void) vfprintf(stderr, format, alist);
2348 2362          va_end(alist);
2349 2363  
2350 2364          (void) putc('\n', stderr);
2351 2365  }
2352 2366  
2353 2367  /*
2354 2368   * Also closes the dladm handle if it is not NULL.
2355 2369   */
2356 2370  /* PRINTFLIKE2 */
2357 2371  static void
2358 2372  die_dlerr(dladm_status_t err, const char *format, ...)
2359 2373  {
2360 2374          va_list alist;
2361 2375          char    errmsg[DLADM_STRSIZE];
2362 2376  
2363 2377          format = gettext(format);
2364 2378          (void) fprintf(stderr, "%s: ", progname);
2365 2379  
2366 2380          va_start(alist, format);
2367 2381          (void) vfprintf(stderr, format, alist);
2368 2382          va_end(alist);
2369 2383          (void) fprintf(stderr, ": %s\n", dladm_status2str(err, errmsg));
2370 2384  
2371 2385          /* close dladm handle if it was opened */
2372 2386          if (handle != NULL)
2373 2387                  dladm_close(handle);
2374 2388  
2375 2389          exit(EXIT_FAILURE);
2376 2390  }
2377 2391  
2378 2392  /* PRINTFLIKE1 */
2379 2393  static void
2380 2394  die(const char *format, ...)
2381 2395  {
2382 2396          va_list alist;
2383 2397  
2384 2398          format = gettext(format);
2385 2399          (void) fprintf(stderr, "%s: ", progname);
2386 2400  
2387 2401          va_start(alist, format);
2388 2402          (void) vfprintf(stderr, format, alist);
2389 2403          va_end(alist);
2390 2404  
2391 2405          (void) putc('\n', stderr);
2392 2406  
2393 2407          /* close dladm handle if it was opened */
2394 2408          if (handle != NULL)
2395 2409                  dladm_close(handle);
2396 2410  
2397 2411          exit(EXIT_FAILURE);
2398 2412  }
2399 2413  
2400 2414  static void
2401 2415  die_optdup(int opt)
2402 2416  {
2403 2417          die("the option -%c cannot be specified more than once", opt);
2404 2418  }
2405 2419  
2406 2420  static void
2407 2421  die_opterr(int opt, int opterr, const char *usage)
2408 2422  {
2409 2423          switch (opterr) {
2410 2424          case ':':
2411 2425                  die("option '-%c' requires a value\nusage: %s", opt,
2412 2426                      gettext(usage));
2413 2427                  break;
2414 2428          case '?':
2415 2429          default:
2416 2430                  die("unrecognized option '-%c'\nusage: %s", opt,
2417 2431                      gettext(usage));
2418 2432                  break;
2419 2433          }
2420 2434  }
2421 2435  
2422 2436  /*
2423 2437   * default output callback function that, when invoked,
2424 2438   * prints string which is offset by ofmt_arg->ofmt_id within buf.
2425 2439   */
2426 2440  static boolean_t
2427 2441  print_default_cb(ofmt_arg_t *ofarg, char *buf, uint_t bufsize)
2428 2442  {
2429 2443          char *value;
2430 2444  
2431 2445          value = (char *)ofarg->ofmt_cbarg + ofarg->ofmt_id;
2432 2446          (void) strlcpy(buf, value, bufsize);
2433 2447          return (B_TRUE);
2434 2448  }
2435 2449  
2436 2450  static void
2437 2451  dlstat_ofmt_check(ofmt_status_t oferr, boolean_t parsable,
2438 2452      ofmt_handle_t ofmt)
2439 2453  {
2440 2454          char buf[OFMT_BUFSIZE];
2441 2455  
2442 2456          if (oferr == OFMT_SUCCESS)
2443 2457                  return;
2444 2458          (void) ofmt_strerror(ofmt, oferr, buf, sizeof (buf));
2445 2459          /*
2446 2460           * All errors are considered fatal in parsable mode.
2447 2461           * NOMEM errors are always fatal, regardless of mode.
2448 2462           * For other errors, we print diagnostics in human-readable
2449 2463           * mode and processs what we can.
2450 2464           */
2451 2465          if (parsable || oferr == OFMT_ENOFIELDS) {
2452 2466                  ofmt_close(ofmt);
2453 2467                  die(buf);
2454 2468          } else {
2455 2469                  warn(buf);
2456 2470          }
2457 2471  }
  
    | 
      ↓ open down ↓ | 
    816 lines elided | 
    
      ↑ open up ↑ | 
  
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX