/* * Wrapper of dladm_walk_flow(query_flow_stats,...) to make it usable for * dladm_walk_datalink_id(). Used for showing flow stats for * all flows on all links. */ static int dump_link_flow_stats(dladm_handle_t dh, datalink_id_t linkid, void * arg) { if (dladm_walk_flow(dump_one_flow_stats, dh, linkid, arg, B_FALSE) == DLADM_STATUS_OK) return (DLADM_WALK_CONTINUE); else return (DLADM_WALK_TERMINATE); }
/* * Wrapper of dladm_walk_flow(show_flow,...) to make it usable to * dladm_walk_datalink_id(). Used for showing flow attributes for * all flows on all links. */ static int show_flows_onelink(dladm_handle_t dh, datalink_id_t linkid, void *arg) { show_flow_state_t *state = arg; (void) dladm_walk_flow(show_flow, dh, linkid, arg, state->fs_persist); return (DLADM_WALK_CONTINUE); }
/* * Wrapper of dladm_walk_flow(show_walk_fn,...) to make it * usable to dladm_walk_datalink_id() */ static int show_flowprop_onelink(dladm_handle_t dh, datalink_id_t linkid, void *arg) { char name[MAXLINKNAMELEN]; if (dladm_datalink_id2info(dh, linkid, NULL, NULL, NULL, name, sizeof (name)) != DLADM_STATUS_OK) return (DLADM_WALK_TERMINATE); (void) dladm_walk_flow(show_flowprop, dh, linkid, arg, B_FALSE); return (DLADM_WALK_CONTINUE); }
/* 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 void dump_all_flow_stats(dladm_flow_attr_t *attrp, void *arg, datalink_id_t linkid, boolean_t flow_arg) { /* Show stats for named flow */ if (flow_arg) { (void) dump_one_flow_stats(handle, attrp, arg); /* Show stats for flows on one link */ } else if (linkid != DATALINK_INVALID_LINKID) { (void) dladm_walk_flow(dump_one_flow_stats, handle, linkid, arg, B_FALSE); /* Show stats for all flows on all links */ } else { (void) dladm_walk_datalink_id(dump_link_flow_stats, handle, arg, DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE, DLADM_OPT_ACTIVE); } }
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); }
static void do_remove_flow(int argc, char *argv[]) { char option; char *flowname = NULL; char linkname[MAXLINKNAMELEN]; datalink_id_t linkid = DATALINK_ALL_LINKID; boolean_t l_arg = B_FALSE; remove_flow_state_t state; dladm_status_t status; bzero(&state, sizeof (state)); opterr = 0; while ((option = getopt_long(argc, argv, ":tR:l:", longopts, NULL)) != -1) { switch (option) { case 't': t_arg = B_TRUE; break; case 'R': altroot = optarg; break; case 'l': if (strlcpy(linkname, optarg, MAXLINKNAMELEN) >= MAXLINKNAMELEN) { die("link name too long"); } 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; } } /* when link not specified get flow name */ if (!l_arg) { if (optind != (argc-1)) { usage(); } else { if (strlen(argv[optind]) >= MAXFLOWNAMELEN) die("flow name too long"); flowname = argv[optind]; } status = dladm_flow_remove(handle, flowname, t_arg, altroot); } else { /* if link is specified then flow name should not be there */ if (optind == argc-1) usage(); /* walk the link to find flows and remove them */ state.fs_tempop = t_arg; state.fs_altroot = altroot; state.fs_status = DLADM_STATUS_OK; status = dladm_walk_flow(remove_flow, handle, linkid, &state, B_FALSE); /* * check if dladm_walk_flow terminated early and see if the * walker function as any status for us */ if (status == DLADM_STATUS_OK) status = state.fs_status; } if (status != DLADM_STATUS_OK) die_dlerr(status, "remove flow failed"); }