예제 #1
0
/* ARGSUSED */
static void
do_init_flow(int argc, char *argv[])
{
	dladm_status_t status;

	status = dladm_flow_init(handle);
	if (status != DLADM_STATUS_OK)
		die_dlerr(status, "flows initialization failed");
}
예제 #2
0
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;
}
예제 #3
0
int
main(int argc, char *argv[])
{
	int	i, arglen, cmdlen;
	cmd_t	*cmdp;
	dladm_status_t status;

	(void) setlocale(LC_ALL, "");
#if !defined(TEXT_DOMAIN)
#define	TEXT_DOMAIN "SYS_TEST"
#endif
	(void) textdomain(TEXT_DOMAIN);

	progname = argv[0];

	if (argc < 2)
		usage();

	for (i = 0; i < sizeof (cmds) / sizeof (cmds[0]); i++) {
		cmdp = &cmds[i];
		arglen = strlen(argv[1]);
		cmdlen = strlen(cmdp->c_name);
		if ((arglen == cmdlen) && (strncmp(argv[1], cmdp->c_name,
		    cmdlen) == 0)) {
			/* Open the libdladm handle */
			if ((status = dladm_open(&handle)) != DLADM_STATUS_OK) {
				die_dlerr(status,
				    "could not open /dev/dld");
			}

			cmdp->c_fn(argc - 1, &argv[1]);

			dladm_close(handle);
			exit(EXIT_SUCCESS);
		}
	}

	(void) fprintf(stderr, gettext("%s: unknown subcommand '%s'\n"),
	    progname, argv[1]);
	usage();

	return (0);
}
예제 #4
0
/* 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);
}
예제 #5
0
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);
}
예제 #6
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");
}
예제 #7
0
static void
do_add_flow(int argc, char *argv[])
{
	char			devname[MAXLINKNAMELEN];
	char			*name = NULL;
	uint_t			index;
	datalink_id_t		linkid;

	char			option;
	boolean_t		l_arg = B_FALSE;
	char			propstr[DLADM_STRSIZE];
	char			attrstr[DLADM_STRSIZE];
	dladm_arg_list_t	*proplist = NULL;
	dladm_arg_list_t	*attrlist = NULL;
	dladm_status_t		status;

	bzero(propstr, DLADM_STRSIZE);
	bzero(attrstr, DLADM_STRSIZE);

	while ((option = getopt_long(argc, argv, "tR:l:a:p:",
	    prop_longopts, NULL)) != -1) {
		switch (option) {
		case 't':
			t_arg = B_TRUE;
			break;
		case 'R':
			altroot = optarg;
			break;
		case 'l':
			if (strlcpy(devname, optarg,
			    MAXLINKNAMELEN) >= MAXLINKNAMELEN) {
				die("link name too long");
			}
			if (dladm_name2info(handle, devname, &linkid, NULL,
			    NULL, NULL) != DLADM_STATUS_OK)
				die("invalid link '%s'", devname);
			l_arg = B_TRUE;
			break;
		case 'a':
			(void) strlcat(attrstr, optarg, DLADM_STRSIZE);
			if (strlcat(attrstr, ",", DLADM_STRSIZE) >=
			    DLADM_STRSIZE)
				die("attribute list too long '%s'", attrstr);
			break;
		case 'p':
			(void) strlcat(propstr, optarg, DLADM_STRSIZE);
			if (strlcat(propstr, ",", DLADM_STRSIZE) >=
			    DLADM_STRSIZE)
				die("property list too long '%s'", propstr);
			break;
		default:
			die_opterr(optopt, option);
		}
	}
	if (!l_arg) {
		die("link is required");
	}

	opterr = 0;
	index = optind;

	if ((index != (argc - 1)) || match_attr(argv[index]) != NULL) {
		die("flow name is required");
	} else {
		/* get flow name; required last argument */
		if (strlen(argv[index]) >= MAXFLOWNAMELEN)
			die("flow name too long");
		name = argv[index];
	}

	if (dladm_parse_flow_attrs(attrstr, &attrlist, B_FALSE)
	    != DLADM_STATUS_OK)
		die("invalid flow attribute specified");
	if (dladm_parse_flow_props(propstr, &proplist, B_FALSE)
	    != DLADM_STATUS_OK)
		die("invalid flow property specified");

	status = dladm_flow_add(handle, linkid, attrlist, proplist, name,
	    t_arg, altroot);
	if (status != DLADM_STATUS_OK)
		die_dlerr(status, "add flow failed");

	dladm_free_attrs(attrlist);
	dladm_free_props(proplist);
}
예제 #8
0
static void
set_flowprop(int argc, char **argv, boolean_t reset)
{
	int			i, option;
	char			errmsg[DLADM_STRSIZE];
	const char		*flow = NULL;
	char			propstr[DLADM_STRSIZE];
	dladm_arg_list_t	*proplist = NULL;
	boolean_t		temp = B_FALSE;
	dladm_status_t		status = DLADM_STATUS_OK;

	opterr = 0;
	bzero(propstr, DLADM_STRSIZE);

	while ((option = getopt_long(argc, argv, ":p:R:t",
	    prop_longopts, NULL)) != -1) {
		switch (option) {
		case 'p':
			(void) strlcat(propstr, optarg, DLADM_STRSIZE);
			if (strlcat(propstr, ",", DLADM_STRSIZE) >=
			    DLADM_STRSIZE)
				die("property list too long '%s'", propstr);
			break;
		case 't':
			temp = B_TRUE;
			break;
		case 'R':
			status = dladm_set_rootdir(optarg);
			if (status != DLADM_STATUS_OK) {
				die_dlerr(status, "invalid directory "
				    "specified");
			}
			break;
		default:
			die_opterr(optopt, option);
			break;
		}
	}

	if (optind == (argc - 1)) {
		if (strlen(argv[optind]) >= MAXFLOWNAMELEN)
			die("flow name too long");
		flow = argv[optind];
	} else if (optind != argc) {
		usage();
	}
	if (flow == NULL)
		die("flow name must be specified");

	if (dladm_parse_flow_props(propstr, &proplist, reset)
	    != DLADM_STATUS_OK)
		die("invalid flow property specified");

	if (proplist == NULL) {
		char *errprop;

		if (!reset)
			die("flow property must be specified");

		status = dladm_set_flowprop(handle, flow, NULL, NULL, 0,
		    DLADM_OPT_ACTIVE, &errprop);
		if (status != DLADM_STATUS_OK) {
			warn_dlerr(status, "cannot reset flow property '%s' "
			    "on '%s'", errprop, flow);
		}
		if (!temp) {
			dladm_status_t	s;

			s = set_flowprop_persist(flow, NULL, NULL, 0, reset);
			if (s != DLADM_STATUS_OK)
				status = s;
		}
		goto done;
	}

	for (i = 0; i < proplist->al_count; i++) {
		dladm_arg_info_t	*aip = &proplist->al_info[i];
		char		**val;
		uint_t		count;
		dladm_status_t	s;

		if (reset) {
			val = NULL;
			count = 0;
		} else {
			val = aip->ai_val;
			count = aip->ai_count;
			if (count == 0) {
				warn("no value specified for '%s'",
				    aip->ai_name);
				status = DLADM_STATUS_BADARG;
				continue;
			}
		}
		s = dladm_set_flowprop(handle, flow, aip->ai_name, val, count,
		    DLADM_OPT_ACTIVE, NULL);
		if (s == DLADM_STATUS_OK) {
			if (!temp) {
				s = set_flowprop_persist(flow,
				    aip->ai_name, val, count, reset);
				if (s != DLADM_STATUS_OK)
					status = s;
			}
			continue;
		}
		status = s;
		switch (s) {
		case DLADM_STATUS_NOTFOUND:
			warn("invalid flow property '%s'", aip->ai_name);
			break;
		case DLADM_STATUS_BADVAL: {
			int		j;
			char		*ptr, *lim;
			char		**propvals = NULL;
			uint_t		valcnt = DLADM_MAX_PROP_VALCNT;

			ptr = malloc((sizeof (char *) +
			    DLADM_PROP_VAL_MAX) * DLADM_MAX_PROP_VALCNT +
			    MAX_PROP_LINE);

			if (ptr == NULL)
				die("insufficient memory");
			propvals = (char **)(void *)ptr;

			for (j = 0; j < DLADM_MAX_PROP_VALCNT; j++) {
				propvals[j] = ptr + sizeof (char *) *
				    DLADM_MAX_PROP_VALCNT +
				    j * DLADM_PROP_VAL_MAX;
			}
			s = dladm_get_flowprop(handle, flow,
			    DLADM_PROP_VAL_MODIFIABLE, aip->ai_name, propvals,
			    &valcnt);

			ptr = errmsg;
			lim = ptr + DLADM_STRSIZE;
			*ptr = '\0';
			for (j = 0; j < valcnt && s == DLADM_STATUS_OK; j++) {
				ptr += snprintf(ptr, lim - ptr, "%s,",
				    propvals[j]);
				if (ptr >= lim)
					break;
			}
			if (ptr > errmsg) {
				*(ptr - 1) = '\0';
				warn("flow property '%s' must be one of: %s",
				    aip->ai_name, errmsg);
			} else
				warn("%s is an invalid value for "
				    "flow property %s", *val, aip->ai_name);
			free(propvals);
			break;
		}
		default:
			if (reset) {
				warn_dlerr(status, "cannot reset flow property "
				    "'%s' on '%s'", aip->ai_name, flow);
			} else {
				warn_dlerr(status, "cannot set flow property "
				    "'%s' on '%s'", aip->ai_name, flow);
			}
			break;
		}
	}
done:
	dladm_free_props(proplist);
	if (status != DLADM_STATUS_OK) {
		dladm_close(handle);
		exit(EXIT_FAILURE);
	}
}