static void do_show_flow(int argc, char *argv[]) { char flowname[MAXFLOWNAMELEN]; char linkname[MAXLINKNAMELEN]; datalink_id_t linkid = DATALINK_ALL_LINKID; int option; boolean_t s_arg = B_FALSE; boolean_t S_arg = B_FALSE; boolean_t i_arg = B_FALSE; boolean_t l_arg = B_FALSE; boolean_t o_arg = B_FALSE; uint32_t interval = 0; show_flow_state_t state; char *fields_str = NULL; ofmt_handle_t ofmt; ofmt_status_t oferr; uint_t ofmtflags = 0; bzero(&state, sizeof (state)); opterr = 0; while ((option = getopt_long(argc, argv, ":pPsSi:l:o:", longopts, NULL)) != -1) { switch (option) { case 'p': state.fs_parsable = B_TRUE; ofmtflags |= OFMT_PARSABLE; break; case 'P': state.fs_persist = B_TRUE; break; case 's': if (s_arg) die_optdup(option); s_arg = B_TRUE; break; case 'S': if (S_arg) die_optdup(option); S_arg = B_TRUE; break; case 'o': if (o_arg) die_optdup(option); o_arg = B_TRUE; fields_str = optarg; break; case 'i': if (i_arg) die_optdup(option); i_arg = B_TRUE; if (!dladm_str2interval(optarg, &interval)) die("invalid interval value '%s'", optarg); break; case 'l': if (strlcpy(linkname, optarg, MAXLINKNAMELEN) >= MAXLINKNAMELEN) die("link name too long\n"); if (dladm_name2info(handle, linkname, &linkid, NULL, NULL, NULL) != DLADM_STATUS_OK) die("invalid link '%s'", linkname); l_arg = B_TRUE; break; default: die_opterr(optopt, option); break; } } if (i_arg && !(s_arg || S_arg)) die("the -i option can be used only with -s or -S"); if (s_arg && S_arg) die("the -s option cannot be used with -S"); /* get flow name (optional last argument */ if (optind == (argc-1)) { if (strlcpy(flowname, argv[optind], MAXFLOWNAMELEN) >= MAXFLOWNAMELEN) die("flow name too long"); state.fs_flow = flowname; } if (S_arg) { dladm_continuous(handle, linkid, state.fs_flow, interval, FLOW_REPORT); return; } if (s_arg) { flow_stats(state.fs_flow, linkid, interval, fields_str, &state); return; } oferr = ofmt_open(fields_str, flow_fields, ofmtflags, 0, &ofmt); flowadm_ofmt_check(oferr, state.fs_parsable, ofmt); state.fs_ofmt = ofmt; /* Show attributes of one flow */ if (state.fs_flow != NULL) { show_one_flow(&state, state.fs_flow); /* Show attributes of flows on one link */ } else if (l_arg) { (void) show_flows_onelink(handle, linkid, &state); /* Show attributes of all flows on all links */ } else { (void) dladm_walk_datalink_id(show_flows_onelink, handle, &state, DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE, DLADM_OPT_ACTIVE); } ofmt_close(ofmt); }
int main(int argc, char *argv[]) { dladm_status_t status; int option; boolean_t r_arg = B_FALSE; boolean_t t_arg = B_FALSE; boolean_t p_arg = B_FALSE; boolean_t i_arg = B_FALSE; boolean_t o_arg = B_FALSE; boolean_t u_arg = B_FALSE; boolean_t A_arg = B_FALSE; boolean_t S_arg = B_FALSE; boolean_t flow_arg = B_FALSE; datalink_id_t linkid = DATALINK_ALL_LINKID; char linkname[MAXLINKNAMELEN]; char flowname[MAXFLOWNAMELEN]; uint32_t interval = 0; char unit = '\0'; show_flow_state_t state; char *fields_str = NULL; char *o_fields_str = NULL; char *total_stat_fields = "flow,ipkts,rbytes,ierrs,opkts,obytes,oerrs"; char *rx_stat_fields = "flow,ipkts,rbytes,ierrs"; char *tx_stat_fields = "flow,opkts,obytes,oerrs"; ofmt_handle_t ofmt; ofmt_status_t oferr; uint_t ofmtflags = OFMT_RIGHTJUST; dladm_flow_attr_t attr; (void) setlocale(LC_ALL, ""); #if !defined(TEXT_DOMAIN) #define TEXT_DOMAIN "SYS_TEST" #endif (void) textdomain(TEXT_DOMAIN); progname = argv[0]; /* Open the libdladm handle */ if ((status = dladm_open(&handle)) != DLADM_STATUS_OK) die_dlerr(status, "could not open /dev/dld"); bzero(&state, sizeof (state)); opterr = 0; while ((option = getopt_long(argc, argv, ":rtApSi:o:u:l:h", NULL, NULL)) != -1) { switch (option) { case 'r': if (r_arg) die_optdup(option); r_arg = B_TRUE; break; case 't': if (t_arg) die_optdup(option); t_arg = B_TRUE; break; case 'A': if (A_arg) die_optdup(option); A_arg = B_TRUE; break; case 'p': if (p_arg) die_optdup(option); p_arg = B_TRUE; break; case 'S': if (S_arg) die_optdup(option); S_arg = B_TRUE; break; case 'i': if (i_arg) die_optdup(option); i_arg = B_TRUE; if (!dladm_str2interval(optarg, &interval)) die("invalid interval value '%s'", optarg); break; case 'o': o_arg = B_TRUE; o_fields_str = optarg; break; case 'u': if (u_arg) die_optdup(option); u_arg = B_TRUE; if (!flowstat_unit(optarg, &unit)) die("invalid unit value '%s'," "unit must be R|K|M|G|T|P", optarg); break; case 'l': if (strlcpy(linkname, optarg, MAXLINKNAMELEN) >= MAXLINKNAMELEN) die("link name too long\n"); if (dladm_name2info(handle, linkname, &linkid, NULL, NULL, NULL) != DLADM_STATUS_OK) die("invalid link '%s'", linkname); break; case 'h': if (r_arg || t_arg || p_arg || o_arg || u_arg || i_arg || S_arg || A_arg) { die("the option -h is not compatible with " "-r, -t, -p, -o, -u, -i, -S, -A"); } do_show_history(argc, argv); return (0); break; default: die_opterr(optopt, option, usage_ermsg); break; } } if (r_arg && t_arg) die("the option -t and -r are not compatible"); if (u_arg && p_arg) die("the option -u and -p are not compatible"); if (p_arg && !o_arg) die("-p requires -o"); if (p_arg && strcasecmp(o_fields_str, "all") == 0) die("\"-o all\" is invalid with -p"); if (S_arg && (r_arg || t_arg || p_arg || o_arg || u_arg)) die("the option -S is not compatible with " "-r, -t, -p, -o, -u"); if (A_arg && (r_arg || t_arg || p_arg || o_arg || u_arg || i_arg)) die("the option -A is not compatible with " "-r, -t, -p, -o, -u, -i"); /* get flow name (optional last argument) */ if (optind == (argc-1)) { if (strlcpy(flowname, argv[optind], MAXFLOWNAMELEN) >= MAXFLOWNAMELEN) die("flow name too long"); flow_arg = B_TRUE; } else if (optind != argc) { usage(); } if (S_arg) { dladm_continuous(handle, linkid, (flow_arg ? flowname : NULL), interval, FLOW_REPORT); return (0); } if (flow_arg && dladm_flow_info(handle, flowname, &attr) != DLADM_STATUS_OK) die("invalid flow %s", flowname); if (A_arg) { dump_all_flow_stats(&attr, &state, linkid, flow_arg); return (0); } state.fs_unit = unit; state.fs_parsable = p_arg; if (state.fs_parsable) ofmtflags |= OFMT_PARSABLE; if (r_arg) fields_str = rx_stat_fields; else if (t_arg) fields_str = tx_stat_fields; else fields_str = total_stat_fields; if (o_arg) { fields_str = (strcasecmp(o_fields_str, "all") == 0) ? fields_str : o_fields_str; } oferr = ofmt_open(fields_str, flow_s_fields, ofmtflags, 0, &ofmt); flowstat_ofmt_check(oferr, state.fs_parsable, ofmt); state.fs_ofmt = ofmt; for (;;) { /* Show stats for named flow */ if (flow_arg) { (void) query_flow_stats(handle, &attr, &state); /* Show stats for flows on one link */ } else if (linkid != DATALINK_INVALID_LINKID) { (void) dladm_walk_flow(query_flow_stats, handle, linkid, &state, B_FALSE); /* Show stats for all flows on all links */ } else { (void) dladm_walk_datalink_id(query_link_flow_stats, handle, &state, DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE, DLADM_OPT_ACTIVE); } if (interval == 0) break; (void) fflush(stdout); cleanup_removed_flows(&state); (void) sleep(interval); } ofmt_close(ofmt); dladm_close(handle); return (0); }