summaryrefslogtreecommitdiff
path: root/usr/src/cmd/dladm/dladm.c
diff options
context:
space:
mode:
authoryz147064 <none@none>2008-01-23 18:09:15 -0800
committeryz147064 <none@none>2008-01-23 18:09:15 -0800
commitd62bc4badc1c1f1549c961cfb8b420e650e1272b (patch)
tree9f466859e9cfb73da13b64261432aba4683f19ad /usr/src/cmd/dladm/dladm.c
parentd38257c4392a9dd690c2f7f2383236c1fc80e509 (diff)
downloadillumos-joyent-d62bc4badc1c1f1549c961cfb8b420e650e1272b.tar.gz
PSARC/2006/499 Clearview Nemo unification and vanity naming
PSARC/2007/527 Addendum for Clearview Vanity Naming and Nemo Unification PSARC/2008/002 Clearview UV Updates 6310766 vlan statistics get reset at unplumb time 6320515 dladm commands with "-R" option should not take effect immediately 6433732 Simplify the GLDv3 control path by making its processing asynchronous 6445912 dladm show-link fails to show a specific link in the debug version 6452413 dladm show-link doesn't show VLAN links for GLDv2 drivers 6504433 libwladm's use of wladm_wlresult2status() needs an overhaul 6504507 dladm set-linkprop failure message is unclear 6534289 DR should work with aggregations 6535719 dladm_aggr_port_attr_db_t`lp_devname should be MAXNAMELEN, not MAXNAMELEN + 1 6539634 GLDv3 should DL_ERROR_ACK a DL_UDQOS_REQ with DL_OUTSTATE when the stream is DL_UNATTACHED 6540246 libdladm should not guess zoneid from DLDIOCZIDGET ioctl errno 6544195 dladm show-dev assumes GLDv3 stats.. incompatible with GLDv2 6563295 dladm show-linkprop -P does not work properly for unavailable links 6577618 integrate network vanity naming and nemo unification 6600446 links assigned to a local zone are still aggregatable by global zone 6607572 "boot net - install" can trigger assertion failure in dld_str_attach() 6613956 "svccfg import -" does not work as bfu expects 6637596 invalid assertion in ip_soft_ring_assignment() 6642350 kernel DLPI processing routines are long overdue 6643338 GLDv3 PPA hack VLAN ID checks don't always work 6647203 bfu: smf_delete_manifest() does not work for non-global zones 6649885 DL_IB GLDv3 mactype plugin must fill in its mtr_nativetype 6650395 libuuid should be lint-clean and linted nightly --HG-- rename : usr/src/cmd/dladm/aggregation.conf => deleted_files/usr/src/cmd/dladm/aggregation.conf rename : usr/src/cmd/dladm/linkprop.conf => deleted_files/usr/src/cmd/dladm/linkprop.conf rename : usr/src/lib/libinetcfg/common/inetcfg_nic.c => deleted_files/usr/src/lib/libinetcfg/common/inetcfg_nic.c rename : usr/src/lib/libinetcfg/common/inetcfg_nic.h => deleted_files/usr/src/lib/libinetcfg/common/inetcfg_nic.h
Diffstat (limited to 'usr/src/cmd/dladm/dladm.c')
-rw-r--r--usr/src/cmd/dladm/dladm.c2801
1 files changed, 2017 insertions, 784 deletions
diff --git a/usr/src/cmd/dladm/dladm.c b/usr/src/cmd/dladm/dladm.c
index 17a3d53e6a..22cc5c515e 100644
--- a/usr/src/cmd/dladm/dladm.c
+++ b/usr/src/cmd/dladm/dladm.c
@@ -19,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -34,6 +34,7 @@
#include <fcntl.h>
#include <string.h>
#include <stropts.h>
+#include <sys/stat.h>
#include <errno.h>
#include <kstat.h>
#include <strings.h>
@@ -45,18 +46,24 @@
#include <auth_attr.h>
#include <auth_list.h>
#include <libintl.h>
+#include <libdevinfo.h>
#include <libdlpi.h>
#include <libdllink.h>
#include <libdlaggr.h>
#include <libdlwlan.h>
+#include <libdlvlan.h>
+#include <libdlvnic.h>
#include <libinetutil.h>
#include <bsm/adt.h>
#include <bsm/adt_event.h>
-#define AGGR_DRV "aggr"
-#define MAXPORT 256
-#define DUMP_LACP_FORMAT " %-9s %-8s %-7s %-12s " \
- "%-5s %-4s %-4s %-9s %-7s\n"
+#define AGGR_DRV "aggr"
+#define MAXPORT 256
+#define BUFLEN(lim, ptr) (((lim) > (ptr)) ? ((lim) - (ptr)) : 0)
+#define MAXLINELEN 1024
+#define SMF_UPGRADE_FILE "/var/svc/profile/upgrade"
+#define SMF_UPGRADEDATALINK_FILE "/var/svc/profile/upgrade_datalink"
+#define SMF_DLADM_UPGRADE_MSG " # added by dladm(1M)"
typedef struct pktsum_s {
uint64_t ipackets;
@@ -67,54 +74,56 @@ typedef struct pktsum_s {
uint32_t oerrors;
} pktsum_t;
-typedef struct show_link_state {
+typedef struct show_state {
boolean_t ls_firstonly;
boolean_t ls_donefirst;
- boolean_t ls_stats;
pktsum_t ls_prevstats;
boolean_t ls_parseable;
-} show_link_state_t;
+ uint32_t ls_flags;
+ dladm_status_t ls_status;
+} show_state_t;
typedef struct show_grp_state {
- uint32_t gs_key;
boolean_t gs_lacp;
- boolean_t gs_found;
+ boolean_t gs_extended;
boolean_t gs_stats;
boolean_t gs_firstonly;
+ boolean_t gs_donefirst;
pktsum_t gs_prevstats[MAXPORT];
boolean_t gs_parseable;
+ uint32_t gs_flags;
+ dladm_status_t gs_status;
} show_grp_state_t;
-typedef struct show_mac_state {
- boolean_t ms_firstonly;
- boolean_t ms_donefirst;
- pktsum_t ms_prevstats;
- boolean_t ms_parseable;
-} show_mac_state_t;
-
-typedef void cmdfunc_t(int, char **);
+typedef void cmdfunc_t(int, char **);
-static cmdfunc_t do_show_link, do_show_dev, do_show_wifi;
+static cmdfunc_t do_show_link, do_show_dev, do_show_wifi, do_show_phys;
static cmdfunc_t do_create_aggr, do_delete_aggr, do_add_aggr, do_remove_aggr;
-static cmdfunc_t do_modify_aggr, do_show_aggr, do_up_aggr, do_down_aggr;
+static cmdfunc_t do_modify_aggr, do_show_aggr, do_up_aggr;
static cmdfunc_t do_scan_wifi, do_connect_wifi, do_disconnect_wifi;
static cmdfunc_t do_show_linkprop, do_set_linkprop, do_reset_linkprop;
static cmdfunc_t do_create_secobj, do_delete_secobj, do_show_secobj;
static cmdfunc_t do_init_linkprop, do_init_secobj;
+static cmdfunc_t do_create_vlan, do_delete_vlan, do_up_vlan, do_show_vlan;
+static cmdfunc_t do_rename_link, do_delete_phys, do_init_phys;
+static cmdfunc_t do_show_linkmap;
-static void show_linkprop_onelink(void *, const char *);
+static void altroot_cmd(char *, int, char **);
+static int show_linkprop_onelink(datalink_id_t, void *);
-static void link_stats(const char *, uint_t);
-static void aggr_stats(uint32_t, uint_t);
+static void link_stats(datalink_id_t, uint_t);
+static void aggr_stats(datalink_id_t, show_grp_state_t *, uint_t);
static void dev_stats(const char *dev, uint32_t);
+static int get_one_kstat(const char *, const char *, uint8_t,
+ void *, boolean_t);
static void get_mac_stats(const char *, pktsum_t *);
static void get_link_stats(const char *, pktsum_t *);
-static uint64_t mac_ifspeed(const char *);
+static uint64_t get_ifspeed(const char *, boolean_t);
static void stats_total(pktsum_t *, pktsum_t *, pktsum_t *);
static void stats_diff(pktsum_t *, pktsum_t *, pktsum_t *);
-static const char *mac_link_state(const char *, char *);
-static const char *mac_link_duplex(const char *, char *);
+static const char *get_linkstate(const char *, boolean_t, char *);
+static const char *get_linkduplex(const char *, boolean_t, char *);
static boolean_t str2int(const char *, int *);
static void die(const char *, ...);
@@ -139,7 +148,6 @@ static cmd_t cmds[] = {
{ "modify-aggr", do_modify_aggr },
{ "show-aggr", do_show_aggr },
{ "up-aggr", do_up_aggr },
- { "down-aggr", do_down_aggr },
{ "scan-wifi", do_scan_wifi },
{ "connect-wifi", do_connect_wifi },
{ "disconnect-wifi", do_disconnect_wifi },
@@ -151,50 +159,67 @@ static cmd_t cmds[] = {
{ "delete-secobj", do_delete_secobj },
{ "show-secobj", do_show_secobj },
{ "init-linkprop", do_init_linkprop },
- { "init-secobj", do_init_secobj }
+ { "init-secobj", do_init_secobj },
+ { "create-vlan", do_create_vlan },
+ { "delete-vlan", do_delete_vlan },
+ { "show-vlan", do_show_vlan },
+ { "up-vlan", do_up_vlan },
+ { "rename-link", do_rename_link },
+ { "delete-phys", do_delete_phys },
+ { "show-phys", do_show_phys },
+ { "init-phys", do_init_phys },
+ { "show-linkmap", do_show_linkmap }
+};
+
+static const struct option lopts[] = {
+ {"vlan-id", required_argument, 0, 'v'},
+ {"dev", required_argument, 0, 'd'},
+ {"policy", required_argument, 0, 'P'},
+ {"lacp-mode", required_argument, 0, 'L'},
+ {"lacp-timer", required_argument, 0, 'T'},
+ {"unicast", required_argument, 0, 'u'},
+ {"temporary", no_argument, 0, 't'},
+ {"root-dir", required_argument, 0, 'R'},
+ {"link", required_argument, 0, 'l'},
+ {"forcible", no_argument, 0, 'f'},
+ { 0, 0, 0, 0 }
};
-static const struct option longopts[] = {
- {"vlan-id", required_argument, 0, 'v' },
- {"dev", required_argument, 0, 'd' },
- {"policy", required_argument, 0, 'P' },
- {"lacp-mode", required_argument, 0, 'l' },
- {"lacp-timer", required_argument, 0, 'T' },
- {"unicast", required_argument, 0, 'u' },
- {"statistics", no_argument, 0, 's' },
- {"interval", required_argument, 0, 'i' },
- {"lacp", no_argument, 0, 'L' },
- {"temporary", no_argument, 0, 't' },
- {"root-dir", required_argument, 0, 'r' },
- {"parseable", no_argument, 0, 'p' },
+static const struct option show_lopts[] = {
+ {"statistics", no_argument, 0, 's'},
+ {"interval", required_argument, 0, 'i'},
+ {"parseable", no_argument, 0, 'p'},
+ {"extended", no_argument, 0, 'x'},
+ {"persistent", no_argument, 0, 'P'},
+ {"lacp", no_argument, 0, 'L'},
{ 0, 0, 0, 0 }
};
static const struct option prop_longopts[] = {
- {"temporary", no_argument, 0, 't' },
- {"root-dir", required_argument, 0, 'R' },
- {"prop", required_argument, 0, 'p' },
- {"parseable", no_argument, 0, 'c' },
- {"persistent", no_argument, 0, 'P' },
+ {"temporary", no_argument, 0, 't' },
+ {"root-dir", required_argument, 0, 'R' },
+ {"prop", required_argument, 0, 'p' },
+ {"parseable", no_argument, 0, 'c' },
+ {"persistent", no_argument, 0, 'P' },
{ 0, 0, 0, 0 }
};
static const struct option wifi_longopts[] = {
- {"parseable", no_argument, 0, 'p' },
- {"output", required_argument, 0, 'o' },
- {"essid", required_argument, 0, 'e' },
- {"bsstype", required_argument, 0, 'b' },
- {"mode", required_argument, 0, 'm' },
- {"key", required_argument, 0, 'k' },
- {"sec", required_argument, 0, 's' },
- {"auth", required_argument, 0, 'a' },
- {"create-ibss", required_argument, 0, 'c' },
- {"timeout", required_argument, 0, 'T' },
- {"all-links", no_argument, 0, 'a' },
- {"temporary", no_argument, 0, 't' },
- {"root-dir", required_argument, 0, 'R' },
- {"persistent", no_argument, 0, 'P' },
- {"file", required_argument, 0, 'f' },
+ {"parseable", no_argument, 0, 'p' },
+ {"output", required_argument, 0, 'o' },
+ {"essid", required_argument, 0, 'e' },
+ {"bsstype", required_argument, 0, 'b' },
+ {"mode", required_argument, 0, 'm' },
+ {"key", required_argument, 0, 'k' },
+ {"sec", required_argument, 0, 's' },
+ {"auth", required_argument, 0, 'a' },
+ {"create-ibss", required_argument, 0, 'c' },
+ {"timeout", required_argument, 0, 'T' },
+ {"all-links", no_argument, 0, 'a' },
+ {"temporary", no_argument, 0, 't' },
+ {"root-dir", required_argument, 0, 'R' },
+ {"persistent", no_argument, 0, 'P' },
+ {"file", required_argument, 0, 'f' },
{ 0, 0, 0, 0 }
};
@@ -205,25 +230,33 @@ static void
usage(void)
{
(void) fprintf(stderr, gettext("usage: dladm <subcommand> <args> ...\n"
- "\tshow-link [-p] [-s [-i <interval>]] [<name>]\n"
- "\tshow-dev [-p] [-s [-i <interval>]] [<dev>]\n"
+ "\tshow-link [-pP] [-s [-i <interval>]] [<link>]\n"
+ "\trename-link [-R <root-dir>] <oldlink> <newlink>\n"
+ "\n"
+ "\tdelete-phys <link>\n"
+ "\tshow-phys [-pP] [<link>]\n"
+ "\tshow-dev [-p] [-s [-i <interval>]] [<dev>]\n"
"\n"
- "\tcreate-aggr [-t] [-R <root-dir>] [-P <policy>] [-l <mode>]\n"
- "\t [-T <time>] [-u <address>] -d <dev> ... <key>\n"
- "\tmodify-aggr [-t] [-R <root-dir>] [-P <policy>] [-l <mode>]\n"
- "\t [-T <time>] [-u <address>] <key>\n"
- "\tdelete-aggr [-t] [-R <root-dir>] <key>\n"
- "\tadd-aggr [-t] [-R <root-dir>] -d <dev> ... <key>\n"
- "\tremove-aggr [-t] [-R <root-dir>] -d <dev> ... <key>\n"
- "\tshow-aggr [-pL][-s [-i <interval>]] [<key>]\n"
+ "\tcreate-aggr [-t] [-R <root-dir>] [-P <policy>] [-L <mode>]\n"
+ "\t [-T <time>] [-u <address>] [-l <link>] ... <link>\n"
+ "\tmodify-aggr [-t] [-R <root-dir>] [-P <policy>] [-L <mode>]\n"
+ "\t [-T <time>] [-u <address>] <link>\n"
+ "\tdelete-aggr [-t] [-R <root-dir>] <link>\n"
+ "\tadd-aggr [-t] [-R <root-dir>] [-l <link>] ... <link>\n"
+ "\tremove-aggr [-t] [-R <root-dir>] [-l <link>] ... <link>"
+ "\n\tshow-aggr [-pPLx][-s [-i <interval>]] [<link>]\n"
"\n"
- "\tscan-wifi [-p] [-o <field>,...] [<name>]\n"
+ "\tcreate-vlan [-ft] [-R <root-dir>] -l <link> -v <vid> [link]"
+ "\n\tdelete-vlan [-t] [-R <root-dir>] <link>\n"
+ "\tshow-vlan [-pP] [<link>]\n"
+ "\n"
+ "\tscan-wifi [-p] [-o <field>,...] [<link>]\n"
"\tconnect-wifi [-e <essid>] [-i <bssid>] [-k <key>,...]"
" [-s wep|wpa]\n"
"\t [-a open|shared] [-b bss|ibss] [-c] [-m a|b|g]\n"
- "\t [-T <time>] [<name>]\n"
- "\tdisconnect-wifi [-a] [<name>]\n"
- "\tshow-wifi [-p] [-o <field>,...] [<name>]\n"
+ "\t [-T <time>] [<link>]\n"
+ "\tdisconnect-wifi [-a] [<link>]\n"
+ "\tshow-wifi [-p] [-o <field>,...] [<link>]\n"
"\n"
"\tset-linkprop [-t] [-R <root-dir>] -p <prop>=<value>[,...]"
" <name>\n"
@@ -276,36 +309,35 @@ main(int argc, char *argv[])
static void
do_create_aggr(int argc, char *argv[])
{
- char option;
- int key;
- uint32_t policy = AGGR_POLICY_L4;
- aggr_lacp_mode_t lacp_mode = AGGR_LACP_OFF;
- aggr_lacp_timer_t lacp_timer = AGGR_LACP_TIMER_SHORT;
+ char option;
+ int key = 0;
+ uint32_t policy = AGGR_POLICY_L4;
+ aggr_lacp_mode_t lacp_mode = AGGR_LACP_OFF;
+ aggr_lacp_timer_t lacp_timer = AGGR_LACP_TIMER_SHORT;
dladm_aggr_port_attr_db_t port[MAXPORT];
- uint_t nport = 0;
- uint8_t mac_addr[ETHERADDRL];
- boolean_t mac_addr_fixed = B_FALSE;
- boolean_t P_arg = B_FALSE;
- boolean_t l_arg = B_FALSE;
- boolean_t t_arg = B_FALSE;
- boolean_t u_arg = B_FALSE;
- boolean_t T_arg = B_FALSE;
- char *altroot = NULL;
- dladm_status_t status;
+ uint_t n, ndev, nlink;
+ uint8_t mac_addr[ETHERADDRL];
+ boolean_t mac_addr_fixed = B_FALSE;
+ boolean_t P_arg = B_FALSE;
+ boolean_t l_arg = B_FALSE;
+ boolean_t u_arg = B_FALSE;
+ boolean_t T_arg = B_FALSE;
+ uint32_t flags = DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST;
+ char *altroot = NULL;
+ char name[MAXLINKNAMELEN];
+ char *devs[MAXPORT];
+ char *links[MAXPORT];
+ dladm_status_t status;
- opterr = 0;
- while ((option = getopt_long(argc, argv, ":d:l:P:R:tu:T:",
- longopts, NULL)) != -1) {
+ ndev = nlink = opterr = 0;
+ while ((option = getopt_long(argc, argv, ":d:l:L:P:R:tfu:T:",
+ lopts, NULL)) != -1) {
switch (option) {
case 'd':
- if (nport >= MAXPORT)
- die("too many <dev> arguments");
-
- if (strlcpy(port[nport].lp_devname, optarg,
- MAXNAMELEN) >= MAXNAMELEN)
- die("device name too long");
+ if (ndev + nlink >= MAXPORT)
+ die("too many ports specified");
- nport++;
+ devs[ndev++] = optarg;
break;
case 'P':
if (P_arg)
@@ -325,6 +357,19 @@ do_create_aggr(int argc, char *argv[])
die("invalid MAC address '%s'", optarg);
break;
case 'l':
+ if (isdigit(optarg[strlen(optarg) - 1])) {
+
+ /*
+ * Ended with digit, possibly a link name.
+ */
+ if (ndev + nlink >= MAXPORT)
+ die("too many ports specified");
+
+ links[nlink++] = optarg;
+ break;
+ }
+ /* FALLTHROUGH */
+ case 'L':
if (l_arg)
die_optdup(option);
@@ -341,7 +386,10 @@ do_create_aggr(int argc, char *argv[])
die("invalid LACP timer value '%s'", optarg);
break;
case 't':
- t_arg = B_TRUE;
+ flags &= ~DLADM_OPT_PERSIST;
+ break;
+ case 'f':
+ flags |= DLADM_OPT_FORCE;
break;
case 'R':
altroot = optarg;
@@ -352,37 +400,100 @@ do_create_aggr(int argc, char *argv[])
}
}
- if (nport == 0)
+ if (ndev + nlink == 0)
usage();
- /* get key value (required last argument) */
+ /* get key value or the aggregation name (required last argument) */
if (optind != (argc-1))
usage();
- if (!str2int(argv[optind], &key) || key < 1)
- die("invalid key value '%s'", argv[optind]);
+ if (!str2int(argv[optind], &key)) {
+ if (strlcpy(name, argv[optind], MAXLINKNAMELEN) >=
+ MAXLINKNAMELEN) {
+ die("link name too long '%s'", argv[optind]);
+ }
- status = dladm_aggr_create(key, nport, port, policy, mac_addr_fixed,
- mac_addr, lacp_mode, lacp_timer, t_arg, altroot);
- if (status != DLADM_STATUS_OK)
- die_dlerr(status, "create operation failed");
+ if (!dladm_valid_linkname(name))
+ die("invalid link name '%s'", argv[optind]);
+ } else {
+ (void) snprintf(name, MAXLINKNAMELEN, "aggr%d", key);
+ }
+
+ if (altroot != NULL)
+ altroot_cmd(altroot, argc, argv);
+
+ for (n = 0; n < ndev; n++) {
+ if (dladm_dev2linkid(devs[n], &port[n].lp_linkid) !=
+ DLADM_STATUS_OK) {
+ die("invalid dev name '%s'", devs[n]);
+ }
+ }
+
+ for (n = 0; n < nlink; n++) {
+ if (dladm_name2info(links[n], &port[ndev + n].lp_linkid,
+ NULL, NULL, NULL) != DLADM_STATUS_OK) {
+ die("invalid link name '%s'", links[n]);
+ }
+ }
+
+ status = dladm_aggr_create(name, key, ndev + nlink, port, policy,
+ mac_addr_fixed, (const uchar_t *)mac_addr, lacp_mode,
+ lacp_timer, flags);
+done:
+ if (status != DLADM_STATUS_OK) {
+ if (status == DLADM_STATUS_NONOTIF) {
+ die_dlerr(status, "not all links have link up/down "
+ "detection; must use -f (see dladm(1M))\n");
+ } else {
+ die_dlerr(status, "create operation failed");
+ }
+ }
+}
+
+/*
+ * arg is either the key or the aggr name. Validate it and convert it to
+ * the linkid if altroot is NULL.
+ */
+static dladm_status_t
+i_dladm_aggr_get_linkid(const char *altroot, const char *arg,
+ datalink_id_t *linkidp, uint32_t flags)
+{
+ int key = 0;
+ char *aggr = NULL;
+ dladm_status_t status;
+
+ if (!str2int(arg, &key))
+ aggr = (char *)arg;
+
+ if (aggr == NULL && key == 0)
+ return (DLADM_STATUS_LINKINVAL);
+
+ if (altroot != NULL)
+ return (DLADM_STATUS_OK);
+
+ if (aggr != NULL) {
+ status = dladm_name2info(aggr, linkidp, NULL, NULL, NULL);
+ } else {
+ status = dladm_key2linkid(key, linkidp, flags);
+ }
+
+ return (status);
}
static void
do_delete_aggr(int argc, char *argv[])
{
- int key;
char option;
- boolean_t t_arg = B_FALSE;
char *altroot = NULL;
+ uint32_t flags = DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST;
dladm_status_t status;
+ datalink_id_t linkid;
opterr = 0;
- while ((option = getopt_long(argc, argv, ":R:t", longopts,
- NULL)) != -1) {
+ while ((option = getopt_long(argc, argv, ":R:t", lopts, NULL)) != -1) {
switch (option) {
case 't':
- t_arg = B_TRUE;
+ flags &= ~DLADM_OPT_PERSIST;
break;
case 'R':
altroot = optarg;
@@ -393,14 +504,19 @@ do_delete_aggr(int argc, char *argv[])
}
}
- /* get key value (required last argument) */
+ /* get key value or the aggregation name (required last argument) */
if (optind != (argc-1))
usage();
- if (!str2int(argv[optind], &key) || key < 1)
- die("invalid key value '%s'", argv[optind]);
+ status = i_dladm_aggr_get_linkid(altroot, argv[optind], &linkid, flags);
+ if (status != DLADM_STATUS_OK)
+ goto done;
- status = dladm_aggr_delete(key, t_arg, altroot);
+ if (altroot != NULL)
+ altroot_cmd(altroot, argc, argv);
+
+ status = dladm_aggr_delete(linkid, flags);
+done:
if (status != DLADM_STATUS_OK)
die_dlerr(status, "delete operation failed");
}
@@ -408,30 +524,37 @@ do_delete_aggr(int argc, char *argv[])
static void
do_add_aggr(int argc, char *argv[])
{
- char option;
- int key;
+ char option;
+ uint_t n, ndev, nlink;
+ char *altroot = NULL;
+ uint32_t flags = DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST;
+ datalink_id_t linkid;
+ dladm_status_t status;
dladm_aggr_port_attr_db_t port[MAXPORT];
- uint_t nport = 0;
- boolean_t t_arg = B_FALSE;
- char *altroot = NULL;
- dladm_status_t status;
+ char *devs[MAXPORT];
+ char *links[MAXPORT];
- opterr = 0;
- while ((option = getopt_long(argc, argv, ":d:R:t", longopts,
+ ndev = nlink = opterr = 0;
+ while ((option = getopt_long(argc, argv, ":d:l:R:tf", lopts,
NULL)) != -1) {
switch (option) {
case 'd':
- if (nport >= MAXPORT)
- die("too many <dev> arguments");
+ if (ndev + nlink >= MAXPORT)
+ die("too many ports specified");
- if (strlcpy(port[nport].lp_devname, optarg,
- MAXNAMELEN) >= MAXNAMELEN)
- die("device name too long");
+ devs[ndev++] = optarg;
+ break;
+ case 'l':
+ if (ndev + nlink >= MAXPORT)
+ die("too many ports specified");
- nport++;
+ links[nlink++] = optarg;
break;
case 't':
- t_arg = B_TRUE;
+ flags &= ~DLADM_OPT_PERSIST;
+ break;
+ case 'f':
+ flags |= DLADM_OPT_FORCE;
break;
case 'R':
altroot = optarg;
@@ -442,17 +565,38 @@ do_add_aggr(int argc, char *argv[])
}
}
- if (nport == 0)
+ if (ndev + nlink == 0)
usage();
- /* get key value (required last argument) */
+ /* get key value or the aggregation name (required last argument) */
if (optind != (argc-1))
usage();
- if (!str2int(argv[optind], &key) || key < 1)
- die("invalid key value '%s'", argv[optind]);
+ if ((status = i_dladm_aggr_get_linkid(altroot, argv[optind], &linkid,
+ flags & (DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST))) !=
+ DLADM_STATUS_OK) {
+ goto done;
+ }
+
+ if (altroot != NULL)
+ altroot_cmd(altroot, argc, argv);
- status = dladm_aggr_add(key, nport, port, t_arg, altroot);
+ for (n = 0; n < ndev; n++) {
+ if (dladm_dev2linkid(devs[n], &(port[n].lp_linkid)) !=
+ DLADM_STATUS_OK) {
+ die("invalid <dev> '%s'", devs[n]);
+ }
+ }
+
+ for (n = 0; n < nlink; n++) {
+ if (dladm_name2info(links[n], &port[n + ndev].lp_linkid,
+ NULL, NULL, NULL) != DLADM_STATUS_OK) {
+ die("invalid <link> '%s'", links[n]);
+ }
+ }
+
+ status = dladm_aggr_add(linkid, ndev + nlink, port, flags);
+done:
if (status != DLADM_STATUS_OK) {
/*
* checking DLADM_STATUS_NOTSUP is a temporary workaround
@@ -462,10 +606,14 @@ do_add_aggr(int argc, char *argv[])
(void) fprintf(stderr,
gettext("%s: add operation failed: %s\n"),
progname,
- gettext("device capabilities don't match"));
+ gettext("link capabilities don't match"));
exit(ENOTSUP);
+ } else if (status == DLADM_STATUS_NONOTIF) {
+ die_dlerr(status, "not all links have link up/down "
+ "detection; must use -f (see dladm(1M))\n");
+ } else {
+ die_dlerr(status, "add operation failed");
}
- die_dlerr(status, "add operation failed");
}
}
@@ -473,29 +621,34 @@ static void
do_remove_aggr(int argc, char *argv[])
{
char option;
- int key;
dladm_aggr_port_attr_db_t port[MAXPORT];
- uint_t nport = 0;
- boolean_t t_arg = B_FALSE;
+ uint_t n, ndev, nlink;
+ char *devs[MAXPORT];
+ char *links[MAXPORT];
char *altroot = NULL;
+ uint32_t flags;
+ datalink_id_t linkid;
dladm_status_t status;
- opterr = 0;
- while ((option = getopt_long(argc, argv, ":d:R:t",
- longopts, NULL)) != -1) {
+ flags = DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST;
+ ndev = nlink = opterr = 0;
+ while ((option = getopt_long(argc, argv, ":d:l:R:t",
+ lopts, NULL)) != -1) {
switch (option) {
case 'd':
- if (nport >= MAXPORT)
- die("too many <dev> arguments");
+ if (ndev + nlink >= MAXPORT)
+ die("too many ports specified");
- if (strlcpy(port[nport].lp_devname, optarg,
- MAXNAMELEN) >= MAXNAMELEN)
- die("device name too long");
+ devs[ndev++] = optarg;
+ break;
+ case 'l':
+ if (ndev + nlink >= MAXPORT)
+ die("too many ports specified");
- nport++;
+ links[nlink++] = optarg;
break;
case 't':
- t_arg = B_TRUE;
+ flags &= ~DLADM_OPT_PERSIST;
break;
case 'R':
altroot = optarg;
@@ -506,17 +659,36 @@ do_remove_aggr(int argc, char *argv[])
}
}
- if (nport == 0)
+ if (ndev + nlink == 0)
usage();
- /* get key value (required last argument) */
+ /* get key value or the aggregation name (required last argument) */
if (optind != (argc-1))
usage();
- if (!str2int(argv[optind], &key) || key < 1)
- die("invalid key value '%s'", argv[optind]);
+ status = i_dladm_aggr_get_linkid(altroot, argv[optind], &linkid, flags);
+ if (status != DLADM_STATUS_OK)
+ goto done;
+
+ if (altroot != NULL)
+ altroot_cmd(altroot, argc, argv);
+
+ for (n = 0; n < ndev; n++) {
+ if (dladm_dev2linkid(devs[n], &(port[n].lp_linkid)) !=
+ DLADM_STATUS_OK) {
+ die("invalid <dev> '%s'", devs[n]);
+ }
+ }
+
+ for (n = 0; n < nlink; n++) {
+ if (dladm_name2info(links[n], &port[n + ndev].lp_linkid,
+ NULL, NULL, NULL) != DLADM_STATUS_OK) {
+ die("invalid <link> '%s'", links[n]);
+ }
+ }
- status = dladm_aggr_remove(key, nport, port, t_arg, altroot);
+ status = dladm_aggr_remove(linkid, ndev + nlink, port, flags);
+done:
if (status != DLADM_STATUS_OK)
die_dlerr(status, "remove operation failed");
}
@@ -525,19 +697,19 @@ static void
do_modify_aggr(int argc, char *argv[])
{
char option;
- int key;
uint32_t policy = AGGR_POLICY_L4;
aggr_lacp_mode_t lacp_mode = AGGR_LACP_OFF;
aggr_lacp_timer_t lacp_timer = AGGR_LACP_TIMER_SHORT;
uint8_t mac_addr[ETHERADDRL];
boolean_t mac_addr_fixed = B_FALSE;
uint8_t modify_mask = 0;
- boolean_t t_arg = B_FALSE;
char *altroot = NULL;
+ uint32_t flags = DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST;
+ datalink_id_t linkid;
dladm_status_t status;
opterr = 0;
- while ((option = getopt_long(argc, argv, ":l:P:R:tu:T:", longopts,
+ while ((option = getopt_long(argc, argv, ":L:l:P:R:tu:T:", lopts,
NULL)) != -1) {
switch (option) {
case 'P':
@@ -560,6 +732,7 @@ do_modify_aggr(int argc, char *argv[])
die("invalid MAC address '%s'", optarg);
break;
case 'l':
+ case 'L':
if (modify_mask & DLADM_AGGR_MODIFY_LACP_MODE)
die_optdup(option);
@@ -578,7 +751,7 @@ do_modify_aggr(int argc, char *argv[])
die("invalid LACP timer value '%s'", optarg);
break;
case 't':
- t_arg = B_TRUE;
+ flags &= ~DLADM_OPT_PERSIST;
break;
case 'R':
altroot = optarg;
@@ -592,15 +765,21 @@ do_modify_aggr(int argc, char *argv[])
if (modify_mask == 0)
die("at least one of the -PulT options must be specified");
- /* get key value (required last argument) */
+ /* get key value or the aggregation name (required last argument) */
if (optind != (argc-1))
usage();
- if (!str2int(argv[optind], &key) || key < 1)
- die("invalid key value '%s'", argv[optind]);
+ status = i_dladm_aggr_get_linkid(altroot, argv[optind], &linkid, flags);
+ if (status != DLADM_STATUS_OK)
+ goto done;
+
+ if (altroot != NULL)
+ altroot_cmd(altroot, argc, argv);
- status = dladm_aggr_modify(key, modify_mask, policy, mac_addr_fixed,
- mac_addr, lacp_mode, lacp_timer, t_arg, altroot);
+ status = dladm_aggr_modify(linkid, modify_mask, policy, mac_addr_fixed,
+ (const uchar_t *)mac_addr, lacp_mode, lacp_timer, flags);
+
+done:
if (status != DLADM_STATUS_OK)
die_dlerr(status, "modify operation failed");
}
@@ -608,21 +787,27 @@ do_modify_aggr(int argc, char *argv[])
static void
do_up_aggr(int argc, char *argv[])
{
- int key = 0;
+ datalink_id_t linkid = DATALINK_ALL_LINKID;
dladm_status_t status;
- /* get aggregation key (optional last argument) */
+ /*
+ * get the key or the name of the aggregation (optional last argument)
+ */
if (argc == 2) {
- if (!str2int(argv[1], &key) || key < 1)
- die("invalid key value '%s'", argv[1]);
+ if ((status = i_dladm_aggr_get_linkid(NULL, argv[1], &linkid,
+ DLADM_OPT_PERSIST)) != DLADM_STATUS_OK) {
+ goto done;
+ }
} else if (argc > 2) {
usage();
}
- if ((status = dladm_aggr_up(key, NULL)) != DLADM_STATUS_OK) {
- if (key != 0) {
- die_dlerr(status, "could not bring up aggregation '%u'",
- key);
+ status = dladm_aggr_up(linkid);
+done:
+ if (status != DLADM_STATUS_OK) {
+ if (argc == 2) {
+ die_dlerr(status,
+ "could not bring up aggregation '%s'", argv[1]);
} else {
die_dlerr(status, "could not bring aggregations up");
}
@@ -630,174 +815,554 @@ do_up_aggr(int argc, char *argv[])
}
static void
-do_down_aggr(int argc, char *argv[])
+do_create_vlan(int argc, char *argv[])
{
+ char *link = NULL;
+ char drv[DLPI_LINKNAME_MAX];
+ uint_t ppa;
+ datalink_id_t linkid;
+ int vid = 0;
+ char option;
+ uint32_t flags = (DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST);
+ char *altroot = NULL;
+ char vlan[MAXLINKNAMELEN];
dladm_status_t status;
- int key = 0;
- /* get aggregation key (optional last argument) */
- if (argc == 2) {
- if (!str2int(argv[1], &key) || key < 1)
- die("invalid key value '%s'", argv[1]);
- } else if (argc > 2) {
+ opterr = 0;
+ while ((option = getopt_long(argc, argv, ":tfl:v:",
+ lopts, NULL)) != -1) {
+ switch (option) {
+ case 'v':
+ if (vid != 0)
+ die_optdup(option);
+
+ if (!str2int(optarg, &vid) || vid < 1 || vid > 4094)
+ die("invalid VLAN identifier '%s'", optarg);
+
+ break;
+ case 'l':
+ if (link != NULL)
+ die_optdup(option);
+
+ link = optarg;
+ break;
+ case 'f':
+ flags |= DLADM_OPT_FORCE;
+ break;
+ case 't':
+ flags &= ~DLADM_OPT_PERSIST;
+ break;
+ case 'R':
+ altroot = optarg;
+ break;
+ default:
+ die_opterr(optopt, option);
+ break;
+ }
+ }
+
+ /* get vlan name if there is any */
+ if ((vid == 0) || (link == NULL) || (argc - optind > 1))
usage();
+
+ if (optind == (argc - 1)) {
+ if (strlcpy(vlan, argv[optind], MAXLINKNAMELEN) >=
+ MAXLINKNAMELEN) {
+ die("vlan name too long '%s'", argv[optind]);
+ }
+ } else {
+ if ((dlpi_parselink(link, drv, &ppa) != DLPI_SUCCESS) ||
+ (ppa >= 1000) ||
+ (dlpi_makelink(vlan, drv, vid * 1000 + ppa) !=
+ DLPI_SUCCESS)) {
+ die("invalid link name '%s'", link);
+ }
}
- if ((status = dladm_aggr_down(key)) != DLADM_STATUS_OK) {
- if (key != 0) {
- die_dlerr(status,
- "could not bring down aggregation '%u'", key);
+ if (altroot != NULL)
+ altroot_cmd(altroot, argc, argv);
+
+ if (dladm_name2info(link, &linkid, NULL, NULL, NULL) !=
+ DLADM_STATUS_OK) {
+ die("invalid link name '%s'", link);
+ }
+
+ if ((status = dladm_vlan_create(vlan, linkid, vid, flags)) !=
+ DLADM_STATUS_OK) {
+ if (status == DLADM_STATUS_NOTSUP) {
+ die_dlerr(status, "VLAN over '%s' may require lowered "
+ "MTU; must use -f (see dladm(1M))\n", link);
} else {
- die_dlerr(status, "could not bring down aggregations");
+ die_dlerr(status, "create operation failed");
}
}
}
-#define TYPE_WIDTH 10
+static void
+do_delete_vlan(int argc, char *argv[])
+{
+ char option;
+ uint32_t flags = (DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST);
+ char *altroot = NULL;
+ datalink_id_t linkid;
+ dladm_status_t status;
+
+ opterr = 0;
+ while ((option = getopt_long(argc, argv, ":R:t", lopts, NULL)) != -1) {
+ switch (option) {
+ case 't':
+ flags &= ~DLADM_OPT_PERSIST;
+ break;
+ case 'R':
+ altroot = optarg;
+ break;
+ default:
+ die_opterr(optopt, option);
+ break;
+ }
+ }
+
+ /* get VLAN link name (required last argument) */
+ if (optind != (argc - 1))
+ usage();
+
+ if (altroot != NULL)
+ altroot_cmd(altroot, argc, argv);
+
+ status = dladm_name2info(argv[optind], &linkid, NULL, NULL, NULL);
+ if (status != DLADM_STATUS_OK)
+ goto done;
+
+ status = dladm_vlan_delete(linkid, flags);
+done:
+ if (status != DLADM_STATUS_OK)
+ die_dlerr(status, "delete operation failed");
+}
static void
-print_link_parseable(const char *name, dladm_attr_t *dap, boolean_t legacy)
+do_up_vlan(int argc, char *argv[])
{
- char type[TYPE_WIDTH];
+ datalink_id_t linkid = DATALINK_ALL_LINKID;
+ dladm_status_t status;
- if (!legacy) {
- char drv[DLPI_LINKNAME_MAX];
- uint_t instance;
+ /*
+ * get the name of the VLAN (optional last argument)
+ */
+ if (argc > 2)
+ usage();
+
+ if (argc == 2) {
+ status = dladm_name2info(argv[1], &linkid, NULL, NULL, NULL);
+ if (status != DLADM_STATUS_OK)
+ goto done;
+ }
- if (dap->da_vid != 0) {
- (void) snprintf(type, TYPE_WIDTH, "vlan %u",
- dap->da_vid);
+ status = dladm_vlan_up(linkid);
+done:
+ if (status != DLADM_STATUS_OK) {
+ if (argc == 2) {
+ die_dlerr(status,
+ "could not bring up VLAN '%s'", argv[1]);
} else {
- (void) snprintf(type, TYPE_WIDTH, "non-vlan");
+ die_dlerr(status, "could not bring VLANs up");
}
+ }
+}
- if (dlpi_parselink(dap->da_dev, drv, &instance) != DLPI_SUCCESS)
- return;
+static void
+do_rename_link(int argc, char *argv[])
+{
+ char option;
+ char *link1, *link2;
+ char *altroot = NULL;
+ dladm_status_t status;
- if (strncmp(drv, AGGR_DRV, sizeof (AGGR_DRV)) == 0) {
- (void) printf("%s type=%s mtu=%d key=%u\n",
- name, type, dap->da_max_sdu, instance);
- } else {
- (void) printf("%s type=%s mtu=%d device=%s\n",
- name, type, dap->da_max_sdu, dap->da_dev);
+ opterr = 0;
+ while ((option = getopt_long(argc, argv, ":R:", lopts, NULL)) != -1) {
+ switch (option) {
+ case 'R':
+ altroot = optarg;
+ break;
+ default:
+ die_opterr(optopt, option);
+ break;
}
- } else {
- (void) printf("%s type=legacy mtu=%d device=%s\n",
- name, dap->da_max_sdu, name);
}
+
+ /* get link1 and link2 name (required the last 2 arguments) */
+ if (optind != (argc - 2))
+ usage();
+
+ if (altroot != NULL)
+ altroot_cmd(altroot, argc, argv);
+
+ link1 = argv[optind++];
+ link2 = argv[optind];
+ if ((status = dladm_rename_link(link1, link2)) != DLADM_STATUS_OK)
+ die_dlerr(status, "rename operation failed");
}
static void
-print_link(const char *name, dladm_attr_t *dap, boolean_t legacy)
+do_delete_phys(int argc, char *argv[])
{
- char type[TYPE_WIDTH];
+ datalink_id_t linkid = DATALINK_ALL_LINKID;
+ dladm_status_t status;
- if (!legacy) {
- char drv[DLPI_LINKNAME_MAX];
- uint_t instance;
+ /* get link name (required the last argument) */
+ if (argc > 2)
+ usage();
- if (dap->da_vid != 0) {
- (void) snprintf(type, TYPE_WIDTH, gettext("vlan %u"),
- dap->da_vid);
- } else {
- (void) snprintf(type, TYPE_WIDTH, gettext("non-vlan"));
- }
+ if (argc == 2) {
+ status = dladm_name2info(argv[1], &linkid, NULL, NULL, NULL);
+ if (status != DLADM_STATUS_OK)
+ die_dlerr(status, "cannot delete '%s'", argv[1]);
+ }
- if (dlpi_parselink(dap->da_dev, drv, &instance) != DLPI_SUCCESS)
- return;
- if (strncmp(drv, AGGR_DRV, sizeof (AGGR_DRV)) == 0) {
- (void) printf(gettext("%-9s\ttype: %s\tmtu: %d"
- "\taggregation: key %u\n"), name, type,
- dap->da_max_sdu, instance);
- } else {
- (void) printf(gettext("%-9s\ttype: %s\tmtu: "
- "%d\tdevice: %s\n"), name, type, dap->da_max_sdu,
- dap->da_dev);
- }
- } else {
- (void) printf(gettext("%-9s\ttype: legacy\tmtu: "
- "%d\tdevice: %s\n"), name, dap->da_max_sdu, name);
+ if ((status = dladm_phys_delete(linkid)) != DLADM_STATUS_OK) {
+ if (argc == 2)
+ die_dlerr(status, "cannot delete '%s'", argv[1]);
+ else
+ die_dlerr(status, "delete operation failed");
}
}
+/*ARGSUSED*/
static int
-get_if_info(const char *name, dladm_attr_t *dlattrp, boolean_t *legacy)
+i_dladm_walk_linkmap(datalink_id_t linkid, void *arg)
{
- int err;
+ char name[MAXLINKNAMELEN];
+ char mediabuf[DLADM_STRSIZE];
+ char classbuf[DLADM_STRSIZE];
+ datalink_class_t class;
+ uint32_t media;
+ uint32_t flags;
+
+ if (dladm_datalink_id2info(linkid, &flags, &class, &media, name,
+ MAXLINKNAMELEN) == DLADM_STATUS_OK) {
+ (void) dladm_class2str(class, classbuf);
+ (void) dladm_media2str(media, mediabuf);
+ (void) printf("%-12s%8d %-12s%-20s %6d\n", name,
+ linkid, classbuf, mediabuf, flags);
+ }
+ return (DLADM_WALK_CONTINUE);
+}
- if ((err = dladm_info(name, dlattrp)) == 0) {
- *legacy = B_FALSE;
- } else if (err < 0 && errno == ENODEV) {
- dlpi_handle_t dh;
- dlpi_info_t dlinfo;
+/*ARGSUSED*/
+static void
+do_show_linkmap(int argc, char *argv[])
+{
+ if (argc != 1)
+ die("invalid arguments");
+
+ (void) printf("%-12s%8s %-12s%-20s %6s\n", "NAME", "LINKID",
+ "CLASS", "MEDIA", "FLAGS");
+ (void) dladm_walk_datalink_id(i_dladm_walk_linkmap, NULL,
+ DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE,
+ DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST);
+}
- /*
- * A return value of ENODEV means that the specified
- * device is not gldv3.
- */
- if (dlpi_open(name, &dh, 0) != DLPI_SUCCESS) {
- errno = ENOENT;
- return (-1);
+/*
+ * Delete inactive physical links.
+ */
+/*ARGSUSED*/
+static int
+purge_phys(datalink_id_t linkid, void *arg)
+{
+ datalink_class_t class;
+ uint32_t flags;
+
+ if (dladm_datalink_id2info(linkid, &flags, &class, NULL,
+ NULL, 0) != DLADM_STATUS_OK) {
+ return (DLADM_WALK_CONTINUE);
+ }
+
+ if (class == DATALINK_CLASS_PHYS && !(flags & DLADM_OPT_ACTIVE))
+ (void) dladm_phys_delete(linkid);
+
+ return (DLADM_WALK_CONTINUE);
+}
+
+/*ARGSUSED*/
+static void
+do_init_phys(int argc, char *argv[])
+{
+ di_node_t devtree;
+
+ if (argc > 1)
+ usage();
+
+ /*
+ * Force all the devices to attach, therefore all the network physical
+ * devices can be known to the dlmgmtd daemon.
+ */
+ if ((devtree = di_init("/", DINFOFORCE | DINFOSUBTREE)) != DI_NODE_NIL)
+ di_fini(devtree);
+
+ (void) dladm_walk_datalink_id(purge_phys, NULL,
+ DATALINK_CLASS_PHYS, DATALINK_ANY_MEDIATYPE, DLADM_OPT_PERSIST);
+}
+
+static void
+print_link_head(show_state_t *state)
+{
+ if (state->ls_donefirst)
+ return;
+ state->ls_donefirst = B_TRUE;
+
+ if (state->ls_parseable)
+ return;
+
+ if (state->ls_flags & DLADM_OPT_ACTIVE) {
+ (void) printf("%-12s%-8s%6s %-9s%s\n", "LINK", "CLASS", "MTU",
+ "STATE", "OVER");
+ } else {
+ (void) printf("%-12s%-8s%s\n", "LINK", "CLASS", "OVER");
+ }
+}
+
+/*
+ * Print the active topology information.
+ */
+static dladm_status_t
+print_link_topology(show_state_t *state, datalink_id_t linkid,
+ datalink_class_t class, char **pptr, char *lim)
+{
+ char *fmt;
+ char over[MAXLINKNAMELEN];
+ uint32_t flags = state->ls_flags;
+ dladm_status_t status = DLADM_STATUS_OK;
+
+ if (state->ls_parseable)
+ fmt = "OVER=\"%s";
+ else
+ fmt = "%s";
+
+ if (class == DATALINK_CLASS_VLAN) {
+ dladm_vlan_attr_t vinfo;
+
+ status = dladm_vlan_info(linkid, &vinfo, flags);
+ if (status != DLADM_STATUS_OK)
+ goto done;
+ status = dladm_datalink_id2info(vinfo.dv_linkid, NULL, NULL,
+ NULL, over, sizeof (over));
+ if (status != DLADM_STATUS_OK)
+ goto done;
+
+ /*LINTED: E_SEC_PRINTF_VAR_FMT*/
+ *pptr += snprintf(*pptr, BUFLEN(lim, *pptr), fmt, over);
+ } else if (class == DATALINK_CLASS_AGGR) {
+ dladm_aggr_grp_attr_t ginfo;
+ int i;
+
+ status = dladm_aggr_info(linkid, &ginfo, flags);
+ if (status != DLADM_STATUS_OK)
+ goto done;
+
+ if (ginfo.lg_nports == 0) {
+ status = DLADM_STATUS_BADVAL;
+ goto done;
}
- if (dlpi_info(dh, &dlinfo, 0) != DLPI_SUCCESS) {
- dlpi_close(dh);
- errno = EINVAL;
- return (-1);
+ for (i = 0; i < ginfo.lg_nports; i++) {
+ status = dladm_datalink_id2info(
+ ginfo.lg_ports[i].lp_linkid, NULL, NULL, NULL, over,
+ sizeof (over));
+ if (status != DLADM_STATUS_OK) {
+ free(ginfo.lg_ports);
+ goto done;
+ }
+ /*LINTED: E_SEC_PRINTF_VAR_FMT*/
+ *pptr += snprintf(*pptr, BUFLEN(lim, *pptr), fmt, over);
+ fmt = " %s";
+ }
+ free(ginfo.lg_ports);
+ } else if (class == DATALINK_CLASS_VNIC) {
+ dladm_vnic_attr_sys_t vinfo;
+
+ if ((status = dladm_vnic_info(linkid, &vinfo, flags)) !=
+ DLADM_STATUS_OK || (status = dladm_datalink_id2info(
+ vinfo.va_link_id, NULL, NULL, NULL, over,
+ sizeof (over))) != DLADM_STATUS_OK) {
+ goto done;
}
- dlpi_close(dh);
- *legacy = B_TRUE;
- bzero(dlattrp, sizeof (*dlattrp));
- dlattrp->da_max_sdu = dlinfo.di_max_sdu;
+ /*LINTED: E_SEC_PRINTF_VAR_FMT*/
+ *pptr += snprintf(*pptr, BUFLEN(lim, *pptr), fmt, over);
} else {
- /*
- * If the return value is not ENODEV, this means that
- * user is either passing in a bogus interface name
- * or a vlan interface name that doesn't exist yet.
- */
- errno = ENOENT;
- return (-1);
+ /*LINTED: E_SEC_PRINTF_VAR_FMT*/
+ *pptr += snprintf(*pptr, BUFLEN(lim, *pptr), fmt,
+ state->ls_parseable ? "" : "--");
}
- return (0);
+ if (state->ls_parseable)
+ *pptr += snprintf(*pptr, BUFLEN(lim, *pptr), "\"\n");
+ else
+ *pptr += snprintf(*pptr, BUFLEN(lim, *pptr), "\n");
+
+done:
+ return (status);
}
-/* ARGSUSED */
-static void
-show_link(void *arg, const char *name)
+static dladm_status_t
+print_link(show_state_t *state, datalink_id_t linkid, char **pptr, char *lim)
{
- dladm_attr_t dlattr;
- boolean_t legacy = B_TRUE;
- show_link_state_t *state = (show_link_state_t *)arg;
+ char link[MAXLINKNAMELEN];
+ char buf[DLADM_STRSIZE];
+ datalink_class_t class;
+ uint_t mtu;
+ char *fmt;
+ uint32_t flags;
+ dladm_status_t status;
+
+ if ((status = dladm_datalink_id2info(linkid, &flags, &class, NULL,
+ link, sizeof (link))) != DLADM_STATUS_OK) {
+ goto done;
+ }
+
+ if (!(state->ls_flags & flags)) {
+ status = DLADM_STATUS_NOTFOUND;
+ goto done;
+ }
+
+ if (state->ls_flags == DLADM_OPT_ACTIVE) {
+ dladm_attr_t dlattr;
+
+ if (class == DATALINK_CLASS_PHYS) {
+ dladm_phys_attr_t dpa;
+ dlpi_handle_t dh;
+ dlpi_info_t dlinfo;
+
+ if ((status = dladm_phys_info(linkid, &dpa,
+ DLADM_OPT_ACTIVE)) != DLADM_STATUS_OK) {
+ goto done;
+ }
+
+ if (!dpa.dp_novanity)
+ goto link_mtu;
+
+ /*
+ * This is a physical link that does not have
+ * vanity naming support.
+ */
+ if (dlpi_open(dpa.dp_dev, &dh, DLPI_DEVONLY) !=
+ DLPI_SUCCESS) {
+ status = DLADM_STATUS_NOTFOUND;
+ goto done;
+ }
+
+ if (dlpi_info(dh, &dlinfo, 0) != DLPI_SUCCESS) {
+ dlpi_close(dh);
+ status = DLADM_STATUS_BADARG;
+ goto done;
+ }
+
+ dlpi_close(dh);
+ mtu = dlinfo.di_max_sdu;
+ } else {
+link_mtu:
+ status = dladm_info(linkid, &dlattr);
+ if (status != DLADM_STATUS_OK)
+ goto done;
+ mtu = dlattr.da_max_sdu;
+ }
+ }
- if (get_if_info(name, &dlattr, &legacy) < 0)
- die("invalid link '%s'", name);
+ if (state->ls_flags == DLADM_OPT_ACTIVE) {
+ if (state->ls_parseable)
+ fmt = "LINK=\"%s\" CLASS=\"%s\" MTU=\"%d\" ";
+ else
+ fmt = "%-12s%-8s%6d ";
+ } else {
+ if (state->ls_parseable)
+ fmt = "LINK=\"%s\" CLASS=\"%s\" ";
+ else
+ fmt = "%-12s%-8s";
+ }
- if (state->ls_parseable) {
- print_link_parseable(name, &dlattr, legacy);
+ (void) dladm_class2str(class, buf);
+ if (state->ls_flags == DLADM_OPT_ACTIVE) {
+ /*LINTED: E_SEC_PRINTF_VAR_FMT*/
+ *pptr += snprintf(*pptr, BUFLEN(lim, *pptr), fmt, link,
+ buf, mtu);
} else {
- print_link(name, &dlattr, legacy);
+ /*LINTED: E_SEC_PRINTF_VAR_FMT*/
+ *pptr += snprintf(*pptr, BUFLEN(lim, *pptr), fmt, link, buf);
}
+
+ (void) get_linkstate(link, B_TRUE, buf);
+ if (state->ls_flags == DLADM_OPT_ACTIVE) {
+ if (state->ls_parseable) {
+ *pptr += snprintf(*pptr, BUFLEN(lim, *pptr),
+ "STATE=\"%s\" ", buf);
+ } else {
+ *pptr += snprintf(*pptr, BUFLEN(lim, *pptr),
+ "%-9s", buf);
+ }
+ }
+
+ status = print_link_topology(state, linkid, class, pptr, lim);
+ if (status != DLADM_STATUS_OK)
+ goto done;
+
+done:
+ return (status);
}
-static void
-show_link_stats(void *arg, const char *name)
+static int
+show_link(datalink_id_t linkid, void *arg)
+{
+ show_state_t *state = arg;
+ dladm_status_t status;
+ char buf[MAXLINELEN];
+ char *ptr = buf, *lim = buf + MAXLINELEN;
+
+ status = print_link(state, linkid, &ptr, lim);
+ if (status != DLADM_STATUS_OK)
+ goto done;
+ print_link_head(state);
+ (void) printf("%s", buf);
+
+done:
+ state->ls_status = status;
+ return (DLADM_WALK_CONTINUE);
+}
+
+static int
+show_link_stats(datalink_id_t linkid, void *arg)
{
- show_link_state_t *state = (show_link_state_t *)arg;
+ char link[MAXLINKNAMELEN];
+ datalink_class_t class;
+ show_state_t *state = arg;
pktsum_t stats, diff_stats;
+ dladm_phys_attr_t dpa;
if (state->ls_firstonly) {
if (state->ls_donefirst)
- return;
+ return (DLADM_WALK_CONTINUE);
state->ls_donefirst = B_TRUE;
} else {
bzero(&state->ls_prevstats, sizeof (state->ls_prevstats));
}
- get_link_stats(name, &stats);
+ if (dladm_datalink_id2info(linkid, NULL, &class, NULL, link,
+ sizeof (link)) != DLADM_STATUS_OK) {
+ return (DLADM_WALK_CONTINUE);
+ }
+
+ if (class == DATALINK_CLASS_PHYS) {
+ if (dladm_phys_info(linkid, &dpa, DLADM_OPT_ACTIVE) !=
+ DLADM_STATUS_OK) {
+ return (DLADM_WALK_CONTINUE);
+ }
+ if (dpa.dp_novanity)
+ get_mac_stats(dpa.dp_dev, &stats);
+ else
+ get_link_stats(link, &stats);
+ } else {
+ get_link_stats(link, &stats);
+ }
stats_diff(&diff_stats, &stats, &state->ls_prevstats);
- (void) printf("%s", name);
- (void) printf("\t\t%-10llu", diff_stats.ipackets);
+ (void) printf("%-12s", link);
+ (void) printf("%-10llu", diff_stats.ipackets);
(void) printf("%-12llu", diff_stats.rbytes);
(void) printf("%-8u", diff_stats.ierrors);
(void) printf("%-10llu", diff_stats.opackets);
@@ -805,218 +1370,358 @@ show_link_stats(void *arg, const char *name)
(void) printf("%-8u\n", diff_stats.oerrors);
state->ls_prevstats = stats;
+ return (DLADM_WALK_CONTINUE);
}
static void
-dump_grp(dladm_aggr_grp_attr_t *grp, boolean_t parseable)
+print_port_stat(const char *port, pktsum_t *old_stats, pktsum_t *port_stats,
+ pktsum_t *tot_stats, char **pptr, char *lim)
{
- char buf[DLADM_STRSIZE];
- char addr_str[ETHERADDRL * 3];
+ pktsum_t diff_stats;
- if (!parseable) {
- (void) printf(gettext("key: %d (0x%04x)"),
- grp->lg_key, grp->lg_key);
+ stats_diff(&diff_stats, port_stats, old_stats);
+ *pptr += snprintf(*pptr, BUFLEN(lim, *pptr),
+ "%-12s%-10s%8llu %8llu %8llu %8llu ", "", port,
+ diff_stats.ipackets, diff_stats.rbytes, diff_stats.opackets,
+ diff_stats.obytes);
- (void) printf(gettext("\tpolicy: %s"),
- dladm_aggr_policy2str(grp->lg_policy, buf));
+ if (tot_stats->ipackets == 0) {
+ *pptr += snprintf(*pptr, BUFLEN(lim, *pptr), "%8s ", "--");
+ } else {
+ *pptr += snprintf(*pptr, BUFLEN(lim, *pptr), "%7.1f%% ",
+ (double)diff_stats.ipackets/
+ (double)tot_stats->ipackets * 100);
+ }
- (void) printf(gettext("\taddress: %s (%s)\n"),
- dladm_aggr_macaddr2str(grp->lg_mac, addr_str),
- (grp->lg_mac_fixed) ? gettext("fixed") : gettext("auto"));
+ if (tot_stats->opackets == 0) {
+ *pptr += snprintf(*pptr, BUFLEN(lim, *pptr), "%8s\n", "--");
} else {
- (void) printf("aggr key=%d", grp->lg_key);
+ *pptr += snprintf(*pptr, BUFLEN(lim, *pptr), "%7.1f%%\n",
+ (double)diff_stats.opackets/
+ (double)tot_stats->opackets * 100);
+ }
- (void) printf(" policy=%s",
- dladm_aggr_policy2str(grp->lg_policy, buf));
+ *old_stats = *port_stats;
+}
- (void) printf(" address=%s",
- dladm_aggr_macaddr2str(grp->lg_mac, addr_str));
+static void
+print_aggr_head(show_grp_state_t *state)
+{
+ if (state->gs_donefirst)
+ return;
+ state->gs_donefirst = B_TRUE;
- (void) printf(" address-type=%s\n",
- (grp->lg_mac_fixed) ? "fixed" : "auto");
+ if (state->gs_parseable)
+ return;
+
+ if (state->gs_lacp) {
+ (void) printf("%-12s%-12s%-13s%-5s%-5s%-5s%-10s%s\n", "LINK",
+ "PORT", "AGGREGATABLE", "SYNC", "COLL", "DIST",
+ "DEFAULTED", "EXPIRED");
+ } else if (state->gs_extended) {
+ (void) printf("%-12s%-14s%6s %-9s%-9s%-18s%s\n", "LINK",
+ "PORT", "SPEED", "DUPLEX", "STATE", "ADDRESS", "PORTSTATE");
+ } else if (!state->gs_stats) {
+ (void) printf("%-12s%-8s%-24s%-13s%-11s%s\n", "LINK", "POLICY",
+ "ADDRPOLICY", "LACPACTIVITY", "LACPTIMER", "FLAGS");
}
}
-static void
-dump_grp_lacp(dladm_aggr_grp_attr_t *grp, boolean_t parseable)
+static dladm_status_t
+print_aggr_info(show_grp_state_t *state, const char *link,
+ dladm_aggr_grp_attr_t *ginfop, char **pptr, char *lim)
{
- char lacp_mode_str[DLADM_STRSIZE];
- char lacp_timer_str[DLADM_STRSIZE];
+ char buf[DLADM_STRSIZE];
+ char *fmt;
+ char addr_str[ETHERADDRL * 3];
+ char str[ETHERADDRL * 3 + 2];
- (void) dladm_aggr_lacpmode2str(grp->lg_lacp_mode, lacp_mode_str);
- (void) dladm_aggr_lacptimer2str(grp->lg_lacp_timer, lacp_timer_str);
+ if (state->gs_parseable)
+ fmt = "LINK=\"%s\" POLICY=\"%s\" ADDRPOLICY=\"%s%s\" ";
+ else
+ fmt = "%-12s%-8s%-6s%-18s";
- if (!parseable) {
- (void) printf(gettext("\t\tLACP mode: %s"), lacp_mode_str);
- (void) printf(gettext("\tLACP timer: %s\n"), lacp_timer_str);
+ if (ginfop->lg_mac_fixed) {
+ (void) dladm_aggr_macaddr2str(ginfop->lg_mac, addr_str);
+ (void) snprintf(str, ETHERADDRL * 3 + 3, " (%s)", addr_str);
} else {
- (void) printf(" lacp-mode=%s", lacp_mode_str);
- (void) printf(" lacp-timer=%s\n", lacp_timer_str);
+ str[0] = '\0';
}
-}
-static void
-dump_grp_stats(dladm_aggr_grp_attr_t *grp)
-{
- (void) printf("key: %d", grp->lg_key);
- (void) printf("\tipackets rbytes opackets obytes ");
- (void) printf("%%ipkts %%opkts\n");
-}
+ /*LINTED: E_SEC_PRINTF_VAR_FMT*/
+ *pptr += snprintf(*pptr, BUFLEN(lim, *pptr), fmt, link,
+ dladm_aggr_policy2str(ginfop->lg_policy, buf),
+ ginfop->lg_mac_fixed ? "fixed" : "auto", str);
-static void
-dump_ports_lacp_head(void)
-{
- (void) printf(DUMP_LACP_FORMAT, gettext("device"), gettext("activity"),
- gettext("timeout"), gettext("aggregatable"), gettext("sync"),
- gettext("coll"), gettext("dist"), gettext("defaulted"),
- gettext("expired"));
-}
+ (void) dladm_aggr_lacpmode2str(ginfop->lg_lacp_mode, buf);
+ if (state->gs_parseable) {
+ *pptr += snprintf(*pptr, BUFLEN(lim, *pptr),
+ "LACPACTIVITY=\"%s\" ", buf);
+ } else {
+ *pptr += snprintf(*pptr, BUFLEN(lim, *pptr), "%-13s", buf);
+ }
-static void
-dump_ports_head(void)
-{
- (void) printf(gettext(" device\taddress\t\t speed\t\tduplex\tlink\t"
- "state\n"));
+ (void) dladm_aggr_lacptimer2str(ginfop->lg_lacp_timer, buf);
+ if (state->gs_parseable) {
+ *pptr += snprintf(*pptr, BUFLEN(lim, *pptr),
+ "LACPTIMER=\"%s\" FLAGS=\"%c----\"\n", buf,
+ ginfop->lg_force ? 'f' : '-');
+ } else {
+ *pptr += snprintf(*pptr, BUFLEN(lim, *pptr),
+ "%-11s%c----\n", buf, ginfop->lg_force ? 'f' : '-');
+ }
+
+ return (DLADM_STATUS_OK);
}
-static void
-dump_port(dladm_aggr_port_attr_t *port, boolean_t parseable)
+static dladm_status_t
+print_aggr_extended(show_grp_state_t *state, const char *link,
+ dladm_aggr_grp_attr_t *ginfop, char **pptr, char *lim)
{
- char *dev = port->lp_devname;
- char mac_addr[ETHERADDRL * 3];
- char buf[DLADM_STRSIZE];
+ char addr_str[ETHERADDRL * 3];
+ char port[MAXLINKNAMELEN];
+ dladm_phys_attr_t dpa;
+ char buf[DLADM_STRSIZE];
+ char *fmt;
+ int i;
+ dladm_status_t status;
- if (!parseable) {
- (void) printf(" %-9s\t%s", dev, dladm_aggr_macaddr2str(
- port->lp_mac, mac_addr));
- (void) printf("\t %5uMb", (int)(mac_ifspeed(dev) /
- 1000000ull));
- (void) printf("\t%s", mac_link_duplex(dev, buf));
- (void) printf("\t%s", mac_link_state(dev, buf));
- (void) printf("\t%s\n",
- dladm_aggr_portstate2str(port->lp_state, buf));
+ if (state->gs_parseable)
+ fmt = "LINK=\"%s\" PORT=\"%s\" SPEED=\"%uMb\" DUPLEX=\"%s\" ";
+ else
+ fmt = "%-12s%-14s%4uMb %-9s";
+ (void) dladm_aggr_macaddr2str(ginfop->lg_mac, addr_str);
+
+ /*LINTED: E_SEC_PRINTF_VAR_FMT*/
+ *pptr += snprintf(*pptr, BUFLEN(lim, *pptr), fmt, link,
+ state->gs_parseable ? "" : "--",
+ (uint_t)((get_ifspeed(link, B_TRUE)) / 1000000ull),
+ get_linkduplex(link, B_TRUE, buf));
+
+ (void) get_linkstate(link, B_TRUE, buf);
+ if (state->gs_parseable) {
+ *pptr += snprintf(*pptr, BUFLEN(lim, *pptr),
+ "STATE=\"%s\" ADDRESS=\"%s\" PORTSTATE=\"%s\"\n", buf,
+ addr_str, "");
} else {
- (void) printf(" device=%s address=%s", dev,
- dladm_aggr_macaddr2str(port->lp_mac, mac_addr));
- (void) printf(" speed=%u", (int)(mac_ifspeed(dev) /
- 1000000ull));
- (void) printf(" duplex=%s", mac_link_duplex(dev, buf));
- (void) printf(" link=%s", mac_link_state(dev, buf));
- (void) printf(" port=%s",
- dladm_aggr_portstate2str(port->lp_state, buf));
+ *pptr += snprintf(*pptr, BUFLEN(lim, *pptr), "%-9s%-18s%s\n",
+ buf, addr_str, "--");
}
-}
-static void
-dump_port_lacp(dladm_aggr_port_attr_t *port)
-{
- aggr_lacp_state_t *state = &port->lp_lacp_state;
+ for (i = 0; i < ginfop->lg_nports; i++) {
+ dladm_aggr_port_attr_t *portp = &(ginfop->lg_ports[i]);
+ const char *tmp;
+
+ if ((status = dladm_datalink_id2info(portp->lp_linkid, NULL,
+ NULL, NULL, port, sizeof (port))) != DLADM_STATUS_OK) {
+ goto done;
+ }
+
+ if ((status = dladm_phys_info(portp->lp_linkid, &dpa,
+ DLADM_OPT_ACTIVE)) != DLADM_STATUS_OK) {
+ goto done;
+ }
+
+ (void) dladm_aggr_macaddr2str(portp->lp_mac, addr_str);
+
+ if (state->gs_parseable)
+ tmp = link;
+ else
+ tmp = "";
+
+ /*LINTED: E_SEC_PRINTF_VAR_FMT*/
+ *pptr += snprintf(*pptr, BUFLEN(lim, *pptr), fmt, tmp, port,
+ (uint_t)((get_ifspeed(dpa.dp_dev, B_FALSE)) / 1000000ull),
+ get_linkduplex(dpa.dp_dev, B_FALSE, buf));
+
+ (void) get_linkstate(dpa.dp_dev, B_FALSE, buf);
+ if (state->gs_parseable) {
+ *pptr += snprintf(*pptr, BUFLEN(lim, *pptr),
+ "STATE=\"%s\" ADDRESS=\"%s\" ", buf, addr_str);
+ } else {
+ *pptr += snprintf(*pptr, BUFLEN(lim, *pptr),
+ "%-9s%-18s", buf, addr_str);
+ }
+
+ (void) dladm_aggr_portstate2str(
+ ginfop->lg_ports[i].lp_state, buf);
+ if (state->gs_parseable) {
+ *pptr += snprintf(*pptr, BUFLEN(lim, *pptr),
+ "PORTSTATE=\"%s\"\n", buf);
+ } else {
+ *pptr += snprintf(*pptr, BUFLEN(lim, *pptr),
+ "%s\n", buf);
+ }
+ }
- (void) printf(DUMP_LACP_FORMAT,
- port->lp_devname, state->bit.activity ? "active" : "passive",
- state->bit.timeout ? "short" : "long",
- state->bit.aggregation ? "yes" : "no",
- state->bit.sync ? "yes" : "no",
- state->bit.collecting ? "yes" : "no",
- state->bit.distributing ? "yes" : "no",
- state->bit.defaulted ? "yes" : "no",
- state->bit.expired ? "yes" : "no");
+ status = DLADM_STATUS_OK;
+done:
+ return (status);
}
-static void
-dump_port_stat(int index, show_grp_state_t *state, pktsum_t *port_stats,
- pktsum_t *tot_stats)
+static dladm_status_t
+print_aggr_lacp(show_grp_state_t *state, const char *link,
+ dladm_aggr_grp_attr_t *ginfop, char **pptr, char *lim)
{
- pktsum_t diff_stats;
- pktsum_t *old_stats = &state->gs_prevstats[index];
-
- stats_diff(&diff_stats, port_stats, old_stats);
+ char port[MAXLINKNAMELEN];
+ char *fmt;
+ const char *dlink = link;
+ int i;
+ dladm_status_t status;
- (void) printf("\t%-10llu", diff_stats.ipackets);
- (void) printf("%-12llu", diff_stats.rbytes);
- (void) printf("%-10llu", diff_stats.opackets);
- (void) printf("%-12llu", diff_stats.obytes);
+ if (state->gs_parseable) {
+ fmt = "LINK=\"%s\" PORT=\"%s\" AGGREGATABLE=\"%s\" SYNC=\"%s\" "
+ "COLL=\"%s\" DIST=\"%s\" DEFAULTED=\"%s\" EXPITED=\"%s\"\n";
+ } else {
+ fmt = "%-12s%-12s%-13s%-5s%-5s%-5s%-10s%s\n";
+ }
- if (tot_stats->ipackets == 0)
- (void) printf("\t-");
- else
- (void) printf("\t%-6.1f", (double)diff_stats.ipackets/
- (double)tot_stats->ipackets * 100);
+ for (i = 0; i < ginfop->lg_nports; i++) {
+ aggr_lacp_state_t *lstate;
- if (tot_stats->opackets == 0)
- (void) printf("\t-");
- else
- (void) printf("\t%-6.1f", (double)diff_stats.opackets/
- (double)tot_stats->opackets * 100);
+ status = dladm_datalink_id2info(ginfop->lg_ports[i].lp_linkid,
+ NULL, NULL, NULL, port, sizeof (port));
+ if (status != DLADM_STATUS_OK)
+ goto done;
- (void) printf("\n");
+ /*
+ * Only display link for the first port.
+ */
+ if ((i > 0) && !(state->gs_parseable))
+ dlink = "";
+ lstate = &(ginfop->lg_ports[i].lp_lacp_state);
+
+ /*LINTED: E_SEC_PRINTF_VAR_FMT*/
+ *pptr += snprintf(*pptr, BUFLEN(lim, *pptr), fmt, dlink, port,
+ lstate->bit.aggregation ? "yes" : "no",
+ lstate->bit.sync ? "yes" : "no",
+ lstate->bit.collecting ? "yes" : "no",
+ lstate->bit.distributing ? "yes" : "no",
+ lstate->bit.defaulted ? "yes" : "no",
+ lstate->bit.expired ? "yes" : "no");
+ }
- *old_stats = *port_stats;
+ status = DLADM_STATUS_OK;
+done:
+ return (status);
}
-static int
-show_key(void *arg, dladm_aggr_grp_attr_t *grp)
+static dladm_status_t
+print_aggr_stats(show_grp_state_t *state, const char *link,
+ dladm_aggr_grp_attr_t *ginfop, char **pptr, char *lim)
{
- show_grp_state_t *state = (show_grp_state_t *)arg;
- int i;
+ char port[MAXLINKNAMELEN];
+ dladm_phys_attr_t dpa;
+ dladm_aggr_port_attr_t *portp;
pktsum_t pktsumtot, port_stat;
+ dladm_status_t status;
+ int i;
- if (state->gs_key != 0 && state->gs_key != grp->lg_key)
- return (0);
if (state->gs_firstonly) {
- if (state->gs_found)
- return (0);
+ if (state->gs_donefirst)
+ return (DLADM_WALK_CONTINUE);
+ state->gs_donefirst = B_TRUE;
} else {
bzero(&state->gs_prevstats, sizeof (state->gs_prevstats));
}
- state->gs_found = B_TRUE;
+ /* sum the ports statistics */
+ bzero(&pktsumtot, sizeof (pktsumtot));
- if (state->gs_stats) {
- /* show statistics */
- dump_grp_stats(grp);
+ for (i = 0; i < ginfop->lg_nports; i++) {
- /* sum the ports statistics */
- bzero(&pktsumtot, sizeof (pktsumtot));
- for (i = 0; i < grp->lg_nports; i++) {
- get_mac_stats(grp->lg_ports[i].lp_devname, &port_stat);
- stats_total(&pktsumtot, &port_stat,
- &state->gs_prevstats[i]);
+ portp = &(ginfop->lg_ports[i]);
+ if ((status = dladm_phys_info(portp->lp_linkid, &dpa,
+ DLADM_OPT_ACTIVE)) != DLADM_STATUS_OK) {
+ goto done;
}
- (void) printf(" Total");
- (void) printf("\t%-10llu", pktsumtot.ipackets);
- (void) printf("%-12llu", pktsumtot.rbytes);
- (void) printf("%-10llu", pktsumtot.opackets);
- (void) printf("%-12llu\n", pktsumtot.obytes);
+ get_mac_stats(dpa.dp_dev, &port_stat);
+ stats_total(&pktsumtot, &port_stat, &state->gs_prevstats[i]);
+ }
+
+ *pptr += snprintf(*pptr, BUFLEN(lim, *pptr),
+ "%-12s%-10s%8llu %8llu %8llu %8llu %8s %8s\n", link, "--",
+ pktsumtot.ipackets, pktsumtot.rbytes, pktsumtot.opackets,
+ pktsumtot.obytes, "--", "--");
+
+ for (i = 0; i < ginfop->lg_nports; i++) {
+ portp = &(ginfop->lg_ports[i]);
- for (i = 0; i < grp->lg_nports; i++) {
- get_mac_stats(grp->lg_ports[i].lp_devname, &port_stat);
- (void) printf(" %s", grp->lg_ports[i].lp_devname);
- dump_port_stat(i, state, &port_stat, &pktsumtot);
+ if ((status = dladm_phys_info(portp->lp_linkid, &dpa,
+ DLADM_OPT_ACTIVE)) != DLADM_STATUS_OK) {
+ goto done;
}
- } else if (state->gs_lacp) {
- /* show LACP info */
- dump_grp(grp, state->gs_parseable);
- dump_grp_lacp(grp, state->gs_parseable);
- dump_ports_lacp_head();
- for (i = 0; i < grp->lg_nports; i++)
- dump_port_lacp(&grp->lg_ports[i]);
- } else {
- dump_grp(grp, state->gs_parseable);
- if (!state->gs_parseable)
- dump_ports_head();
- for (i = 0; i < grp->lg_nports; i++) {
- if (state->gs_parseable)
- (void) printf("dev key=%d", grp->lg_key);
- dump_port(&grp->lg_ports[i], state->gs_parseable);
- if (state->gs_parseable)
- (void) printf("\n");
+
+ get_mac_stats(dpa.dp_dev, &port_stat);
+
+ if ((status = dladm_datalink_id2info(portp->lp_linkid, NULL,
+ NULL, NULL, port, sizeof (port))) != DLADM_STATUS_OK) {
+ goto done;
}
+
+ print_port_stat(port, &state->gs_prevstats[i], &port_stat,
+ &pktsumtot, pptr, lim);
}
- return (0);
+ status = DLADM_STATUS_OK;
+done:
+ return (status);
+}
+
+static dladm_status_t
+print_aggr(show_grp_state_t *state, datalink_id_t linkid, char **pptr,
+ char *lim)
+{
+ char link[MAXLINKNAMELEN];
+ dladm_aggr_grp_attr_t ginfo;
+ uint32_t flags;
+ dladm_status_t status;
+
+ if ((status = dladm_datalink_id2info(linkid, &flags, NULL, NULL, link,
+ sizeof (link))) != DLADM_STATUS_OK) {
+ return (status);
+ }
+
+ if (!(state->gs_flags & flags))
+ return (DLADM_STATUS_NOTFOUND);
+
+ status = dladm_aggr_info(linkid, &ginfo, state->gs_flags);
+ if (status != DLADM_STATUS_OK)
+ return (status);
+
+ if (state->gs_lacp)
+ status = print_aggr_lacp(state, link, &ginfo, pptr, lim);
+ else if (state->gs_extended)
+ status = print_aggr_extended(state, link, &ginfo, pptr, lim);
+ else if (state->gs_stats)
+ status = print_aggr_stats(state, link, &ginfo, pptr, lim);
+ else
+ status = print_aggr_info(state, link, &ginfo, pptr, lim);
+
+done:
+ free(ginfo.lg_ports);
+ return (status);
+}
+
+static int
+show_aggr(datalink_id_t linkid, void *arg)
+{
+ show_grp_state_t *state = arg;
+ dladm_status_t status;
+ char buf[MAXLINELEN];
+ char *ptr = buf, *lim = buf + MAXLINELEN;
+
+ status = print_aggr(state, linkid, &ptr, lim);
+ if (status != DLADM_STATUS_OK)
+ goto done;
+ print_aggr_head(state);
+ (void) printf("%s", buf);
+
+done:
+ state->gs_status = status;
+ return (DLADM_WALK_CONTINUE);
}
static int
@@ -1044,77 +1749,90 @@ kstat_value(kstat_t *ksp, const char *name, uint8_t type, void *buf)
return (0);
}
-static void
-show_dev(void *arg, const char *dev)
+static int
+show_dev(const char *dev, void *arg)
{
- show_mac_state_t *state = (show_mac_state_t *)arg;
- char buf[DLADM_STRSIZE];
+ show_state_t *state = arg;
+ char buf[DLADM_STRSIZE];
+ char *fmt;
- (void) printf("%s", dev);
+ if (state->ls_parseable)
+ fmt = "DEV=\"%s\" STATE=\"%s\" SPEED=\"%u\" ";
+ else
+ fmt = "%-12s%-10s%4uMb ";
- if (!state->ms_parseable) {
- (void) printf(gettext("\t\tlink: %s"),
- mac_link_state(dev, buf));
- (void) printf(gettext("\tspeed: %5uMb"),
- (unsigned int)(mac_ifspeed(dev) / 1000000ull));
- (void) printf(gettext("\tduplex: %s\n"),
- mac_link_duplex(dev, buf));
- } else {
- (void) printf(" link=%s", mac_link_state(dev, buf));
- (void) printf(" speed=%u",
- (unsigned int)(mac_ifspeed(dev) / 1000000ull));
- (void) printf(" duplex=%s\n", mac_link_duplex(dev, buf));
+ if (!state->ls_donefirst) {
+ if (!state->ls_parseable) {
+ (void) printf("%-12s%-10s%6s %s\n", "DEV", "STATE",
+ "SPEED", "DUPLEX");
+ }
+ state->ls_donefirst = B_TRUE;
}
+
+ /*LINTED: E_SEC_PRINTF_VAR_FMT*/
+ (void) printf(fmt, dev, get_linkstate(dev, B_FALSE, buf),
+ (uint_t)(get_ifspeed(dev, B_FALSE) / 1000000ull));
+
+ (void) get_linkduplex(dev, B_FALSE, buf);
+ if (state->ls_parseable)
+ (void) printf("DUPLEX=\"%s\"\n", buf);
+ else
+ (void) printf("%s\n", buf);
+
+ return (DLADM_WALK_CONTINUE);
}
-/*ARGSUSED*/
-static void
-show_dev_stats(void *arg, const char *dev)
+static int
+show_dev_stats(const char *dev, void *arg)
{
- show_mac_state_t *state = (show_mac_state_t *)arg;
+ show_state_t *state = arg;
pktsum_t stats, diff_stats;
- if (state->ms_firstonly) {
- if (state->ms_donefirst)
- return;
- state->ms_donefirst = B_TRUE;
+ if (state->ls_firstonly) {
+ if (state->ls_donefirst)
+ return (DLADM_WALK_CONTINUE);
+ state->ls_donefirst = B_TRUE;
} else {
- bzero(&state->ms_prevstats, sizeof (state->ms_prevstats));
+ bzero(&state->ls_prevstats, sizeof (state->ls_prevstats));
}
get_mac_stats(dev, &stats);
- stats_diff(&diff_stats, &stats, &state->ms_prevstats);
+ stats_diff(&diff_stats, &stats, &state->ls_prevstats);
- (void) printf("%s", dev);
- (void) printf("\t\t%-10llu", diff_stats.ipackets);
+ (void) printf("%-12s", dev);
+ (void) printf("%-10llu", diff_stats.ipackets);
(void) printf("%-12llu", diff_stats.rbytes);
(void) printf("%-8u", diff_stats.ierrors);
(void) printf("%-10llu", diff_stats.opackets);
(void) printf("%-12llu", diff_stats.obytes);
(void) printf("%-8u\n", diff_stats.oerrors);
- state->ms_prevstats = stats;
+ state->ls_prevstats = stats;
+ return (DLADM_WALK_CONTINUE);
}
static void
do_show_link(int argc, char *argv[])
{
- char *name = NULL;
int option;
boolean_t s_arg = B_FALSE;
boolean_t i_arg = B_FALSE;
+ uint32_t flags = DLADM_OPT_ACTIVE;
+ boolean_t p_arg = B_FALSE;
+ datalink_id_t linkid = DATALINK_ALL_LINKID;
int interval = 0;
- show_link_state_t state;
-
- state.ls_stats = B_FALSE;
- state.ls_parseable = B_FALSE;
+ show_state_t state;
+ dladm_status_t status;
opterr = 0;
- while ((option = getopt_long(argc, argv, ":psi:",
- longopts, NULL)) != -1) {
+ while ((option = getopt_long(argc, argv, ":pPsi:",
+ show_lopts, NULL)) != -1) {
switch (option) {
case 'p':
- state.ls_parseable = B_TRUE;
+ if (p_arg)
+ die_optdup(option);
+
+ p_arg = B_TRUE;
break;
case 's':
if (s_arg)
@@ -1122,6 +1840,12 @@ do_show_link(int argc, char *argv[])
s_arg = B_TRUE;
break;
+ case 'P':
+ if (flags != DLADM_OPT_ACTIVE)
+ die_optdup(option);
+
+ flags = DLADM_OPT_PERSIST;
+ break;
case 'i':
if (i_arg)
die_optdup(option);
@@ -1139,74 +1863,101 @@ do_show_link(int argc, char *argv[])
if (i_arg && !s_arg)
die("the option -i can be used only with -s");
+ if (s_arg && (p_arg || flags != DLADM_OPT_ACTIVE))
+ die("the option -%c cannot be used with -s", p_arg ? 'p' : 'P');
+
/* get link name (optional last argument) */
- if (optind == (argc-1))
- name = argv[optind];
- else if (optind != argc)
+ if (optind == (argc-1)) {
+ uint32_t f;
+
+ if ((status = dladm_name2info(argv[optind], &linkid, &f,
+ NULL, NULL)) != DLADM_STATUS_OK) {
+ die_dlerr(status, "link %s is not valid", argv[optind]);
+ }
+
+ if (!(f & flags)) {
+ die_dlerr(DLADM_STATUS_BADARG, "link %s is %s",
+ argv[optind], flags == DLADM_OPT_PERSIST ?
+ "a temporary link" : "temporarily removed");
+ }
+ } else if (optind != argc) {
usage();
+ }
if (s_arg) {
- link_stats(name, interval);
+ link_stats(linkid, interval);
return;
}
- if (name == NULL) {
- (void) dladm_walk(show_link, &state);
+ state.ls_parseable = p_arg;
+ state.ls_flags = flags;
+ state.ls_donefirst = B_FALSE;
+ if (linkid == DATALINK_ALL_LINKID) {
+ (void) dladm_walk_datalink_id(show_link, &state,
+ DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE, flags);
} else {
- show_link(&state, name);
+ (void) show_link(linkid, &state);
+ if (state.ls_status != DLADM_STATUS_OK) {
+ die_dlerr(state.ls_status, "failed to show link %s",
+ argv[optind]);
+ }
}
}
static void
do_show_aggr(int argc, char *argv[])
{
- int option;
- int key = 0;
boolean_t L_arg = B_FALSE;
boolean_t s_arg = B_FALSE;
boolean_t i_arg = B_FALSE;
+ boolean_t p_arg = B_FALSE;
+ boolean_t x_arg = B_FALSE;
show_grp_state_t state;
+ uint32_t flags = DLADM_OPT_ACTIVE;
+ datalink_id_t linkid = DATALINK_ALL_LINKID;
+ int option;
int interval = 0;
-
- state.gs_stats = B_FALSE;
- state.gs_lacp = B_FALSE;
- state.gs_parseable = B_FALSE;
+ int key;
+ dladm_status_t status;
opterr = 0;
- while ((option = getopt_long(argc, argv, ":Lpsi:",
- longopts, NULL)) != -1) {
+ while ((option = getopt_long(argc, argv, ":LpPxsi:",
+ show_lopts, NULL)) != -1) {
switch (option) {
case 'L':
if (L_arg)
die_optdup(option);
- if (s_arg || i_arg) {
- die("the option -L cannot be used with -i "
- "or -s");
- }
-
L_arg = B_TRUE;
- state.gs_lacp = B_TRUE;
break;
case 'p':
- state.gs_parseable = B_TRUE;
+ if (p_arg)
+ die_optdup(option);
+
+ p_arg = B_TRUE;
+ break;
+ case 'x':
+ if (x_arg)
+ die_optdup(option);
+
+ x_arg = B_TRUE;
+ break;
+ case 'P':
+ if (flags != DLADM_OPT_ACTIVE)
+ die_optdup(option);
+
+ flags = DLADM_OPT_PERSIST;
break;
case 's':
if (s_arg)
die_optdup(option);
- if (L_arg)
- die("the option -s cannot be used with -L");
-
s_arg = B_TRUE;
break;
case 'i':
if (i_arg)
die_optdup(option);
- if (L_arg)
- die("the option -i cannot be used with -L");
-
i_arg = B_TRUE;
if (!str2int(optarg, &interval) || interval == 0)
die("invalid interval value '%s'", optarg);
@@ -1220,26 +1971,56 @@ do_show_aggr(int argc, char *argv[])
if (i_arg && !s_arg)
die("the option -i can be used only with -s");
- /* get aggregation key (optional last argument) */
+ if (s_arg && (L_arg || p_arg || x_arg || flags != DLADM_OPT_ACTIVE)) {
+ die("the option -%c cannot be used with -s",
+ L_arg ? 'L' : (p_arg ? 'p' : (x_arg ? 'x' : 'P')));
+ }
+
+ if (L_arg && flags != DLADM_OPT_ACTIVE)
+ die("the option -P cannot be used with -L");
+
+ if (x_arg && (L_arg || flags != DLADM_OPT_ACTIVE))
+ die("the option -%c cannot be used with -x", L_arg ? 'L' : 'P');
+
+ /* get aggregation key or aggrname (optional last argument) */
if (optind == (argc-1)) {
- if (!str2int(argv[optind], &key) || key < 1)
- die("invalid key value '%s'", argv[optind]);
+ if (!str2int(argv[optind], &key)) {
+ status = dladm_name2info(argv[optind], &linkid, NULL,
+ NULL, NULL);
+ } else {
+ status = dladm_key2linkid((uint16_t)key,
+ &linkid, DLADM_OPT_ACTIVE);
+ }
+
+ if (status != DLADM_STATUS_OK)
+ die("non-existent aggregation '%s'", argv[optind]);
+
} else if (optind != argc) {
usage();
}
+ bzero(&state, sizeof (state));
+ state.gs_lacp = L_arg;
+ state.gs_stats = s_arg;
+ state.gs_flags = flags;
+ state.gs_parseable = p_arg;
+ state.gs_extended = x_arg;
+
if (s_arg) {
- aggr_stats(key, interval);
+ aggr_stats(linkid, &state, interval);
return;
}
- state.gs_key = key;
- state.gs_found = B_FALSE;
-
- (void) dladm_aggr_walk(show_key, &state);
-
- if (key != 0 && !state.gs_found)
- die("non-existent aggregation key '%u'", key);
+ if (linkid == DATALINK_ALL_LINKID) {
+ (void) dladm_walk_datalink_id(show_aggr, &state,
+ DATALINK_CLASS_AGGR, DATALINK_ANY_MEDIATYPE, flags);
+ } else {
+ (void) show_aggr(linkid, &state);
+ if (state.gs_status != DLADM_STATUS_OK) {
+ die_dlerr(state.gs_status, "failed to show aggr %s",
+ argv[optind]);
+ }
+ }
}
static void
@@ -1249,17 +2030,20 @@ do_show_dev(int argc, char *argv[])
char *dev = NULL;
boolean_t s_arg = B_FALSE;
boolean_t i_arg = B_FALSE;
+ boolean_t p_arg = B_FALSE;
+ datalink_id_t linkid;
int interval = 0;
- show_mac_state_t state;
-
- state.ms_parseable = B_FALSE;
+ show_state_t state;
opterr = 0;
while ((option = getopt_long(argc, argv, ":psi:",
- longopts, NULL)) != -1) {
+ show_lopts, NULL)) != -1) {
switch (option) {
case 'p':
- state.ms_parseable = B_TRUE;
+ if (p_arg)
+ die_optdup(option);
+
+ p_arg = B_TRUE;
break;
case 's':
if (s_arg)
@@ -1284,26 +2068,25 @@ do_show_dev(int argc, char *argv[])
if (i_arg && !s_arg)
die("the option -i can be used only with -s");
+ if (s_arg && p_arg)
+ die("the option -s cannot be used with -p");
+
/* get dev name (optional last argument) */
- if (optind == (argc-1))
+ if (optind == (argc-1)) {
+ uint32_t flags;
+
dev = argv[optind];
- else if (optind != argc)
- usage();
- if (dev != NULL) {
- uint_t ppa;
- char drv[DLPI_LINKNAME_MAX];
- dladm_attr_t dlattr;
- boolean_t legacy;
+ if (dladm_dev2linkid(dev, &linkid) != DLADM_STATUS_OK)
+ die("invalid device %s", dev);
- /*
- * Check for invalid devices.
- * aggregations and vlans are not considered devices.
- */
- if (dlpi_parselink(dev, drv, &ppa) != DLPI_SUCCESS ||
- strcmp(drv, "aggr") == 0 || ppa >= 1000 ||
- get_if_info(dev, &dlattr, &legacy) < 0)
- die("invalid device '%s'", dev);
+ if ((dladm_datalink_id2info(linkid, &flags, NULL, NULL,
+ NULL, 0) != DLADM_STATUS_OK) ||
+ !(flags & DLADM_OPT_ACTIVE)) {
+ die("device %s has been removed", dev);
+ }
+ } else if (optind != argc) {
+ usage();
}
if (s_arg) {
@@ -1311,22 +2094,336 @@ do_show_dev(int argc, char *argv[])
return;
}
- if (dev == NULL)
+ state.ls_donefirst = B_FALSE;
+ state.ls_parseable = p_arg;
+ if (dev == NULL) {
(void) dladm_mac_walk(show_dev, &state);
+ } else {
+ (void) show_dev(dev, &state);
+ }
+}
+
+static void
+print_phys_head(show_state_t *state)
+{
+ if (state->ls_donefirst)
+ return;
+ state->ls_donefirst = B_TRUE;
+
+ if (state->ls_parseable)
+ return;
+
+ if (state->ls_flags == DLADM_OPT_ACTIVE) {
+ (void) printf("%-12s%-20s%-10s%6s %-9s%s\n", "LINK",
+ "MEDIA", "STATE", "SPEED", "DUPLEX", "DEVICE");
+ } else {
+ (void) printf("%-12s%-12s%-20s%s\n", "LINK", "DEVICE",
+ "MEDIA", "FLAGS");
+ }
+}
+
+static dladm_status_t
+print_phys(show_state_t *state, datalink_id_t linkid, char **pptr, char *lim)
+{
+ char link[MAXLINKNAMELEN];
+ dladm_phys_attr_t dpa;
+ char buf[DLADM_STRSIZE];
+ uint32_t flags;
+ datalink_class_t class;
+ uint32_t media;
+ dladm_status_t status;
+
+ if ((status = dladm_datalink_id2info(linkid, &flags, &class, &media,
+ link, sizeof (link))) != DLADM_STATUS_OK) {
+ goto done;
+ }
+
+ if (class != DATALINK_CLASS_PHYS) {
+ status = DLADM_STATUS_BADARG;
+ goto done;
+ }
+
+ if (!(state->ls_flags & flags)) {
+ status = DLADM_STATUS_NOTFOUND;
+ goto done;
+ }
+
+ status = dladm_phys_info(linkid, &dpa, state->ls_flags);
+ if (status != DLADM_STATUS_OK)
+ goto done;
+
+ if (state->ls_flags == DLADM_OPT_ACTIVE) {
+ char name[MAXLINKNAMELEN];
+ boolean_t islink;
+
+ if (!dpa.dp_novanity) {
+ (void) strlcpy(name, link, sizeof (name));
+ islink = B_TRUE;
+ } else {
+ /*
+ * This is a physical link that does not have
+ * vanity naming support.
+ */
+ (void) strlcpy(name, dpa.dp_dev, sizeof (name));
+ islink = B_FALSE;
+ }
+
+ if (state->ls_parseable) {
+ *pptr += snprintf(*pptr, BUFLEN(lim, *pptr),
+ "LINK=\"%s\" MEDIA=\"%s\" ", link,
+ dladm_media2str(media, buf));
+ *pptr += snprintf(*pptr, BUFLEN(lim, *pptr),
+ "STATE=\"%s\" SPEED=\"%uMb\" ",
+ get_linkstate(name, islink, buf),
+ (uint_t)((get_ifspeed(name, islink)) / 1000000ull));
+ *pptr += snprintf(*pptr, BUFLEN(lim, *pptr),
+ "DUPLEX=\"%s\" DEVICE=\"%s\"\n",
+ get_linkduplex(name, islink, buf), dpa.dp_dev);
+ } else {
+ *pptr += snprintf(*pptr, BUFLEN(lim, *pptr),
+ "%-12s%-20s", link,
+ dladm_media2str(media, buf));
+ *pptr += snprintf(*pptr, BUFLEN(lim, *pptr),
+ "%-10s%4uMb ",
+ get_linkstate(name, islink, buf),
+ (uint_t)((get_ifspeed(name, islink)) / 1000000ull));
+ *pptr += snprintf(*pptr, BUFLEN(lim, *pptr),
+ "%-9s%s\n", get_linkduplex(name, islink, buf),
+ dpa.dp_dev);
+ }
+ } else {
+ if (state->ls_parseable) {
+ *pptr += snprintf(*pptr, BUFLEN(lim, *pptr),
+ "LINK=\"%s\" DEVICE=\"%s\" MEDIA=\"%s\" "
+ "FLAGS=\"%c----\"\n", link, dpa.dp_dev,
+ dladm_media2str(media, buf),
+ flags & DLADM_OPT_ACTIVE ? '-' : 'r');
+ } else {
+ *pptr += snprintf(*pptr, BUFLEN(lim, *pptr),
+ "%-12s%-12s%-20s%c----\n", link,
+ dpa.dp_dev, dladm_media2str(media, buf),
+ flags & DLADM_OPT_ACTIVE ? '-' : 'r');
+ }
+ }
+
+done:
+ return (status);
+}
+
+static int
+show_phys(datalink_id_t linkid, void *arg)
+{
+ show_state_t *state = arg;
+ dladm_status_t status;
+ char buf[MAXLINELEN];
+ char *ptr = buf, *lim = buf + MAXLINELEN;
+
+ status = print_phys(state, linkid, &ptr, lim);
+ if (status != DLADM_STATUS_OK)
+ goto done;
+ print_phys_head(state);
+ (void) printf("%s", buf);
+
+done:
+ state->ls_status = status;
+ return (DLADM_WALK_CONTINUE);
+}
+
+static void
+print_vlan_head(show_state_t *state)
+{
+ if (state->ls_donefirst)
+ return;
+ state->ls_donefirst = B_TRUE;
+
+ if (state->ls_parseable)
+ return;
+
+ (void) printf("%-12s%5s %-12s%s\n", "LINK", "VID", "OVER", "FLAGS");
+}
+
+/*
+ * Print the active topology information.
+ */
+static dladm_status_t
+print_vlan(show_state_t *state, datalink_id_t linkid, char **pptr, char *lim)
+{
+ char link[MAXLINKNAMELEN];
+ char over[MAXLINKNAMELEN];
+ char *fmt;
+ dladm_vlan_attr_t vinfo;
+ uint32_t flags;
+ dladm_status_t status;
+
+ if ((status = dladm_datalink_id2info(linkid, &flags, NULL, NULL, link,
+ sizeof (link))) != DLADM_STATUS_OK) {
+ goto done;
+ }
+
+ if (!(state->ls_flags & flags)) {
+ status = DLADM_STATUS_NOTFOUND;
+ goto done;
+ }
+
+ if ((status = dladm_vlan_info(linkid, &vinfo, state->ls_flags)) !=
+ DLADM_STATUS_OK || (status = dladm_datalink_id2info(
+ vinfo.dv_linkid, NULL, NULL, NULL, over, sizeof (over))) !=
+ DLADM_STATUS_OK) {
+ goto done;
+ }
+
+ if (state->ls_parseable)
+ fmt = "LINK=\"%s\" VID=\"%d\" OVER=\"%s\" FLAGS=\"%c%c---\"\n";
else
- show_dev(&state, dev);
+ fmt = "%-12s%5d %-12s%c%c---\n";
+ /*LINTED: E_SEC_PRINTF_VAR_FMT*/
+ *pptr += snprintf(*pptr, BUFLEN(lim, *pptr), fmt, link,
+ vinfo.dv_vid, over, vinfo.dv_force ? 'f' : '-',
+ vinfo.dv_implicit ? 'i' : '-');
+
+done:
+ return (status);
+}
+
+static int
+show_vlan(datalink_id_t linkid, void *arg)
+{
+ show_state_t *state = arg;
+ dladm_status_t status;
+ char buf[MAXLINELEN];
+ char *ptr = buf, *lim = buf + MAXLINELEN;
+
+ status = print_vlan(state, linkid, &ptr, lim);
+ if (status != DLADM_STATUS_OK)
+ goto done;
+ print_vlan_head(state);
+ (void) printf("%s", buf);
+
+done:
+ state->ls_status = status;
+ return (DLADM_WALK_CONTINUE);
+}
+
+static void
+do_show_phys(int argc, char *argv[])
+{
+ int option;
+ uint32_t flags = DLADM_OPT_ACTIVE;
+ boolean_t p_arg = B_FALSE;
+ datalink_id_t linkid = DATALINK_ALL_LINKID;
+ show_state_t state;
+ dladm_status_t status;
+
+ opterr = 0;
+ while ((option = getopt_long(argc, argv, ":pP",
+ show_lopts, NULL)) != -1) {
+ switch (option) {
+ case 'p':
+ if (p_arg)
+ die_optdup(option);
+
+ p_arg = B_TRUE;
+ break;
+ case 'P':
+ if (flags != DLADM_OPT_ACTIVE)
+ die_optdup(option);
+
+ flags = DLADM_OPT_PERSIST;
+ break;
+ default:
+ die_opterr(optopt, option);
+ break;
+ }
+ }
+
+ /* get link name (optional last argument) */
+ if (optind == (argc-1)) {
+ if ((status = dladm_name2info(argv[optind], &linkid, NULL,
+ NULL, NULL)) != DLADM_STATUS_OK) {
+ die_dlerr(status, "link %s is not valid", argv[optind]);
+ }
+ } else if (optind != argc) {
+ usage();
+ }
+
+ state.ls_parseable = p_arg;
+ state.ls_flags = flags;
+ state.ls_donefirst = B_FALSE;
+
+ if (linkid == DATALINK_ALL_LINKID) {
+ (void) dladm_walk_datalink_id(show_phys, &state,
+ DATALINK_CLASS_PHYS, DATALINK_ANY_MEDIATYPE, flags);
+ } else {
+ (void) show_phys(linkid, &state);
+ if (state.ls_status != DLADM_STATUS_OK) {
+ die_dlerr(state.ls_status,
+ "failed to show physical link %s", argv[optind]);
+ }
+ }
}
-/* ARGSUSED */
static void
-link_stats(const char *link, uint_t interval)
+do_show_vlan(int argc, char *argv[])
{
- dladm_attr_t dlattr;
- boolean_t legacy;
- show_link_state_t state;
+ int option;
+ uint32_t flags = DLADM_OPT_ACTIVE;
+ boolean_t p_arg = B_FALSE;
+ datalink_id_t linkid = DATALINK_ALL_LINKID;
+ show_state_t state;
+ dladm_status_t status;
- if (link != NULL && get_if_info(link, &dlattr, &legacy) < 0)
- die("invalid link '%s'", link);
+ opterr = 0;
+ while ((option = getopt_long(argc, argv, ":pP",
+ show_lopts, NULL)) != -1) {
+ switch (option) {
+ case 'p':
+ if (p_arg)
+ die_optdup(option);
+
+ p_arg = B_TRUE;
+ break;
+ case 'P':
+ if (flags != DLADM_OPT_ACTIVE)
+ die_optdup(option);
+
+ flags = DLADM_OPT_PERSIST;
+ break;
+ default:
+ die_opterr(optopt, option);
+ break;
+ }
+ }
+
+ /* get link name (optional last argument) */
+ if (optind == (argc-1)) {
+ if ((status = dladm_name2info(argv[optind], &linkid, NULL,
+ NULL, NULL)) != DLADM_STATUS_OK) {
+ die_dlerr(status, "link %s is not valid", argv[optind]);
+ }
+ } else if (optind != argc) {
+ usage();
+ }
+
+ state.ls_parseable = p_arg;
+ state.ls_flags = flags;
+ state.ls_donefirst = B_FALSE;
+
+ if (linkid == DATALINK_ALL_LINKID) {
+ (void) dladm_walk_datalink_id(show_vlan, &state,
+ DATALINK_CLASS_VLAN, DATALINK_ANY_MEDIATYPE, flags);
+ } else {
+ (void) show_vlan(linkid, &state);
+ if (state.ls_status != DLADM_STATUS_OK) {
+ die_dlerr(state.ls_status, "failed to show vlan %s",
+ argv[optind]);
+ }
+ }
+}
+
+static void
+link_stats(datalink_id_t linkid, uint_t interval)
+{
+ show_state_t state;
bzero(&state, sizeof (state));
@@ -1337,14 +2434,18 @@ link_stats(const char *link, uint_t interval)
state.ls_firstonly = (interval != 0);
for (;;) {
- (void) printf("\t\tipackets rbytes ierrors ");
- (void) printf("opackets obytes oerrors\n");
+ (void) printf("%-12s%-10s%-12s%-8s%-10s%-12s%-8s\n",
+ "LINK", "IPACKETS", "RBYTES", "IERRORS", "OPACKETS",
+ "OBYTES", "OERRORS");
state.ls_donefirst = B_FALSE;
- if (link == NULL)
- (void) dladm_walk(show_link_stats, &state);
- else
- show_link_stats(&state, link);
+ if (linkid == DATALINK_ALL_LINKID) {
+ (void) dladm_walk_datalink_id(show_link_stats, &state,
+ DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE,
+ DLADM_OPT_ACTIVE);
+ } else {
+ (void) show_link_stats(linkid, &state);
+ }
if (interval == 0)
break;
@@ -1353,27 +2454,28 @@ link_stats(const char *link, uint_t interval)
}
}
-/* ARGSUSED */
static void
-aggr_stats(uint32_t key, uint_t interval)
+aggr_stats(datalink_id_t linkid, show_grp_state_t *state, uint_t interval)
{
- show_grp_state_t state;
-
- bzero(&state, sizeof (state));
- state.gs_stats = B_TRUE;
- state.gs_key = key;
-
/*
* If an interval is specified, continuously show the stats
* only for the first group.
*/
- state.gs_firstonly = (interval != 0);
+ state->gs_firstonly = (interval != 0);
for (;;) {
- state.gs_found = B_FALSE;
- (void) dladm_aggr_walk(show_key, &state);
- if (state.gs_key != 0 && !state.gs_found)
- die("non-existent aggregation key '%u'", key);
+
+ (void) printf("%-12s%-10s%8s %8s %8s %8s %-9s%s\n",
+ "LINK", "PORT", "IPACKETS", "RBYTES", "OPACKETS",
+ "OBYTES", "IPKTDIST", "OPKTDIST");
+
+ state->gs_donefirst = B_FALSE;
+ if (linkid == DATALINK_ALL_LINKID)
+ (void) dladm_walk_datalink_id(show_aggr, state,
+ DATALINK_CLASS_AGGR, DATALINK_ANY_MEDIATYPE,
+ DLADM_OPT_ACTIVE);
+ else
+ (void) show_aggr(linkid, state);
if (interval == 0)
break;
@@ -1382,11 +2484,10 @@ aggr_stats(uint32_t key, uint_t interval)
}
}
-/* ARGSUSED */
static void
dev_stats(const char *dev, uint32_t interval)
{
- show_mac_state_t state;
+ show_state_t state;
bzero(&state, sizeof (state));
@@ -1394,24 +2495,28 @@ dev_stats(const char *dev, uint32_t interval)
* If an interval is specified, continuously show the stats
* only for the first MAC port.
*/
- state.ms_firstonly = (interval != 0);
+ state.ls_firstonly = (interval != 0);
for (;;) {
- (void) printf("\t\tipackets rbytes ierrors ");
- (void) printf("opackets obytes oerrors\n");
+ (void) printf("%-12s%-10s%-12s%-8s%-10s%-12s%-8s\n",
+ "DEV", "IPACKETS", "RBYTES", "IERRORS", "OPACKETS",
+ "OBYTES", "OERRORS");
- state.ms_donefirst = B_FALSE;
+ state.ls_donefirst = B_FALSE;
if (dev == NULL)
(void) dladm_mac_walk(show_dev_stats, &state);
else
- show_dev_stats(&state, dev);
+ (void) show_dev_stats(dev, &state);
if (interval == 0)
break;
(void) sleep(interval);
}
+
+ if (dev != NULL && state.ls_status != DLADM_STATUS_OK)
+ die_dlerr(state.ls_status, "cannot show device '%s'", dev);
}
/* accumulate stats (s1 += (s2 - s3)) */
@@ -1438,16 +2543,8 @@ stats_diff(pktsum_t *s1, pktsum_t *s2, pktsum_t *s3)
s1->oerrors = s2->oerrors - s3->oerrors;
}
-/*
- * In the following routines, we do the first kstat_lookup() assuming that
- * the device is gldv3-based and that the kstat name is the one passed in
- * as the "name" argument. If the lookup fails, we redo the kstat_lookup()
- * omitting the kstat name. This second lookup is needed for getting kstats
- * from legacy devices. This can fail too if the device is not attached or
- * the device is legacy and doesn't export the kstats we need.
- */
static void
-get_stats(char *module, int instance, char *name, pktsum_t *stats)
+get_stats(char *module, int instance, const char *name, pktsum_t *stats)
{
kstat_ctl_t *kcp;
kstat_t *ksp;
@@ -1457,8 +2554,7 @@ get_stats(char *module, int instance, char *name, pktsum_t *stats)
return;
}
- if ((ksp = kstat_lookup(kcp, module, instance, name)) == NULL &&
- (ksp = kstat_lookup(kcp, module, instance, NULL)) == NULL) {
+ if ((ksp = kstat_lookup(kcp, module, instance, (char *)name)) == NULL) {
/*
* The kstat query could fail if the underlying MAC
* driver was already detached.
@@ -1494,56 +2590,45 @@ get_stats(char *module, int instance, char *name, pktsum_t *stats)
&stats->oerrors) < 0)
goto bail;
+bail:
(void) kstat_close(kcp);
return;
-bail:
- (void) kstat_close(kcp);
}
static void
get_mac_stats(const char *dev, pktsum_t *stats)
{
- char module[DLPI_LINKNAME_MAX];
- uint_t instance;
+ char module[DLPI_LINKNAME_MAX];
+ uint_t instance;
+ bzero(stats, sizeof (*stats));
if (dlpi_parselink(dev, module, &instance) != DLPI_SUCCESS)
return;
- bzero(stats, sizeof (*stats));
+
get_stats(module, instance, "mac", stats);
}
static void
get_link_stats(const char *link, pktsum_t *stats)
{
- char module[DLPI_LINKNAME_MAX];
- uint_t instance;
-
- if (dlpi_parselink(link, module, &instance) != DLPI_SUCCESS)
- return;
bzero(stats, sizeof (*stats));
- get_stats(module, instance, (char *)link, stats);
+ get_stats("link", 0, link, stats);
}
static int
-get_single_mac_stat(const char *dev, const char *name, uint8_t type,
- void *val)
+query_kstat(char *module, int instance, const char *name, const char *stat,
+ uint8_t type, void *val)
{
- char module[DLPI_LINKNAME_MAX];
- uint_t instance;
kstat_ctl_t *kcp;
kstat_t *ksp;
- if (dlpi_parselink(dev, module, &instance) != DLPI_SUCCESS)
- return (-1);
-
if ((kcp = kstat_open()) == NULL) {
warn("kstat open operation failed");
return (-1);
}
- if ((ksp = kstat_lookup(kcp, module, instance, "mac")) == NULL &&
- (ksp = kstat_lookup(kcp, module, instance, NULL)) == NULL) {
+ if ((ksp = kstat_lookup(kcp, module, instance, (char *)name)) == NULL) {
/*
* The kstat query could fail if the underlying MAC
* driver was already detached.
@@ -1556,7 +2641,7 @@ get_single_mac_stat(const char *dev, const char *name, uint8_t type,
goto bail;
}
- if (kstat_value(ksp, name, type, val) < 0)
+ if (kstat_value(ksp, stat, type, val) < 0)
goto bail;
(void) kstat_close(kcp);
@@ -1567,41 +2652,59 @@ bail:
return (-1);
}
+static int
+get_one_kstat(const char *name, const char *stat, uint8_t type,
+ void *val, boolean_t islink)
+{
+ char module[DLPI_LINKNAME_MAX];
+ uint_t instance;
+
+ if (islink) {
+ return (query_kstat("link", 0, name, stat, type, val));
+ } else {
+ if (dlpi_parselink(name, module, &instance) != DLPI_SUCCESS)
+ return (-1);
+
+ return (query_kstat(module, instance, "mac", stat, type, val));
+ }
+}
+
static uint64_t
-mac_ifspeed(const char *dev)
+get_ifspeed(const char *name, boolean_t islink)
{
uint64_t ifspeed = 0;
- (void) get_single_mac_stat(dev, "ifspeed", KSTAT_DATA_UINT64, &ifspeed);
+ (void) get_one_kstat(name, "ifspeed", KSTAT_DATA_UINT64,
+ &ifspeed, islink);
+
return (ifspeed);
}
static const char *
-mac_link_state(const char *dev, char *buf)
+get_linkstate(const char *name, boolean_t islink, char *buf)
{
- link_state_t link_state;
+ link_state_t linkstate;
- if (get_single_mac_stat(dev, "link_state", KSTAT_DATA_UINT32,
- &link_state) != 0) {
+ if (get_one_kstat(name, "link_state", KSTAT_DATA_UINT32,
+ &linkstate, islink) != 0) {
(void) strlcpy(buf, "unknown", DLADM_STRSIZE);
return (buf);
}
-
- return (dladm_linkstate2str(link_state, buf));
+ return (dladm_linkstate2str(linkstate, buf));
}
static const char *
-mac_link_duplex(const char *dev, char *buf)
+get_linkduplex(const char *name, boolean_t islink, char *buf)
{
- link_duplex_t link_duplex;
+ link_duplex_t linkduplex;
- if (get_single_mac_stat(dev, "link_duplex", KSTAT_DATA_UINT32,
- &link_duplex) != 0) {
+ if (get_one_kstat(name, "link_duplex", KSTAT_DATA_UINT32,
+ &linkduplex, islink) != 0) {
(void) strlcpy(buf, "unknown", DLADM_STRSIZE);
return (buf);
}
- return (dladm_linkduplex2str(link_duplex, buf));
+ return (dladm_linkduplex2str(linkduplex, buf));
}
#define WIFI_CMD_SCAN 0x00000001
@@ -1616,17 +2719,17 @@ typedef struct wifi_field {
} wifi_field_t;
static wifi_field_t wifi_fields[] = {
-{ "link", "LINK", 10, 0, WIFI_CMD_ALL},
+{ "link", "LINK", 10, 0, WIFI_CMD_ALL},
{ "essid", "ESSID", 19, DLADM_WLAN_ATTR_ESSID, WIFI_CMD_ALL},
{ "bssid", "BSSID/IBSSID", 17, DLADM_WLAN_ATTR_BSSID, WIFI_CMD_ALL},
{ "ibssid", "BSSID/IBSSID", 17, DLADM_WLAN_ATTR_BSSID, WIFI_CMD_ALL},
{ "mode", "MODE", 6, DLADM_WLAN_ATTR_MODE, WIFI_CMD_ALL},
{ "speed", "SPEED", 6, DLADM_WLAN_ATTR_SPEED, WIFI_CMD_ALL},
{ "auth", "AUTH", 8, DLADM_WLAN_ATTR_AUTH, WIFI_CMD_SHOW},
-{ "bsstype", "BSSTYPE", 8, DLADM_WLAN_ATTR_BSSTYPE, WIFI_CMD_ALL},
-{ "sec", "SEC", 6, DLADM_WLAN_ATTR_SECMODE, WIFI_CMD_ALL},
-{ "status", "STATUS", 17, DLADM_WLAN_LINKATTR_STATUS, WIFI_CMD_SHOW},
-{ "strength", "STRENGTH", 10, DLADM_WLAN_ATTR_STRENGTH, WIFI_CMD_ALL}}
+{ "bsstype", "BSSTYPE", 8, DLADM_WLAN_ATTR_BSSTYPE, WIFI_CMD_ALL},
+{ "sec", "SEC", 6, DLADM_WLAN_ATTR_SECMODE, WIFI_CMD_ALL},
+{ "status", "STATUS", 17, DLADM_WLAN_LINKATTR_STATUS, WIFI_CMD_SHOW},
+{ "strength", "STRENGTH", 10, DLADM_WLAN_ATTR_STRENGTH, WIFI_CMD_ALL}}
;
static char *all_scan_wifi_fields =
@@ -1751,7 +2854,7 @@ fail:
}
typedef struct print_wifi_state {
- const char *ws_link;
+ char *ws_link;
boolean_t ws_parseable;
boolean_t ws_header;
wifi_field_t **ws_fields;
@@ -1877,18 +2980,24 @@ print_scan_results(void *arg, dladm_wlan_attr_t *attrp)
return (B_TRUE);
}
-static boolean_t
-scan_wifi(void *arg, const char *link)
+static int
+scan_wifi(datalink_id_t linkid, void *arg)
{
print_wifi_state_t *statep = arg;
dladm_status_t status;
+ char link[MAXLINKNAMELEN];
+
+ if (dladm_datalink_id2info(linkid, NULL, NULL, NULL, link,
+ sizeof (link)) != DLADM_STATUS_OK) {
+ return (DLADM_WALK_CONTINUE);
+ }
statep->ws_link = link;
- status = dladm_wlan_scan(link, statep, print_scan_results);
+ status = dladm_wlan_scan(linkid, statep, print_scan_results);
if (status != DLADM_STATUS_OK)
- die_dlerr(status, "cannot scan link '%s'", link);
+ die_dlerr(status, "cannot scan link '%s'", statep->ws_link);
- return (B_TRUE);
+ return (DLADM_WALK_CONTINUE);
}
static void
@@ -1907,17 +3016,25 @@ print_link_attr(print_wifi_state_t *statep, wifi_field_t *wfp,
print_wlan_attr(statep, wfp, &attrp->la_wlan_attr);
}
-static boolean_t
-show_wifi(void *arg, const char *link)
+static int
+show_wifi(datalink_id_t linkid, void *arg)
{
int i;
print_wifi_state_t *statep = arg;
dladm_wlan_linkattr_t attr;
dladm_status_t status;
+ char link[MAXLINKNAMELEN];
+
+ if (dladm_datalink_id2info(linkid, NULL, NULL, NULL, link,
+ sizeof (link)) != DLADM_STATUS_OK) {
+ return (DLADM_WALK_CONTINUE);
+ }
- status = dladm_wlan_get_linkattr(link, &attr);
+ status = dladm_wlan_get_linkattr(linkid, &attr);
if (status != DLADM_STATUS_OK)
- die_dlerr(status, "cannot get link attributes for '%s'", link);
+ die_dlerr(status, "cannot get link attributes for %s", link);
+
+ statep->ws_link = link;
if (statep->ws_header) {
statep->ws_header = B_FALSE;
@@ -1925,14 +3042,13 @@ show_wifi(void *arg, const char *link)
print_wifi_head(statep);
}
- statep->ws_link = link;
statep->ws_overflow = 0;
for (i = 0; i < statep->ws_nfields; i++) {
statep->ws_lastfield = (i + 1 == statep->ws_nfields);
print_link_attr(statep, statep->ws_fields[i], &attr);
}
(void) putchar('\n');
- return (B_TRUE);
+ return (DLADM_WALK_CONTINUE);
}
static void
@@ -1941,9 +3057,10 @@ do_display_wifi(int argc, char **argv, int cmd)
int option;
char *fields_str = NULL;
wifi_field_t **fields;
- boolean_t (*callback)(void *, const char *);
+ int (*callback)(datalink_id_t, void *);
uint_t nfields;
print_wifi_state_t state;
+ datalink_id_t linkid = DATALINK_ALL_LINKID;
dladm_status_t status;
if (cmd == WIFI_CMD_SCAN)
@@ -1953,7 +3070,6 @@ do_display_wifi(int argc, char **argv, int cmd)
else
return;
- state.ws_link = NULL;
state.ws_parseable = B_FALSE;
state.ws_header = B_TRUE;
opterr = 0;
@@ -1974,10 +3090,14 @@ do_display_wifi(int argc, char **argv, int cmd)
}
}
- if (optind == (argc - 1))
- state.ws_link = argv[optind];
- else if (optind != argc)
+ if (optind == (argc - 1)) {
+ if ((status = dladm_name2info(argv[optind], &linkid, NULL,
+ NULL, NULL)) != DLADM_STATUS_OK) {
+ die_dlerr(status, "link %s is not valid", argv[optind]);
+ }
+ } else if (optind != argc) {
usage();
+ }
if (parse_wifi_fields(fields_str, &fields, &nfields, cmd) < 0)
die("invalid field(s) specified");
@@ -1985,12 +3105,11 @@ do_display_wifi(int argc, char **argv, int cmd)
state.ws_fields = fields;
state.ws_nfields = nfields;
- if (state.ws_link == NULL) {
- status = dladm_wlan_walk(&state, callback);
- if (status != DLADM_STATUS_OK)
- die_dlerr(status, "cannot walk wifi links");
+ if (linkid == DATALINK_ALL_LINKID) {
+ (void) dladm_walk_datalink_id(callback, &state,
+ DATALINK_CLASS_PHYS, DL_WIFI, DLADM_OPT_ACTIVE);
} else {
- (void) (*callback)(&state, state.ws_link);
+ (void) (*callback)(linkid, &state);
}
free(fields);
}
@@ -2009,18 +3128,18 @@ do_show_wifi(int argc, char **argv)
typedef struct wlan_count_attr {
uint_t wc_count;
- const char *wc_link;
+ datalink_id_t wc_linkid;
} wlan_count_attr_t;
-static boolean_t
-do_count_wlan(void *arg, const char *link)
+static int
+do_count_wlan(datalink_id_t linkid, void *arg)
{
wlan_count_attr_t *cp = arg;
if (cp->wc_count == 0)
- cp->wc_link = strdup(link);
+ cp->wc_linkid = linkid;
cp->wc_count++;
- return (B_TRUE);
+ return (DLADM_WALK_CONTINUE);
}
static int
@@ -2086,7 +3205,7 @@ do_connect_wifi(int argc, char **argv)
dladm_wlan_attr_t attr, *attrp;
dladm_status_t status = DLADM_STATUS_OK;
int timeout = DLADM_WLAN_CONNECT_TIMEOUT_DEFAULT;
- const char *link = NULL;
+ datalink_id_t linkid = DATALINK_ALL_LINKID;
dladm_wlan_key_t *keys = NULL;
uint_t key_count = 0;
uint_t flags = 0;
@@ -2186,28 +3305,33 @@ do_connect_wifi(int argc, char **argv)
attr.wa_secmode = keysecmode;
}
- if (optind == (argc - 1))
- link = argv[optind];
- else if (optind != argc)
+ if (optind == (argc - 1)) {
+ if ((status = dladm_name2info(argv[optind], &linkid, NULL,
+ NULL, NULL)) != DLADM_STATUS_OK) {
+ die_dlerr(status, "link %s is not valid", argv[optind]);
+ }
+ } else if (optind != argc) {
usage();
+ }
- if (link == NULL) {
+ if (linkid == DATALINK_ALL_LINKID) {
wlan_count_attr_t wcattr;
- wcattr.wc_link = NULL;
+ wcattr.wc_linkid = DATALINK_INVALID_LINKID;
wcattr.wc_count = 0;
- (void) dladm_wlan_walk(&wcattr, do_count_wlan);
+ (void) dladm_walk_datalink_id(do_count_wlan, &wcattr,
+ DATALINK_CLASS_PHYS, DL_WIFI, DLADM_OPT_ACTIVE);
if (wcattr.wc_count == 0) {
die("no wifi links are available");
} else if (wcattr.wc_count > 1) {
die("link name is required when more than one wifi "
"link is available");
}
- link = wcattr.wc_link;
+ linkid = wcattr.wc_linkid;
}
attrp = (attr.wa_valid == 0) ? NULL : &attr;
again:
- if ((status = dladm_wlan_connect(link, attrp, timeout, keys,
+ if ((status = dladm_wlan_connect(linkid, attrp, timeout, keys,
key_count, flags)) != DLADM_STATUS_OK) {
if ((flags & DLADM_WLAN_CONNECT_NOSCAN) != 0) {
/*
@@ -2225,29 +3349,29 @@ again:
"criteria are available");
}
}
- die_dlerr(status, "cannot connect link '%s'", link);
+ die_dlerr(status, "cannot connect");
}
free(keys);
}
/* ARGSUSED */
-static boolean_t
-do_all_disconnect_wifi(void *arg, const char *link)
+static int
+do_all_disconnect_wifi(datalink_id_t linkid, void *arg)
{
dladm_status_t status;
- status = dladm_wlan_disconnect(link);
+ status = dladm_wlan_disconnect(linkid);
if (status != DLADM_STATUS_OK)
- warn_dlerr(status, "cannot disconnect link '%s'", link);
+ warn_dlerr(status, "cannot disconnect link");
- return (B_TRUE);
+ return (DLADM_WALK_CONTINUE);
}
static void
do_disconnect_wifi(int argc, char **argv)
{
int option;
- const char *link = NULL;
+ datalink_id_t linkid = DATALINK_ALL_LINKID;
boolean_t all_links = B_FALSE;
dladm_status_t status;
wlan_count_attr_t wcattr;
@@ -2265,41 +3389,46 @@ do_disconnect_wifi(int argc, char **argv)
}
}
- if (optind == (argc - 1))
- link = argv[optind];
- else if (optind != argc)
+ if (optind == (argc - 1)) {
+ if ((status = dladm_name2info(argv[optind], &linkid, NULL,
+ NULL, NULL)) != DLADM_STATUS_OK) {
+ die_dlerr(status, "link %s is not valid", argv[optind]);
+ }
+ } else if (optind != argc) {
usage();
+ }
- if (link == NULL) {
+ if (linkid == DATALINK_ALL_LINKID) {
if (!all_links) {
- wcattr.wc_link = NULL;
+ wcattr.wc_linkid = linkid;
wcattr.wc_count = 0;
- (void) dladm_wlan_walk(&wcattr, do_count_wlan);
+ (void) dladm_walk_datalink_id(do_count_wlan, &wcattr,
+ DATALINK_CLASS_PHYS, DL_WIFI, DLADM_OPT_ACTIVE);
if (wcattr.wc_count == 0) {
die("no wifi links are available");
} else if (wcattr.wc_count > 1) {
die("link name is required when more than "
"one wifi link is available");
}
- link = wcattr.wc_link;
+ linkid = wcattr.wc_linkid;
} else {
- (void) dladm_wlan_walk(&all_links,
- do_all_disconnect_wifi);
+ (void) dladm_walk_datalink_id(do_all_disconnect_wifi,
+ NULL, DATALINK_CLASS_PHYS, DL_WIFI,
+ DLADM_OPT_ACTIVE);
return;
}
}
- status = dladm_wlan_disconnect(link);
+ status = dladm_wlan_disconnect(linkid);
if (status != DLADM_STATUS_OK)
- die_dlerr(status, "cannot disconnect link '%s'", link);
+ die_dlerr(status, "cannot disconnect");
}
#define MAX_PROPS 32
-#define MAX_PROP_VALS 32
#define MAX_PROP_LINE 512
typedef struct prop_info {
char *pi_name;
- char *pi_val[MAX_PROP_VALS];
+ char *pi_val[DLADM_MAX_PROP_VALCNT];
uint_t pi_count;
} prop_info_t;
@@ -2310,7 +3439,7 @@ typedef struct prop_list {
} prop_list_t;
typedef struct show_linkprop_state {
- const char *ls_link;
+ char ls_link[MAXLINKNAMELEN];
char *ls_line;
char **ls_propvals;
prop_list_t *ls_proplist;
@@ -2364,7 +3493,7 @@ parse_props(char *str, prop_list_t **listp, boolean_t novalues)
}
if (pip != NULL && c != '=') {
- if (pip->pi_count > MAX_PROP_VALS)
+ if (pip->pi_count > DLADM_MAX_PROP_VALCNT)
goto fail;
if (novalues)
@@ -2401,24 +3530,29 @@ print_linkprop_head(void)
}
static void
-print_linkprop(show_linkprop_state_t *statep, const char *propname,
- dladm_prop_type_t type, const char *typename, const char *format,
- char **pptr)
+print_linkprop(datalink_id_t linkid, show_linkprop_state_t *statep,
+ const char *propname, dladm_prop_type_t type, const char *typename,
+ const char *format, char **pptr)
{
int i;
char *ptr, *lim;
char buf[DLADM_STRSIZE];
char *unknown = "?", *notsup = "";
char **propvals = statep->ls_propvals;
- uint_t valcnt = MAX_PROP_VALS;
+ uint_t valcnt = DLADM_MAX_PROP_VALCNT;
dladm_status_t status;
- status = dladm_get_prop(statep->ls_link, type, propname,
- propvals, &valcnt);
+ status = dladm_get_linkprop(linkid, type, propname, propvals, &valcnt);
if (status != DLADM_STATUS_OK) {
if (status == DLADM_STATUS_TEMPONLY) {
- statep->ls_status = status;
- return;
+ if (type == DLADM_PROP_VAL_MODIFIABLE &&
+ statep->ls_persist) {
+ valcnt = 1;
+ propvals = &unknown;
+ } else {
+ statep->ls_status = status;
+ return;
+ }
} else if (status == DLADM_STATUS_NOTSUP ||
statep->ls_persist) {
valcnt = 1;
@@ -2428,9 +3562,11 @@ print_linkprop(show_linkprop_state_t *statep, const char *propname,
propvals = &notsup;
} else {
statep->ls_status = status;
- warn_dlerr(status,
- "cannot get link property '%s' for %s",
- propname, statep->ls_link);
+ if (statep->ls_proplist) {
+ warn_dlerr(status,
+ "cannot get link property '%s' for %s",
+ propname, statep->ls_link);
+ }
return;
}
}
@@ -2457,8 +3593,8 @@ print_linkprop(show_linkprop_state_t *statep, const char *propname,
}
}
-static boolean_t
-show_linkprop(void *arg, const char *propname)
+static int
+show_linkprop(datalink_id_t linkid, const char *propname, void *arg)
{
show_linkprop_state_t *statep = arg;
char *ptr = statep->ls_line;
@@ -2475,7 +3611,7 @@ show_linkprop(void *arg, const char *propname)
else
ptr += snprintf(ptr, lim - ptr, "%-15s ", propname);
- print_linkprop(statep, propname,
+ print_linkprop(linkid, statep, propname,
statep->ls_persist ? DLADM_PROP_VAL_PERSISTENT :
DLADM_PROP_VAL_CURRENT, "VALUE", "%-14s ", &ptr);
@@ -2485,17 +3621,17 @@ show_linkprop(void *arg, const char *propname)
* skip the output.
*/
if (statep->ls_status != DLADM_STATUS_OK)
- return (B_TRUE);
+ return (DLADM_WALK_CONTINUE);
- print_linkprop(statep, propname, DLADM_PROP_VAL_DEFAULT,
+ print_linkprop(linkid, statep, propname, DLADM_PROP_VAL_DEFAULT,
"DEFAULT", "%-14s ", &ptr);
if (statep->ls_status != DLADM_STATUS_OK)
- return (B_TRUE);
+ return (DLADM_WALK_CONTINUE);
- print_linkprop(statep, propname, DLADM_PROP_VAL_MODIFIABLE,
+ print_linkprop(linkid, statep, propname, DLADM_PROP_VAL_MODIFIABLE,
"POSSIBLE", "%-20s ", &ptr);
if (statep->ls_status != DLADM_STATUS_OK)
- return (B_TRUE);
+ return (DLADM_WALK_CONTINUE);
if (statep->ls_header) {
statep->ls_header = B_FALSE;
@@ -2503,7 +3639,7 @@ show_linkprop(void *arg, const char *propname)
print_linkprop_head();
}
(void) printf("%s\n", statep->ls_line);
- return (B_TRUE);
+ return (DLADM_WALK_CONTINUE);
}
static void
@@ -2511,10 +3647,12 @@ do_show_linkprop(int argc, char **argv)
{
int option;
prop_list_t *proplist = NULL;
+ datalink_id_t linkid = DATALINK_ALL_LINKID;
show_linkprop_state_t state;
+ uint32_t flags = DLADM_OPT_ACTIVE;
+ dladm_status_t status;
opterr = 0;
- state.ls_link = NULL;
state.ls_propvals = NULL;
state.ls_line = NULL;
state.ls_parseable = B_FALSE;
@@ -2532,6 +3670,7 @@ do_show_linkprop(int argc, char **argv)
break;
case 'P':
state.ls_persist = B_TRUE;
+ flags = DLADM_OPT_PERSIST;
break;
default:
die_opterr(optopt, option);
@@ -2539,40 +3678,59 @@ do_show_linkprop(int argc, char **argv)
}
}
- if (optind == (argc - 1))
- state.ls_link = argv[optind];
- else if (optind != argc)
+ if (optind == (argc - 1)) {
+ if ((status = dladm_name2info(argv[optind], &linkid, NULL,
+ NULL, NULL)) != DLADM_STATUS_OK) {
+ die_dlerr(status, "link %s is not valid", argv[optind]);
+ }
+ } else if (optind != argc) {
usage();
+ }
state.ls_proplist = proplist;
state.ls_status = DLADM_STATUS_OK;
- if (state.ls_link == NULL) {
- (void) dladm_walk(show_linkprop_onelink, &state);
+ if (linkid == DATALINK_ALL_LINKID) {
+ (void) dladm_walk_datalink_id(show_linkprop_onelink, &state,
+ DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE, flags);
} else {
- show_linkprop_onelink(&state, state.ls_link);
+ (void) show_linkprop_onelink(linkid, &state);
}
free_props(proplist);
- if (state.ls_status != DLADM_STATUS_OK)
+ if (state.ls_status != DLADM_STATUS_OK) {
+ if (optind == (argc - 1)) {
+ warn_dlerr(state.ls_status,
+ "show-linkprop failed for %s", argv[optind]);
+ }
exit(EXIT_FAILURE);
+ }
}
-static void
-show_linkprop_onelink(void *arg, const char *link)
+static int
+show_linkprop_onelink(datalink_id_t linkid, void *arg)
{
int i;
- int retval;
char *buf;
- dladm_status_t status;
+ uint32_t flags;
prop_list_t *proplist = NULL;
- show_linkprop_state_t *statep;
- const char *savep;
- dlpi_handle_t dh;
+ show_linkprop_state_t *statep = arg;
+ dlpi_handle_t dh = NULL;
+
+ statep->ls_status = DLADM_STATUS_OK;
+
+ if (dladm_datalink_id2info(linkid, &flags, NULL, NULL, statep->ls_link,
+ MAXLINKNAMELEN) != DLADM_STATUS_OK) {
+ statep->ls_status = DLADM_STATUS_NOTFOUND;
+ return (DLADM_WALK_CONTINUE);
+ }
+
+ if ((statep->ls_persist && !(flags & DLADM_OPT_PERSIST)) ||
+ (!statep->ls_persist && !(flags & DLADM_OPT_ACTIVE))) {
+ statep->ls_status = DLADM_STATUS_BADARG;
+ return (DLADM_WALK_CONTINUE);
+ }
- statep = (show_linkprop_state_t *)arg;
- savep = statep->ls_link;
- statep->ls_link = link;
proplist = statep->ls_proplist;
/*
@@ -2580,58 +3738,55 @@ show_linkprop_onelink(void *arg, const char *link)
* automatically scans for APs and does other slow operations. Thus,
* if there are no open links, the retrieval of link properties
* (below) will proceed slowly unless we hold the link open.
+ *
+ * Note that failure of dlpi_open() does not necessarily mean invalid
+ * link properties, because dlpi_open() may fail because of incorrect
+ * autopush configuration. Therefore, we ingore the return value of
+ * dlpi_open().
*/
- if ((retval = dlpi_open(link, &dh, 0)) != DLPI_SUCCESS) {
- warn("cannot open %s: %s", link, dlpi_strerror(retval));
- statep->ls_status = DLADM_STATUS_NOTFOUND;
- return;
- }
+ if (!statep->ls_persist)
+ (void) dlpi_open(statep->ls_link, &dh, 0);
- buf = malloc((sizeof (char *) + DLADM_PROP_VAL_MAX) * MAX_PROP_VALS +
- MAX_PROP_LINE);
+ buf = malloc((sizeof (char *) + DLADM_PROP_VAL_MAX) *
+ DLADM_MAX_PROP_VALCNT + MAX_PROP_LINE);
if (buf == NULL)
die("insufficient memory");
statep->ls_propvals = (char **)(void *)buf;
- for (i = 0; i < MAX_PROP_VALS; i++) {
- statep->ls_propvals[i] = buf + sizeof (char *) * MAX_PROP_VALS +
+ for (i = 0; i < DLADM_MAX_PROP_VALCNT; i++) {
+ statep->ls_propvals[i] = buf +
+ sizeof (char *) * DLADM_MAX_PROP_VALCNT +
i * DLADM_PROP_VAL_MAX;
}
statep->ls_line = buf +
- (sizeof (char *) + DLADM_PROP_VAL_MAX) * MAX_PROP_VALS;
+ (sizeof (char *) + DLADM_PROP_VAL_MAX) * DLADM_MAX_PROP_VALCNT;
if (proplist != NULL) {
- for (i = 0; i < proplist->pl_count; i++)
- (void) show_linkprop(statep,
- proplist->pl_info[i].pi_name);
+ for (i = 0; i < proplist->pl_count; i++) {
+ (void) show_linkprop(linkid,
+ proplist->pl_info[i].pi_name, statep);
+ }
} else {
- status = dladm_walk_prop(link, statep, show_linkprop);
- if (status != DLADM_STATUS_OK)
- warn_dlerr(status, "show-linkprop failed for %s", link);
+ (void) dladm_walk_linkprop(linkid, statep, show_linkprop);
}
- dlpi_close(dh);
+ if (dh != NULL)
+ dlpi_close(dh);
free(buf);
- statep->ls_link = savep;
+ return (DLADM_WALK_CONTINUE);
}
static dladm_status_t
-set_linkprop_persist(const char *link, const char *prop_name, char **prop_val,
- uint_t val_cnt, boolean_t reset)
+set_linkprop_persist(datalink_id_t linkid, const char *prop_name,
+ char **prop_val, uint_t val_cnt, boolean_t reset)
{
dladm_status_t status;
- char *errprop;
- status = dladm_set_prop(link, prop_name, prop_val, val_cnt,
- DLADM_OPT_PERSIST, &errprop);
+ status = dladm_set_linkprop(linkid, prop_name, prop_val, val_cnt,
+ DLADM_OPT_PERSIST);
if (status != DLADM_STATUS_OK) {
- if (reset) {
- warn_dlerr(status, "cannot persistently reset link "
- "property '%s' on '%s'", errprop, link);
- } else {
- warn_dlerr(status, "cannot persistently set link "
- "property '%s' on '%s'", errprop, link);
- }
+ warn_dlerr(status, "cannot persistently %s link property",
+ reset ? "reset" : "set");
}
return (status);
}
@@ -2641,7 +3796,8 @@ set_linkprop(int argc, char **argv, boolean_t reset)
{
int i, option;
char errmsg[DLADM_STRSIZE];
- const char *link = NULL;
+ char *altroot = NULL;
+ datalink_id_t linkid;
prop_list_t *proplist = NULL;
boolean_t temp = B_FALSE;
dladm_status_t status = DLADM_STATUS_OK;
@@ -2658,11 +3814,7 @@ set_linkprop(int argc, char **argv, boolean_t reset)
temp = B_TRUE;
break;
case 'R':
- status = dladm_set_rootdir(optarg);
- if (status != DLADM_STATUS_OK) {
- die_dlerr(status, "invalid directory "
- "specified");
- }
+ altroot = optarg;
break;
default:
die_opterr(optopt, option);
@@ -2670,30 +3822,32 @@ set_linkprop(int argc, char **argv, boolean_t reset)
}
}
- if (optind == (argc - 1))
- link = argv[optind];
- else if (optind != argc)
+ /* get link name (required last argument) */
+ if (optind != (argc - 1))
usage();
- if (link == NULL)
- die("link name must be specified");
+ if (proplist == NULL && !reset)
+ die("link property must be specified");
- if (proplist == NULL) {
- char *errprop;
+ if (altroot != NULL) {
+ free_props(proplist);
+ altroot_cmd(altroot, argc, argv);
+ }
- if (!reset)
- die("link property must be specified");
+ status = dladm_name2info(argv[optind], &linkid, NULL, NULL, NULL);
+ if (status != DLADM_STATUS_OK)
+ die_dlerr(status, "link %s is not valid", argv[optind]);
- status = dladm_set_prop(link, NULL, NULL, 0, DLADM_OPT_TEMP,
- &errprop);
- if (status != DLADM_STATUS_OK) {
- warn_dlerr(status, "cannot reset link property '%s' "
- "on '%s'", errprop, link);
+ if (proplist == NULL) {
+ if ((status = dladm_set_linkprop(linkid, NULL, NULL, 0,
+ DLADM_OPT_ACTIVE)) != DLADM_STATUS_OK) {
+ warn_dlerr(status, "cannot reset link property "
+ "on '%s'", argv[optind]);
}
if (!temp) {
dladm_status_t s;
- s = set_linkprop_persist(link, NULL, NULL, 0, reset);
+ s = set_linkprop_persist(linkid, NULL, NULL, 0, reset);
if (s != DLADM_STATUS_OK)
status = s;
}
@@ -2719,11 +3873,11 @@ set_linkprop(int argc, char **argv, boolean_t reset)
continue;
}
}
- s = dladm_set_prop(link, pip->pi_name, val, count,
- DLADM_OPT_TEMP, NULL);
+ s = dladm_set_linkprop(linkid, pip->pi_name, val, count,
+ DLADM_OPT_ACTIVE);
if (s == DLADM_STATUS_OK) {
if (!temp) {
- s = set_linkprop_persist(link,
+ s = set_linkprop_persist(linkid,
pip->pi_name, val, count, reset);
if (s != DLADM_STATUS_OK)
status = s;
@@ -2739,28 +3893,36 @@ set_linkprop(int argc, char **argv, boolean_t reset)
int j;
char *ptr, *lim;
char **propvals = NULL;
- uint_t valcnt = MAX_PROP_VALS;
+ uint_t valcnt = DLADM_MAX_PROP_VALCNT;
ptr = malloc((sizeof (char *) +
- DLADM_PROP_VAL_MAX) * MAX_PROP_VALS +
+ DLADM_PROP_VAL_MAX) * DLADM_MAX_PROP_VALCNT +
MAX_PROP_LINE);
propvals = (char **)(void *)ptr;
if (propvals == NULL)
die("insufficient memory");
- for (j = 0; j < MAX_PROP_VALS; j++) {
+ for (j = 0; j < DLADM_MAX_PROP_VALCNT; j++) {
propvals[j] = ptr + sizeof (char *) *
- MAX_PROP_VALS +
+ DLADM_MAX_PROP_VALCNT +
j * DLADM_PROP_VAL_MAX;
}
- s = dladm_get_prop(link, DLADM_PROP_VAL_MODIFIABLE,
- pip->pi_name, propvals, &valcnt);
+ s = dladm_get_linkprop(linkid,
+ DLADM_PROP_VAL_MODIFIABLE, pip->pi_name, propvals,
+ &valcnt);
+
+ if (s != DLADM_STATUS_OK) {
+ warn_dlerr(status, "cannot set link property "
+ "'%s' on '%s'", pip->pi_name, argv[optind]);
+ free(propvals);
+ break;
+ }
ptr = errmsg;
lim = ptr + DLADM_STRSIZE;
*ptr = '\0';
- for (j = 0; j < valcnt && s == DLADM_STATUS_OK; j++) {
+ for (j = 0; j < valcnt; j++) {
ptr += snprintf(ptr, lim - ptr, "%s,",
propvals[j]);
if (ptr >= lim)
@@ -2778,10 +3940,10 @@ set_linkprop(int argc, char **argv, boolean_t reset)
default:
if (reset) {
warn_dlerr(status, "cannot reset link property "
- "'%s' on '%s'", pip->pi_name, link);
+ "'%s' on '%s'", pip->pi_name, argv[optind]);
} else {
warn_dlerr(status, "cannot set link property "
- "'%s' on '%s'", pip->pi_name, link);
+ "'%s' on '%s'", pip->pi_name, argv[optind]);
}
break;
}
@@ -3097,7 +4259,7 @@ do_create_secobj(int argc, char **argv)
}
status = dladm_set_secobj(obj_name, class, obj_val, obj_len,
- DLADM_OPT_CREATE | DLADM_OPT_TEMP);
+ DLADM_OPT_CREATE | DLADM_OPT_ACTIVE);
if (status != DLADM_STATUS_OK) {
die_dlerr(status, "could not create secure object '%s'",
obj_name);
@@ -3161,7 +4323,7 @@ do_delete_secobj(int argc, char **argv)
die("authorization '%s' is required", LINK_SEC_AUTH);
for (i = 0; i < sp->s_nfields; i++) {
- status = dladm_unset_secobj(sp->s_fields[i], DLADM_OPT_TEMP);
+ status = dladm_unset_secobj(sp->s_fields[i], DLADM_OPT_ACTIVE);
if (!temp) {
pstatus = dladm_unset_secobj(sp->s_fields[i],
DLADM_OPT_PERSIST);
@@ -3301,15 +4463,24 @@ do_show_secobj(int argc, char **argv)
die_dlerr(status, "show-secobj");
}
+/*ARGSUSED*/
+static int
+i_dladm_init_linkprop(datalink_id_t linkid, void *arg)
+{
+ (void) dladm_init_linkprop(linkid);
+ return (DLADM_WALK_CONTINUE);
+}
+
/* ARGSUSED */
static void
do_init_linkprop(int argc, char **argv)
{
- dladm_status_t status;
-
- status = dladm_init_linkprop();
- if (status != DLADM_STATUS_OK)
- die_dlerr(status, "link property initialization failed");
+ /*
+ * linkprops of links of other classes have been initialized as a
+ * part of the dladm up-xxx operation.
+ */
+ (void) dladm_walk_datalink_id(i_dladm_init_linkprop, NULL,
+ DATALINK_CLASS_PHYS, DATALINK_ANY_MEDIATYPE, DLADM_OPT_PERSIST);
}
/* ARGSUSED */
@@ -3323,6 +4494,68 @@ do_init_secobj(int argc, char **argv)
die_dlerr(status, "secure object initialization failed");
}
+/*
+ * "-R" option support. It is used for live upgrading. Append dladm commands
+ * to a upgrade script which will be run when the alternative root boots up:
+ *
+ * - If the dlmgmtd door file exists on the alternative root, append dladm
+ * commands to the <altroot>/var/svc/profile/upgrade_datalink script. This
+ * script will be run as part of the network/physical service. We cannot defer
+ * this to /var/svc/profile/upgrade because then the configuration will not
+ * be able to take effect before network/physical plumbs various interfaces.
+ *
+ * - If the dlmgmtd door file does not exist on the alternative root, append
+ * dladm commands to the <altroot>/var/svc/profile/upgrade script, which will
+ * be run in the manifest-import service.
+ *
+ * Note that the SMF team is considering to move the manifest-import service
+ * to be run at the very begining of boot. Once that is done, the need for
+ * the /var/svc/profile/upgrade_datalink script will not exist any more.
+ */
+static void
+altroot_cmd(char *altroot, int argc, char *argv[])
+{
+ char path[MAXPATHLEN];
+ struct stat stbuf;
+ FILE *fp;
+ int i;
+
+ /*
+ * Check for the existence of the dlmgmtd door file, and determine
+ * the name of script file.
+ */
+ (void) snprintf(path, MAXPATHLEN, "/%s/%s", altroot, DLMGMT_DOOR);
+ if (stat(path, &stbuf) < 0) {
+ (void) snprintf(path, MAXPATHLEN, "/%s/%s", altroot,
+ SMF_UPGRADE_FILE);
+ } else {
+ (void) snprintf(path, MAXPATHLEN, "/%s/%s", altroot,
+ SMF_UPGRADEDATALINK_FILE);
+ }
+
+ if ((fp = fopen(path, "a+")) == NULL)
+ die("operation not supported on %s", altroot);
+
+ (void) fprintf(fp, "/sbin/dladm ");
+ for (i = 0; i < argc; i++) {
+ /*
+ * Directly write to the file if it is not the "-R <altroot>"
+ * option. In which case, skip it.
+ */
+ if (strcmp(argv[i], "-R") != 0)
+ (void) fprintf(fp, "%s ", argv[i]);
+ else
+ i ++;
+ }
+ (void) fprintf(fp, "%s\n", SMF_DLADM_UPGRADE_MSG);
+ (void) fclose(fp);
+ exit(0);
+}
+
+/*
+ * Convert the string to an integer. Note that the string must not have any
+ * trailing non-integer characters.
+ */
static boolean_t
str2int(const char *str, int *valp)
{