/* ARGSUSED */ static int show_history_date(dladm_usage_t *history, void *arg) { show_history_state_t *state = (show_history_state_t *)arg; time_t stime; char timebuf[20]; dladm_flow_attr_t attr; dladm_status_t status; /* * Only show historical information for existing flows unless '-a' * is specified. */ if (!state->us_showall && ((status = dladm_flow_info(handle, history->du_name, &attr)) != DLADM_STATUS_OK)) { return (status); } stime = history->du_stime; (void) strftime(timebuf, sizeof (timebuf), "%m/%d/%Y", localtime(&stime)); (void) printf("%s\n", timebuf); return (DLADM_STATUS_OK); }
static void show_one_flow(void *arg, const char *name) { dladm_flow_attr_t attr; if (dladm_flow_info(handle, name, &attr) != DLADM_STATUS_OK) die("invalid flow: '%s'", name); else (void) show_flow(handle, &attr, arg); }
static void show_flowprop_one_flow(void *arg, const char *flow) { int i; char *buf; dladm_status_t status; dladm_arg_list_t *proplist = NULL; show_flowprop_state_t *statep = arg; dladm_flow_attr_t attr; const char *savep; /* * Do not print flow props for invalid flows. */ if ((status = dladm_flow_info(handle, flow, &attr)) != DLADM_STATUS_OK) { die("invalid flow: '%s'", flow); } savep = statep->fs_flow; statep->fs_flow = flow; proplist = statep->fs_proplist; buf = malloc((sizeof (char *) + DLADM_PROP_VAL_MAX) * DLADM_MAX_PROP_VALCNT + MAX_PROP_LINE); if (buf == NULL) die("insufficient memory"); statep->fs_propvals = (char **)(void *)buf; for (i = 0; i < DLADM_MAX_PROP_VALCNT; i++) { statep->fs_propvals[i] = buf + sizeof (char *) * DLADM_MAX_PROP_VALCNT + i * DLADM_PROP_VAL_MAX; } statep->fs_line = buf + (sizeof (char *) + DLADM_PROP_VAL_MAX) * DLADM_MAX_PROP_VALCNT; /* show only specified flow properties */ if (proplist != NULL) { for (i = 0; i < proplist->al_count; i++) { if (show_one_flowprop(statep, proplist->al_info[i].ai_name) != DLADM_STATUS_OK) break; } /* show all flow properties */ } else { status = dladm_walk_flowprop(show_one_flowprop, flow, statep); if (status != DLADM_STATUS_OK) die_dlerr(status, "show-flowprop"); } free(buf); statep->fs_flow = savep; }
/* ARGSUSED */ static void flow_stats(const char *flow, datalink_id_t linkid, uint_t interval, char *fields_str, show_flow_state_t *state) { dladm_flow_attr_t attr; ofmt_handle_t ofmt; ofmt_status_t oferr; uint_t ofmtflags = 0; oferr = ofmt_open(fields_str, flow_s_fields, ofmtflags, 0, &ofmt); flowadm_ofmt_check(oferr, state->fs_parsable, ofmt); state->fs_ofmt = ofmt; if (flow != NULL && dladm_flow_info(handle, flow, &attr) != DLADM_STATUS_OK) die("invalid flow %s", flow); /* * If an interval is specified, continuously show the stats * for only the first flow. */ state->fs_firstonly = (interval != 0); for (;;) { state->fs_donefirst = B_FALSE; /* Show stats for named flow */ if (flow != NULL) { state->fs_flow = flow; (void) show_flow_stats(handle, &attr, state); /* Show all stats on a link */ } else if (linkid != DATALINK_INVALID_LINKID) { (void) dladm_walk_flow(show_flow_stats, handle, linkid, state, B_FALSE); /* Show all stats by datalink */ } else { (void) dladm_walk_datalink_id(show_link_flow_stats, handle, state, DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE, DLADM_OPT_ACTIVE); } if (interval == 0) break; (void) fflush(stdout); (void) sleep(interval); } ofmt_close(ofmt); }
static int show_history_res(dladm_usage_t *history, void *arg) { show_history_state_t *state = (show_history_state_t *)arg; char buf[DLADM_STRSIZE]; history_fields_buf_t ubuf; dladm_flow_attr_t attr; dladm_status_t status; /* * Only show historical information for existing flows unless '-a' * is specified. */ if (!state->us_showall && ((status = dladm_flow_info(handle, history->du_name, &attr)) != DLADM_STATUS_OK)) { return (status); } bzero(&ubuf, sizeof (ubuf)); (void) snprintf(ubuf.history_flow, sizeof (ubuf.history_flow), "%s", history->du_name); (void) snprintf(ubuf.history_duration, sizeof (ubuf.history_duration), "%llu", history->du_duration); (void) snprintf(ubuf.history_ipackets, sizeof (ubuf.history_ipackets), "%llu", history->du_ipackets); (void) snprintf(ubuf.history_rbytes, sizeof (ubuf.history_rbytes), "%llu", history->du_rbytes); (void) snprintf(ubuf.history_opackets, sizeof (ubuf.history_opackets), "%llu", history->du_opackets); (void) snprintf(ubuf.history_obytes, sizeof (ubuf.history_obytes), "%llu", history->du_obytes); (void) snprintf(ubuf.history_bandwidth, sizeof (ubuf.history_bandwidth), "%s Mbps", dladm_bw2str(history->du_bandwidth, buf)); ofmt_print(state->us_ofmt, (void *)&ubuf); return (DLADM_STATUS_OK); }
/* ARGSUSED */ static dladm_status_t do_get_dscp(dladm_handle_t handle, const char *flow, char **prop_val, uint_t *val_cnt) { mac_resource_props_t *mrp; dladm_flow_attr_t fa; dladm_status_t status; status = dladm_flow_info(handle, flow, &fa); if (status != DLADM_STATUS_OK) return (status); mrp = &(fa.fa_resource_props); *val_cnt = 1; if (mrp->mrp_mask & MRP_DSCP) { (void) snprintf(prop_val[0], DLADM_STRSIZE, "%u", mrp->mrp_dscp); } else { return (DLADM_STATUS_NOTSUP); } return (DLADM_STATUS_OK); }
/* ARGSUSED */ static dladm_status_t do_get_maxbw(dladm_handle_t handle, const char *flow, char **prop_val, uint_t *val_cnt) { char buf[DLADM_STRSIZE]; mac_resource_props_t *mrp; dladm_flow_attr_t fa; dladm_status_t status; status = dladm_flow_info(handle, flow, &fa); if (status != DLADM_STATUS_OK) return (status); mrp = &(fa.fa_resource_props); *val_cnt = 1; if (mrp->mrp_mask & MRP_MAXBW) { (void) snprintf(prop_val[0], DLADM_STRSIZE, "%s", dladm_bw2str(mrp->mrp_maxbw, buf)); } else { return (DLADM_STATUS_NOTSUP); } return (DLADM_STATUS_OK); }
/* ARGSUSED */ static dladm_status_t do_get_priority(dladm_handle_t handle, const char *flow, char **prop_val, uint_t *val_cnt) { mac_resource_props_t *mrp; char buf[DLADM_STRSIZE]; dladm_flow_attr_t fa; dladm_status_t status; bzero(&fa, sizeof (dladm_flow_attr_t)); status = dladm_flow_info(handle, flow, &fa); if (status != DLADM_STATUS_OK) return (status); mrp = &(fa.fa_resource_props); *val_cnt = 1; if (mrp->mrp_mask & MRP_PRIORITY) { (void) snprintf(prop_val[0], DLADM_STRSIZE, "%s", dladm_pri2str(mrp->mrp_priority, buf)); } else { return (DLADM_STATUS_NOTSUP); } return (DLADM_STATUS_OK); }
/* ARGSUSED */ static void do_show_history(int argc, char *argv[]) { char *file = NULL; int opt; dladm_status_t status; boolean_t d_arg = B_FALSE; char *stime = NULL; char *etime = NULL; char *resource = NULL; show_history_state_t state; boolean_t o_arg = B_FALSE; boolean_t F_arg = B_FALSE; char *fields_str = NULL; char *formatspec_str = NULL; char *all_fields = "flow,duration,ipackets,rbytes,opackets,obytes,bandwidth"; char *all_l_fields = "flow,start,end,rbytes,obytes,bandwidth"; ofmt_handle_t ofmt; ofmt_status_t oferr; uint_t ofmtflags = 0; bzero(&state, sizeof (show_history_state_t)); state.us_parsable = B_FALSE; state.us_printheader = B_FALSE; state.us_plot = B_FALSE; state.us_first = B_TRUE; while ((opt = getopt(argc, argv, "das:e:o:f:F:")) != -1) { switch (opt) { case 'd': d_arg = B_TRUE; break; case 'a': state.us_showall = B_TRUE; break; case 'f': file = optarg; break; case 's': stime = optarg; break; case 'e': etime = optarg; break; case 'o': o_arg = B_TRUE; fields_str = optarg; break; case 'F': state.us_plot = F_arg = B_TRUE; formatspec_str = optarg; break; default: die_opterr(optopt, opt, usage_ermsg); } } if (file == NULL) die("-h requires a file"); if (optind == (argc-1)) { dladm_flow_attr_t attr; resource = argv[optind]; if (!state.us_showall && dladm_flow_info(handle, resource, &attr) != DLADM_STATUS_OK) { die("invalid flow: '%s'", resource); } } if (state.us_parsable) ofmtflags |= OFMT_PARSABLE; if (resource == NULL && stime == NULL && etime == NULL) { if (!o_arg || (o_arg && strcasecmp(fields_str, "all") == 0)) fields_str = all_fields; oferr = ofmt_open(fields_str, history_fields, ofmtflags, 0, &ofmt); } else { if (!o_arg || (o_arg && strcasecmp(fields_str, "all") == 0)) fields_str = all_l_fields; oferr = ofmt_open(fields_str, history_l_fields, ofmtflags, 0, &ofmt); } ofmt_check(oferr, state.us_parsable, ofmt, die, warn); state.us_ofmt = ofmt; if (F_arg && d_arg) die("incompatible -d and -F options"); if (F_arg && !valid_formatspec(formatspec_str)) die("Format specifier %s not supported", formatspec_str); if (d_arg) { /* Print log dates */ status = dladm_usage_dates(show_history_date, DLADM_LOGTYPE_FLOW, file, resource, &state); } else if (resource == NULL && stime == NULL && etime == NULL && !F_arg) { /* Print summary */ status = dladm_usage_summary(show_history_res, DLADM_LOGTYPE_FLOW, file, &state); } else if (resource != NULL) { /* Print log entries for named resource */ status = dladm_walk_usage_res(show_history_time, DLADM_LOGTYPE_FLOW, file, resource, stime, etime, &state); } else { /* Print time and information for each flow */ status = dladm_walk_usage_time(show_history_time, DLADM_LOGTYPE_FLOW, file, stime, etime, &state); } ofmt_close(ofmt); if (status != DLADM_STATUS_OK) die_dlerr(status, "-h"); dladm_close(handle); }
static int show_history_time(dladm_usage_t *history, void *arg) { show_history_state_t *state = (show_history_state_t *)arg; char buf[DLADM_STRSIZE]; history_l_fields_buf_t ubuf; time_t time; double bw; dladm_flow_attr_t attr; dladm_status_t status; /* * Only show historical information for existing flows unless '-a' * is specified. */ if (!state->us_showall && ((status = dladm_flow_info(handle, history->du_name, &attr)) != DLADM_STATUS_OK)) { return (status); } if (state->us_plot) { if (!state->us_printheader) { if (state->us_first) { (void) printf("# Time"); state->us_first = B_FALSE; } (void) printf(" %s", history->du_name); if (history->du_last) { (void) printf("\n"); state->us_first = B_TRUE; state->us_printheader = B_TRUE; } } else { if (state->us_first) { time = history->du_etime; (void) strftime(buf, sizeof (buf), "%T", localtime(&time)); state->us_first = B_FALSE; (void) printf("%s", buf); } bw = (double)history->du_bandwidth/1000; (void) printf(" %.2f", bw); if (history->du_last) { (void) printf("\n"); state->us_first = B_TRUE; } } return (DLADM_STATUS_OK); } bzero(&ubuf, sizeof (ubuf)); (void) snprintf(ubuf.history_l_flow, sizeof (ubuf.history_l_flow), "%s", history->du_name); time = history->du_stime; (void) strftime(buf, sizeof (buf), "%T", localtime(&time)); (void) snprintf(ubuf.history_l_stime, sizeof (ubuf.history_l_stime), "%s", buf); time = history->du_etime; (void) strftime(buf, sizeof (buf), "%T", localtime(&time)); (void) snprintf(ubuf.history_l_etime, sizeof (ubuf.history_l_etime), "%s", buf); (void) snprintf(ubuf.history_l_rbytes, sizeof (ubuf.history_l_rbytes), "%llu", history->du_rbytes); (void) snprintf(ubuf.history_l_obytes, sizeof (ubuf.history_l_obytes), "%llu", history->du_obytes); (void) snprintf(ubuf.history_l_bandwidth, sizeof (ubuf.history_l_bandwidth), "%s Mbps", dladm_bw2str(history->du_bandwidth, buf)); ofmt_print(state->us_ofmt, (void *)&ubuf); return (DLADM_STATUS_OK); }
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 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 *zonename = 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"); linkname[0] = '\0'; bzero(&state, sizeof (state)); opterr = 0; while ((option = getopt_long(argc, argv, ":rtApi:o:u:l:hz:", 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 '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"); break; case 'h': if (r_arg || t_arg || p_arg || o_arg || u_arg || i_arg || A_arg) { die("the option -h is not compatible with " "-r, -t, -p, -o, -u, -i, -A"); } do_show_history(argc, argv); return (0); break; case 'z': zonename = optarg; 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 (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"); if (linkname[0] != '\0') { if (dladm_zname2info(handle, zonename, linkname, &linkid, NULL, NULL, NULL) != DLADM_STATUS_OK) die("invalid link '%s'", linkname); } /* 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 (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); ofmt_check(oferr, state.fs_parsable, ofmt, die, warn); 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); }