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