Print this page
OS-277 add ZONE column to dlstat output


  45 #include <libintl.h>
  46 #include <libdevinfo.h>
  47 #include <libdlpi.h>
  48 #include <libdladm.h>
  49 #include <libdllink.h>
  50 #include <libdlstat.h>
  51 #include <libdlaggr.h>
  52 #include <libinetutil.h>
  53 #include <bsm/adt.h>
  54 #include <bsm/adt_event.h>
  55 #include <stddef.h>
  56 #include <ofmt.h>
  57 
  58 typedef struct link_chain_s {
  59         datalink_id_t           lc_linkid;
  60         boolean_t               lc_visited;
  61         dladm_stat_chain_t      *lc_statchain[DLADM_STAT_NUM_STATS];
  62         struct link_chain_s     *lc_next;
  63 } link_chain_t;
  64 
  65 typedef void *  (*stats2str_t)(const char *, void *,
  66                     char, boolean_t);
  67 
  68 typedef struct show_state {
  69         link_chain_t    *ls_linkchain;
  70         boolean_t       ls_stattype[DLADM_STAT_NUM_STATS];
  71         stats2str_t     ls_stats2str[DLADM_STAT_NUM_STATS];
  72         ofmt_handle_t   ls_ofmt;
  73         char            ls_unit;
  74         boolean_t       ls_parsable;
  75 } show_state_t;
  76 
  77 typedef struct show_history_state_s {
  78         boolean_t       hs_plot;
  79         boolean_t       hs_parsable;
  80         boolean_t       hs_printheader;
  81         boolean_t       hs_first;
  82         boolean_t       hs_showall;
  83         ofmt_handle_t   hs_ofmt;
  84 } show_history_state_t;
  85 


 124             "                 [-s <DD/MM/YYYY,HH:MM:SS>] "
 125             "[-e <DD/MM/YYYY,HH:MM:SS>]\n"
 126             "                 -f <logfile> [<link>]" },
 127         { "show-aggr", do_show_aggr,
 128             "dlstat show-aggr [-r | -t] [-i interval] [-p]\n"
 129             "                 [ -o field[,...]] [-u R|K|M|G|T|P] "
 130             " [link]" }
 131 };
 132 
 133 #define MAXSTATLEN 15
 134 
 135 /*
 136  * dlstat : total stat fields
 137  */
 138 typedef struct total_fields_buf_s {
 139         char t_linkname[MAXLINKNAMELEN];
 140         char t_ipackets[MAXSTATLEN];
 141         char t_rbytes[MAXSTATLEN];
 142         char t_opackets[MAXSTATLEN];
 143         char t_obytes[MAXSTATLEN];

 144 } total_fields_buf_t;
 145 
 146 static ofmt_field_t total_s_fields[] = {
 147 { "LINK",       15,
 148     offsetof(total_fields_buf_t, t_linkname),   print_default_cb},
 149 { "IPKTS",      8,
 150     offsetof(total_fields_buf_t, t_ipackets),   print_default_cb},
 151 { "RBYTES",     8,
 152     offsetof(total_fields_buf_t, t_rbytes),     print_default_cb},
 153 { "OPKTS",      8,
 154     offsetof(total_fields_buf_t, t_opackets),   print_default_cb},
 155 { "OBYTES",     8,
 156     offsetof(total_fields_buf_t, t_obytes),     print_default_cb},


 157 { NULL,         0,      0,              NULL}};
 158 
 159 /*
 160  * dlstat show-phys: both Rx and Tx stat fields
 161  */
 162 typedef struct ring_fields_buf_s {
 163         char r_linkname[MAXLINKNAMELEN];
 164         char r_type[MAXSTATLEN];
 165         char r_id[MAXSTATLEN];
 166         char r_index[MAXSTATLEN];
 167         char r_packets[MAXSTATLEN];
 168         char r_bytes[MAXSTATLEN];
 169 } ring_fields_buf_t;
 170 
 171 static ofmt_field_t ring_s_fields[] = {
 172 { "LINK",       15,
 173     offsetof(ring_fields_buf_t, r_linkname),    print_default_cb},
 174 { "TYPE",       5,
 175     offsetof(ring_fields_buf_t, r_type),        print_default_cb},
 176 { "ID",         7,


 940                 }
 941                                 /* Is it head of the list? */
 942                 if (lcurr == state->ls_linkchain)
 943                         state->ls_linkchain = lcurr->lc_next;
 944                 else
 945                         lprev->lc_next = lcurr->lc_next;
 946                                 /* lprev remains the same */
 947                 tofree = lcurr;
 948                 lcurr = lcurr->lc_next;
 949 
 950                                 /* Free stats memory for the removed link */
 951                 for (i = 0; i < DLADM_STAT_NUM_STATS; i++) {
 952                         if (state->ls_stattype[i])
 953                                 dladm_link_stat_free(tofree->lc_statchain[i]);
 954                 }
 955                 free(tofree);
 956         }
 957 }
 958 
 959 void *
 960 print_total_stats(const char *linkname, void *statentry, char unit,
 961     boolean_t parsable)
 962 {
 963         total_stat_entry_t      *sentry = statentry;
 964         total_stat_t            *link_stats = &sentry->tse_stats;
 965         total_fields_buf_t      *buf;
 966 
 967         buf = malloc(sizeof (total_fields_buf_t));
 968         if (buf == NULL)
 969                 goto done;
 970 
 971         (void) snprintf(buf->t_linkname, sizeof (buf->t_linkname), "%s",
 972             linkname);

 973 
 974         map_to_units(buf->t_ipackets, sizeof (buf->t_ipackets),
 975             link_stats->ts_ipackets, unit, parsable);
 976 
 977         map_to_units(buf->t_rbytes, sizeof (buf->t_rbytes),
 978             link_stats->ts_rbytes, unit, parsable);
 979 
 980         map_to_units(buf->t_opackets, sizeof (buf->t_opackets),
 981             link_stats->ts_opackets, unit, parsable);
 982 
 983         map_to_units(buf->t_obytes, sizeof (buf->t_obytes),
 984             link_stats->ts_obytes, unit, parsable);
 985 
 986 done:
 987         return (buf);
 988 }
 989 
 990 void *
 991 print_rx_generic_ring_stats(const char *linkname, void *statentry, char unit,
 992     boolean_t parsable)
 993 {
 994         ring_stat_entry_t       *sentry = statentry;
 995         ring_stat_t             *link_stats = &sentry->re_stats;
 996         ring_fields_buf_t       *buf;
 997 
 998         buf = malloc(sizeof (ring_fields_buf_t));
 999         if (buf == NULL)
1000                 goto done;
1001 
1002         (void) snprintf(buf->r_linkname, sizeof (buf->r_linkname), "%s",
1003             linkname);
1004 
1005         (void) snprintf(buf->r_type, sizeof (buf->r_type), "rx");
1006 
1007         if (sentry->re_index == DLSTAT_INVALID_ENTRY) {
1008                 (void) snprintf(buf->r_index, sizeof (buf->r_index), "--");
1009         } else {
1010                 (void) snprintf(buf->r_index, sizeof (buf->r_index),
1011                     "%llu", sentry->re_index);
1012         }
1013 
1014         map_to_units(buf->r_packets, sizeof (buf->r_packets),
1015             link_stats->r_packets, unit, parsable);
1016 
1017         map_to_units(buf->r_bytes, sizeof (buf->r_bytes),
1018             link_stats->r_bytes, unit, parsable);
1019 
1020 done:
1021         return (buf);
1022 }
1023 
1024 void *
1025 print_tx_generic_ring_stats(const char *linkname, void *statentry, char unit,
1026     boolean_t parsable)
1027 {
1028         ring_stat_entry_t       *sentry = statentry;
1029         ring_stat_t             *link_stats = &sentry->re_stats;
1030         ring_fields_buf_t       *buf;
1031 
1032         buf = malloc(sizeof (ring_fields_buf_t));
1033         if (buf == NULL)
1034                 goto done;
1035 
1036         (void) snprintf(buf->r_linkname, sizeof (buf->r_linkname), "%s",
1037             linkname);
1038 
1039         (void) snprintf(buf->r_type, sizeof (buf->r_type), "tx");
1040 
1041         if (sentry->re_index == DLSTAT_INVALID_ENTRY) {
1042                 (void) snprintf(buf->r_index, sizeof (buf->r_index), "--");
1043         } else {
1044                 (void) snprintf(buf->r_index, sizeof (buf->r_index),
1045                     "%llu", sentry->re_index);
1046         }
1047 
1048         map_to_units(buf->r_packets, sizeof (buf->r_packets),
1049             link_stats->r_packets, unit, parsable);
1050 
1051         map_to_units(buf->r_bytes, sizeof (buf->r_bytes),
1052             link_stats->r_bytes, unit, parsable);
1053 
1054 done:
1055         return (buf);
1056 }
1057 
1058 void *
1059 print_rx_ring_stats(const char *linkname, void *statentry, char unit,
1060     boolean_t parsable)
1061 {
1062         ring_stat_entry_t       *sentry = statentry;
1063         ring_stat_t             *link_stats = &sentry->re_stats;
1064         rx_ring_fields_buf_t    *buf;
1065 
1066         buf = malloc(sizeof (rx_ring_fields_buf_t));
1067         if (buf == NULL)
1068                 goto done;
1069 
1070         (void) snprintf(buf->rr_linkname, sizeof (buf->rr_linkname), "%s",
1071             linkname);
1072 
1073         (void) snprintf(buf->rr_type, sizeof (buf->rr_type), "rx");
1074 
1075         if (sentry->re_index == DLSTAT_INVALID_ENTRY) {
1076                 (void) snprintf(buf->rr_index, sizeof (buf->rr_index), "--");
1077         } else {
1078                 (void) snprintf(buf->rr_index, sizeof (buf->rr_index),
1079                     "%llu", sentry->re_index);
1080         }
1081 
1082         map_to_units(buf->rr_ipackets, sizeof (buf->rr_ipackets),
1083             link_stats->r_packets, unit, parsable);
1084 
1085         map_to_units(buf->rr_rbytes, sizeof (buf->rr_rbytes),
1086             link_stats->r_bytes, unit, parsable);
1087 
1088 done:
1089         return (buf);
1090 }
1091 
1092 void *
1093 print_tx_ring_stats(const char *linkname, void *statentry, char unit,
1094     boolean_t parsable)
1095 {
1096         ring_stat_entry_t       *sentry = statentry;
1097         ring_stat_t             *link_stats = &sentry->re_stats;
1098         tx_ring_fields_buf_t    *buf;
1099 
1100         buf = malloc(sizeof (tx_ring_fields_buf_t));
1101         if (buf == NULL)
1102                 goto done;
1103 
1104         (void) snprintf(buf->tr_linkname, sizeof (buf->tr_linkname), "%s",
1105             linkname);
1106 
1107         (void) snprintf(buf->tr_type, sizeof (buf->tr_type), "tx");
1108 
1109         if (sentry->re_index == DLSTAT_INVALID_ENTRY) {
1110                 (void) snprintf(buf->tr_index, sizeof (buf->tr_index), "--");
1111         } else {
1112                 (void) snprintf(buf->tr_index, sizeof (buf->tr_index),
1113                     "%llu", sentry->re_index);
1114         }
1115 
1116         map_to_units(buf->tr_opackets, sizeof (buf->tr_opackets),
1117             link_stats->r_packets, unit, parsable);
1118 
1119         map_to_units(buf->tr_obytes, sizeof (buf->tr_obytes),
1120             link_stats->r_bytes, unit, parsable);
1121 
1122 done:
1123         return (buf);
1124 }
1125 
1126 void *
1127 print_rx_generic_lane_stats(const char *linkname, void *statentry, char unit,
1128     boolean_t parsable)
1129 {
1130         rx_lane_stat_entry_t    *sentry = statentry;
1131         rx_lane_stat_t          *link_stats = &sentry->rle_stats;
1132         lane_fields_buf_t       *buf;
1133 
1134         if (sentry->rle_id == L_DFNCT)
1135                 return (NULL);
1136 
1137         buf = malloc(sizeof (lane_fields_buf_t));
1138         if (buf == NULL)
1139                 goto done;
1140 
1141         (void) snprintf(buf->l_linkname, sizeof (buf->l_linkname), "%s",
1142             linkname);
1143 
1144         (void) snprintf(buf->l_type, sizeof (buf->l_type), "rx");
1145 
1146         if (sentry->rle_id == L_HWLANE)
1147                 (void) snprintf(buf->l_id, sizeof (buf->l_id), "hw");
1148         else if (sentry->rle_id == L_SWLANE)


1155                 (void) snprintf(buf->l_id, sizeof (buf->l_id), "--");
1156 
1157         if (sentry->rle_index == DLSTAT_INVALID_ENTRY) {
1158                 (void) snprintf(buf->l_index, sizeof (buf->l_index), "--");
1159         } else {
1160                 (void) snprintf(buf->l_index, sizeof (buf->l_index),
1161                     "%llu", sentry->rle_index);
1162         }
1163 
1164         map_to_units(buf->l_packets, sizeof (buf->l_packets),
1165             link_stats->rl_ipackets, unit, parsable);
1166 
1167         map_to_units(buf->l_bytes, sizeof (buf->l_bytes),
1168             link_stats->rl_rbytes, unit, parsable);
1169 
1170 done:
1171         return (buf);
1172 }
1173 
1174 void *
1175 print_tx_generic_lane_stats(const char *linkname, void *statentry, char unit,
1176     boolean_t parsable)
1177 {
1178         tx_lane_stat_entry_t    *sentry = statentry;
1179         tx_lane_stat_t          *link_stats = &sentry->tle_stats;
1180         lane_fields_buf_t       *buf;
1181 
1182         if (sentry->tle_id == L_DFNCT)
1183                 return (NULL);
1184 
1185         buf = malloc(sizeof (lane_fields_buf_t));
1186         if (buf == NULL)
1187                 goto done;
1188 
1189         (void) snprintf(buf->l_linkname, sizeof (buf->l_linkname), "%s",
1190             linkname);
1191 
1192         (void) snprintf(buf->l_type, sizeof (buf->l_type), "tx");
1193 
1194         if (sentry->tle_id == L_HWLANE)
1195                 (void) snprintf(buf->l_id, sizeof (buf->l_id), "hw");
1196         else if (sentry->tle_id == L_SWLANE)


1200         else
1201                 (void) snprintf(buf->l_id, sizeof (buf->l_id), "--");
1202 
1203         if (sentry->tle_index == DLSTAT_INVALID_ENTRY) {
1204                 (void) snprintf(buf->l_index, sizeof (buf->l_index), "--");
1205         } else {
1206                 (void) snprintf(buf->l_index, sizeof (buf->l_index),
1207                     "%llu", sentry->tle_index);
1208         }
1209         map_to_units(buf->l_packets, sizeof (buf->l_packets),
1210             link_stats->tl_opackets, unit, parsable);
1211 
1212         map_to_units(buf->l_bytes, sizeof (buf->l_bytes),
1213             link_stats->tl_obytes, unit, parsable);
1214 
1215 done:
1216         return (buf);
1217 }
1218 
1219 void *
1220 print_rx_lane_stats(const char *linkname, void *statentry, char unit,
1221     boolean_t parsable)
1222 {
1223         rx_lane_stat_entry_t    *sentry = statentry;
1224         rx_lane_stat_t          *link_stats = &sentry->rle_stats;
1225         rx_lane_fields_buf_t    *buf;
1226 
1227         if (sentry->rle_id == L_DFNCT)
1228                 return (NULL);
1229 
1230         buf = malloc(sizeof (rx_lane_fields_buf_t));
1231         if (buf == NULL)
1232                 goto done;
1233 
1234         (void) snprintf(buf->rl_linkname, sizeof (buf->rl_linkname), "%s",
1235             linkname);
1236 
1237         (void) snprintf(buf->rl_type, sizeof (buf->rl_type), "rx");
1238 
1239         if (sentry->rle_id == L_HWLANE)
1240                 (void) snprintf(buf->rl_id, sizeof (buf->rl_id), "hw");
1241         else if (sentry->rle_id == L_SWLANE)


1266         map_to_units(buf->rl_polls, sizeof (buf->rl_polls),
1267             link_stats->rl_polls, unit, parsable);
1268 
1269         map_to_units(buf->rl_sdrops, sizeof (buf->rl_sdrops),
1270             link_stats->rl_sdrops, unit, parsable);
1271 
1272         map_to_units(buf->rl_chl10, sizeof (buf->rl_chl10),
1273             link_stats->rl_chl10, unit, parsable);
1274 
1275         map_to_units(buf->rl_ch10_50, sizeof (buf->rl_ch10_50),
1276             link_stats->rl_ch10_50, unit, parsable);
1277 
1278         map_to_units(buf->rl_chg50, sizeof (buf->rl_chg50),
1279             link_stats->rl_chg50, unit, parsable);
1280 
1281 done:
1282         return (buf);
1283 }
1284 
1285 void *
1286 print_tx_lane_stats(const char *linkname, void *statentry, char unit,
1287     boolean_t parsable)
1288 {
1289         tx_lane_stat_entry_t    *sentry = statentry;
1290         tx_lane_stat_t          *link_stats = &sentry->tle_stats;
1291         tx_lane_fields_buf_t    *buf = NULL;
1292 
1293         if (sentry->tle_id == L_DFNCT)
1294                 return (NULL);
1295 
1296         buf = malloc(sizeof (tx_lane_fields_buf_t));
1297         if (buf == NULL)
1298                 goto done;
1299 
1300         (void) snprintf(buf->tl_linkname, sizeof (buf->tl_linkname), "%s",
1301             linkname);
1302 
1303         (void) snprintf(buf->tl_type, sizeof (buf->tl_type), "tx");
1304 
1305         if (sentry->tle_id == L_HWLANE)
1306                 (void) snprintf(buf->tl_id, sizeof (buf->tl_id), "hw");
1307         else if (sentry->tle_id == L_SWLANE)
1308                 (void) snprintf(buf->tl_id, sizeof (buf->tl_id), "sw");


1321         map_to_units(buf->tl_opackets, sizeof (buf->tl_opackets),
1322             link_stats->tl_opackets, unit, parsable);
1323 
1324         map_to_units(buf->tl_obytes, sizeof (buf->tl_obytes),
1325             link_stats->tl_obytes, unit, parsable);
1326 
1327         map_to_units(buf->tl_blockcnt, sizeof (buf->tl_blockcnt),
1328             link_stats->tl_blockcnt, unit, parsable);
1329 
1330         map_to_units(buf->tl_unblockcnt, sizeof (buf->tl_unblockcnt),
1331             link_stats->tl_unblockcnt, unit, parsable);
1332 
1333         map_to_units(buf->tl_sdrops, sizeof (buf->tl_sdrops),
1334             link_stats->tl_sdrops, unit, parsable);
1335 
1336 done:
1337         return (buf);
1338 }
1339 
1340 void *
1341 print_fanout_stats(const char *linkname, void *statentry, char unit,
1342     boolean_t parsable)
1343 {
1344         fanout_stat_entry_t             *sentry = statentry;
1345         fanout_stat_t                   *link_stats = &sentry->fe_stats;
1346         rx_fanout_lane_fields_buf_t     *buf;
1347 
1348         buf = malloc(sizeof (rx_fanout_lane_fields_buf_t));
1349         if (buf == NULL)
1350                 goto done;
1351 
1352         (void) snprintf(buf->rfl_linkname, sizeof (buf->rfl_linkname), "%s",
1353             linkname);
1354 
1355         (void) snprintf(buf->rfl_type, sizeof (buf->rfl_type), "rx");
1356 
1357         if (sentry->fe_id == L_HWLANE)
1358                 (void) snprintf(buf->rfl_id, sizeof (buf->rfl_id), "hw");
1359         else if (sentry->fe_id == L_SWLANE)
1360                 (void) snprintf(buf->rfl_id, sizeof (buf->rfl_id), "sw");
1361         else if (sentry->fe_id == L_LCLSWLANE)
1362                 (void) snprintf(buf->rfl_id, sizeof (buf->rfl_id), "lcl/sw");


1375         }
1376 
1377         if (sentry->fe_foutindex == DLSTAT_INVALID_ENTRY)
1378                 (void) snprintf(buf->rfl_fout, sizeof (buf->rfl_fout), "--");
1379         else {
1380                 (void) snprintf(buf->rfl_fout, sizeof (buf->rfl_fout), "%llu",
1381                     sentry->fe_foutindex);
1382         }
1383 
1384         map_to_units(buf->rfl_ipackets, sizeof (buf->rfl_ipackets),
1385             link_stats->f_ipackets, unit, parsable);
1386 
1387         map_to_units(buf->rfl_rbytes, sizeof (buf->rfl_rbytes),
1388             link_stats->f_rbytes, unit, parsable);
1389 
1390 done:
1391         return (buf);
1392 }
1393 
1394 void *
1395 print_aggr_port_stats(const char *linkname, void *statentry, char unit,
1396     boolean_t parsable)
1397 {
1398         aggr_port_stat_entry_t  *sentry = statentry;
1399         aggr_port_stat_t        *link_stats = &sentry->ape_stats;
1400         aggr_port_fields_buf_t  *buf;
1401         char                    portname[MAXLINKNAMELEN];
1402 
1403         buf = malloc(sizeof (aggr_port_fields_buf_t));
1404         if (buf == NULL)
1405                 goto done;
1406 
1407         (void) snprintf(buf->ap_linkname, sizeof (buf->ap_linkname), "%s",
1408             linkname);
1409 
1410         if (dladm_datalink_id2info(handle, sentry->ape_portlinkid, NULL,
1411             NULL, NULL, portname, DLPI_LINKNAME_MAX)
1412             != DLADM_STATUS_OK) {
1413                 (void) snprintf(buf->ap_portname,
1414                     sizeof (buf->ap_portname), "--");
1415         } else {
1416                 (void) snprintf(buf->ap_portname,


1453         /* Query library for current stats */
1454         curr_stat = dladm_link_stat_query(dh, linkid, stattype);
1455         if (curr_stat == NULL)
1456                 goto done;
1457 
1458         /* current stats - prev iteration stats */
1459         diff_stat = dladm_link_stat_diffchain(curr_stat, prev_stat, stattype);
1460 
1461         /* Free prev stats */
1462         dladm_link_stat_free(prev_stat);
1463 
1464         /* Prev <- curr stats */
1465         link_node->lc_statchain[stattype] = curr_stat;
1466 
1467 done:
1468         return (diff_stat);
1469 }
1470 
1471 void
1472 walk_dlstat_stats(show_state_t *state, const char *linkname,
1473     dladm_stat_type_t stattype, dladm_stat_chain_t *diff_stat)

1474 {
1475         dladm_stat_chain_t  *curr;
1476 
1477         /* Unpack invidual stat entry and call library consumer's callback */
1478         for (curr = diff_stat; curr != NULL; curr = curr->dc_next) {
1479                 void    *fields_buf;
1480 
1481                 /* Format the raw numbers for printing */
1482                 fields_buf = state->ls_stats2str[stattype](linkname,
1483                     curr->dc_statentry, state->ls_unit, state->ls_parsable);

1484                 /* Print the stats */
1485                 if (fields_buf != NULL)
1486                         ofmt_print(state->ls_ofmt, fields_buf);
1487                 free(fields_buf);
1488         }
1489 }
1490 
1491 static int
1492 show_queried_stats(dladm_handle_t dh, datalink_id_t linkid, void *arg)
1493 {
1494         show_state_t            *state = arg;
1495         int                     i;
1496         dladm_stat_chain_t      *diff_stat;
1497         char                    linkname[DLPI_LINKNAME_MAX];



1498 
1499         if (dladm_datalink_id2info(dh, linkid, NULL, NULL, NULL, linkname,
1500             DLPI_LINKNAME_MAX) != DLADM_STATUS_OK) {
1501                 goto done;
1502         }
1503 





1504         for (i = 0; i < DLADM_STAT_NUM_STATS; i++) {
1505                 if (state->ls_stattype[i]) {
1506                         /*
1507                          * Query library for stats
1508                          * Stats are returned as chain of raw numbers
1509                          */
1510                         diff_stat = query_link_stats(handle, linkid, arg, i);
1511                         walk_dlstat_stats(state, linkname, i, diff_stat);

1512                         dladm_link_stat_free(diff_stat);
1513                 }
1514         }
1515 done:
1516         return (DLADM_WALK_CONTINUE);
1517 }
1518 
1519 void
1520 show_link_stats(datalink_id_t linkid, show_state_t state, uint32_t interval)
1521 {
1522         for (;;) {
1523                 if (linkid == DATALINK_ALL_LINKID) {
1524                         (void) dladm_walk_datalink_id(show_queried_stats,
1525                             handle, &state, DATALINK_CLASS_ALL,
1526                             DATALINK_ANY_MEDIATYPE, DLADM_OPT_ACTIVE);
1527                 } else {
1528                         (void) show_queried_stats(handle, linkid, &state);
1529                 }
1530 
1531                 if (interval == 0)


1611 {
1612         int                     option;
1613         boolean_t               r_arg = B_FALSE;
1614         boolean_t               t_arg = B_FALSE;
1615         boolean_t               i_arg = B_FALSE;
1616         boolean_t               p_arg = B_FALSE;
1617         boolean_t               o_arg = B_FALSE;
1618         boolean_t               u_arg = B_FALSE;
1619         boolean_t               a_arg = B_FALSE;
1620         boolean_t               A_arg = B_FALSE;
1621         uint32_t                flags = DLADM_OPT_ACTIVE;
1622         datalink_id_t           linkid = DATALINK_ALL_LINKID;
1623         uint32_t                interval = 0;
1624         char                    unit = '\0';
1625         show_state_t            state;
1626         dladm_status_t          status;
1627         char                    *fields_str = NULL;
1628         char                    *o_fields_str = NULL;
1629 
1630         char                    *total_stat_fields =
1631             "link,ipkts,rbytes,opkts,obytes";
1632         char                    *rx_total_stat_fields =
1633             "link,ipkts,rbytes,intrs,polls,ch<10,ch10-50,ch>50";
1634         char                    *tx_total_stat_fields =
1635             "link,opkts,obytes,blkcnt,ublkcnt";
1636 
1637         ofmt_handle_t           ofmt;
1638         ofmt_status_t           oferr;
1639         uint_t                  ofmtflags = OFMT_RIGHTJUST;
1640         ofmt_field_t            *oftemplate;
1641 
1642         bzero(&state, sizeof (state));
1643         opterr = 0;
1644         while ((option = getopt_long(argc, argv, ":rtaApi:o:u:",
1645             NULL, NULL)) != -1) {
1646                 switch (option) {
1647                 case 'r':
1648                         if (r_arg)
1649                                 die_optdup(option);
1650 
1651                         r_arg = B_TRUE;




  45 #include <libintl.h>
  46 #include <libdevinfo.h>
  47 #include <libdlpi.h>
  48 #include <libdladm.h>
  49 #include <libdllink.h>
  50 #include <libdlstat.h>
  51 #include <libdlaggr.h>
  52 #include <libinetutil.h>
  53 #include <bsm/adt.h>
  54 #include <bsm/adt_event.h>
  55 #include <stddef.h>
  56 #include <ofmt.h>
  57 
  58 typedef struct link_chain_s {
  59         datalink_id_t           lc_linkid;
  60         boolean_t               lc_visited;
  61         dladm_stat_chain_t      *lc_statchain[DLADM_STAT_NUM_STATS];
  62         struct link_chain_s     *lc_next;
  63 } link_chain_t;
  64 
  65 typedef void *  (*stats2str_t)(const char *, const char *, void *,
  66                     char, boolean_t);
  67 
  68 typedef struct show_state {
  69         link_chain_t    *ls_linkchain;
  70         boolean_t       ls_stattype[DLADM_STAT_NUM_STATS];
  71         stats2str_t     ls_stats2str[DLADM_STAT_NUM_STATS];
  72         ofmt_handle_t   ls_ofmt;
  73         char            ls_unit;
  74         boolean_t       ls_parsable;
  75 } show_state_t;
  76 
  77 typedef struct show_history_state_s {
  78         boolean_t       hs_plot;
  79         boolean_t       hs_parsable;
  80         boolean_t       hs_printheader;
  81         boolean_t       hs_first;
  82         boolean_t       hs_showall;
  83         ofmt_handle_t   hs_ofmt;
  84 } show_history_state_t;
  85 


 124             "                 [-s <DD/MM/YYYY,HH:MM:SS>] "
 125             "[-e <DD/MM/YYYY,HH:MM:SS>]\n"
 126             "                 -f <logfile> [<link>]" },
 127         { "show-aggr", do_show_aggr,
 128             "dlstat show-aggr [-r | -t] [-i interval] [-p]\n"
 129             "                 [ -o field[,...]] [-u R|K|M|G|T|P] "
 130             " [link]" }
 131 };
 132 
 133 #define MAXSTATLEN 15
 134 
 135 /*
 136  * dlstat : total stat fields
 137  */
 138 typedef struct total_fields_buf_s {
 139         char t_linkname[MAXLINKNAMELEN];
 140         char t_ipackets[MAXSTATLEN];
 141         char t_rbytes[MAXSTATLEN];
 142         char t_opackets[MAXSTATLEN];
 143         char t_obytes[MAXSTATLEN];
 144         char t_zone[ZONENAME_MAX];
 145 } total_fields_buf_t;
 146 
 147 static ofmt_field_t total_s_fields[] = {
 148 { "LINK",       15,
 149     offsetof(total_fields_buf_t, t_linkname),   print_default_cb},
 150 { "IPKTS",      8,
 151     offsetof(total_fields_buf_t, t_ipackets),   print_default_cb},
 152 { "RBYTES",     8,
 153     offsetof(total_fields_buf_t, t_rbytes),     print_default_cb},
 154 { "OPKTS",      8,
 155     offsetof(total_fields_buf_t, t_opackets),   print_default_cb},
 156 { "OBYTES",     8,
 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},
 160 { NULL,         0,      0,              NULL}};
 161 
 162 /*
 163  * dlstat show-phys: both Rx and Tx stat fields
 164  */
 165 typedef struct ring_fields_buf_s {
 166         char r_linkname[MAXLINKNAMELEN];
 167         char r_type[MAXSTATLEN];
 168         char r_id[MAXSTATLEN];
 169         char r_index[MAXSTATLEN];
 170         char r_packets[MAXSTATLEN];
 171         char r_bytes[MAXSTATLEN];
 172 } ring_fields_buf_t;
 173 
 174 static ofmt_field_t ring_s_fields[] = {
 175 { "LINK",       15,
 176     offsetof(ring_fields_buf_t, r_linkname),    print_default_cb},
 177 { "TYPE",       5,
 178     offsetof(ring_fields_buf_t, r_type),        print_default_cb},
 179 { "ID",         7,


 943                 }
 944                                 /* Is it head of the list? */
 945                 if (lcurr == state->ls_linkchain)
 946                         state->ls_linkchain = lcurr->lc_next;
 947                 else
 948                         lprev->lc_next = lcurr->lc_next;
 949                                 /* lprev remains the same */
 950                 tofree = lcurr;
 951                 lcurr = lcurr->lc_next;
 952 
 953                                 /* Free stats memory for the removed link */
 954                 for (i = 0; i < DLADM_STAT_NUM_STATS; i++) {
 955                         if (state->ls_stattype[i])
 956                                 dladm_link_stat_free(tofree->lc_statchain[i]);
 957                 }
 958                 free(tofree);
 959         }
 960 }
 961 
 962 void *
 963 print_total_stats(const char *linkname, const char *zonename, void *statentry,
 964     char unit, boolean_t parsable)
 965 {
 966         total_stat_entry_t      *sentry = statentry;
 967         total_stat_t            *link_stats = &sentry->tse_stats;
 968         total_fields_buf_t      *buf;
 969 
 970         buf = malloc(sizeof (total_fields_buf_t));
 971         if (buf == NULL)
 972                 goto done;
 973 
 974         (void) snprintf(buf->t_linkname, sizeof (buf->t_linkname), "%s",
 975             linkname);
 976         (void) snprintf(buf->t_zone, sizeof (buf->t_zone), "%s", zonename);
 977 
 978         map_to_units(buf->t_ipackets, sizeof (buf->t_ipackets),
 979             link_stats->ts_ipackets, unit, parsable);
 980 
 981         map_to_units(buf->t_rbytes, sizeof (buf->t_rbytes),
 982             link_stats->ts_rbytes, unit, parsable);
 983 
 984         map_to_units(buf->t_opackets, sizeof (buf->t_opackets),
 985             link_stats->ts_opackets, unit, parsable);
 986 
 987         map_to_units(buf->t_obytes, sizeof (buf->t_obytes),
 988             link_stats->ts_obytes, unit, parsable);
 989 
 990 done:
 991         return (buf);
 992 }
 993 
 994 void *
 995 print_rx_generic_ring_stats(const char *linkname, const char *zonename, 
 996     void *statentry, char unit, boolean_t parsable)
 997 {
 998         ring_stat_entry_t       *sentry = statentry;
 999         ring_stat_t             *link_stats = &sentry->re_stats;
1000         ring_fields_buf_t       *buf;
1001 
1002         buf = malloc(sizeof (ring_fields_buf_t));
1003         if (buf == NULL)
1004                 goto done;
1005 
1006         (void) snprintf(buf->r_linkname, sizeof (buf->r_linkname), "%s",
1007             linkname);
1008 
1009         (void) snprintf(buf->r_type, sizeof (buf->r_type), "rx");
1010 
1011         if (sentry->re_index == DLSTAT_INVALID_ENTRY) {
1012                 (void) snprintf(buf->r_index, sizeof (buf->r_index), "--");
1013         } else {
1014                 (void) snprintf(buf->r_index, sizeof (buf->r_index),
1015                     "%llu", sentry->re_index);
1016         }
1017 
1018         map_to_units(buf->r_packets, sizeof (buf->r_packets),
1019             link_stats->r_packets, unit, parsable);
1020 
1021         map_to_units(buf->r_bytes, sizeof (buf->r_bytes),
1022             link_stats->r_bytes, unit, parsable);
1023 
1024 done:
1025         return (buf);
1026 }
1027 
1028 void *
1029 print_tx_generic_ring_stats(const char *linkname, const char *zonename,
1030     void *statentry, char unit, boolean_t parsable)
1031 {
1032         ring_stat_entry_t       *sentry = statentry;
1033         ring_stat_t             *link_stats = &sentry->re_stats;
1034         ring_fields_buf_t       *buf;
1035 
1036         buf = malloc(sizeof (ring_fields_buf_t));
1037         if (buf == NULL)
1038                 goto done;
1039 
1040         (void) snprintf(buf->r_linkname, sizeof (buf->r_linkname), "%s",
1041             linkname);
1042 
1043         (void) snprintf(buf->r_type, sizeof (buf->r_type), "tx");
1044 
1045         if (sentry->re_index == DLSTAT_INVALID_ENTRY) {
1046                 (void) snprintf(buf->r_index, sizeof (buf->r_index), "--");
1047         } else {
1048                 (void) snprintf(buf->r_index, sizeof (buf->r_index),
1049                     "%llu", sentry->re_index);
1050         }
1051 
1052         map_to_units(buf->r_packets, sizeof (buf->r_packets),
1053             link_stats->r_packets, unit, parsable);
1054 
1055         map_to_units(buf->r_bytes, sizeof (buf->r_bytes),
1056             link_stats->r_bytes, unit, parsable);
1057 
1058 done:
1059         return (buf);
1060 }
1061 
1062 void *
1063 print_rx_ring_stats(const char *linkname, const char *zonename, void *statentry,
1064     char unit, boolean_t parsable)
1065 {
1066         ring_stat_entry_t       *sentry = statentry;
1067         ring_stat_t             *link_stats = &sentry->re_stats;
1068         rx_ring_fields_buf_t    *buf;
1069 
1070         buf = malloc(sizeof (rx_ring_fields_buf_t));
1071         if (buf == NULL)
1072                 goto done;
1073 
1074         (void) snprintf(buf->rr_linkname, sizeof (buf->rr_linkname), "%s",
1075             linkname);
1076 
1077         (void) snprintf(buf->rr_type, sizeof (buf->rr_type), "rx");
1078 
1079         if (sentry->re_index == DLSTAT_INVALID_ENTRY) {
1080                 (void) snprintf(buf->rr_index, sizeof (buf->rr_index), "--");
1081         } else {
1082                 (void) snprintf(buf->rr_index, sizeof (buf->rr_index),
1083                     "%llu", sentry->re_index);
1084         }
1085 
1086         map_to_units(buf->rr_ipackets, sizeof (buf->rr_ipackets),
1087             link_stats->r_packets, unit, parsable);
1088 
1089         map_to_units(buf->rr_rbytes, sizeof (buf->rr_rbytes),
1090             link_stats->r_bytes, unit, parsable);
1091 
1092 done:
1093         return (buf);
1094 }
1095 
1096 void *
1097 print_tx_ring_stats(const char *linkname, const char *zonename, void *statentry,
1098     char unit, boolean_t parsable)
1099 {
1100         ring_stat_entry_t       *sentry = statentry;
1101         ring_stat_t             *link_stats = &sentry->re_stats;
1102         tx_ring_fields_buf_t    *buf;
1103 
1104         buf = malloc(sizeof (tx_ring_fields_buf_t));
1105         if (buf == NULL)
1106                 goto done;
1107 
1108         (void) snprintf(buf->tr_linkname, sizeof (buf->tr_linkname), "%s",
1109             linkname);
1110 
1111         (void) snprintf(buf->tr_type, sizeof (buf->tr_type), "tx");
1112 
1113         if (sentry->re_index == DLSTAT_INVALID_ENTRY) {
1114                 (void) snprintf(buf->tr_index, sizeof (buf->tr_index), "--");
1115         } else {
1116                 (void) snprintf(buf->tr_index, sizeof (buf->tr_index),
1117                     "%llu", sentry->re_index);
1118         }
1119 
1120         map_to_units(buf->tr_opackets, sizeof (buf->tr_opackets),
1121             link_stats->r_packets, unit, parsable);
1122 
1123         map_to_units(buf->tr_obytes, sizeof (buf->tr_obytes),
1124             link_stats->r_bytes, unit, parsable);
1125 
1126 done:
1127         return (buf);
1128 }
1129 
1130 void *
1131 print_rx_generic_lane_stats(const char *linkname, const char *zonename,
1132     void *statentry, char unit, boolean_t parsable)
1133 {
1134         rx_lane_stat_entry_t    *sentry = statentry;
1135         rx_lane_stat_t          *link_stats = &sentry->rle_stats;
1136         lane_fields_buf_t       *buf;
1137 
1138         if (sentry->rle_id == L_DFNCT)
1139                 return (NULL);
1140 
1141         buf = malloc(sizeof (lane_fields_buf_t));
1142         if (buf == NULL)
1143                 goto done;
1144 
1145         (void) snprintf(buf->l_linkname, sizeof (buf->l_linkname), "%s",
1146             linkname);
1147 
1148         (void) snprintf(buf->l_type, sizeof (buf->l_type), "rx");
1149 
1150         if (sentry->rle_id == L_HWLANE)
1151                 (void) snprintf(buf->l_id, sizeof (buf->l_id), "hw");
1152         else if (sentry->rle_id == L_SWLANE)


1159                 (void) snprintf(buf->l_id, sizeof (buf->l_id), "--");
1160 
1161         if (sentry->rle_index == DLSTAT_INVALID_ENTRY) {
1162                 (void) snprintf(buf->l_index, sizeof (buf->l_index), "--");
1163         } else {
1164                 (void) snprintf(buf->l_index, sizeof (buf->l_index),
1165                     "%llu", sentry->rle_index);
1166         }
1167 
1168         map_to_units(buf->l_packets, sizeof (buf->l_packets),
1169             link_stats->rl_ipackets, unit, parsable);
1170 
1171         map_to_units(buf->l_bytes, sizeof (buf->l_bytes),
1172             link_stats->rl_rbytes, unit, parsable);
1173 
1174 done:
1175         return (buf);
1176 }
1177 
1178 void *
1179 print_tx_generic_lane_stats(const char *linkname, const char *zonename,
1180     void *statentry, char unit, boolean_t parsable)
1181 {
1182         tx_lane_stat_entry_t    *sentry = statentry;
1183         tx_lane_stat_t          *link_stats = &sentry->tle_stats;
1184         lane_fields_buf_t       *buf;
1185 
1186         if (sentry->tle_id == L_DFNCT)
1187                 return (NULL);
1188 
1189         buf = malloc(sizeof (lane_fields_buf_t));
1190         if (buf == NULL)
1191                 goto done;
1192 
1193         (void) snprintf(buf->l_linkname, sizeof (buf->l_linkname), "%s",
1194             linkname);
1195 
1196         (void) snprintf(buf->l_type, sizeof (buf->l_type), "tx");
1197 
1198         if (sentry->tle_id == L_HWLANE)
1199                 (void) snprintf(buf->l_id, sizeof (buf->l_id), "hw");
1200         else if (sentry->tle_id == L_SWLANE)


1204         else
1205                 (void) snprintf(buf->l_id, sizeof (buf->l_id), "--");
1206 
1207         if (sentry->tle_index == DLSTAT_INVALID_ENTRY) {
1208                 (void) snprintf(buf->l_index, sizeof (buf->l_index), "--");
1209         } else {
1210                 (void) snprintf(buf->l_index, sizeof (buf->l_index),
1211                     "%llu", sentry->tle_index);
1212         }
1213         map_to_units(buf->l_packets, sizeof (buf->l_packets),
1214             link_stats->tl_opackets, unit, parsable);
1215 
1216         map_to_units(buf->l_bytes, sizeof (buf->l_bytes),
1217             link_stats->tl_obytes, unit, parsable);
1218 
1219 done:
1220         return (buf);
1221 }
1222 
1223 void *
1224 print_rx_lane_stats(const char *linkname, const char *zonename, void *statentry,
1225     char unit, boolean_t parsable)
1226 {
1227         rx_lane_stat_entry_t    *sentry = statentry;
1228         rx_lane_stat_t          *link_stats = &sentry->rle_stats;
1229         rx_lane_fields_buf_t    *buf;
1230 
1231         if (sentry->rle_id == L_DFNCT)
1232                 return (NULL);
1233 
1234         buf = malloc(sizeof (rx_lane_fields_buf_t));
1235         if (buf == NULL)
1236                 goto done;
1237 
1238         (void) snprintf(buf->rl_linkname, sizeof (buf->rl_linkname), "%s",
1239             linkname);
1240 
1241         (void) snprintf(buf->rl_type, sizeof (buf->rl_type), "rx");
1242 
1243         if (sentry->rle_id == L_HWLANE)
1244                 (void) snprintf(buf->rl_id, sizeof (buf->rl_id), "hw");
1245         else if (sentry->rle_id == L_SWLANE)


1270         map_to_units(buf->rl_polls, sizeof (buf->rl_polls),
1271             link_stats->rl_polls, unit, parsable);
1272 
1273         map_to_units(buf->rl_sdrops, sizeof (buf->rl_sdrops),
1274             link_stats->rl_sdrops, unit, parsable);
1275 
1276         map_to_units(buf->rl_chl10, sizeof (buf->rl_chl10),
1277             link_stats->rl_chl10, unit, parsable);
1278 
1279         map_to_units(buf->rl_ch10_50, sizeof (buf->rl_ch10_50),
1280             link_stats->rl_ch10_50, unit, parsable);
1281 
1282         map_to_units(buf->rl_chg50, sizeof (buf->rl_chg50),
1283             link_stats->rl_chg50, unit, parsable);
1284 
1285 done:
1286         return (buf);
1287 }
1288 
1289 void *
1290 print_tx_lane_stats(const char *linkname, const char *zonename, void *statentry,
1291     char unit, boolean_t parsable) {

1292         tx_lane_stat_entry_t    *sentry = statentry;
1293         tx_lane_stat_t          *link_stats = &sentry->tle_stats;
1294         tx_lane_fields_buf_t    *buf = NULL;
1295 
1296         if (sentry->tle_id == L_DFNCT)
1297                 return (NULL);
1298 
1299         buf = malloc(sizeof (tx_lane_fields_buf_t));
1300         if (buf == NULL)
1301                 goto done;
1302 
1303         (void) snprintf(buf->tl_linkname, sizeof (buf->tl_linkname), "%s",
1304             linkname);
1305 
1306         (void) snprintf(buf->tl_type, sizeof (buf->tl_type), "tx");
1307 
1308         if (sentry->tle_id == L_HWLANE)
1309                 (void) snprintf(buf->tl_id, sizeof (buf->tl_id), "hw");
1310         else if (sentry->tle_id == L_SWLANE)
1311                 (void) snprintf(buf->tl_id, sizeof (buf->tl_id), "sw");


1324         map_to_units(buf->tl_opackets, sizeof (buf->tl_opackets),
1325             link_stats->tl_opackets, unit, parsable);
1326 
1327         map_to_units(buf->tl_obytes, sizeof (buf->tl_obytes),
1328             link_stats->tl_obytes, unit, parsable);
1329 
1330         map_to_units(buf->tl_blockcnt, sizeof (buf->tl_blockcnt),
1331             link_stats->tl_blockcnt, unit, parsable);
1332 
1333         map_to_units(buf->tl_unblockcnt, sizeof (buf->tl_unblockcnt),
1334             link_stats->tl_unblockcnt, unit, parsable);
1335 
1336         map_to_units(buf->tl_sdrops, sizeof (buf->tl_sdrops),
1337             link_stats->tl_sdrops, unit, parsable);
1338 
1339 done:
1340         return (buf);
1341 }
1342 
1343 void *
1344 print_fanout_stats(const char *linkname, const char *zonename, void *statentry,
1345     char unit, boolean_t parsable)
1346 {
1347         fanout_stat_entry_t             *sentry = statentry;
1348         fanout_stat_t                   *link_stats = &sentry->fe_stats;
1349         rx_fanout_lane_fields_buf_t     *buf;
1350 
1351         buf = malloc(sizeof (rx_fanout_lane_fields_buf_t));
1352         if (buf == NULL)
1353                 goto done;
1354 
1355         (void) snprintf(buf->rfl_linkname, sizeof (buf->rfl_linkname), "%s",
1356             linkname);
1357 
1358         (void) snprintf(buf->rfl_type, sizeof (buf->rfl_type), "rx");
1359 
1360         if (sentry->fe_id == L_HWLANE)
1361                 (void) snprintf(buf->rfl_id, sizeof (buf->rfl_id), "hw");
1362         else if (sentry->fe_id == L_SWLANE)
1363                 (void) snprintf(buf->rfl_id, sizeof (buf->rfl_id), "sw");
1364         else if (sentry->fe_id == L_LCLSWLANE)
1365                 (void) snprintf(buf->rfl_id, sizeof (buf->rfl_id), "lcl/sw");


1378         }
1379 
1380         if (sentry->fe_foutindex == DLSTAT_INVALID_ENTRY)
1381                 (void) snprintf(buf->rfl_fout, sizeof (buf->rfl_fout), "--");
1382         else {
1383                 (void) snprintf(buf->rfl_fout, sizeof (buf->rfl_fout), "%llu",
1384                     sentry->fe_foutindex);
1385         }
1386 
1387         map_to_units(buf->rfl_ipackets, sizeof (buf->rfl_ipackets),
1388             link_stats->f_ipackets, unit, parsable);
1389 
1390         map_to_units(buf->rfl_rbytes, sizeof (buf->rfl_rbytes),
1391             link_stats->f_rbytes, unit, parsable);
1392 
1393 done:
1394         return (buf);
1395 }
1396 
1397 void *
1398 print_aggr_port_stats(const char *linkname, const char *zonename,
1399     void *statentry, char unit, boolean_t parsable)
1400 {
1401         aggr_port_stat_entry_t  *sentry = statentry;
1402         aggr_port_stat_t        *link_stats = &sentry->ape_stats;
1403         aggr_port_fields_buf_t  *buf;
1404         char                    portname[MAXLINKNAMELEN];
1405 
1406         buf = malloc(sizeof (aggr_port_fields_buf_t));
1407         if (buf == NULL)
1408                 goto done;
1409 
1410         (void) snprintf(buf->ap_linkname, sizeof (buf->ap_linkname), "%s",
1411             linkname);
1412 
1413         if (dladm_datalink_id2info(handle, sentry->ape_portlinkid, NULL,
1414             NULL, NULL, portname, DLPI_LINKNAME_MAX)
1415             != DLADM_STATUS_OK) {
1416                 (void) snprintf(buf->ap_portname,
1417                     sizeof (buf->ap_portname), "--");
1418         } else {
1419                 (void) snprintf(buf->ap_portname,


1456         /* Query library for current stats */
1457         curr_stat = dladm_link_stat_query(dh, linkid, stattype);
1458         if (curr_stat == NULL)
1459                 goto done;
1460 
1461         /* current stats - prev iteration stats */
1462         diff_stat = dladm_link_stat_diffchain(curr_stat, prev_stat, stattype);
1463 
1464         /* Free prev stats */
1465         dladm_link_stat_free(prev_stat);
1466 
1467         /* Prev <- curr stats */
1468         link_node->lc_statchain[stattype] = curr_stat;
1469 
1470 done:
1471         return (diff_stat);
1472 }
1473 
1474 void
1475 walk_dlstat_stats(show_state_t *state, const char *linkname,
1476     const char *zonename, dladm_stat_type_t stattype,
1477     dladm_stat_chain_t *diff_stat)
1478 {
1479         dladm_stat_chain_t  *curr;
1480 
1481         /* Unpack invidual stat entry and call library consumer's callback */
1482         for (curr = diff_stat; curr != NULL; curr = curr->dc_next) {
1483                 void    *fields_buf;
1484 
1485                 /* Format the raw numbers for printing */
1486                 fields_buf = state->ls_stats2str[stattype](linkname,
1487                     zonename, curr->dc_statentry, state->ls_unit,
1488                     state->ls_parsable);
1489                 /* Print the stats */
1490                 if (fields_buf != NULL)
1491                         ofmt_print(state->ls_ofmt, fields_buf);
1492                 free(fields_buf);
1493         }
1494 }
1495 
1496 static int
1497 show_queried_stats(dladm_handle_t dh, datalink_id_t linkid, void *arg)
1498 {
1499         show_state_t            *state = arg;
1500         int                     i;
1501         dladm_stat_chain_t      *diff_stat;
1502         char                    linkname[DLPI_LINKNAME_MAX];
1503         char                    zonename[DLADM_PROP_VAL_MAX + 1];
1504         char                    *valptr[1];
1505         uint_t                  valcnt = 1;
1506 
1507         if (dladm_datalink_id2info(dh, linkid, NULL, NULL, NULL, linkname,
1508             DLPI_LINKNAME_MAX) != DLADM_STATUS_OK) {
1509                 goto done;
1510         }
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 
1517         for (i = 0; i < DLADM_STAT_NUM_STATS; i++) {
1518                 if (state->ls_stattype[i]) {
1519                         /*
1520                          * Query library for stats
1521                          * Stats are returned as chain of raw numbers
1522                          */
1523                         diff_stat = query_link_stats(handle, linkid, arg, i);
1524                         walk_dlstat_stats(state, linkname, zonename, i,
1525                             diff_stat);
1526                         dladm_link_stat_free(diff_stat);
1527                 }
1528         }
1529 done:
1530         return (DLADM_WALK_CONTINUE);
1531 }
1532 
1533 void
1534 show_link_stats(datalink_id_t linkid, show_state_t state, uint32_t interval)
1535 {
1536         for (;;) {
1537                 if (linkid == DATALINK_ALL_LINKID) {
1538                         (void) dladm_walk_datalink_id(show_queried_stats,
1539                             handle, &state, DATALINK_CLASS_ALL,
1540                             DATALINK_ANY_MEDIATYPE, DLADM_OPT_ACTIVE);
1541                 } else {
1542                         (void) show_queried_stats(handle, linkid, &state);
1543                 }
1544 
1545                 if (interval == 0)


1625 {
1626         int                     option;
1627         boolean_t               r_arg = B_FALSE;
1628         boolean_t               t_arg = B_FALSE;
1629         boolean_t               i_arg = B_FALSE;
1630         boolean_t               p_arg = B_FALSE;
1631         boolean_t               o_arg = B_FALSE;
1632         boolean_t               u_arg = B_FALSE;
1633         boolean_t               a_arg = B_FALSE;
1634         boolean_t               A_arg = B_FALSE;
1635         uint32_t                flags = DLADM_OPT_ACTIVE;
1636         datalink_id_t           linkid = DATALINK_ALL_LINKID;
1637         uint32_t                interval = 0;
1638         char                    unit = '\0';
1639         show_state_t            state;
1640         dladm_status_t          status;
1641         char                    *fields_str = NULL;
1642         char                    *o_fields_str = NULL;
1643 
1644         char                    *total_stat_fields =
1645             "link,ipkts,rbytes,opkts,obytes,zone";
1646         char                    *rx_total_stat_fields =
1647             "link,ipkts,rbytes,intrs,polls,ch<10,ch10-50,ch>50";
1648         char                    *tx_total_stat_fields =
1649             "link,opkts,obytes,blkcnt,ublkcnt";
1650 
1651         ofmt_handle_t           ofmt;
1652         ofmt_status_t           oferr;
1653         uint_t                  ofmtflags = OFMT_RIGHTJUST;
1654         ofmt_field_t            *oftemplate;
1655 
1656         bzero(&state, sizeof (state));
1657         opterr = 0;
1658         while ((option = getopt_long(argc, argv, ":rtaApi:o:u:",
1659             NULL, NULL)) != -1) {
1660                 switch (option) {
1661                 case 'r':
1662                         if (r_arg)
1663                                 die_optdup(option);
1664 
1665                         r_arg = B_TRUE;