summaryrefslogtreecommitdiff
path: root/usr/src
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src')
-rw-r--r--usr/src/cmd/dladm/dladm.c2680
-rw-r--r--usr/src/cmd/dladm/dladm.xcl48
-rw-r--r--usr/src/lib/libdladm/Makefile.com3
-rw-r--r--usr/src/lib/libdladm/common/libdladm.c2
-rw-r--r--usr/src/lib/libdladm/common/libdllink.c98
-rw-r--r--usr/src/lib/libdladm/common/libdllink.h10
-rw-r--r--usr/src/lib/libdladm/common/libdlwlan.c30
-rw-r--r--usr/src/lib/libdladm/common/linkprop.c793
-rw-r--r--usr/src/lib/libdladm/common/mapfile-vers4
-rw-r--r--usr/src/lib/libdlpi/common/libdlpi.c12
-rw-r--r--usr/src/uts/common/io/aggr/aggr_grp.c13
-rw-r--r--usr/src/uts/common/io/bge/bge_chip2.c29
-rw-r--r--usr/src/uts/common/io/bge/bge_impl.h22
-rw-r--r--usr/src/uts/common/io/bge/bge_kstats.c27
-rw-r--r--usr/src/uts/common/io/bge/bge_main2.c516
-rw-r--r--usr/src/uts/common/io/bge/bge_ndd.c73
-rw-r--r--usr/src/uts/common/io/bge/bge_recv2.c8
-rw-r--r--usr/src/uts/common/io/dld/dld_drv.c74
-rw-r--r--usr/src/uts/common/io/dld/dld_proto.c12
-rw-r--r--usr/src/uts/common/io/dld/dld_str.c41
-rw-r--r--usr/src/uts/common/io/gld.c42
-rw-r--r--usr/src/uts/common/io/ipw/ipw2100.c1
-rw-r--r--usr/src/uts/common/io/ipw/ipw2100_impl.h7
-rw-r--r--usr/src/uts/common/io/mac/mac.c72
-rw-r--r--usr/src/uts/common/io/nge/nge_kstats.c25
-rw-r--r--usr/src/uts/common/io/strplumb.c1
-rw-r--r--usr/src/uts/common/io/vnic/vnic_dev.c5
-rw-r--r--usr/src/uts/common/sys/dld.h64
-rw-r--r--usr/src/uts/common/sys/mac.h31
-rw-r--r--usr/src/uts/common/sys/mac_impl.h2
-rw-r--r--usr/src/uts/common/xen/io/xnbo.c9
-rw-r--r--usr/src/uts/intel/mac/Makefile8
-rw-r--r--usr/src/uts/sparc/mac/Makefile8
-rw-r--r--usr/src/uts/sun/io/hme.c4
34 files changed, 3748 insertions, 1026 deletions
diff --git a/usr/src/cmd/dladm/dladm.c b/usr/src/cmd/dladm/dladm.c
index 22cc5c515e..0de78dfd63 100644
--- a/usr/src/cmd/dladm/dladm.c
+++ b/usr/src/cmd/dladm/dladm.c
@@ -56,8 +56,10 @@
#include <libinetutil.h>
#include <bsm/adt.h>
#include <bsm/adt_event.h>
+#include <stddef.h>
#define AGGR_DRV "aggr"
+#define STR_UNDEF_VAL "--"
#define MAXPORT 256
#define BUFLEN(lim, ptr) (((lim) > (ptr)) ? ((lim) - (ptr)) : 0)
#define MAXLINELEN 1024
@@ -65,6 +67,132 @@
#define SMF_UPGRADEDATALINK_FILE "/var/svc/profile/upgrade_datalink"
#define SMF_DLADM_UPGRADE_MSG " # added by dladm(1M)"
+#define CMD_TYPE_ANY 0xffffffff
+#define WIFI_CMD_SCAN 0x00000001
+#define WIFI_CMD_SHOW 0x00000002
+#define WIFI_CMD_ALL (WIFI_CMD_SCAN | WIFI_CMD_SHOW)
+
+/*
+ * data structures and routines for printing output.
+ * All non-parseable output is assumed to be in a columnar format.
+ * Parseable output will be printed as <pf_header>="<value>"
+ *
+ * Each sub-command is associated with a global array of pointers,
+ * print_field_t *fields[], where the print_field_t contains information
+ * about the format in which the output is to be printed.
+ *
+ * Sub-commands may be implemented in one of two ways:
+ * (i) the implementation could get all field values into a character
+ * buffer, with pf_offset containing the offset (for pf_name) within
+ * the buffer. The sub-command would make the needed system calls
+ * to obtain all possible column values and then invoke the
+ * dladm_print_field() function to print the specific fields
+ * requested in the command line. See the comments for dladm_print_field
+ * for further details.
+ * (ii) Alternatively, each fields[i] entry could store a pf_index value
+ * that uniquely identifies the column to be printed. The implementation
+ * of the sub-command would then invoke dladm_print_output() with a
+ * callback function whose semantics are described below (see comments
+ * for dladm_print_output())
+ *
+ * Thus, an implementation of a sub-command must provide the following:
+ *
+ * static print_field_t sub_command_fields[] = {
+ * {<name>, <header>,<field width>, <offset_or_index>, cmdtype},
+ * :
+ * {<name>, <header>,<field width>, <offset_or_index>, cmdtype}
+ * };
+ *
+ * #define SUB_COMMAND_MAX_FIELDS sizeof \
+ * (sub_comand_fields) / sizeof (print_field_t))
+ *
+ * print_state_t sub_command_print_state;
+ *
+ * The function that parses command line arguments (typically
+ * do_sub_command()) should then contain an invocation like:
+ *
+ * fields = parse_output_fields(fields_str, sub_command_fields,
+ * SUB_COMMAND_MAX_FIELDS, CMD_TYPE_ANY, &nfields);
+ *
+ * and store the resulting fields and nfields value in a print_state_t
+ * structure tracked for the command.
+ *
+ * sub_command_print_state.ps_fields = fields;
+ * sub_command_print_state.ps_nfields = nfields;
+ *
+ * To print the column header for the output, the print_header()
+ * function must then be invoked by do_sub_command().
+ *
+ * Then if method (i) is used for the sub_command, the do_sub_command()
+ * function should make the necessary system calls to fill up the buffer
+ * and then invoke dladm_print_field(). An example of this method is
+ * the implementation of do_show_link() and show_link();
+ *
+ * If method (ii) is used, do_sub_command should invoke dladm_print_output()
+ * with a callback function that will be called for each field to be printed.
+ * The callback function will be passed a pointer to the print_field_t
+ * for the field, and the pf_index may then be used to identify the
+ * system call required to find the value to be printed. An example of
+ * this implementation may be found in the do_show_dev() and print_dev()
+ * invocation.
+ */
+
+typedef struct print_field_s {
+ const char *pf_name; /* name of column to be printed */
+ const char *pf_header; /* header for this column */
+ uint_t pf_width;
+ union {
+ uint_t _pf_index; /* private index for sub-command */
+ size_t _pf_offset;
+ }_pf_un;
+#define pf_index _pf_un._pf_index
+#define pf_offset _pf_un._pf_offset;
+ uint_t pf_cmdtype;
+} print_field_t;
+
+/*
+ * The state of the output is tracked in a print_state_t structure.
+ * Each ps_fields[i] entry points at the global print_field_t array for
+ * the sub-command, where ps_nfields is the number of requested fields.
+ */
+typedef struct print_state_s {
+ print_field_t **ps_fields;
+ uint_t ps_nfields;
+ boolean_t ps_lastfield;
+ uint_t ps_overflow;
+} print_state_t;
+
+typedef char *(*print_callback_t)(print_field_t *, void *);
+static print_field_t **parse_output_fields(char *, print_field_t *, int,
+ uint_t, uint_t *);
+/*
+ * print the header for the output
+ */
+static void print_header(print_state_t *);
+static void print_field(print_state_t *, print_field_t *, const char *,
+ boolean_t);
+
+/*
+ * to print output values, call dladm_print_output with a callback
+ * function (*func)() that should parse the args and return an
+ * unformatted character buffer with the value to be printed.
+ *
+ * dladm_print_output() prints the character buffer using the formatting
+ * information provided in the print_field_t for that column.
+ */
+static void dladm_print_output(print_state_t *, boolean_t,
+ print_callback_t, void *);
+
+/*
+ * helper function that, when invoked as dladm_print_field(pf, buf)
+ * prints string which is offset by pf->pf_offset within buf
+ */
+static char *dladm_print_field(print_field_t *, void *);
+
+
+#define MAX_FIELD_LEN 32
+
+
typedef struct pktsum_s {
uint64_t ipackets;
uint64_t opackets;
@@ -78,21 +206,25 @@ typedef struct show_state {
boolean_t ls_firstonly;
boolean_t ls_donefirst;
pktsum_t ls_prevstats;
- boolean_t ls_parseable;
uint32_t ls_flags;
dladm_status_t ls_status;
+ print_state_t ls_print;
+ boolean_t ls_parseable;
+ boolean_t ls_printheader;
} show_state_t;
typedef struct show_grp_state {
+ pktsum_t gs_prevstats[MAXPORT];
+ uint32_t gs_flags;
+ dladm_status_t gs_status;
+ boolean_t gs_parseable;
boolean_t gs_lacp;
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;
+ boolean_t gs_printheader;
+ print_state_t gs_print;
} show_grp_state_t;
typedef void cmdfunc_t(int, char **);
@@ -107,13 +239,14 @@ 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 cmdfunc_t do_show_ether;
static void altroot_cmd(char *, int, char **);
static int show_linkprop_onelink(datalink_id_t, void *);
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 void dev_stats(const char *dev, uint32_t, char *, show_state_t *);
static int get_one_kstat(const char *, const char *, uint8_t,
void *, boolean_t);
@@ -125,6 +258,16 @@ static void stats_diff(pktsum_t *, pktsum_t *, pktsum_t *);
static const char *get_linkstate(const char *, boolean_t, char *);
static const char *get_linkduplex(const char *, boolean_t, char *);
+static int show_etherprop(datalink_id_t, void *);
+static void show_ether_xprop(datalink_id_t, void *);
+static boolean_t get_speed_duplex(datalink_id_t, const char *, char *,
+ char *, boolean_t);
+static char *pause_str(int, int);
+static boolean_t link_is_ether(const char *, datalink_id_t *);
+
+#define IS_FDX 0x10
+#define IS_HDX 0x01
+
static boolean_t str2int(const char *, int *);
static void die(const char *, ...);
static void die_optdup(int);
@@ -155,6 +298,7 @@ static cmd_t cmds[] = {
{ "show-linkprop", do_show_linkprop },
{ "set-linkprop", do_set_linkprop },
{ "reset-linkprop", do_reset_linkprop },
+ { "show-ether", do_show_ether },
{ "create-secobj", do_create_secobj },
{ "delete-secobj", do_delete_secobj },
{ "show-secobj", do_show_secobj },
@@ -173,6 +317,7 @@ static cmd_t cmds[] = {
static const struct option lopts[] = {
{"vlan-id", required_argument, 0, 'v'},
+ {"output", required_argument, 0, 'o'},
{"dev", required_argument, 0, 'd'},
{"policy", required_argument, 0, 'P'},
{"lacp-mode", required_argument, 0, 'L'},
@@ -190,6 +335,7 @@ static const struct option show_lopts[] = {
{"interval", required_argument, 0, 'i'},
{"parseable", no_argument, 0, 'p'},
{"extended", no_argument, 0, 'x'},
+ {"output", required_argument, 0, 'o'},
{"persistent", no_argument, 0, 'P'},
{"lacp", no_argument, 0, 'L'},
{ 0, 0, 0, 0 }
@@ -197,6 +343,7 @@ static const struct option show_lopts[] = {
static const struct option prop_longopts[] = {
{"temporary", no_argument, 0, 't' },
+ {"output", required_argument, 0, 'o' },
{"root-dir", required_argument, 0, 'R' },
{"prop", required_argument, 0, 'p' },
{"parseable", no_argument, 0, 'c' },
@@ -222,6 +369,418 @@ static const struct option wifi_longopts[] = {
{"file", required_argument, 0, 'f' },
{ 0, 0, 0, 0 }
};
+static const struct option showeth_lopts[] = {
+ {"parseable", no_argument, 0, 'p' },
+ {"extended", no_argument, 0, 'x' },
+ {"output", required_argument, 0, 'o' },
+ { 0, 0, 0, 0 }
+};
+
+/*
+ * structures for 'dladm show-ether'
+ */
+typedef struct ether_fields_buf_s
+{
+ char eth_link[15];
+ char eth_ptype[8];
+ char eth_state[8];
+ char eth_autoneg[5];
+ char eth_spdx[31];
+ char eth_pause[6];
+ char eth_rem_fault[16];
+} ether_fields_buf_t;
+
+static print_field_t ether_fields[] = {
+/* name, header, field width, offset, cmdtype */
+{ "link", "LINK", 15,
+ offsetof(ether_fields_buf_t, eth_link), CMD_TYPE_ANY},
+{ "ptype", "PTYPE", 8,
+ offsetof(ether_fields_buf_t, eth_ptype), CMD_TYPE_ANY},
+{ "state", "STATE", 8,
+ offsetof(ether_fields_buf_t, eth_state), CMD_TYPE_ANY},
+{ "auto", "AUTO", 5,
+ offsetof(ether_fields_buf_t, eth_autoneg), CMD_TYPE_ANY},
+{ "speed-duplex", "SPEED-DUPLEX", 31,
+ offsetof(ether_fields_buf_t, eth_spdx), CMD_TYPE_ANY},
+{ "pause", "PAUSE", 6,
+ offsetof(ether_fields_buf_t, eth_pause), CMD_TYPE_ANY},
+{ "rem_fault", "REM_FAULT", 16,
+ offsetof(ether_fields_buf_t, eth_rem_fault), CMD_TYPE_ANY}}
+;
+#define ETHER_MAX_FIELDS (sizeof (ether_fields) / sizeof (print_field_t))
+
+typedef struct print_ether_state {
+ const char *es_link;
+ boolean_t es_parseable;
+ boolean_t es_header;
+ boolean_t es_extended;
+ print_state_t es_print;
+} print_ether_state_t;
+
+/*
+ * structures for 'dladm show-dev'.
+ */
+typedef enum {
+ DEV_LINK,
+ DEV_STATE,
+ DEV_SPEED,
+ DEV_DUPLEX
+} dev_field_index_t;
+
+static print_field_t dev_fields[] = {
+/* name, header, field width, index, cmdtype */
+{ "link", "LINK", 15, DEV_LINK, CMD_TYPE_ANY},
+{ "state", "STATE", 6, DEV_STATE, CMD_TYPE_ANY},
+{ "speed", "SPEED", 8, DEV_SPEED, CMD_TYPE_ANY},
+{ "duplex", "DUPLEX", 8, DEV_DUPLEX, CMD_TYPE_ANY}}
+;
+#define DEV_MAX_FIELDS (sizeof (dev_fields) / sizeof (print_field_t))
+
+/*
+ * structures for 'dladm show-dev -s' (print statistics)
+ */
+typedef enum {
+ DEVS_LINK,
+ DEVS_IPKTS,
+ DEVS_RBYTES,
+ DEVS_IERRORS,
+ DEVS_OPKTS,
+ DEVS_OBYTES,
+ DEVS_OERRORS
+} devs_field_index_t;
+
+static print_field_t devs_fields[] = {
+/* name, header, field width, index, cmdtype */
+{ "link", "LINK", 15, DEVS_LINK, CMD_TYPE_ANY},
+{ "ipackets", "IPACKETS", 10, DEVS_IPKTS, CMD_TYPE_ANY},
+{ "rbytes", "RBYTES", 8, DEVS_RBYTES, CMD_TYPE_ANY},
+{ "ierrors", "IERRORS", 10, DEVS_IERRORS, CMD_TYPE_ANY},
+{ "opackets", "OPACKETS", 12, DEVS_OPKTS, CMD_TYPE_ANY},
+{ "obytes", "OBYTES", 12, DEVS_OBYTES, CMD_TYPE_ANY},
+{ "oerrors", "OERRORS", 8, DEVS_OERRORS, CMD_TYPE_ANY}}
+;
+#define DEVS_MAX_FIELDS (sizeof (devs_fields) / sizeof (print_field_t))
+typedef struct dev_args_s {
+ char *devs_link;
+ pktsum_t *devs_psum;
+} dev_args_t;
+static char *print_dev_stats(print_field_t *, void *);
+static char *print_dev(print_field_t *, void *);
+
+/*
+ * buffer used by print functions for show-{link,phys,vlan} commands.
+ */
+typedef struct link_fields_buf_s {
+ char link_name[MAXLINKNAMELEN];
+ char link_class[DLADM_STRSIZE];
+ char link_mtu[6];
+ char link_state[DLADM_STRSIZE];
+ char link_over[MAXLINKNAMELEN];
+ char link_phys_state[6];
+ char link_phys_media[DLADM_STRSIZE];
+ char link_phys_speed[DLADM_STRSIZE];
+ char link_phys_duplex[DLPI_LINKNAME_MAX];
+ char link_phys_device[DLPI_LINKNAME_MAX];
+ char link_flags[6];
+ char link_vlan_vid[6];
+} link_fields_buf_t;
+
+/*
+ * structures for 'dladm show-link'
+ */
+static print_field_t link_fields[] = {
+/* name, header, field width, offset, cmdtype */
+{ "link", "LINK", 11,
+ offsetof(link_fields_buf_t, link_name), CMD_TYPE_ANY},
+{ "class", "CLASS", 8,
+ offsetof(link_fields_buf_t, link_class), CMD_TYPE_ANY},
+{ "mtu", "MTU", 6,
+ offsetof(link_fields_buf_t, link_mtu), CMD_TYPE_ANY},
+{ "state", "STATE", 8,
+ offsetof(link_fields_buf_t, link_state), CMD_TYPE_ANY},
+{ "over", "OVER", DLPI_LINKNAME_MAX,
+ offsetof(link_fields_buf_t, link_over), CMD_TYPE_ANY}}
+;
+#define DEV_LINK_FIELDS (sizeof (link_fields) / sizeof (print_field_t))
+
+/*
+ * structures for 'dladm show-aggr'
+ */
+typedef struct laggr_fields_buf_s {
+ char laggr_name[DLPI_LINKNAME_MAX];
+ char laggr_policy[9];
+ char laggr_addrpolicy[ETHERADDRL * 3 + 3];
+ char laggr_lacpactivity[14];
+ char laggr_lacptimer[DLADM_STRSIZE];
+ char laggr_flags[7];
+} laggr_fields_buf_t;
+
+typedef struct laggr_args_s {
+ int laggr_lport; /* -1 indicates the aggr itself */
+ const char *laggr_link;
+ dladm_aggr_grp_attr_t *laggr_ginfop;
+ dladm_status_t *laggr_status;
+ pktsum_t *laggr_pktsumtot; /* -s only */
+ pktsum_t *laggr_prevstats; /* -s only */
+ boolean_t laggr_parseable;
+} laggr_args_t;
+
+static print_field_t laggr_fields[] = {
+/* name, header, field width, offset, cmdtype */
+{ "link", "LINK", 15,
+ offsetof(laggr_fields_buf_t, laggr_name), CMD_TYPE_ANY},
+{ "policy", "POLICY", 8,
+ offsetof(laggr_fields_buf_t, laggr_policy), CMD_TYPE_ANY},
+{ "addrpolicy", "ADDRPOLICY", ETHERADDRL * 3 + 2,
+ offsetof(laggr_fields_buf_t, laggr_addrpolicy), CMD_TYPE_ANY},
+{ "lacpactivity", "LACPACTIVITY", 13,
+ offsetof(laggr_fields_buf_t, laggr_lacpactivity), CMD_TYPE_ANY},
+{ "lacptimer", "LACPTIMER", 11,
+ offsetof(laggr_fields_buf_t, laggr_lacptimer), CMD_TYPE_ANY},
+{ "flags", "FLAGS", 7,
+ offsetof(laggr_fields_buf_t, laggr_flags), CMD_TYPE_ANY}}
+;
+#define LAGGR_MAX_FIELDS (sizeof (laggr_fields) / sizeof (print_field_t))
+
+/*
+ * structures for 'dladm show-aggr -x'.
+ */
+typedef enum {
+ AGGR_X_LINK,
+ AGGR_X_PORT,
+ AGGR_X_SPEED,
+ AGGR_X_DUPLEX,
+ AGGR_X_STATE,
+ AGGR_X_ADDRESS,
+ AGGR_X_PORTSTATE
+} aggr_x_field_index_t;
+
+static print_field_t aggr_x_fields[] = {
+/* name, header, field width, index, cmdtype */
+{ "link", "LINK", 11, AGGR_X_LINK, CMD_TYPE_ANY},
+{ "port", "PORT", 14, AGGR_X_PORT, CMD_TYPE_ANY},
+{ "speed", "SPEED", 4, AGGR_X_SPEED, CMD_TYPE_ANY},
+{ "duplex", "DUPLEX", 9, AGGR_X_DUPLEX, CMD_TYPE_ANY},
+{ "state", "STATE", 9, AGGR_X_STATE, CMD_TYPE_ANY},
+{ "address", "ADDRESS", 18, AGGR_X_ADDRESS, CMD_TYPE_ANY},
+{ "portstate", "PORTSTATE", 15, AGGR_X_PORTSTATE, CMD_TYPE_ANY}}
+;
+#define AGGR_X_MAX_FIELDS \
+ (sizeof (aggr_x_fields) / sizeof (print_field_t))
+
+/*
+ * structures for 'dladm show-aggr -s'.
+ */
+typedef enum {
+ AGGR_S_LINK,
+ AGGR_S_PORT,
+ AGGR_S_IPKTS,
+ AGGR_S_RBYTES,
+ AGGR_S_OPKTS,
+ AGGR_S_OBYTES,
+ AGGR_S_IPKTDIST,
+ AGGR_S_OPKTDIST
+} aggr_s_field_index_t;
+
+static print_field_t aggr_s_fields[] = {
+/* name, header, field width, index, cmdtype */
+{ "link", "LINK", 11, AGGR_S_LINK,
+ CMD_TYPE_ANY},
+{ "port", "PORT", 9, AGGR_S_PORT,
+ CMD_TYPE_ANY},
+{ "ipackets", "IPACKETS", 7, AGGR_S_IPKTS,
+ CMD_TYPE_ANY},
+{ "rbytes", "RBYTES", 7, AGGR_S_RBYTES,
+ CMD_TYPE_ANY},
+{ "opackets", "OPACKETS", 7, AGGR_S_OPKTS,
+ CMD_TYPE_ANY},
+{ "obytes", "OBYTES", 7, AGGR_S_OBYTES,
+ CMD_TYPE_ANY},
+{ "ipktdist", "IPKTDIST", 8, AGGR_S_IPKTDIST,
+ CMD_TYPE_ANY},
+{ "opktdist", "OPKTDIST", 14, AGGR_S_OPKTDIST,
+ CMD_TYPE_ANY}}
+;
+#define AGGR_S_MAX_FIELDS \
+ (sizeof (aggr_l_fields) / sizeof (print_field_t))
+
+/*
+ * structures for 'dladm show-dev -L'.
+ */
+typedef enum {
+ AGGR_L_LINK,
+ AGGR_L_PORT,
+ AGGR_L_AGGREGATABLE,
+ AGGR_L_SYNC,
+ AGGR_L_COLL,
+ AGGR_L_DIST,
+ AGGR_L_DEFAULTED,
+ AGGR_L_EXPIRED
+} aggr_l_field_index_t;
+
+static print_field_t aggr_l_fields[] = {
+/* name, header, field width, index, cmdtype */
+{ "link", "LINK", 11, AGGR_L_LINK,
+ CMD_TYPE_ANY},
+{ "port", "PORT", 12, AGGR_L_PORT,
+ CMD_TYPE_ANY},
+{ "aggregatable", "AGGREGATABLE", 12, AGGR_L_AGGREGATABLE,
+ CMD_TYPE_ANY},
+{ "sync", "SYNC", 4, AGGR_L_SYNC,
+ CMD_TYPE_ANY},
+{ "coll", "COLL", 4, AGGR_L_COLL,
+ CMD_TYPE_ANY},
+{ "dist", "DIST", 4, AGGR_L_DIST,
+ CMD_TYPE_ANY},
+{ "defaulted", "DEFAULTED", 9, AGGR_L_DEFAULTED,
+ CMD_TYPE_ANY},
+{ "expired", "EXPIRED", 14, AGGR_L_EXPIRED,
+ CMD_TYPE_ANY}}
+;
+#define AGGR_L_MAX_FIELDS \
+ (sizeof (aggr_l_fields) / sizeof (print_field_t))
+
+/*
+ * structures for 'dladm show-phys'
+ */
+
+static print_field_t phys_fields[] = {
+/* name, header, field width, offset, cmdtype */
+{ "link", "LINK", 12,
+ offsetof(link_fields_buf_t, link_name), CMD_TYPE_ANY},
+{ "media", "MEDIA", 20,
+ offsetof(link_fields_buf_t, link_phys_media), CMD_TYPE_ANY},
+{ "state", "STATE", 10,
+ offsetof(link_fields_buf_t, link_phys_state), CMD_TYPE_ANY},
+{ "speed", "SPEED", 4,
+ offsetof(link_fields_buf_t, link_phys_speed), CMD_TYPE_ANY},
+{ "duplex", "DUPLEX", 9,
+ offsetof(link_fields_buf_t, link_phys_duplex), CMD_TYPE_ANY},
+{ "device", "DEVICE", 12,
+ offsetof(link_fields_buf_t, link_phys_device), CMD_TYPE_ANY},
+{ "flags", "FLAGS", 6,
+ offsetof(link_fields_buf_t, link_flags), CMD_TYPE_ANY}}
+;
+#define PHYS_MAX_FIELDS (sizeof (phys_fields) / sizeof (print_field_t))
+
+/*
+ * structures for 'dladm show-vlan'
+ */
+static print_field_t vlan_fields[] = {
+/* name, header, field width, offset, cmdtype */
+{ "link", "LINK", 15,
+ offsetof(link_fields_buf_t, link_name), CMD_TYPE_ANY},
+{ "vid", "VID", 8,
+ offsetof(link_fields_buf_t, link_vlan_vid), CMD_TYPE_ANY},
+{ "over", "OVER", 12,
+ offsetof(link_fields_buf_t, link_over), CMD_TYPE_ANY},
+{ "flags", "FLAGS", 6,
+ offsetof(link_fields_buf_t, link_flags), CMD_TYPE_ANY}}
+;
+#define VLAN_MAX_FIELDS (sizeof (vlan_fields) / sizeof (print_field_t))
+
+/*
+ * structures for 'dladm show-wifi'
+ */
+static print_field_t wifi_fields[] = {
+{ "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}}
+;
+
+static char *all_scan_wifi_fields =
+ "link,essid,bssid,sec,strength,mode,speed,bsstype";
+static char *all_show_wifi_fields =
+ "link,status,essid,sec,strength,mode,speed,auth,bssid,bsstype";
+static char *def_scan_wifi_fields =
+ "link,essid,bssid,sec,strength,mode,speed";
+static char *def_show_wifi_fields =
+ "link,status,essid,sec,strength,mode,speed";
+
+#define WIFI_MAX_FIELDS (sizeof (wifi_fields) / sizeof (print_field_t))
+
+/*
+ * structures for 'dladm show-linkprop'
+ */
+typedef enum {
+ LINKPROP_LINK,
+ LINKPROP_PROPERTY,
+ LINKPROP_VALUE,
+ LINKPROP_DEFAULT,
+ LINKPROP_POSSIBLE
+} linkprop_field_index_t;
+
+static print_field_t linkprop_fields[] = {
+/* name, header, field width, index, cmdtype */
+{ "link", "LINK", 12, LINKPROP_LINK, CMD_TYPE_ANY},
+{ "property", "PROPERTY", 15, LINKPROP_PROPERTY, CMD_TYPE_ANY},
+{ "value", "VALUE", 14, LINKPROP_VALUE, CMD_TYPE_ANY},
+{ "default", "DEFAULT", 14, LINKPROP_DEFAULT, CMD_TYPE_ANY},
+{ "possible", "POSSIBLE", 20, LINKPROP_POSSIBLE, CMD_TYPE_ANY}}
+;
+#define LINKPROP_MAX_FIELDS \
+ (sizeof (linkprop_fields) / sizeof (print_field_t))
+
+#define MAX_PROPS 32
+#define MAX_PROP_LINE 512
+
+typedef struct prop_info {
+ char *pi_name;
+ char *pi_val[DLADM_MAX_PROP_VALCNT];
+ uint_t pi_count;
+} prop_info_t;
+
+typedef struct prop_list {
+ prop_info_t pl_info[MAX_PROPS];
+ uint_t pl_count;
+ char *pl_buf;
+} prop_list_t;
+
+typedef struct show_linkprop_state {
+ char ls_link[MAXLINKNAMELEN];
+ char *ls_line;
+ char **ls_propvals;
+ prop_list_t *ls_proplist;
+ boolean_t ls_parseable;
+ boolean_t ls_persist;
+ boolean_t ls_header;
+ dladm_status_t ls_status;
+ dladm_status_t ls_retstatus;
+ print_state_t ls_print;
+} show_linkprop_state_t;
+
+typedef struct linkprop_args_s {
+ show_linkprop_state_t *ls_state;
+ char *ls_propname;
+ datalink_id_t ls_linkid;
+} linkprop_args_t;
+
+/*
+ * structures for 'dladm show-secobj'
+ */
+typedef struct secobj_fields_buf_s {
+ char ss_obj_name[DLADM_SECOBJ_VAL_MAX];
+ char ss_class[20];
+ char ss_val[30];
+} secobj_fields_buf_t;
+static print_field_t secobj_fields[] = {
+/* name, header, field width, offset, cmdtype */
+{ "object", "OBJECT", 20,
+ offsetof(secobj_fields_buf_t, ss_obj_name), CMD_TYPE_ANY},
+{ "class", "CLASS", 20,
+ offsetof(secobj_fields_buf_t, ss_class), CMD_TYPE_ANY},
+{ "value", "VALUE", 30,
+ offsetof(secobj_fields_buf_t, ss_val), CMD_TYPE_ANY}}
+;
+#define DEV_SOBJ_FIELDS (sizeof (secobj_fields) / sizeof (print_field_t))
static char *progname;
static sig_atomic_t signalled;
@@ -230,25 +789,28 @@ static void
usage(void)
{
(void) fprintf(stderr, gettext("usage: dladm <subcommand> <args> ...\n"
- "\tshow-link [-pP] [-s [-i <interval>]] [<link>]\n"
+ "\tshow-link [-pP] [-o <field>,..] [-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"
+ "\tshow-phys [-pP] [-o <field>,..] [<link>]\n"
+ "\tshow-dev [-p] [-o <field>,..] [-s [-i <interval>]] "
+ "[<dev>]\n"
"\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"
+ "\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\tshow-aggr [-pPLx] [-o <field>,..] [-s [-i <interval>]] "
+ "[<link>]\n"
"\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"
+ "\tshow-vlan [-pP] [-o <field>,..] [<link>]\n"
"\n"
"\tscan-wifi [-p] [-o <field>,...] [<link>]\n"
"\tconnect-wifi [-e <essid>] [-i <bssid>] [-k <key>,...]"
@@ -261,12 +823,15 @@ usage(void)
"\tset-linkprop [-t] [-R <root-dir>] -p <prop>=<value>[,...]"
" <name>\n"
"\treset-linkprop [-t] [-R <root-dir>] [-p <prop>,...] <name>\n"
- "\tshow-linkprop [-cP][-p <prop>,...] <name>\n"
+ "\tshow-linkprop [-cP][-o <field>,...][-p <prop>,...] <name>\n"
"\n"
"\tcreate-secobj [-t] [-R <root-dir>] [-f <file>] -c <class>"
" <secobj>\n"
"\tdelete-secobj [-t] [-R <root-dir>] <secobj>[,...]\n"
- "\tshow-secobj [-pP][<secobj>,...]\n"));
+ "\tshow-secobj [-pP][-o <field>,...][<secobj>,...]\n"
+ "\n"
+ "\tshow-ether [-px][-o <field>,...] <link>\n"));
+
exit(1);
}
@@ -890,8 +1455,8 @@ do_create_vlan(int argc, char *argv[])
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);
+ 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");
}
@@ -1102,40 +1667,21 @@ do_init_phys(int argc, char *argv[])
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)
+ datalink_class_t class, link_fields_buf_t *lbuf)
{
- 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";
+ if (!state->ls_parseable)
+ (void) sprintf(lbuf->link_over, STR_UNDEF_VAL);
else
- fmt = "%s";
+ (void) sprintf(lbuf->link_over, "");
if (class == DATALINK_CLASS_VLAN) {
dladm_vlan_attr_t vinfo;
@@ -1144,12 +1690,9 @@ print_link_topology(show_state_t *state, datalink_id_t linkid,
if (status != DLADM_STATUS_OK)
goto done;
status = dladm_datalink_id2info(vinfo.dv_linkid, NULL, NULL,
- NULL, over, sizeof (over));
+ NULL, lbuf->link_over, sizeof (lbuf->link_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;
@@ -1164,15 +1707,12 @@ print_link_topology(show_state_t *state, datalink_id_t linkid,
}
for (i = 0; i < ginfo.lg_nports; i++) {
status = dladm_datalink_id2info(
- ginfo.lg_ports[i].lp_linkid, NULL, NULL, NULL, over,
- sizeof (over));
+ ginfo.lg_ports[i].lp_linkid, NULL, NULL, NULL,
+ lbuf->link_over, sizeof (lbuf->link_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) {
@@ -1180,35 +1720,21 @@ print_link_topology(show_state_t *state, datalink_id_t linkid,
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) {
+ vinfo.va_link_id, NULL, NULL, NULL, lbuf->link_over,
+ sizeof (lbuf->link_over)) != DLADM_STATUS_OK)) {
goto done;
}
-
- /*LINTED: E_SEC_PRINTF_VAR_FMT*/
- *pptr += snprintf(*pptr, BUFLEN(lim, *pptr), fmt, over);
- } else {
- /*LINTED: E_SEC_PRINTF_VAR_FMT*/
- *pptr += snprintf(*pptr, BUFLEN(lim, *pptr), fmt,
- state->ls_parseable ? "" : "--");
}
- if (state->ls_parseable)
- *pptr += snprintf(*pptr, BUFLEN(lim, *pptr), "\"\n");
- else
- *pptr += snprintf(*pptr, BUFLEN(lim, *pptr), "\n");
-
done:
return (status);
}
static dladm_status_t
-print_link(show_state_t *state, datalink_id_t linkid, char **pptr, char *lim)
+print_link(show_state_t *state, datalink_id_t linkid, link_fields_buf_t *lbuf)
{
char link[MAXLINKNAMELEN];
- char buf[DLADM_STRSIZE];
datalink_class_t class;
uint_t mtu;
- char *fmt;
uint32_t flags;
dladm_status_t status;
@@ -1265,40 +1791,16 @@ link_mtu:
}
}
+ (void) snprintf(lbuf->link_name, sizeof (lbuf->link_name),
+ "%s", link);
+ (void) dladm_class2str(class, lbuf->link_class);
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";
- }
-
- (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 {
- /*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);
- }
+ (void) snprintf(lbuf->link_mtu, sizeof (lbuf->link_mtu),
+ "%d", mtu);
+ (void) get_linkstate(link, B_TRUE, lbuf->link_state);
}
- status = print_link_topology(state, linkid, class, pptr, lim);
+ status = print_link_topology(state, linkid, class, lbuf);
if (status != DLADM_STATUS_OK)
goto done;
@@ -1306,19 +1808,29 @@ done:
return (status);
}
+
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;
+ show_state_t *state = (show_state_t *)arg;
+ dladm_status_t status;
+ link_fields_buf_t lbuf;
+
+ /*
+ * first get all the link attributes into lbuf;
+ */
+ status = print_link(state, linkid, &lbuf);
- status = print_link(state, linkid, &ptr, lim);
if (status != DLADM_STATUS_OK)
goto done;
- print_link_head(state);
- (void) printf("%s", buf);
+
+ if (!state->ls_parseable && !state->ls_printheader) {
+ print_header(&state->ls_print);
+ state->ls_printheader = B_TRUE;
+ }
+
+ dladm_print_output(&state->ls_print, state->ls_parseable,
+ dladm_print_field, (void *)&lbuf);
done:
state->ls_status = status;
@@ -1328,9 +1840,9 @@ done:
static int
show_link_stats(datalink_id_t linkid, void *arg)
{
- char link[MAXLINKNAMELEN];
+ char link[DLPI_LINKNAME_MAX];
datalink_class_t class;
- show_state_t *state = arg;
+ show_state_t *state = (show_state_t *)arg;
pktsum_t stats, diff_stats;
dladm_phys_attr_t dpa;
@@ -1343,7 +1855,7 @@ show_link_stats(datalink_id_t linkid, void *arg)
}
if (dladm_datalink_id2info(linkid, NULL, &class, NULL, link,
- sizeof (link)) != DLADM_STATUS_OK) {
+ DLPI_LINKNAME_MAX) != DLADM_STATUS_OK) {
return (DLADM_WALK_CONTINUE);
}
@@ -1373,233 +1885,270 @@ show_link_stats(datalink_id_t linkid, void *arg)
return (DLADM_WALK_CONTINUE);
}
-static void
-print_port_stat(const char *port, pktsum_t *old_stats, pktsum_t *port_stats,
- pktsum_t *tot_stats, char **pptr, char *lim)
+
+static dladm_status_t
+print_aggr_info(show_grp_state_t *state, const char *link,
+ dladm_aggr_grp_attr_t *ginfop)
{
- pktsum_t diff_stats;
+ char addr_str[ETHERADDRL * 3];
+ laggr_fields_buf_t lbuf;
- 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) snprintf(lbuf.laggr_name, sizeof (lbuf.laggr_name),
+ "%s", link);
- 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) dladm_aggr_policy2str(ginfop->lg_policy,
+ lbuf.laggr_policy);
- if (tot_stats->opackets == 0) {
- *pptr += snprintf(*pptr, BUFLEN(lim, *pptr), "%8s\n", "--");
+ if (ginfop->lg_mac_fixed) {
+ (void) dladm_aggr_macaddr2str(ginfop->lg_mac, addr_str);
+ (void) snprintf(lbuf.laggr_addrpolicy,
+ sizeof (lbuf.laggr_addrpolicy), "fixed (%s)", addr_str);
} else {
- *pptr += snprintf(*pptr, BUFLEN(lim, *pptr), "%7.1f%%\n",
- (double)diff_stats.opackets/
- (double)tot_stats->opackets * 100);
+ (void) snprintf(lbuf.laggr_addrpolicy,
+ sizeof (lbuf.laggr_addrpolicy), "auto");
}
- *old_stats = *port_stats;
-}
-static void
-print_aggr_head(show_grp_state_t *state)
-{
- if (state->gs_donefirst)
- return;
- state->gs_donefirst = B_TRUE;
+ (void) dladm_aggr_lacpmode2str(ginfop->lg_lacp_mode,
+ lbuf.laggr_lacpactivity);
+ (void) dladm_aggr_lacptimer2str(ginfop->lg_lacp_timer,
+ lbuf.laggr_lacptimer);
+ (void) snprintf(lbuf.laggr_flags, sizeof (lbuf.laggr_flags), "%c----",
+ ginfop->lg_force ? 'f' : '-');
- 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");
+ if (!state->gs_parseable && !state->gs_printheader) {
+ print_header(&state->gs_print);
+ state->gs_printheader = B_TRUE;
}
+
+ dladm_print_output(&state->gs_print, state->gs_parseable,
+ dladm_print_field, (void *)&lbuf);
+
+ return (DLADM_STATUS_OK);
}
-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)
+static char *
+print_xaggr_callback(print_field_t *pf, void *arg)
{
- char buf[DLADM_STRSIZE];
- char *fmt;
- char addr_str[ETHERADDRL * 3];
- char str[ETHERADDRL * 3 + 2];
+ const laggr_args_t *l = arg;
+ int portnum;
+ static char buf[DLADM_STRSIZE];
+ boolean_t is_port = (l->laggr_lport >= 0);
+ dladm_aggr_port_attr_t *portp;
+ dladm_phys_attr_t dpa;
+ dladm_status_t *stat, status;
- if (state->gs_parseable)
- fmt = "LINK=\"%s\" POLICY=\"%s\" ADDRPOLICY=\"%s%s\" ";
- else
- fmt = "%-12s%-8s%-6s%-18s";
+ stat = l->laggr_status;
+ *stat = DLADM_STATUS_OK;
- if (ginfop->lg_mac_fixed) {
- (void) dladm_aggr_macaddr2str(ginfop->lg_mac, addr_str);
- (void) snprintf(str, ETHERADDRL * 3 + 3, " (%s)", addr_str);
- } else {
- str[0] = '\0';
+ if (is_port) {
+ portnum = l->laggr_lport;
+ portp = &(l->laggr_ginfop->lg_ports[portnum]);
+ if ((status = dladm_datalink_id2info(portp->lp_linkid,
+ NULL, NULL, NULL, buf, sizeof (buf))) !=
+ DLADM_STATUS_OK) {
+ goto err;
+ }
+ if ((status = dladm_phys_info(portp->lp_linkid, &dpa,
+ DLADM_OPT_ACTIVE)) != DLADM_STATUS_OK) {
+ goto err;
+ }
}
- /*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);
+ switch (pf->pf_index) {
+ case AGGR_X_LINK:
+ (void) snprintf(buf, sizeof (buf), "%s",
+ (is_port && !l->laggr_parseable ? " " : l->laggr_link));
+ break;
+ case AGGR_X_PORT:
+ if (is_port)
+ break;
+ return ("");
+ break;
- (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);
- }
+ case AGGR_X_SPEED:
+ if (is_port) {
+ (void) snprintf(buf, sizeof (buf), "%uMb",
+ (uint_t)((get_ifspeed(dpa.dp_dev,
+ B_FALSE)) / 1000000ull));
+ } else {
+ (void) snprintf(buf, sizeof (buf), "%uMb",
+ (uint_t)((get_ifspeed(l->laggr_link,
+ B_TRUE)) / 1000000ull));
+ }
+ break;
- (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' : '-');
+ case AGGR_X_DUPLEX:
+ if (is_port)
+ (void) get_linkduplex(dpa.dp_dev, B_FALSE, buf);
+ else
+ (void) get_linkduplex(l->laggr_link, B_TRUE, buf);
+ break;
+
+ case AGGR_X_STATE:
+ if (is_port) {
+ (void) dladm_aggr_portstate2str(
+ portp->lp_state, buf);
+ } else {
+ return (STR_UNDEF_VAL);
+ }
+ break;
+ case AGGR_X_ADDRESS:
+ (void) dladm_aggr_macaddr2str(
+ (is_port ? portp->lp_mac : l->laggr_ginfop->lg_mac),
+ buf);
+ break;
+
+ case AGGR_X_PORTSTATE:
+ (void) snprintf(buf, sizeof (buf), "%s",
+ (is_port ? dladm_aggr_portstate2str(portp->lp_state, buf):
+ (l->laggr_parseable ? "" : STR_UNDEF_VAL)));
+ break;
}
+ return (buf);
- return (DLADM_STATUS_OK);
+err:
+ *stat = status;
+ buf[0] = '\0';
+ return (buf);
}
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)
+ dladm_aggr_grp_attr_t *ginfop)
{
- 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;
+ laggr_args_t largs;
- if (state->gs_parseable)
- fmt = "LINK=\"%s\" PORT=\"%s\" SPEED=\"%uMb\" DUPLEX=\"%s\" ";
- else
- fmt = "%-12s%-14s%4uMb %-9s";
+ if (!state->gs_parseable && !state->gs_printheader) {
+ print_header(&state->gs_print);
+ state->gs_printheader = B_TRUE;
+ }
- (void) dladm_aggr_macaddr2str(ginfop->lg_mac, addr_str);
+ largs.laggr_lport = -1;
+ largs.laggr_link = link;
+ largs.laggr_ginfop = ginfop;
+ largs.laggr_status = &status;
+ largs.laggr_parseable = state->gs_parseable;
- /*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));
+ dladm_print_output(&state->gs_print, state->gs_parseable,
+ print_xaggr_callback, &largs);
- (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 {
- *pptr += snprintf(*pptr, BUFLEN(lim, *pptr), "%-9s%-18s%s\n",
- buf, addr_str, "--");
- }
+ if (status != DLADM_STATUS_OK)
+ goto done;
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) {
+ largs.laggr_lport = i;
+ dladm_print_output(&state->gs_print, state->gs_parseable,
+ print_xaggr_callback, &largs);
+ if (status != DLADM_STATUS_OK)
goto done;
- }
+ }
- if ((status = dladm_phys_info(portp->lp_linkid, &dpa,
- DLADM_OPT_ACTIVE)) != DLADM_STATUS_OK) {
- goto done;
- }
+ status = DLADM_STATUS_OK;
+done:
+ return (status);
+}
- (void) dladm_aggr_macaddr2str(portp->lp_mac, addr_str);
- if (state->gs_parseable)
- tmp = link;
- else
- tmp = "";
+static char *
+print_lacp_callback(print_field_t *pf, void *arg)
+{
+ const laggr_args_t *l = arg;
+ int portnum;
+ static char buf[DLADM_STRSIZE];
+ boolean_t is_port = (l->laggr_lport >= 0);
+ dladm_aggr_port_attr_t *portp;
+ dladm_status_t *stat, status;
+ aggr_lacp_state_t *lstate;
- /*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));
+ if (!is_port) {
+ return (NULL); /* cannot happen! */
+ }
- (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);
- }
+ stat = l->laggr_status;
- (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);
- }
+ portnum = l->laggr_lport;
+ portp = &(l->laggr_ginfop->lg_ports[portnum]);
+ if ((status = dladm_datalink_id2info(portp->lp_linkid,
+ NULL, NULL, NULL, buf, sizeof (buf))) != DLADM_STATUS_OK) {
+ goto err;
}
+ lstate = &(portp->lp_lacp_state);
- status = DLADM_STATUS_OK;
-done:
- return (status);
+ switch (pf->pf_index) {
+ case AGGR_L_LINK:
+ (void) snprintf(buf, sizeof (buf), "%s",
+ (portnum > 0 ? "" : l->laggr_link));
+ break;
+
+ case AGGR_L_PORT:
+ break;
+
+ case AGGR_L_AGGREGATABLE:
+ (void) snprintf(buf, sizeof (buf), "%s",
+ (lstate->bit.aggregation ? "yes" : "no"));
+ break;
+
+ case AGGR_L_SYNC:
+ (void) snprintf(buf, sizeof (buf), "%s",
+ (lstate->bit.sync ? "yes" : "no"));
+ break;
+
+ case AGGR_L_COLL:
+ (void) snprintf(buf, sizeof (buf), "%s",
+ (lstate->bit.collecting ? "yes" : "no"));
+ break;
+
+ case AGGR_L_DIST:
+ (void) snprintf(buf, sizeof (buf), "%s",
+ (lstate->bit.distributing ? "yes" : "no"));
+ break;
+
+ case AGGR_L_DEFAULTED:
+ (void) snprintf(buf, sizeof (buf), "%s",
+ (lstate->bit.defaulted ? "yes" : "no"));
+ break;
+
+ case AGGR_L_EXPIRED:
+ (void) snprintf(buf, sizeof (buf), "%s",
+ (lstate->bit.expired ? "yes" : "no"));
+ break;
+ }
+
+ *stat = DLADM_STATUS_OK;
+ return (buf);
+
+err:
+ *stat = status;
+ buf[0] = '\0';
+ return (buf);
}
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)
+ dladm_aggr_grp_attr_t *ginfop)
{
- char port[MAXLINKNAMELEN];
- char *fmt;
- const char *dlink = link;
int i;
dladm_status_t status;
+ laggr_args_t largs;
- 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 (!state->gs_parseable && !state->gs_printheader) {
+ print_header(&state->gs_print);
+ state->gs_printheader = B_TRUE;
}
- for (i = 0; i < ginfop->lg_nports; i++) {
- aggr_lacp_state_t *lstate;
+ largs.laggr_link = link;
+ largs.laggr_ginfop = ginfop;
+ largs.laggr_status = &status;
- status = dladm_datalink_id2info(ginfop->lg_ports[i].lp_linkid,
- NULL, NULL, NULL, port, sizeof (port));
+ for (i = 0; i < ginfop->lg_nports; i++) {
+ largs.laggr_lport = i;
+ dladm_print_output(&state->gs_print, state->gs_parseable,
+ print_lacp_callback, &largs);
if (status != DLADM_STATUS_OK)
goto done;
-
- /*
- * 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");
}
status = DLADM_STATUS_OK;
@@ -1607,24 +2156,127 @@ done:
return (status);
}
+static char *
+print_aggr_stats_callback(print_field_t *pf, void *arg)
+{
+ const laggr_args_t *l = arg;
+ int portnum;
+ static char buf[DLADM_STRSIZE];
+ boolean_t is_port = (l->laggr_lport >= 0);
+ dladm_aggr_port_attr_t *portp;
+ dladm_phys_attr_t dpa;
+ dladm_status_t *stat, status;
+ pktsum_t port_stat, diff_stats;
+
+ stat = l->laggr_status;
+ *stat = DLADM_STATUS_OK;
+
+ if (is_port) {
+ portnum = l->laggr_lport;
+ portp = &(l->laggr_ginfop->lg_ports[portnum]);
+ if ((status = dladm_phys_info(portp->lp_linkid, &dpa,
+ DLADM_OPT_ACTIVE)) != DLADM_STATUS_OK) {
+ goto err;
+ }
+
+ get_mac_stats(dpa.dp_dev, &port_stat);
+
+ if ((status = dladm_datalink_id2info(portp->lp_linkid, NULL,
+ NULL, NULL, buf, sizeof (buf))) != DLADM_STATUS_OK) {
+ goto err;
+ }
+
+ stats_diff(&diff_stats, &port_stat, l->laggr_prevstats);
+ }
+
+ switch (pf->pf_index) {
+ case AGGR_S_LINK:
+ (void) snprintf(buf, sizeof (buf), "%s",
+ (is_port ? "" : l->laggr_link));
+ break;
+ case AGGR_S_PORT:
+ if (is_port)
+ break;
+ return (STR_UNDEF_VAL);
+ break;
+
+ case AGGR_S_IPKTS:
+ if (is_port) {
+ (void) snprintf(buf, sizeof (buf), "%llu",
+ diff_stats.ipackets);
+ } else {
+ (void) snprintf(buf, sizeof (buf), "%llu",
+ l->laggr_pktsumtot->ipackets);
+ }
+ break;
+
+ case AGGR_S_RBYTES:
+ if (is_port) {
+ (void) snprintf(buf, sizeof (buf), "%llu",
+ diff_stats.rbytes);
+ } else {
+ (void) snprintf(buf, sizeof (buf), "%llu",
+ l->laggr_pktsumtot->rbytes);
+ }
+ break;
+
+ case AGGR_S_OPKTS:
+ if (is_port) {
+ (void) snprintf(buf, sizeof (buf), "%llu",
+ diff_stats.opackets);
+ } else {
+ (void) snprintf(buf, sizeof (buf), "%llu",
+ l->laggr_pktsumtot->opackets);
+ }
+ break;
+ case AGGR_S_OBYTES:
+ if (is_port) {
+ (void) snprintf(buf, sizeof (buf), "%llu",
+ diff_stats.obytes);
+ } else {
+ (void) snprintf(buf, sizeof (buf), "%llu",
+ l->laggr_pktsumtot->obytes);
+
+ }
+ break;
+
+ case AGGR_S_IPKTDIST:
+ if (is_port) {
+ (void) snprintf(buf, sizeof (buf), "%-6.1f",
+ (double)diff_stats.opackets/
+ (double)l->laggr_pktsumtot->ipackets * 100);
+ } else {
+ return (STR_UNDEF_VAL);
+ }
+ break;
+ case AGGR_S_OPKTDIST:
+ if (is_port) {
+ (void) snprintf(buf, sizeof (buf), "%-6.1f",
+ (double)diff_stats.opackets/
+ (double)l->laggr_pktsumtot->opackets * 100);
+ } else {
+ (void) sprintf(buf, STR_UNDEF_VAL);
+ }
+ break;
+ }
+ return (buf);
+
+err:
+ *stat = status;
+ buf[0] = '\0';
+ return (buf);
+}
+
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)
+ dladm_aggr_grp_attr_t *ginfop)
{
- 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_firstonly) {
- if (state->gs_donefirst)
- return (DLADM_WALK_CONTINUE);
- state->gs_donefirst = B_TRUE;
- } else {
- bzero(&state->gs_prevstats, sizeof (state->gs_prevstats));
- }
+ laggr_args_t largs;
/* sum the ports statistics */
bzero(&pktsumtot, sizeof (pktsumtot));
@@ -1641,28 +2293,30 @@ print_aggr_stats(show_grp_state_t *state, const char *link,
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, "--", "--");
+ if (!state->gs_parseable && !state->gs_printheader) {
+ print_header(&state->gs_print);
+ state->gs_printheader = B_TRUE;
+ }
- for (i = 0; i < ginfop->lg_nports; i++) {
- portp = &(ginfop->lg_ports[i]);
+ largs.laggr_lport = -1;
+ largs.laggr_link = link;
+ largs.laggr_ginfop = ginfop;
+ largs.laggr_status = &status;
+ largs.laggr_pktsumtot = &pktsumtot;
- if ((status = dladm_phys_info(portp->lp_linkid, &dpa,
- DLADM_OPT_ACTIVE)) != DLADM_STATUS_OK) {
- goto done;
- }
+ dladm_print_output(&state->gs_print, state->gs_parseable,
+ print_aggr_stats_callback, &largs);
- get_mac_stats(dpa.dp_dev, &port_stat);
+ if (status != DLADM_STATUS_OK)
+ goto done;
- if ((status = dladm_datalink_id2info(portp->lp_linkid, NULL,
- NULL, NULL, port, sizeof (port))) != DLADM_STATUS_OK) {
+ for (i = 0; i < ginfop->lg_nports; i++) {
+ largs.laggr_lport = i;
+ largs.laggr_prevstats = &state->gs_prevstats[i];
+ dladm_print_output(&state->gs_print, state->gs_parseable,
+ print_aggr_stats_callback, &largs);
+ if (status != DLADM_STATUS_OK)
goto done;
- }
-
- print_port_stat(port, &state->gs_prevstats[i], &port_stat,
- &pktsumtot, pptr, lim);
}
status = DLADM_STATUS_OK;
@@ -1671,8 +2325,7 @@ done:
}
static dladm_status_t
-print_aggr(show_grp_state_t *state, datalink_id_t linkid, char **pptr,
- char *lim)
+print_aggr(show_grp_state_t *state, datalink_id_t linkid)
{
char link[MAXLINKNAMELEN];
dladm_aggr_grp_attr_t ginfo;
@@ -1680,7 +2333,7 @@ print_aggr(show_grp_state_t *state, datalink_id_t linkid, char **pptr,
dladm_status_t status;
if ((status = dladm_datalink_id2info(linkid, &flags, NULL, NULL, link,
- sizeof (link))) != DLADM_STATUS_OK) {
+ MAXLINKNAMELEN)) != DLADM_STATUS_OK) {
return (status);
}
@@ -1692,13 +2345,14 @@ print_aggr(show_grp_state_t *state, datalink_id_t linkid, char **pptr,
return (status);
if (state->gs_lacp)
- status = print_aggr_lacp(state, link, &ginfo, pptr, lim);
+ status = print_aggr_lacp(state, link, &ginfo);
else if (state->gs_extended)
- status = print_aggr_extended(state, link, &ginfo, pptr, lim);
+ status = print_aggr_extended(state, link, &ginfo);
else if (state->gs_stats)
- status = print_aggr_stats(state, link, &ginfo, pptr, lim);
- else
- status = print_aggr_info(state, link, &ginfo, pptr, lim);
+ status = print_aggr_stats(state, link, &ginfo);
+ else {
+ status = print_aggr_info(state, link, &ginfo);
+ }
done:
free(ginfo.lg_ports);
@@ -1710,83 +2364,107 @@ 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);
+ status = print_aggr(state, linkid);
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
-kstat_value(kstat_t *ksp, const char *name, uint8_t type, void *buf)
+static char *
+print_dev(print_field_t *pf, void *arg)
{
- kstat_named_t *knp;
-
- if ((knp = kstat_data_lookup(ksp, (char *)name)) == NULL)
- return (-1);
-
- if (knp->data_type != type)
- return (-1);
+ const char *dev = arg;
+ static char buf[DLADM_STRSIZE];
- switch (type) {
- case KSTAT_DATA_UINT64:
- *(uint64_t *)buf = knp->value.ui64;
+ switch (pf->pf_index) {
+ case DEV_LINK:
+ (void) snprintf(buf, sizeof (buf), "%s", dev);
+ break;
+ case DEV_STATE:
+ (void) get_linkstate(dev, B_FALSE, buf);
+ break;
+ case DEV_SPEED:
+ (void) snprintf(buf, sizeof (buf), "%uMb",
+ (unsigned int)(get_ifspeed(dev, B_FALSE) / 1000000ull));
break;
- case KSTAT_DATA_UINT32:
- *(uint32_t *)buf = knp->value.ui32;
+ case DEV_DUPLEX:
+ (void) get_linkduplex(dev, B_FALSE, buf);
break;
default:
- return (-1);
+ die("invalid index '%d'", pf->pf_index);
+ break;
}
-
- return (0);
+ return (buf);
}
static int
show_dev(const char *dev, void *arg)
{
show_state_t *state = arg;
- char buf[DLADM_STRSIZE];
- char *fmt;
-
- if (state->ls_parseable)
- fmt = "DEV=\"%s\" STATE=\"%s\" SPEED=\"%u\" ";
- else
- fmt = "%-12s%-10s%4uMb ";
- if (!state->ls_donefirst) {
- if (!state->ls_parseable) {
- (void) printf("%-12s%-10s%6s %s\n", "DEV", "STATE",
- "SPEED", "DUPLEX");
- }
- state->ls_donefirst = B_TRUE;
+ if (!state->ls_parseable && !state->ls_printheader) {
+ print_header(&state->ls_print);
+ state->ls_printheader = 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);
+ dladm_print_output(&state->ls_print, state->ls_parseable,
+ print_dev, (void *)dev);
return (DLADM_WALK_CONTINUE);
}
+static char *
+print_dev_stats(print_field_t *pf, void *arg)
+{
+ dev_args_t *dargs = arg;
+ pktsum_t *diff_stats = dargs->devs_psum;
+ static char buf[DLADM_STRSIZE];
+
+ switch (pf->pf_index) {
+ case DEVS_LINK:
+ (void) snprintf(buf, sizeof (buf), "%s", dargs->devs_link);
+ break;
+ case DEVS_IPKTS:
+ (void) snprintf(buf, sizeof (buf), "%llu",
+ diff_stats->ipackets);
+ break;
+ case DEVS_RBYTES:
+ (void) snprintf(buf, sizeof (buf), "%llu",
+ diff_stats->rbytes);
+ break;
+ case DEVS_IERRORS:
+ (void) snprintf(buf, sizeof (buf), "%u",
+ diff_stats->ierrors);
+ break;
+ case DEVS_OPKTS:
+ (void) snprintf(buf, sizeof (buf), "%llu",
+ diff_stats->opackets);
+ break;
+ case DEVS_OBYTES:
+ (void) snprintf(buf, sizeof (buf), "%llu",
+ diff_stats->obytes);
+ break;
+ case DEVS_OERRORS:
+ (void) snprintf(buf, sizeof (buf), "%u",
+ diff_stats->oerrors);
+ break;
+ default:
+ die("invalid input");
+ break;
+ }
+ return (buf);
+}
+
static int
show_dev_stats(const char *dev, void *arg)
{
show_state_t *state = arg;
pktsum_t stats, diff_stats;
+ dev_args_t dargs;
if (state->ls_firstonly) {
if (state->ls_donefirst)
@@ -1799,13 +2477,10 @@ show_dev_stats(const char *dev, void *arg)
get_mac_stats(dev, &stats);
stats_diff(&diff_stats, &stats, &state->ls_prevstats);
- (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);
+ dargs.devs_link = (char *)dev;
+ dargs.devs_psum = &diff_stats;
+ dladm_print_output(&state->ls_print, state->ls_parseable,
+ print_dev_stats, &dargs);
state->ls_prevstats = stats;
return (DLADM_WALK_CONTINUE);
@@ -1823,9 +2498,17 @@ do_show_link(int argc, char *argv[])
int interval = 0;
show_state_t state;
dladm_status_t status;
+ boolean_t o_arg = B_FALSE;
+ char *fields_str = NULL;
+ print_field_t **fields;
+ uint_t nfields;
+ char *all_active_fields = "link,class,mtu,state,over";
+ char *all_inactive_fields = "link,class,over";
+
+ bzero(&state, sizeof (state));
opterr = 0;
- while ((option = getopt_long(argc, argv, ":pPsi:",
+ while ((option = getopt_long(argc, argv, ":pPsi:o:",
show_lopts, NULL)) != -1) {
switch (option) {
case 'p':
@@ -1846,6 +2529,10 @@ do_show_link(int argc, char *argv[])
flags = DLADM_OPT_PERSIST;
break;
+ case 'o':
+ o_arg = B_TRUE;
+ fields_str = optarg;
+ break;
case 'i':
if (i_arg)
die_optdup(option);
@@ -1892,6 +2579,26 @@ do_show_link(int argc, char *argv[])
state.ls_parseable = p_arg;
state.ls_flags = flags;
state.ls_donefirst = B_FALSE;
+
+ if (!o_arg || (o_arg && strcasecmp(fields_str, "all") == 0)) {
+ if (state.ls_flags & DLADM_OPT_ACTIVE)
+ fields_str = all_active_fields;
+ else
+ fields_str = all_inactive_fields;
+ }
+
+
+ fields = parse_output_fields(fields_str, link_fields, DEV_LINK_FIELDS,
+ CMD_TYPE_ANY, &nfields);
+
+ if (fields == NULL) {
+ die("invalid field(s) specified");
+ return;
+ }
+
+ state.ls_print.ps_fields = fields;
+ state.ls_print.ps_nfields = nfields;
+
if (linkid == DATALINK_ALL_LINKID) {
(void) dladm_walk_datalink_id(show_link, &state,
DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE, flags);
@@ -1919,9 +2626,25 @@ do_show_aggr(int argc, char *argv[])
int interval = 0;
int key;
dladm_status_t status;
+ boolean_t o_arg = B_FALSE;
+ char *fields_str = NULL;
+ print_field_t **fields;
+ uint_t nfields;
+ char *all_fields =
+ "link,policy,addrpolicy,lacpactivity,lacptimer,flags";
+ char *all_lacp_fields =
+ "link,port,aggregatable,sync,coll,dist,defaulted,expired";
+ char *all_stats_fields =
+ "link,port,ipackets,rbytes,opackets,obytes,ipktdist,opktdist";
+ char *all_extended_fields =
+ "link,port,speed,duplex,state,address,portstate";
+ print_field_t *pf;
+ int pfmax;
+
+ bzero(&state, sizeof (state));
opterr = 0;
- while ((option = getopt_long(argc, argv, ":LpPxsi:",
+ while ((option = getopt_long(argc, argv, ":LpPxsi:o:",
show_lopts, NULL)) != -1) {
switch (option) {
case 'L':
@@ -1954,6 +2677,10 @@ do_show_aggr(int argc, char *argv[])
s_arg = B_TRUE;
break;
+ case 'o':
+ o_arg = B_TRUE;
+ fields_str = optarg;
+ break;
case 'i':
if (i_arg)
die_optdup(option);
@@ -2006,6 +2733,41 @@ do_show_aggr(int argc, char *argv[])
state.gs_parseable = p_arg;
state.gs_extended = x_arg;
+ if (!o_arg || (o_arg && strcasecmp(fields_str, "all") == 0)) {
+ if (state.gs_lacp)
+ fields_str = all_lacp_fields;
+ else if (state.gs_stats)
+ fields_str = all_stats_fields;
+ else if (state.gs_extended)
+ fields_str = all_extended_fields;
+ else
+ fields_str = all_fields;
+ }
+
+ if (state.gs_lacp) {
+ pf = aggr_l_fields;
+ pfmax = AGGR_L_MAX_FIELDS;
+ } else if (state.gs_stats) {
+ pf = aggr_s_fields;
+ pfmax = AGGR_S_MAX_FIELDS;
+ } else if (state.gs_extended) {
+ pf = aggr_x_fields;
+ pfmax = AGGR_X_MAX_FIELDS;
+ } else {
+ pf = laggr_fields;
+ pfmax = LAGGR_MAX_FIELDS;
+ }
+ fields = parse_output_fields(fields_str, pf, pfmax, CMD_TYPE_ANY,
+ &nfields);
+
+ if (fields == NULL) {
+ die("invalid field(s) specified");
+ return;
+ }
+
+ state.gs_print.ps_fields = fields;
+ state.gs_print.ps_nfields = nfields;
+
if (s_arg) {
aggr_stats(linkid, &state, interval);
return;
@@ -2030,13 +2792,23 @@ do_show_dev(int argc, char *argv[])
char *dev = NULL;
boolean_t s_arg = B_FALSE;
boolean_t i_arg = B_FALSE;
+ boolean_t o_arg = B_FALSE;
boolean_t p_arg = B_FALSE;
datalink_id_t linkid;
int interval = 0;
show_state_t state;
+ char *fields_str = NULL;
+ print_field_t **fields;
+ uint_t nfields;
+ char *all_fields = "link,state,speed,duplex";
+ static char *allstat_fields =
+ "link,ipackets,rbytes,ierrors,opackets,obytes,oerrors";
+
+ bzero(&state, sizeof (state));
+ fields_str = all_fields;
opterr = 0;
- while ((option = getopt_long(argc, argv, ":psi:",
+ while ((option = getopt_long(argc, argv, ":psi:o:",
show_lopts, NULL)) != -1) {
switch (option) {
case 'p':
@@ -2051,6 +2823,10 @@ do_show_dev(int argc, char *argv[])
s_arg = B_TRUE;
break;
+ case 'o':
+ o_arg = B_TRUE;
+ fields_str = optarg;
+ break;
case 'i':
if (i_arg)
die_optdup(option);
@@ -2068,6 +2844,16 @@ do_show_dev(int argc, char *argv[])
if (i_arg && !s_arg)
die("the option -i can be used only with -s");
+ if (o_arg && strcasecmp(fields_str, "all") == 0) {
+ if (!s_arg)
+ fields_str = all_fields;
+ else
+ fields_str = allstat_fields;
+ }
+
+ if (!o_arg && s_arg)
+ fields_str = allstat_fields;
+
if (s_arg && p_arg)
die("the option -s cannot be used with -p");
@@ -2089,52 +2875,45 @@ do_show_dev(int argc, char *argv[])
usage();
}
+ state.ls_parseable = p_arg;
+ state.ls_donefirst = B_FALSE;
+
if (s_arg) {
- dev_stats(dev, interval);
+ dev_stats(dev, interval, fields_str, &state);
return;
}
- 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);
- }
-}
+ fields = parse_output_fields(fields_str, dev_fields, DEV_MAX_FIELDS,
+ CMD_TYPE_ANY, &nfields);
-static void
-print_phys_head(show_state_t *state)
-{
- if (state->ls_donefirst)
+ if (fields == NULL) {
+ die("invalid field(s) specified");
return;
- state->ls_donefirst = B_TRUE;
+ }
- if (state->ls_parseable)
- return;
+ state.ls_print.ps_fields = fields;
+ state.ls_print.ps_nfields = nfields;
- if (state->ls_flags == DLADM_OPT_ACTIVE) {
- (void) printf("%-12s%-20s%-10s%6s %-9s%s\n", "LINK",
- "MEDIA", "STATE", "SPEED", "DUPLEX", "DEVICE");
+ if (dev == NULL) {
+ (void) dladm_mac_walk(show_dev, &state);
} else {
- (void) printf("%-12s%-12s%-20s%s\n", "LINK", "DEVICE",
- "MEDIA", "FLAGS");
+ (void) show_dev(dev, &state);
}
}
+
static dladm_status_t
-print_phys(show_state_t *state, datalink_id_t linkid, char **pptr, char *lim)
+print_phys(show_state_t *state, datalink_id_t linkid, link_fields_buf_t *pattr)
{
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) {
+ link, MAXLINKNAMELEN)) != DLADM_STATUS_OK) {
goto done;
}
@@ -2152,58 +2931,39 @@ print_phys(show_state_t *state, datalink_id_t linkid, char **pptr, char *lim)
if (status != DLADM_STATUS_OK)
goto done;
+ (void) snprintf(pattr->link_phys_device,
+ sizeof (pattr->link_phys_device), "%s", dpa.dp_dev);
+ (void) dladm_media2str(media, pattr->link_phys_media);
if (state->ls_flags == DLADM_OPT_ACTIVE) {
- char name[MAXLINKNAMELEN];
boolean_t islink;
if (!dpa.dp_novanity) {
- (void) strlcpy(name, link, sizeof (name));
+ (void) strlcpy(pattr->link_name, link,
+ sizeof (pattr->link_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));
+ (void) strlcpy(pattr->link_name, dpa.dp_dev,
+ sizeof (pattr->link_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);
- }
+ (void) get_linkstate(pattr->link_name, islink,
+ pattr->link_phys_state);
+ (void) snprintf(pattr->link_phys_speed,
+ sizeof (pattr->link_phys_speed), "%u",
+ (uint_t)((get_ifspeed(pattr->link_name,
+ islink)) / 1000000ull));
+ (void) get_linkduplex(pattr->link_name, islink,
+ pattr->link_phys_duplex);
} 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');
- }
+ (void) snprintf(pattr->link_name, sizeof (pattr->link_name),
+ "%s", link);
+ (void) snprintf(pattr->link_flags, sizeof (pattr->link_flags),
+ "%c----", flags & DLADM_OPT_ACTIVE ? '-' : 'r');
}
done:
@@ -2215,48 +2975,38 @@ 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;
+ link_fields_buf_t pattr;
- status = print_phys(state, linkid, &ptr, lim);
+ status = print_phys(state, linkid, &pattr);
if (status != DLADM_STATUS_OK)
goto done;
- print_phys_head(state);
- (void) printf("%s", buf);
+
+ if (!state->ls_parseable && !state->ls_printheader) {
+ print_header(&state->ls_print);
+ state->ls_printheader = B_TRUE;
+ }
+
+ dladm_print_output(&state->ls_print, state->ls_parseable,
+ dladm_print_field, (void *)&pattr);
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)
+print_vlan(show_state_t *state, datalink_id_t linkid, link_fields_buf_t *l)
{
- 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) {
+ if ((status = dladm_datalink_id2info(linkid, &flags, NULL, NULL,
+ l->link_name, sizeof (l->link_name))) != DLADM_STATUS_OK) {
goto done;
}
@@ -2267,19 +3017,15 @@ print_vlan(show_state_t *state, datalink_id_t linkid, char **pptr, char *lim)
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) {
+ vinfo.dv_linkid, NULL, NULL, NULL, l->link_over,
+ sizeof (l->link_over))) != DLADM_STATUS_OK) {
goto done;
}
- if (state->ls_parseable)
- fmt = "LINK=\"%s\" VID=\"%d\" OVER=\"%s\" FLAGS=\"%c%c---\"\n";
- else
- 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' : '-');
+ (void) snprintf(l->link_vlan_vid, sizeof (l->link_vlan_vid), "%d",
+ vinfo.dv_vid);
+ (void) snprintf(l->link_flags, sizeof (l->link_flags), "%c%c---",
+ vinfo.dv_force ? 'f' : '-', vinfo.dv_implicit ? 'i' : '-');
done:
return (status);
@@ -2290,14 +3036,19 @@ 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;
+ link_fields_buf_t lbuf;
- status = print_vlan(state, linkid, &ptr, lim);
+ status = print_vlan(state, linkid, &lbuf);
if (status != DLADM_STATUS_OK)
goto done;
- print_vlan_head(state);
- (void) printf("%s", buf);
+
+ if (!state->ls_parseable && !state->ls_printheader) {
+ print_header(&state->ls_print);
+ state->ls_printheader = B_TRUE;
+ }
+
+ dladm_print_output(&state->ls_print, state->ls_parseable,
+ dladm_print_field, (void *)&lbuf);
done:
state->ls_status = status;
@@ -2310,12 +3061,21 @@ do_show_phys(int argc, char *argv[])
int option;
uint32_t flags = DLADM_OPT_ACTIVE;
boolean_t p_arg = B_FALSE;
+ boolean_t o_arg = B_FALSE;
datalink_id_t linkid = DATALINK_ALL_LINKID;
show_state_t state;
dladm_status_t status;
+ char *fields_str = NULL;
+ print_field_t **fields;
+ uint_t nfields;
+ char *all_active_fields =
+ "link,media,state,speed,duplex,device";
+ char *all_inactive_fields =
+ "link,device,media,flags";
+ bzero(&state, sizeof (state));
opterr = 0;
- while ((option = getopt_long(argc, argv, ":pP",
+ while ((option = getopt_long(argc, argv, ":pPo:",
show_lopts, NULL)) != -1) {
switch (option) {
case 'p':
@@ -2330,6 +3090,10 @@ do_show_phys(int argc, char *argv[])
flags = DLADM_OPT_PERSIST;
break;
+ case 'o':
+ o_arg = B_TRUE;
+ fields_str = optarg;
+ break;
default:
die_opterr(optopt, option);
break;
@@ -2350,6 +3114,24 @@ do_show_phys(int argc, char *argv[])
state.ls_flags = flags;
state.ls_donefirst = B_FALSE;
+ if (!o_arg || (o_arg && strcasecmp(fields_str, "all") == 0)) {
+ if (state.ls_flags & DLADM_OPT_ACTIVE)
+ fields_str = all_active_fields;
+ else
+ fields_str = all_inactive_fields;
+ }
+
+ fields = parse_output_fields(fields_str, phys_fields,
+ PHYS_MAX_FIELDS, CMD_TYPE_ANY, &nfields);
+
+ if (fields == NULL) {
+ die("invalid field(s) specified");
+ return;
+ }
+
+ state.ls_print.ps_fields = fields;
+ state.ls_print.ps_nfields = nfields;
+
if (linkid == DATALINK_ALL_LINKID) {
(void) dladm_walk_datalink_id(show_phys, &state,
DATALINK_CLASS_PHYS, DATALINK_ANY_MEDIATYPE, flags);
@@ -2371,9 +3153,16 @@ do_show_vlan(int argc, char *argv[])
datalink_id_t linkid = DATALINK_ALL_LINKID;
show_state_t state;
dladm_status_t status;
+ boolean_t o_arg = B_FALSE;
+ char *fields_str = NULL;
+ print_field_t **fields;
+ uint_t nfields;
+ char *all_fields = "link,vid,over,flags";
+
+ bzero(&state, sizeof (state));
opterr = 0;
- while ((option = getopt_long(argc, argv, ":pP",
+ while ((option = getopt_long(argc, argv, ":pPo:",
show_lopts, NULL)) != -1) {
switch (option) {
case 'p':
@@ -2388,6 +3177,10 @@ do_show_vlan(int argc, char *argv[])
flags = DLADM_OPT_PERSIST;
break;
+ case 'o':
+ o_arg = B_TRUE;
+ fields_str = optarg;
+ break;
default:
die_opterr(optopt, option);
break;
@@ -2408,6 +3201,19 @@ do_show_vlan(int argc, char *argv[])
state.ls_flags = flags;
state.ls_donefirst = B_FALSE;
+ if (!o_arg || (o_arg && strcasecmp(fields_str, "all") == 0))
+ fields_str = all_fields;
+
+ fields = parse_output_fields(fields_str, vlan_fields, VLAN_MAX_FIELDS,
+ CMD_TYPE_ANY, &nfields);
+
+ if (fields == NULL) {
+ die("invalid field(s) specified");
+ return;
+ }
+ state.ls_print.ps_fields = fields;
+ state.ls_print.ps_nfields = nfields;
+
if (linkid == DATALINK_ALL_LINKID) {
(void) dladm_walk_datalink_id(show_vlan, &state,
DATALINK_CLASS_VLAN, DATALINK_ANY_MEDIATYPE, flags);
@@ -2464,11 +3270,6 @@ aggr_stats(datalink_id_t linkid, show_grp_state_t *state, uint_t interval)
state->gs_firstonly = (interval != 0);
for (;;) {
-
- (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,
@@ -2485,29 +3286,40 @@ aggr_stats(datalink_id_t linkid, show_grp_state_t *state, uint_t interval)
}
static void
-dev_stats(const char *dev, uint32_t interval)
+dev_stats(const char *dev, uint32_t interval, char *fields_str,
+ show_state_t *state)
{
- show_state_t state;
+ print_field_t **fields;
+ uint_t nfields;
+
+ fields = parse_output_fields(fields_str, devs_fields, DEVS_MAX_FIELDS,
+ CMD_TYPE_ANY, &nfields);
+
+ if (fields == NULL) {
+ die("invalid field(s) specified");
+ return;
+ }
+
+ state->ls_print.ps_fields = fields;
+ state->ls_print.ps_nfields = nfields;
- bzero(&state, sizeof (state));
/*
* If an interval is specified, continuously show the stats
* only for the first MAC port.
*/
- state.ls_firstonly = (interval != 0);
+ state->ls_firstonly = (interval != 0);
for (;;) {
- (void) printf("%-12s%-10s%-12s%-8s%-10s%-12s%-8s\n",
- "DEV", "IPACKETS", "RBYTES", "IERRORS", "OPACKETS",
- "OBYTES", "OERRORS");
+ if (!state->ls_parseable)
+ print_header(&state->ls_print);
+ state->ls_donefirst = B_FALSE;
- state.ls_donefirst = B_FALSE;
if (dev == NULL)
- (void) dladm_mac_walk(show_dev_stats, &state);
+ (void) dladm_mac_walk(show_dev_stats, state);
else
- (void) show_dev_stats(dev, &state);
+ (void) show_dev_stats(dev, state);
if (interval == 0)
break;
@@ -2515,8 +3327,8 @@ dev_stats(const char *dev, uint32_t interval)
(void) sleep(interval);
}
- if (dev != NULL && state.ls_status != DLADM_STATUS_OK)
- die_dlerr(state.ls_status, "cannot show device '%s'", dev);
+ if (dev != NULL && state->ls_status != DLADM_STATUS_OK)
+ die_dlerr(state->ls_status, "cannot show device '%s'", dev);
}
/* accumulate stats (s1 += (s2 - s3)) */
@@ -2566,27 +3378,27 @@ get_stats(char *module, int instance, const char *name, pktsum_t *stats)
if (kstat_read(kcp, ksp, NULL) == -1)
goto bail;
- if (kstat_value(ksp, "ipackets64", KSTAT_DATA_UINT64,
+ if (dladm_kstat_value(ksp, "ipackets64", KSTAT_DATA_UINT64,
&stats->ipackets) < 0)
goto bail;
- if (kstat_value(ksp, "opackets64", KSTAT_DATA_UINT64,
+ if (dladm_kstat_value(ksp, "opackets64", KSTAT_DATA_UINT64,
&stats->opackets) < 0)
goto bail;
- if (kstat_value(ksp, "rbytes64", KSTAT_DATA_UINT64,
+ if (dladm_kstat_value(ksp, "rbytes64", KSTAT_DATA_UINT64,
&stats->rbytes) < 0)
goto bail;
- if (kstat_value(ksp, "obytes64", KSTAT_DATA_UINT64,
+ if (dladm_kstat_value(ksp, "obytes64", KSTAT_DATA_UINT64,
&stats->obytes) < 0)
goto bail;
- if (kstat_value(ksp, "ierrors", KSTAT_DATA_UINT32,
+ if (dladm_kstat_value(ksp, "ierrors", KSTAT_DATA_UINT32,
&stats->ierrors) < 0)
goto bail;
- if (kstat_value(ksp, "oerrors", KSTAT_DATA_UINT32,
+ if (dladm_kstat_value(ksp, "oerrors", KSTAT_DATA_UINT32,
&stats->oerrors) < 0)
goto bail;
@@ -2641,7 +3453,7 @@ query_kstat(char *module, int instance, const char *name, const char *stat,
goto bail;
}
- if (kstat_value(ksp, stat, type, val) < 0)
+ if (dladm_kstat_value(ksp, stat, type, val) < 0)
goto bail;
(void) kstat_close(kcp);
@@ -2707,43 +3519,6 @@ get_linkduplex(const char *name, boolean_t islink, char *buf)
return (dladm_linkduplex2str(linkduplex, buf));
}
-#define WIFI_CMD_SCAN 0x00000001
-#define WIFI_CMD_SHOW 0x00000002
-#define WIFI_CMD_ALL (WIFI_CMD_SCAN | WIFI_CMD_SHOW)
-typedef struct wifi_field {
- const char *wf_name;
- const char *wf_header;
- uint_t wf_width;
- uint_t wf_mask;
- uint_t wf_cmdtype;
-} wifi_field_t;
-
-static wifi_field_t wifi_fields[] = {
-{ "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}}
-;
-
-static char *all_scan_wifi_fields =
- "link,essid,bssid,sec,strength,mode,speed,bsstype";
-static char *all_show_wifi_fields =
- "link,status,essid,sec,strength,mode,speed,auth,bssid,bsstype";
-static char *def_scan_wifi_fields =
- "link,essid,bssid,sec,strength,mode,speed";
-static char *def_show_wifi_fields =
- "link,status,essid,sec,strength,mode,speed";
-
-#define WIFI_MAX_FIELDS (sizeof (wifi_fields) / sizeof (wifi_field_t))
-#define WIFI_MAX_FIELD_LEN 32
-
typedef struct {
char *s_buf;
char **s_fields; /* array of pointer to the fields in s_buf */
@@ -2798,13 +3573,9 @@ fail:
}
static int
-parse_wifi_fields(char *str, wifi_field_t ***fields, uint_t *countp,
+parse_wifi_fields(char *str, print_field_t ***fields, uint_t *countp,
uint_t cmdtype)
{
- uint_t i, j;
- wifi_field_t **wf = NULL;
- split_t *sp;
- boolean_t good_match = B_FALSE;
if (cmdtype == WIFI_CMD_SCAN) {
if (str == NULL)
@@ -2819,21 +3590,35 @@ parse_wifi_fields(char *str, wifi_field_t ***fields, uint_t *countp,
} else {
return (-1);
}
+ *fields = parse_output_fields(str, wifi_fields, WIFI_MAX_FIELDS,
+ cmdtype, countp);
+ if (*fields != NULL)
+ return (0);
+ return (-1);
+}
+static print_field_t **
+parse_output_fields(char *str, print_field_t *template, int max_fields,
+ uint_t cmdtype, uint_t *countp)
+{
+ split_t *sp;
+ boolean_t good_match = B_FALSE;
+ uint_t i, j;
+ print_field_t **pf = NULL;
+
+ sp = split(str, max_fields, MAX_FIELD_LEN);
- sp = split(str, WIFI_MAX_FIELDS, WIFI_MAX_FIELD_LEN);
if (sp == NULL)
- return (-1);
+ return (NULL);
- wf = malloc(sp->s_nfields * sizeof (wifi_field_t *));
- if (wf == NULL)
+ pf = malloc(sp->s_nfields * sizeof (print_field_t *));
+ if (pf == NULL)
goto fail;
for (i = 0; i < sp->s_nfields; i++) {
- for (j = 0; j < WIFI_MAX_FIELDS; j++) {
+ for (j = 0; j < max_fields; j++) {
if (strcasecmp(sp->s_fields[i],
- wifi_fields[j].wf_name) == 0) {
- good_match = wifi_fields[j].
- wf_cmdtype & cmdtype;
+ template[j].pf_name) == 0) {
+ good_match = template[j]. pf_cmdtype & cmdtype;
break;
}
}
@@ -2841,142 +3626,127 @@ parse_wifi_fields(char *str, wifi_field_t ***fields, uint_t *countp,
goto fail;
good_match = B_FALSE;
- wf[i] = &wifi_fields[j];
+ pf[i] = &template[j];
}
*countp = i;
- *fields = wf;
splitfree(sp);
- return (0);
+ return (pf);
fail:
- free(wf);
+ free(pf);
splitfree(sp);
- return (-1);
+ return (NULL);
}
typedef struct print_wifi_state {
char *ws_link;
boolean_t ws_parseable;
boolean_t ws_header;
- wifi_field_t **ws_fields;
- uint_t ws_nfields;
- boolean_t ws_lastfield;
- uint_t ws_overflow;
+ print_state_t ws_print_state;
} print_wifi_state_t;
-static void
-print_wifi_head(print_wifi_state_t *statep)
-{
- int i;
- wifi_field_t *wfp;
+typedef struct wlan_scan_args_s {
+ print_wifi_state_t *ws_state;
+ void *ws_attr;
+} wlan_scan_args_t;
- for (i = 0; i < statep->ws_nfields; i++) {
- wfp = statep->ws_fields[i];
- if (i + 1 < statep->ws_nfields)
- (void) printf("%-*s ", wfp->wf_width, wfp->wf_header);
- else
- (void) printf("%s", wfp->wf_header);
- }
- (void) printf("\n");
-}
static void
-print_wifi_field(print_wifi_state_t *statep, wifi_field_t *wfp,
- const char *value)
+print_field(print_state_t *statep, print_field_t *pfp, const char *value,
+ boolean_t parseable)
{
- uint_t width = wfp->wf_width;
+ uint_t width = pfp->pf_width;
uint_t valwidth = strlen(value);
uint_t compress;
- if (statep->ws_parseable) {
- (void) printf("%s=\"%s\"", wfp->wf_header, value);
+ if (parseable) {
+ (void) printf("%s=\"%s\"", pfp->pf_header, value);
} else {
if (value[0] == '\0')
- value = "--";
- if (statep->ws_lastfield) {
+ value = STR_UNDEF_VAL;
+ if (statep->ps_lastfield) {
(void) printf("%s", value);
return;
}
if (valwidth > width) {
- statep->ws_overflow += valwidth - width;
- } else if (valwidth < width && statep->ws_overflow > 0) {
- compress = min(statep->ws_overflow, width - valwidth);
- statep->ws_overflow -= compress;
+ statep->ps_overflow += valwidth - width;
+ } else if (valwidth < width && statep->ps_overflow > 0) {
+ compress = min(statep->ps_overflow, width - valwidth);
+ statep->ps_overflow -= compress;
width -= compress;
}
(void) printf("%-*s", width, value);
}
- if (!statep->ws_lastfield)
+ if (!statep->ps_lastfield)
(void) putchar(' ');
}
-static void
-print_wlan_attr(print_wifi_state_t *statep, wifi_field_t *wfp,
- dladm_wlan_attr_t *attrp)
+static char *
+print_wlan_attr(print_field_t *wfp, void *warg)
{
- char buf[DLADM_STRSIZE];
- const char *str = "";
+ static char buf[DLADM_STRSIZE];
+ wlan_scan_args_t *w = warg;
+ print_wifi_state_t *statep = w->ws_state;
+ dladm_wlan_attr_t *attrp = w->ws_attr;
- if (wfp->wf_mask == 0) {
- print_wifi_field(statep, wfp, statep->ws_link);
- return;
+ if (wfp->pf_index == 0) {
+ return ((char *)statep->ws_link);
}
- if ((wfp->wf_mask & attrp->wa_valid) == 0) {
- print_wifi_field(statep, wfp, "");
- return;
+ if ((wfp->pf_index & attrp->wa_valid) == 0) {
+ return ("");
}
- switch (wfp->wf_mask) {
+ switch (wfp->pf_index) {
case DLADM_WLAN_ATTR_ESSID:
- str = dladm_wlan_essid2str(&attrp->wa_essid, buf);
+ (void) dladm_wlan_essid2str(&attrp->wa_essid, buf);
break;
case DLADM_WLAN_ATTR_BSSID:
- str = dladm_wlan_bssid2str(&attrp->wa_bssid, buf);
+ (void) dladm_wlan_bssid2str(&attrp->wa_bssid, buf);
break;
case DLADM_WLAN_ATTR_SECMODE:
- str = dladm_wlan_secmode2str(&attrp->wa_secmode, buf);
+ (void) dladm_wlan_secmode2str(&attrp->wa_secmode, buf);
break;
case DLADM_WLAN_ATTR_STRENGTH:
- str = dladm_wlan_strength2str(&attrp->wa_strength, buf);
+ (void) dladm_wlan_strength2str(&attrp->wa_strength, buf);
break;
case DLADM_WLAN_ATTR_MODE:
- str = dladm_wlan_mode2str(&attrp->wa_mode, buf);
+ (void) dladm_wlan_mode2str(&attrp->wa_mode, buf);
break;
case DLADM_WLAN_ATTR_SPEED:
- str = dladm_wlan_speed2str(&attrp->wa_speed, buf);
+ (void) dladm_wlan_speed2str(&attrp->wa_speed, buf);
(void) strlcat(buf, "Mb", sizeof (buf));
break;
case DLADM_WLAN_ATTR_AUTH:
- str = dladm_wlan_auth2str(&attrp->wa_auth, buf);
+ (void) dladm_wlan_auth2str(&attrp->wa_auth, buf);
break;
case DLADM_WLAN_ATTR_BSSTYPE:
- str = dladm_wlan_bsstype2str(&attrp->wa_bsstype, buf);
+ (void) dladm_wlan_bsstype2str(&attrp->wa_bsstype, buf);
break;
}
- print_wifi_field(statep, wfp, str);
+ return (buf);
}
static boolean_t
print_scan_results(void *arg, dladm_wlan_attr_t *attrp)
{
print_wifi_state_t *statep = arg;
- int i;
+ wlan_scan_args_t warg;
if (statep->ws_header) {
statep->ws_header = B_FALSE;
if (!statep->ws_parseable)
- print_wifi_head(statep);
+ print_header(&statep->ws_print_state);
}
- statep->ws_overflow = 0;
- for (i = 0; i < statep->ws_nfields; i++) {
- statep->ws_lastfield = (i + 1 == statep->ws_nfields);
- print_wlan_attr(statep, statep->ws_fields[i], attrp);
- }
- (void) putchar('\n');
+ statep->ws_print_state.ps_overflow = 0;
+ bzero(&warg, sizeof (warg));
+ warg.ws_state = statep;
+ warg.ws_attr = attrp;
+ dladm_print_output(&statep->ws_print_state, statep->ws_parseable,
+ print_wlan_attr, &warg);
return (B_TRUE);
}
@@ -2987,8 +3757,8 @@ scan_wifi(datalink_id_t linkid, void *arg)
dladm_status_t status;
char link[MAXLINKNAMELEN];
- if (dladm_datalink_id2info(linkid, NULL, NULL, NULL, link,
- sizeof (link)) != DLADM_STATUS_OK) {
+ if ((status = dladm_datalink_id2info(linkid, NULL, NULL, NULL, link,
+ sizeof (link))) != DLADM_STATUS_OK) {
return (DLADM_WALK_CONTINUE);
}
@@ -3000,33 +3770,40 @@ scan_wifi(datalink_id_t linkid, void *arg)
return (DLADM_WALK_CONTINUE);
}
-static void
-print_link_attr(print_wifi_state_t *statep, wifi_field_t *wfp,
- dladm_wlan_linkattr_t *attrp)
+static char *
+print_link_attr(print_field_t *wfp, void *warg)
{
- char buf[DLADM_STRSIZE];
- const char *str = "";
-
- if (strcmp(wfp->wf_name, "status") == 0) {
- if ((wfp->wf_mask & attrp->la_valid) != 0)
- str = dladm_wlan_linkstatus2str(&attrp->la_status, buf);
- print_wifi_field(statep, wfp, str);
- return;
+ static char buf[DLADM_STRSIZE];
+ char *ptr;
+ wlan_scan_args_t *w = warg, w1;
+ print_wifi_state_t *statep = w->ws_state;
+ dladm_wlan_linkattr_t *attrp = w->ws_attr;
+
+ if (strcmp(wfp->pf_name, "status") == 0) {
+ if ((wfp->pf_index & attrp->la_valid) != 0)
+ (void) dladm_wlan_linkstatus2str(
+ &attrp->la_status, buf);
+ return (buf);
}
- print_wlan_attr(statep, wfp, &attrp->la_wlan_attr);
+ statep->ws_print_state.ps_overflow = 0;
+ bzero(&w1, sizeof (w1));
+ w1.ws_state = statep;
+ w1.ws_attr = &attrp->la_wlan_attr;
+ ptr = print_wlan_attr(wfp, &w1);
+ return (ptr);
}
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];
+ wlan_scan_args_t warg;
- if (dladm_datalink_id2info(linkid, NULL, NULL, NULL, link,
- sizeof (link)) != DLADM_STATUS_OK) {
+ if ((status = dladm_datalink_id2info(linkid, NULL, NULL, NULL, link,
+ sizeof (link))) != DLADM_STATUS_OK) {
return (DLADM_WALK_CONTINUE);
}
@@ -3039,15 +3816,15 @@ show_wifi(datalink_id_t linkid, void *arg)
if (statep->ws_header) {
statep->ws_header = B_FALSE;
if (!statep->ws_parseable)
- print_wifi_head(statep);
+ print_header(&statep->ws_print_state);
}
- 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');
+ statep->ws_print_state.ps_overflow = 0;
+ bzero(&warg, sizeof (warg));
+ warg.ws_state = statep;
+ warg.ws_attr = &attr;
+ dladm_print_output(&statep->ws_print_state, statep->ws_parseable,
+ print_link_attr, &warg);
return (DLADM_WALK_CONTINUE);
}
@@ -3056,7 +3833,7 @@ do_display_wifi(int argc, char **argv, int cmd)
{
int option;
char *fields_str = NULL;
- wifi_field_t **fields;
+ print_field_t **fields;
int (*callback)(datalink_id_t, void *);
uint_t nfields;
print_wifi_state_t state;
@@ -3102,8 +3879,9 @@ do_display_wifi(int argc, char **argv, int cmd)
if (parse_wifi_fields(fields_str, &fields, &nfields, cmd) < 0)
die("invalid field(s) specified");
- state.ws_fields = fields;
- state.ws_nfields = nfields;
+ bzero(&state.ws_print_state, sizeof (state.ws_print_state));
+ state.ws_print_state.ps_fields = fields;
+ state.ws_print_state.ps_nfields = nfields;
if (linkid == DATALINK_ALL_LINKID) {
(void) dladm_walk_datalink_id(callback, &state,
@@ -3423,32 +4201,6 @@ do_disconnect_wifi(int argc, char **argv)
die_dlerr(status, "cannot disconnect");
}
-#define MAX_PROPS 32
-#define MAX_PROP_LINE 512
-
-typedef struct prop_info {
- char *pi_name;
- char *pi_val[DLADM_MAX_PROP_VALCNT];
- uint_t pi_count;
-} prop_info_t;
-
-typedef struct prop_list {
- prop_info_t pl_info[MAX_PROPS];
- uint_t pl_count;
- char *pl_buf;
-} prop_list_t;
-
-typedef struct show_linkprop_state {
- char ls_link[MAXLINKNAMELEN];
- char *ls_line;
- char **ls_propvals;
- prop_list_t *ls_proplist;
- uint32_t ls_parseable : 1,
- ls_persist : 1,
- ls_header : 1,
- ls_pad_bits : 29;
- dladm_status_t ls_status;
-} show_linkprop_state_t;
static void
free_props(prop_list_t *list)
@@ -3476,6 +4228,19 @@ parse_props(char *str, prop_list_t **listp, boolean_t novalues)
if (buf == NULL)
goto fail;
+ /*
+ * buf is a string of form [<propname>=<value>][,<propname>=<value>]+
+ * where each <value> string itself could be a comma-separated array.
+ * The loop below will count the number of propname assignments
+ * in pl_count; for each property, there is a pip entry with
+ * pi_name == <propname>, pi_count == # of elements in <value> array.
+ * pi_val[] contains the actual values.
+ *
+ * This could really be a combination of calls to
+ * strtok (token delimiter is ",") and strchr (chr '=')
+ * with appropriate null/string-bound-checks.
+ */
+
curr = buf;
len = strlen(buf);
pip = NULL;
@@ -3523,15 +4288,8 @@ fail:
}
static void
-print_linkprop_head(void)
-{
- (void) printf("%-12s %-15s %-14s %-14s %-20s \n",
- "LINK", "PROPERTY", "VALUE", "DEFAULT", "POSSIBLE");
-}
-
-static void
print_linkprop(datalink_id_t linkid, show_linkprop_state_t *statep,
- const char *propname, dladm_prop_type_t type, const char *typename,
+ const char *propname, dladm_prop_type_t type,
const char *format, char **pptr)
{
int i;
@@ -3551,6 +4309,7 @@ print_linkprop(datalink_id_t linkid, show_linkprop_state_t *statep,
propvals = &unknown;
} else {
statep->ls_status = status;
+ statep->ls_retstatus = status;
return;
}
} else if (status == DLADM_STATUS_NOTSUP ||
@@ -3561,21 +4320,25 @@ print_linkprop(datalink_id_t linkid, show_linkprop_state_t *statep,
else
propvals = &notsup;
} else {
- statep->ls_status = status;
- if (statep->ls_proplist) {
+ if (statep->ls_proplist &&
+ statep->ls_status == DLADM_STATUS_OK) {
warn_dlerr(status,
"cannot get link property '%s' for %s",
propname, statep->ls_link);
}
+ statep->ls_status = status;
+ statep->ls_retstatus = status;
return;
}
}
+ statep->ls_status = DLADM_STATUS_OK;
+
ptr = buf;
lim = buf + DLADM_STRSIZE;
for (i = 0; i < valcnt; i++) {
if (propvals[i][0] == '\0' && !statep->ls_parseable)
- ptr += snprintf(ptr, lim - ptr, "--,");
+ ptr += snprintf(ptr, lim - ptr, STR_UNDEF_VAL",");
else
ptr += snprintf(ptr, lim - ptr, "%s,", propvals[i]);
if (ptr >= lim)
@@ -3587,58 +4350,87 @@ print_linkprop(datalink_id_t linkid, show_linkprop_state_t *statep,
lim = statep->ls_line + MAX_PROP_LINE;
if (statep->ls_parseable) {
*pptr += snprintf(*pptr, lim - *pptr,
- "%s=\"%s\" ", typename, buf);
+ "%s", buf);
} else {
*pptr += snprintf(*pptr, lim - *pptr, format, buf);
}
}
-static int
-show_linkprop(datalink_id_t linkid, const char *propname, void *arg)
+static char *
+linkprop_callback(print_field_t *pf, void *ls_arg)
{
- show_linkprop_state_t *statep = arg;
+ linkprop_args_t *arg = ls_arg;
+ char *propname = arg->ls_propname;
+ show_linkprop_state_t *statep = arg->ls_state;
char *ptr = statep->ls_line;
char *lim = ptr + MAX_PROP_LINE;
+ datalink_id_t linkid = arg->ls_linkid;
- if (statep->ls_parseable)
- ptr += snprintf(ptr, lim - ptr, "LINK=\"%s\" ",
- statep->ls_link);
- else
- ptr += snprintf(ptr, lim - ptr, "%-12s ", statep->ls_link);
-
- if (statep->ls_parseable)
- ptr += snprintf(ptr, lim - ptr, "PROPERTY=\"%s\" ", propname);
- else
- ptr += snprintf(ptr, lim - ptr, "%-15s ", propname);
-
- print_linkprop(linkid, statep, propname,
- statep->ls_persist ? DLADM_PROP_VAL_PERSISTENT :
- DLADM_PROP_VAL_CURRENT, "VALUE", "%-14s ", &ptr);
-
- /*
- * If we failed to query the link property, for example, query
- * the persistent value of a non-persistable link property, simply
- * skip the output.
- */
+ switch (pf->pf_index) {
+ case LINKPROP_LINK:
+ (void) snprintf(ptr, lim - ptr, "%s", statep->ls_link);
+ break;
+ case LINKPROP_PROPERTY:
+ (void) snprintf(ptr, lim - ptr, "%s", propname);
+ break;
+ case LINKPROP_VALUE:
+ print_linkprop(linkid, statep, propname,
+ statep->ls_persist ? DLADM_PROP_VAL_PERSISTENT :
+ DLADM_PROP_VAL_CURRENT, "%s", &ptr);
+ /*
+ * If we failed to query the link property, for example, query
+ * the persistent value of a non-persistable link property,
+ * simply skip the output.
+ */
+ if (statep->ls_status != DLADM_STATUS_OK)
+ goto skip;
+ ptr = statep->ls_line;
+ break;
+ case LINKPROP_DEFAULT:
+ print_linkprop(linkid, statep, propname,
+ DLADM_PROP_VAL_DEFAULT, "%s", &ptr);
+ if (statep->ls_status != DLADM_STATUS_OK)
+ goto skip;
+ ptr = statep->ls_line;
+ break;
+ case LINKPROP_POSSIBLE:
+ print_linkprop(linkid, statep, propname,
+ DLADM_PROP_VAL_MODIFIABLE, "%s ", &ptr);
+ if (statep->ls_status != DLADM_STATUS_OK)
+ goto skip;
+ ptr = statep->ls_line;
+ break;
+ default:
+ die("invalid input");
+ break;
+ }
+ return (ptr);
+skip:
if (statep->ls_status != DLADM_STATUS_OK)
- return (DLADM_WALK_CONTINUE);
+ return (NULL);
+ else
+ return ("");
+}
- print_linkprop(linkid, statep, propname, DLADM_PROP_VAL_DEFAULT,
- "DEFAULT", "%-14s ", &ptr);
- if (statep->ls_status != DLADM_STATUS_OK)
- return (DLADM_WALK_CONTINUE);
+static int
+show_linkprop(datalink_id_t linkid, const char *propname, void *arg)
+{
+ show_linkprop_state_t *statep = arg;
+ linkprop_args_t ls_arg;
- print_linkprop(linkid, statep, propname, DLADM_PROP_VAL_MODIFIABLE,
- "POSSIBLE", "%-20s ", &ptr);
- if (statep->ls_status != DLADM_STATUS_OK)
- return (DLADM_WALK_CONTINUE);
+ bzero(&ls_arg, sizeof (ls_arg));
+ ls_arg.ls_state = statep;
+ ls_arg.ls_propname = (char *)propname;
+ ls_arg.ls_linkid = linkid;
if (statep->ls_header) {
statep->ls_header = B_FALSE;
if (!statep->ls_parseable)
- print_linkprop_head();
+ print_header(&statep->ls_print);
}
- (void) printf("%s\n", statep->ls_line);
+ dladm_print_output(&statep->ls_print, statep->ls_parseable,
+ linkprop_callback, (void *)&ls_arg);
+
return (DLADM_WALK_CONTINUE);
}
@@ -3651,6 +4443,13 @@ do_show_linkprop(int argc, char **argv)
show_linkprop_state_t state;
uint32_t flags = DLADM_OPT_ACTIVE;
dladm_status_t status;
+ char *fields_str = NULL;
+ print_field_t **fields;
+ uint_t nfields;
+ char *all_fields =
+ "link,property,value,default,possible";
+
+ fields_str = all_fields;
opterr = 0;
state.ls_propvals = NULL;
@@ -3658,7 +4457,8 @@ do_show_linkprop(int argc, char **argv)
state.ls_parseable = B_FALSE;
state.ls_persist = B_FALSE;
state.ls_header = B_TRUE;
- while ((option = getopt_long(argc, argv, ":p:cP",
+ state.ls_retstatus = DLADM_STATUS_OK;
+ while ((option = getopt_long(argc, argv, ":p:cPo:",
prop_longopts, NULL)) != -1) {
switch (option) {
case 'p':
@@ -3672,6 +4472,12 @@ do_show_linkprop(int argc, char **argv)
state.ls_persist = B_TRUE;
flags = DLADM_OPT_PERSIST;
break;
+ case 'o':
+ if (strcasecmp(optarg, "all") == 0)
+ fields_str = all_fields;
+ else
+ fields_str = optarg;
+ break;
default:
die_opterr(optopt, option);
break;
@@ -3687,9 +4493,20 @@ do_show_linkprop(int argc, char **argv)
usage();
}
+ bzero(&state.ls_print, sizeof (print_state_t));
state.ls_proplist = proplist;
state.ls_status = DLADM_STATUS_OK;
+ fields = parse_output_fields(fields_str, linkprop_fields,
+ LINKPROP_MAX_FIELDS, CMD_TYPE_ANY, &nfields);
+
+ if (fields == NULL) {
+ die("invalid field(s) specified");
+ return;
+ }
+
+ state.ls_print.ps_fields = fields;
+ state.ls_print.ps_nfields = nfields;
if (linkid == DATALINK_ALL_LINKID) {
(void) dladm_walk_datalink_id(show_linkprop_onelink, &state,
DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE, flags);
@@ -3698,13 +4515,8 @@ do_show_linkprop(int argc, char **argv)
}
free_props(proplist);
- if (state.ls_status != DLADM_STATUS_OK) {
- if (optind == (argc - 1)) {
- warn_dlerr(state.ls_status,
- "show-linkprop failed for %s", argv[optind]);
- }
+ if (state.ls_retstatus != DLADM_STATUS_OK)
exit(EXIT_FAILURE);
- }
}
static int
@@ -3839,8 +4651,9 @@ set_linkprop(int argc, char **argv, boolean_t reset)
die_dlerr(status, "link %s is not valid", argv[optind]);
if (proplist == NULL) {
- if ((status = dladm_set_linkprop(linkid, NULL, NULL, 0,
- DLADM_OPT_ACTIVE)) != DLADM_STATUS_OK) {
+ status = dladm_set_linkprop(linkid, NULL, NULL, 0,
+ DLADM_OPT_ACTIVE);
+ if (status != DLADM_STATUS_OK) {
warn_dlerr(status, "cannot reset link property "
"on '%s'", argv[optind]);
}
@@ -4347,18 +5160,10 @@ do_delete_secobj(int argc, char **argv)
typedef struct show_secobj_state {
boolean_t ss_persist;
boolean_t ss_parseable;
- boolean_t ss_debug;
boolean_t ss_header;
+ print_state_t ss_print;
} show_secobj_state_t;
-static void
-print_secobj_head(show_secobj_state_t *statep)
-{
- (void) printf("%-20s %-20s ", "OBJECT", "CLASS");
- if (statep->ss_debug)
- (void) printf("%-30s", "VALUE");
- (void) putchar('\n');
-}
static boolean_t
show_secobj(void *arg, const char *obj_name)
@@ -4370,6 +5175,7 @@ show_secobj(void *arg, const char *obj_name)
dladm_secobj_class_t class;
show_secobj_state_t *statep = arg;
dladm_status_t status;
+ secobj_fields_buf_t sbuf;
if (statep->ss_persist)
flags |= DLADM_OPT_PERSIST;
@@ -4381,29 +5187,23 @@ show_secobj(void *arg, const char *obj_name)
if (statep->ss_header) {
statep->ss_header = B_FALSE;
if (!statep->ss_parseable)
- print_secobj_head(statep);
- }
-
- if (statep->ss_parseable) {
- (void) printf("OBJECT=\"%s\" CLASS=\"%s\" ", obj_name,
- dladm_secobjclass2str(class, buf));
- } else {
- (void) printf("%-20s %-20s ", obj_name,
- dladm_secobjclass2str(class, buf));
+ print_header(&statep->ss_print);
}
- if (statep->ss_debug) {
+ (void) snprintf(sbuf.ss_obj_name, sizeof (sbuf.ss_obj_name),
+ obj_name);
+ (void) dladm_secobjclass2str(class, buf);
+ (void) snprintf(sbuf.ss_class, sizeof (sbuf.ss_class), "%s", buf);
+ if (getuid() == 0) {
char val[DLADM_SECOBJ_VAL_MAX * 2];
uint_t len = sizeof (val);
- if (octet_to_hexascii(obj_val, obj_len, val, &len) == 0) {
- if (statep->ss_parseable)
- (void) printf("VALUE=\"0x%s\"", val);
- else
- (void) printf("0x%-30s", val);
- }
+ if (octet_to_hexascii(obj_val, obj_len, val, &len) == 0)
+ (void) snprintf(sbuf.ss_val,
+ sizeof (sbuf.ss_val), "%s", val);
}
- (void) putchar('\n');
+ dladm_print_output(&statep->ss_print, statep->ss_parseable,
+ dladm_print_field, (void *)&sbuf);
return (B_TRUE);
}
@@ -4416,13 +5216,20 @@ do_show_secobj(int argc, char **argv)
uint_t i;
split_t *sp;
uint_t flags;
+ char *fields_str = NULL;
+ print_field_t **fields;
+ uint_t nfields;
+ char *def_fields = "object,class";
+ char *all_fields = "object,class,value";
opterr = 0;
+ bzero(&state, sizeof (state));
+ state.ss_parseable = B_FALSE;
+ fields_str = def_fields;
state.ss_persist = B_FALSE;
state.ss_parseable = B_FALSE;
- state.ss_debug = B_FALSE;
state.ss_header = B_TRUE;
- while ((option = getopt_long(argc, argv, ":pPd",
+ while ((option = getopt_long(argc, argv, ":pPo:",
wifi_longopts, NULL)) != -1) {
switch (option) {
case 'p':
@@ -4431,10 +5238,11 @@ do_show_secobj(int argc, char **argv)
case 'P':
state.ss_persist = B_TRUE;
break;
- case 'd':
- if (getuid() != 0)
- die("insufficient privileges");
- state.ss_debug = B_TRUE;
+ case 'o':
+ if (strcasecmp(optarg, "all") == 0)
+ fields_str = all_fields;
+ else
+ fields_str = optarg;
break;
default:
die_opterr(optopt, option);
@@ -4442,6 +5250,17 @@ do_show_secobj(int argc, char **argv)
}
}
+ fields = parse_output_fields(fields_str, secobj_fields,
+ DEV_SOBJ_FIELDS, CMD_TYPE_ANY, &nfields);
+
+ if (fields == NULL) {
+ die("invalid field(s) specified");
+ return;
+ }
+ state.ss_print.ps_fields = fields;
+ state.ss_print.ps_nfields = nfields;
+
+ flags = state.ss_persist ? DLADM_OPT_PERSIST : 0;
if (optind == (argc - 1)) {
sp = split(argv[optind], MAX_SECOBJS, MAX_SECOBJ_NAMELEN);
if (sp == NULL) {
@@ -4457,7 +5276,6 @@ do_show_secobj(int argc, char **argv)
} else if (optind != argc)
usage();
- flags = state.ss_persist ? DLADM_OPT_PERSIST : 0;
status = dladm_walk_secobj(&state, show_secobj, flags);
if (status != DLADM_STATUS_OK)
die_dlerr(status, "show-secobj");
@@ -4485,6 +5303,153 @@ do_init_linkprop(int argc, char **argv)
/* ARGSUSED */
static void
+do_show_ether(int argc, char **argv)
+{
+ int option;
+ datalink_id_t linkid;
+ print_ether_state_t state;
+ print_field_t **fields;
+ char *fields_str;
+ uint_t nfields;
+ char *all_fields =
+ "link,ptype,state,auto,speed-duplex,pause,rem_fault";
+ char *default_fields =
+ "link,ptype,state,auto,speed-duplex,pause";
+
+ fields_str = default_fields;
+ bzero(&state, sizeof (state));
+ state.es_link = NULL;
+ state.es_parseable = B_FALSE;
+
+ while ((option = getopt_long(argc, argv, "o:px",
+ showeth_lopts, NULL)) != -1) {
+ switch (option) {
+ case 'x':
+ state.es_extended = B_TRUE;
+ break;
+ case 'p':
+ state.es_parseable = B_TRUE;
+ break;
+ case 'o':
+ if (strcasecmp(optarg, "all") == 0)
+ fields_str = all_fields;
+ else
+ fields_str = optarg;
+ break;
+ default:
+ die_opterr(optopt, option);
+ break;
+ }
+ }
+
+ if (optind == (argc - 1))
+ state.es_link = argv[optind];
+
+ fields = parse_output_fields(fields_str, ether_fields,
+ ETHER_MAX_FIELDS, CMD_TYPE_ANY, &nfields);
+
+ if (fields == NULL) {
+ die("invalid field(s) specified");
+ exit(EXIT_FAILURE);
+ }
+ state.es_print.ps_fields = fields;
+ state.es_print.ps_nfields = nfields;
+
+ if (state.es_link == NULL) {
+ (void) dladm_walk_datalink_id(show_etherprop, &state,
+ DATALINK_CLASS_PHYS, DL_ETHER,
+ DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST);
+ } else {
+ if (!link_is_ether(state.es_link, &linkid)) {
+ die("invalid link specified");
+ }
+ (void) show_etherprop(linkid, &state);
+ }
+
+ exit(DLADM_STATUS_OK);
+
+}
+
+static char *
+dladm_print_field(print_field_t *pf, void *arg)
+{
+ char *value;
+
+ value = (char *)arg + pf->pf_offset;
+ return (value);
+}
+
+static int
+show_etherprop(datalink_id_t linkid, void *arg)
+{
+ print_ether_state_t *statep = arg;
+ char buf[DLADM_STRSIZE];
+ int speed;
+ uint64_t s;
+ uint32_t autoneg, pause, asmpause, adv_rf, cap_rf, lp_rf;
+ ether_fields_buf_t ebuf;
+ char speed_unit = 'M';
+
+ if (dladm_datalink_id2info(linkid, NULL, NULL, NULL,
+ ebuf.eth_link, sizeof (ebuf.eth_link)) != DLADM_STATUS_OK) {
+ return (DLADM_WALK_CONTINUE);
+ }
+
+ if (!statep->es_header && !statep->es_parseable) {
+ print_header(&statep->es_print);
+ statep->es_header = B_TRUE;
+ }
+ (void) snprintf(ebuf.eth_ptype, sizeof (ebuf.eth_ptype),
+ "%s", "current");
+
+ (void) dladm_get_single_mac_stat(linkid, "link_autoneg",
+ KSTAT_DATA_UINT32, &autoneg);
+ (void) snprintf(ebuf.eth_autoneg, sizeof (ebuf.eth_autoneg),
+ "%s", (autoneg ? "yes" : "no"));
+
+ (void) dladm_get_single_mac_stat(linkid, "link_pause",
+ KSTAT_DATA_UINT32, &pause);
+ (void) dladm_get_single_mac_stat(linkid, "link_asmpause",
+ KSTAT_DATA_UINT32, &asmpause);
+ (void) snprintf(ebuf.eth_pause, sizeof (ebuf.eth_pause),
+ "%s", pause_str(pause, asmpause));
+
+ (void) dladm_get_single_mac_stat(linkid, "ifspeed",
+ KSTAT_DATA_UINT64, &s);
+ speed = (int)(s/1000000ull);
+
+ if (speed >= 1000) {
+ speed = speed/1000;
+ speed_unit = 'G';
+ }
+ (void) get_linkduplex(ebuf.eth_link, B_FALSE, buf);
+ (void) snprintf(ebuf.eth_spdx, sizeof (ebuf.eth_spdx), "%d%c-%c",
+ speed, speed_unit, buf[0]);
+
+ (void) get_linkstate(ebuf.eth_link, B_FALSE, buf);
+ (void) snprintf(ebuf.eth_state, sizeof (ebuf.eth_state),
+ "%s", buf);
+
+ (void) dladm_get_single_mac_stat(linkid, "adv_rem_fault",
+ KSTAT_DATA_UINT32, &adv_rf);
+ (void) dladm_get_single_mac_stat(linkid, "cap_rem_fault",
+ KSTAT_DATA_UINT32, &cap_rf);
+ (void) dladm_get_single_mac_stat(linkid, "lp_rem_fault",
+ KSTAT_DATA_UINT32, &lp_rf);
+ (void) snprintf(ebuf.eth_rem_fault, sizeof (ebuf.eth_rem_fault),
+ "%s", (adv_rf == 0 && lp_rf == 0 ? "none" : "fault"));
+
+ dladm_print_output(&statep->es_print, statep->es_parseable,
+ dladm_print_field, &ebuf);
+
+ if (statep->es_extended)
+ show_ether_xprop(linkid, arg);
+
+ return (DLADM_WALK_CONTINUE);
+}
+
+/* ARGSUSED */
+static void
do_init_secobj(int argc, char **argv)
{
dladm_status_t status;
@@ -4657,3 +5622,224 @@ die_opterr(int opt, int opterr)
break;
}
}
+
+static void
+show_ether_xprop(datalink_id_t linkid, void *arg)
+{
+ print_ether_state_t *statep = arg;
+ char buf[DLADM_STRSIZE];
+ uint32_t autoneg, pause, asmpause, adv_rf, cap_rf, lp_rf;
+ boolean_t add_comma, r1;
+ ether_fields_buf_t ebuf;
+
+ /* capable */
+ bzero(&ebuf, sizeof (ebuf));
+ (void) snprintf(ebuf.eth_link, sizeof (ebuf.eth_link), "");
+
+ (void) snprintf(ebuf.eth_ptype, sizeof (ebuf.eth_ptype),
+ "%s", "capable");
+ (void) snprintf(ebuf.eth_state, sizeof (ebuf.eth_state),
+ STR_UNDEF_VAL);
+
+ (void) dladm_get_single_mac_stat(linkid, "cap_autoneg",
+ KSTAT_DATA_UINT32, &autoneg);
+ (void) snprintf(ebuf.eth_autoneg, sizeof (ebuf.eth_autoneg),
+ "%s", (autoneg ? "yes" : "no"));
+
+ add_comma = B_FALSE;
+ bzero(buf, sizeof (buf));
+ r1 = get_speed_duplex(linkid, "cap_1000", buf, "1G", B_FALSE);
+ if (r1)
+ add_comma = B_TRUE;
+ r1 = get_speed_duplex(linkid, "cap_100", buf, "100M", add_comma);
+ if (r1)
+ add_comma = B_TRUE;
+ r1 = get_speed_duplex(linkid, "cap_10", buf, "10M", add_comma);
+ add_comma = B_FALSE;
+ (void) snprintf(ebuf.eth_spdx, sizeof (ebuf.eth_spdx), "%s", buf);
+
+ (void) dladm_get_single_mac_stat(linkid, "cap_pause",
+ KSTAT_DATA_UINT32, &pause);
+ (void) dladm_get_single_mac_stat(linkid, "cap_asmpause",
+ KSTAT_DATA_UINT32, &asmpause);
+ (void) snprintf(ebuf.eth_pause, sizeof (ebuf.eth_pause),
+ "%s", pause_str(pause, asmpause));
+
+ (void) dladm_get_single_mac_stat(linkid, "adv_rem_fault",
+ KSTAT_DATA_UINT32, &adv_rf);
+ (void) dladm_get_single_mac_stat(linkid, "cap_rem_fault",
+ KSTAT_DATA_UINT32, &cap_rf);
+ (void) dladm_get_single_mac_stat(linkid, "lp_rem_fault",
+ KSTAT_DATA_UINT32, &lp_rf);
+
+ (void) snprintf(ebuf.eth_rem_fault, sizeof (ebuf.eth_rem_fault),
+ "%s", (cap_rf ? "yes" : "no"));
+
+ dladm_print_output(&statep->es_print, statep->es_parseable,
+ dladm_print_field, &ebuf);
+
+ /* advertised */
+ bzero(&ebuf, sizeof (ebuf));
+ (void) snprintf(ebuf.eth_ptype, sizeof (ebuf.eth_ptype),
+ "%s", "adv");
+ (void) snprintf(ebuf.eth_state, sizeof (ebuf.eth_state),
+ STR_UNDEF_VAL);
+
+ (void) dladm_get_single_mac_stat(linkid, "adv_cap_autoneg",
+ KSTAT_DATA_UINT32, &autoneg);
+ (void) snprintf(ebuf.eth_autoneg, sizeof (ebuf.eth_autoneg),
+ "%s", (autoneg ? "yes" : "no"));
+
+ add_comma = B_FALSE;
+ bzero(buf, sizeof (buf));
+ r1 = get_speed_duplex(linkid, "adv_cap_1000", buf, "1G", add_comma);
+ if (r1)
+ add_comma = B_TRUE;
+ r1 = get_speed_duplex(linkid, "adv_cap_100", buf, "100M", add_comma);
+ if (r1)
+ add_comma = B_TRUE;
+ r1 = get_speed_duplex(linkid, "adv_cap_10", buf, "10M", add_comma);
+ add_comma = B_FALSE;
+ (void) snprintf(ebuf.eth_spdx, sizeof (ebuf.eth_spdx), "%s", buf);
+
+ (void) dladm_get_single_mac_stat(linkid, "adv_cap_pause",
+ KSTAT_DATA_UINT32, &pause);
+ (void) dladm_get_single_mac_stat(linkid, "adv_cap_asmpause",
+ KSTAT_DATA_UINT32, &asmpause);
+ (void) snprintf(ebuf.eth_pause, sizeof (ebuf.eth_pause),
+ "%s", pause_str(pause, asmpause));
+
+ (void) snprintf(ebuf.eth_rem_fault, sizeof (ebuf.eth_rem_fault),
+ "%s", (adv_rf ? "fault" : "none"));
+
+ dladm_print_output(&statep->es_print, statep->es_parseable,
+ dladm_print_field, &ebuf);
+
+ /* peeradv */
+ bzero(&ebuf, sizeof (ebuf));
+ (void) snprintf(ebuf.eth_ptype, sizeof (ebuf.eth_ptype),
+ "%s", "peeradv");
+ (void) snprintf(ebuf.eth_state, sizeof (ebuf.eth_state),
+ STR_UNDEF_VAL);
+
+ (void) dladm_get_single_mac_stat(linkid, "lp_cap_autoneg",
+ KSTAT_DATA_UINT32, &autoneg);
+ (void) snprintf(ebuf.eth_autoneg, sizeof (ebuf.eth_autoneg),
+ "%s", (autoneg ? "yes" : "no"));
+
+ add_comma = B_FALSE;
+ bzero(buf, sizeof (buf));
+ r1 = get_speed_duplex(linkid, "lp_cap_1000", buf, "1G", add_comma);
+ if (r1)
+ add_comma = B_TRUE;
+ r1 = get_speed_duplex(linkid, "lp_cap_100", buf, "100M", add_comma);
+ if (r1)
+ add_comma = B_TRUE;
+ r1 = get_speed_duplex(linkid, "lp_cap_10", buf, "10M", add_comma);
+ (void) snprintf(ebuf.eth_spdx, sizeof (ebuf.eth_spdx), "%s", buf);
+
+ (void) dladm_get_single_mac_stat(linkid, "lp_cap_pause",
+ KSTAT_DATA_UINT32, &pause);
+ (void) dladm_get_single_mac_stat(linkid, "lp_cap_asmpause",
+ KSTAT_DATA_UINT32, &asmpause);
+ (void) snprintf(ebuf.eth_pause, sizeof (ebuf.eth_pause),
+ "%s", pause_str(pause, asmpause));
+
+ (void) snprintf(ebuf.eth_rem_fault, sizeof (ebuf.eth_rem_fault),
+ "%s", (lp_rf ? "fault" : "none"));
+
+ dladm_print_output(&statep->es_print, statep->es_parseable,
+ dladm_print_field, &ebuf);
+}
+
+static boolean_t
+get_speed_duplex(datalink_id_t linkid, const char *mii_prop_prefix,
+ char *spbuf, char *sp, boolean_t add_comma)
+{
+ int speed, duplex = 0;
+ boolean_t ret = B_FALSE;
+ char mii_prop[DLADM_STRSIZE];
+
+ (void) snprintf(mii_prop, DLADM_STRSIZE, "%sfdx", mii_prop_prefix);
+ (void) dladm_get_single_mac_stat(linkid, mii_prop, KSTAT_DATA_UINT32,
+ &speed);
+ if (speed) {
+ ret = B_TRUE;
+ duplex |= IS_FDX;
+ }
+ (void) snprintf(mii_prop, DLADM_STRSIZE, "%shdx", mii_prop_prefix);
+ (void) dladm_get_single_mac_stat(linkid, mii_prop,
+ KSTAT_DATA_UINT32, &speed);
+ if (speed) {
+ ret = B_TRUE;
+ duplex |= IS_HDX;
+ }
+ if (ret) {
+ if (add_comma)
+ (void) strncat(spbuf, ",", DLADM_STRSIZE);
+ (void) strncat(spbuf, sp, DLADM_STRSIZE);
+ if ((duplex & (IS_FDX|IS_HDX)) == (IS_FDX|IS_HDX))
+ (void) strncat(spbuf, "-fh", DLADM_STRSIZE);
+ else if (duplex & IS_FDX)
+ (void) strncat(spbuf, "-f", DLADM_STRSIZE);
+ else if (duplex & IS_HDX)
+ (void) strncat(spbuf, "-h", DLADM_STRSIZE);
+ }
+ return (ret);
+}
+
+static void
+dladm_print_output(print_state_t *statep, boolean_t parseable,
+ print_callback_t fn, void *arg)
+{
+ int i;
+ char *value;
+ print_field_t **pf;
+
+ pf = statep->ps_fields;
+ for (i = 0; i < statep->ps_nfields; i++) {
+ statep->ps_lastfield = (i + 1 == statep->ps_nfields);
+ value = (*fn)(pf[i], arg);
+ if (value != NULL)
+ print_field(statep, pf[i], value, parseable);
+ }
+ (void) putchar('\n');
+}
+
+static void
+print_header(print_state_t *ps)
+{
+ int i;
+ print_field_t **pf;
+
+ pf = ps->ps_fields;
+ for (i = 0; i < ps->ps_nfields; i++) {
+ ps->ps_lastfield = (i + 1 == ps->ps_nfields);
+ print_field(ps, pf[i], pf[i]->pf_header, B_FALSE);
+ }
+ (void) putchar('\n');
+}
+
+static char *
+pause_str(int pause, int asmpause)
+{
+ if (pause == 1)
+ return ("bi");
+ if (asmpause == 1)
+ return ("tx");
+ return ("none");
+}
+
+static boolean_t
+link_is_ether(const char *link, datalink_id_t *linkid)
+{
+ uint32_t media;
+ datalink_class_t class;
+
+ if (dladm_name2info(link, linkid, NULL, &class, &media) ==
+ DLADM_STATUS_OK) {
+ if (class == DATALINK_CLASS_PHYS && media == DL_ETHER)
+ return (B_TRUE);
+ }
+ return (B_FALSE);
+}
diff --git a/usr/src/cmd/dladm/dladm.xcl b/usr/src/cmd/dladm/dladm.xcl
index c48e5d4bbb..b849b22f79 100644
--- a/usr/src/cmd/dladm/dladm.xcl
+++ b/usr/src/cmd/dladm/dladm.xcl
@@ -83,24 +83,30 @@ msgid ":p:cP"
msgid ":pPd"
msgid ":psi:"
msgid "?"
+msgid "100M"
msgid "ADT_dladm_create_secobj"
msgid "ADT_dladm_delete_secobj"
msgid "AUTH"
+msgid "AUTO"
msgid "BSSID/IBSSID"
msgid "BSSTYPE"
msgid "CLASS"
msgid "DEFAULT"
+msgid "DUPLEX"
msgid "ESSID"
msgid "LINK"
msgid "MODE"
msgid "Mb"
msgid "OBJECT"
msgid "OBJECT=\"%s\" CLASS=\"%s\" "
+msgid "PAUSE"
msgid "POSSIBLE"
msgid "PROPERTY"
msgid "PROPERTY=\"%s\" "
+msgid "REM_FAULT"
msgid "SEC"
msgid "SPEED"
+msgid "SPEED-DUPLEX"
msgid "STATUS"
msgid "STRENGTH"
msgid "VALUE"
@@ -116,6 +122,12 @@ msgid "\t\t%-10llu"
msgid "\t\tipackets rbytes ierrors "
msgid "\tipackets rbytes opackets obytes "
msgid "active"
+msgid "adv_cap_10"
+msgid "adv_cap_100"
+msgid "adv_cap_1000"
+msgid "adv_cap_asmpause"
+msgid "adv_cap_autoneg"
+msgid "adv_cap_pause"
msgid "add-aggr"
msgid "adt_alloc_event (%s): %s"
msgid "adt_start_session: %s"
@@ -125,13 +137,20 @@ msgid "all"
msgid "all-links"
msgid "attached"
msgid "auth"
+msgid "auto"
msgid "bssid"
msgid "bsstype"
+msgid "cap_pause"
+msgid "cap_10"
+msgid "cap_1000"
+msgid "cap_autoneg"
+msgid "capable"
msgid "connect-wifi"
msgid "create-aggr"
msgid "create-ibss"
msgid "create-secobj"
msgid "create-vlan"
+msgid "current"
msgid "delete-aggr"
msgid "delete-phys"
msgid "delete-secobj"
@@ -141,7 +160,9 @@ msgid "dev"
msgid "disconnect-wifi"
msgid "down"
msgid "down-aggr"
+msgid "duplex"
msgid "essid"
+msgid "fault"
msgid "file"
msgid "forever"
msgid "full"
@@ -152,19 +173,41 @@ msgid "ifspeed"
msgid "init-linkprop"
msgid "init-secobj"
msgid "interval"
+msgid "invalid input"
msgid "ipackets64"
msgid "key"
msgid "lacp"
msgid "lacp-mode"
msgid "lacp-timer"
msgid "link"
+msgid "link,class,mtu,state,over"
+msgid "link,device,media,flags"
msgid "link,essid,bssid,sec,strength,mode,speed"
msgid "link,essid,bssid,sec,strength,mode,speed,auth,bsstype"
+msgid "link,ipackets,rbytes,ierrors,opackets,obytes,oerrors"
+msgid "link,media,state,speed,duplex,device"
+msgid "link,property,value,default,possible"
+msgid "link,policy,addrpolicy,lacpactivity,lacptimer,flags"
+msigd "link,port,aggregatable,sync,coll,dist,defaulted,expired"
+msgid "link,port,ipackets,rbytes,opackets,obytes,ipktdist,opktdist"
+msgid "link,port,speed,duplex,state,address,portstate"
+msgid "link,state,speed,duplex"
+msgid "link,vid,over,flags"
msgid "link,status,essid,sec,strength,mode,speed"
msgid "link,status,essid,sec,strength,mode,speed,auth,bssid,bsstype"
+msgid "link_asmpause"
+msgid "link_autoneg"
msgid "link_duplex"
+msgid "link_pause"
msgid "link_state"
msgid "long"
+msgid "lp_cap_10"
+msgid "lp_cap_100"
+msgid "lp_cap_1000"
+msgid "lp_cap_autoneg"
+msgid "lp_cap_asmpause"
+msgid "lp_cap_pause"
+msgid "lp_rem_fault"
msgid "mac"
msgid "mode"
msgid "modify-aggr"
@@ -177,11 +220,14 @@ msgid "opackets64"
msgid "output"
msgid "parseable"
msgid "passive"
+msgid "pause"
+msgid "peeradv"
msgid "persistent"
msgid "policy"
msgid "prop"
msgid "r"
msgid "rbytes64"
+msgid "rem_fault"
msgid "remove-aggr"
msgid "rename-link"
msgid "reset-linkprop"
@@ -198,8 +244,10 @@ msgid "show-phys"
msgid "show-secobj"
msgid "show-wifi"
msgid "show-vlan"
+msgid "show-ether"
msgid "solaris.network.link.security"
msgid "speed"
+msgid "speed-duplex"
msgid "standby"
msgid "statistics"
msgid "status"
diff --git a/usr/src/lib/libdladm/Makefile.com b/usr/src/lib/libdladm/Makefile.com
index 4caeb08465..0f6419bd29 100644
--- a/usr/src/lib/libdladm/Makefile.com
+++ b/usr/src/lib/libdladm/Makefile.com
@@ -36,7 +36,8 @@ include ../../Makefile.lib
include ../../Makefile.rootfs
LIBS = $(DYNLIB) $(LINTLIB)
-LDLIBS += -ldevinfo -lc -linetutil -lsocket -lscf -lrcm -lnvpair
+LDLIBS += -ldevinfo -lc -linetutil -lsocket -lscf -lrcm \
+ -lnvpair -lkstat
SRCDIR = ../common
$(LINTLIB) := SRCS = $(SRCDIR)/$(LINTSRC)
diff --git a/usr/src/lib/libdladm/common/libdladm.c b/usr/src/lib/libdladm/common/libdladm.c
index 58f15038bc..5a25d01c9d 100644
--- a/usr/src/lib/libdladm/common/libdladm.c
+++ b/usr/src/lib/libdladm/common/libdladm.c
@@ -163,6 +163,8 @@ dladm_status_t
dladm_errno2status(int err)
{
switch (err) {
+ case 0:
+ return (DLADM_STATUS_OK);
case EINVAL:
return (DLADM_STATUS_BADARG);
case EEXIST:
diff --git a/usr/src/lib/libdladm/common/libdllink.c b/usr/src/lib/libdladm/common/libdllink.c
index bd046acda9..79e644c4e7 100644
--- a/usr/src/lib/libdladm/common/libdllink.c
+++ b/usr/src/lib/libdladm/common/libdllink.c
@@ -43,6 +43,7 @@
#include <libdllink.h>
#include <libdlmgmt.h>
#include <libdladm_impl.h>
+#include <libinetutil.h>
/*
* Return the attributes of the specified datalink from the DLD driver.
@@ -926,3 +927,100 @@ dladm_linkid2legacyname(datalink_id_t linkid, char *dev, size_t len)
done:
return (status);
}
+
+dladm_status_t
+dladm_get_single_mac_stat(datalink_id_t linkid, const char *name, uint8_t type,
+ void *val)
+{
+ char module[DLPI_LINKNAME_MAX];
+ uint_t instance;
+ char link[DLPI_LINKNAME_MAX];
+ dladm_status_t status;
+ uint32_t flags, media;
+ kstat_ctl_t *kcp;
+ kstat_t *ksp;
+ dladm_phys_attr_t dpap;
+
+ if ((status = dladm_datalink_id2info(linkid, &flags, NULL, &media,
+ link, DLPI_LINKNAME_MAX)) != DLADM_STATUS_OK)
+ return (status);
+
+ if (media != DL_ETHER)
+ return (DLADM_STATUS_LINKINVAL);
+
+ status = dladm_phys_info(linkid, &dpap, DLADM_OPT_PERSIST);
+
+ if (status != DLADM_STATUS_OK)
+ return (status);
+
+ status = dladm_parselink(dpap.dp_dev, module, &instance);
+
+ if (status != DLADM_STATUS_OK)
+ return (status);
+
+ if ((kcp = kstat_open()) == NULL)
+ return (dladm_errno2status(errno));
+
+ /*
+ * The kstat query could fail if the underlying MAC
+ * driver was already detached.
+ */
+ if ((ksp = kstat_lookup(kcp, module, instance, "mac")) == NULL &&
+ (ksp = kstat_lookup(kcp, module, instance, NULL)) == NULL)
+ goto bail;
+
+ if (kstat_read(kcp, ksp, NULL) == -1)
+ goto bail;
+
+ if (dladm_kstat_value(ksp, name, type, val) < 0)
+ goto bail;
+
+ (void) kstat_close(kcp);
+ return (DLADM_STATUS_OK);
+bail:
+ (void) kstat_close(kcp);
+ return (dladm_errno2status(errno));
+
+}
+
+int
+dladm_kstat_value(kstat_t *ksp, const char *name, uint8_t type, void *buf)
+{
+ kstat_named_t *knp;
+
+ if ((knp = kstat_data_lookup(ksp, (char *)name)) == NULL)
+ return (-1);
+
+ if (knp->data_type != type)
+ return (-1);
+
+ switch (type) {
+ case KSTAT_DATA_UINT64:
+ *(uint64_t *)buf = knp->value.ui64;
+ break;
+ case KSTAT_DATA_UINT32:
+ *(uint32_t *)buf = knp->value.ui32;
+ break;
+ default:
+ return (-1);
+ }
+
+ return (0);
+}
+
+dladm_status_t
+dladm_parselink(const char *dev, char *provider, uint_t *ppa)
+{
+ ifspec_t ifsp;
+
+ if (dev == NULL || !ifparse_ifspec(dev, &ifsp))
+ return (DLADM_STATUS_LINKINVAL);
+
+ if (provider != NULL)
+ (void) strlcpy(provider, ifsp.ifsp_devnm, DLPI_LINKNAME_MAX);
+
+ if (ppa != NULL)
+ *ppa = ifsp.ifsp_ppa;
+
+ return (DLADM_STATUS_OK);
+}
diff --git a/usr/src/lib/libdladm/common/libdllink.h b/usr/src/lib/libdladm/common/libdllink.h
index 2b762ff6d8..80f6f725e6 100644
--- a/usr/src/lib/libdladm/common/libdllink.h
+++ b/usr/src/lib/libdladm/common/libdllink.h
@@ -36,6 +36,7 @@
#include <sys/types.h>
#include <sys/param.h>
#include <libdladm.h>
+#include <kstat.h>
#ifdef __cplusplus
extern "C" {
@@ -74,6 +75,10 @@ typedef enum {
#define DLADM_SECOBJ_NAME_MAX 32
#define DLADM_MAX_PROP_VALCNT 32
+/*
+ * Size of prop_val buffer passed to pd_get function must be at
+ * least DLADM_PROP_VAL_MAX
+ */
#define DLADM_PROP_VAL_MAX 128
#define DLADM_SECOBJ_CLASS_WEP 0
@@ -145,6 +150,11 @@ extern dladm_status_t dladm_phys_delete(datalink_id_t);
extern dladm_status_t dladm_phys_info(datalink_id_t, dladm_phys_attr_t *,
uint32_t);
+extern dladm_status_t dladm_get_single_mac_stat(datalink_id_t, const char *,
+ uint8_t, void *);
+extern int dladm_kstat_value(kstat_t *, const char *, uint8_t,
+ void *);
+extern dladm_status_t dladm_parselink(const char *, char *, uint_t *);
#ifdef __cplusplus
}
diff --git a/usr/src/lib/libdladm/common/libdlwlan.c b/usr/src/lib/libdladm/common/libdlwlan.c
index 6597b84ce0..47eb8823c0 100644
--- a/usr/src/lib/libdladm/common/libdlwlan.c
+++ b/usr/src/lib/libdladm/common/libdlwlan.c
@@ -83,39 +83,39 @@ static dladm_status_t dladm_wlan_wlresult2status(wldp_t *);
static dladm_status_t dladm_wlan_validate(datalink_id_t);
static val_desc_t linkstatus_vals[] = {
- { "disconnected", DLADM_WLAN_LINK_DISCONNECTED },
- { "connected", DLADM_WLAN_LINK_CONNECTED }
+ { "disconnected", DLADM_WLAN_LINK_DISCONNECTED },
+ { "connected", DLADM_WLAN_LINK_CONNECTED }
};
static val_desc_t secmode_vals[] = {
- { "none", DLADM_WLAN_SECMODE_NONE },
- { "wep", DLADM_WLAN_SECMODE_WEP },
- { "wpa", DLADM_WLAN_SECMODE_WPA }
+ { "none", DLADM_WLAN_SECMODE_NONE },
+ { "wep", DLADM_WLAN_SECMODE_WEP },
+ { "wpa", DLADM_WLAN_SECMODE_WPA }
};
static val_desc_t strength_vals[] = {
- { "very weak", DLADM_WLAN_STRENGTH_VERY_WEAK },
+ { "very weak", DLADM_WLAN_STRENGTH_VERY_WEAK },
{ "weak", DLADM_WLAN_STRENGTH_WEAK },
{ "good", DLADM_WLAN_STRENGTH_GOOD },
- { "very good", DLADM_WLAN_STRENGTH_VERY_GOOD},
- { "excellent", DLADM_WLAN_STRENGTH_EXCELLENT}
+ { "very good", DLADM_WLAN_STRENGTH_VERY_GOOD },
+ { "excellent", DLADM_WLAN_STRENGTH_EXCELLENT }
};
static val_desc_t mode_vals[] = {
- { "a", DLADM_WLAN_MODE_80211A },
- { "b", DLADM_WLAN_MODE_80211B },
- { "g", DLADM_WLAN_MODE_80211G },
+ { "a", DLADM_WLAN_MODE_80211A },
+ { "b", DLADM_WLAN_MODE_80211B },
+ { "g", DLADM_WLAN_MODE_80211G },
};
static val_desc_t auth_vals[] = {
{ "open", DLADM_WLAN_AUTH_OPEN },
- { "shared", DLADM_WLAN_AUTH_SHARED }
+ { "shared", DLADM_WLAN_AUTH_SHARED }
};
static val_desc_t bsstype_vals[] = {
- { "bss", DLADM_WLAN_BSSTYPE_BSS },
- { "ibss", DLADM_WLAN_BSSTYPE_IBSS },
- { "any", DLADM_WLAN_BSSTYPE_ANY }
+ { "bss", DLADM_WLAN_BSSTYPE_BSS },
+ { "ibss", DLADM_WLAN_BSSTYPE_IBSS },
+ { "any", DLADM_WLAN_BSSTYPE_ANY }
};
#define IS_CONNECTED(gbuf) \
diff --git a/usr/src/lib/libdladm/common/linkprop.c b/usr/src/lib/libdladm/common/linkprop.c
index a05f6ce877..8742dbbd44 100644
--- a/usr/src/lib/libdladm/common/linkprop.c
+++ b/usr/src/lib/libdladm/common/linkprop.c
@@ -46,42 +46,81 @@
#include <dlfcn.h>
#include <link.h>
#include <inet/wifi_ioctl.h>
+#include <libdladm.h>
+#include <sys/param.h>
+#include <sys/dld.h>
+#include <inttypes.h>
+#include <sys/ethernet.h>
/*
* The linkprop get() callback.
+ * - pd: pointer to the struct prop_desc
* - propstrp: a property string array to keep the returned property.
* Caller allocated.
* - cntp: number of returned properties.
* Caller also uses it to indicate how many it expects.
*/
-typedef dladm_status_t pd_getf_t(datalink_id_t, char **propstp, uint_t *cntp);
+struct prop_desc;
+
+typedef dladm_status_t pd_getf_t(struct prop_desc *pd,
+ datalink_id_t, char **propstp, uint_t *cntp);
/*
* The linkprop set() callback.
* - propval: a val_desc_t array which keeps the property values to be set.
* - cnt: number of properties to be set.
+ * - flags: additional flags passed down the system call.
+ *
+ * pd_set takes val_desc_t given by pd_check(), translates it into
+ * a format suitable for kernel consumption. This may require allocation
+ * of ioctl buffers etc. pd_set() may call another common routine (used
+ * by all other pd_sets) which invokes the ioctl.
*/
-typedef dladm_status_t pd_setf_t(datalink_id_t, val_desc_t *propval,
- uint_t cnt);
+typedef dladm_status_t pd_setf_t(struct prop_desc *, datalink_id_t,
+ val_desc_t *propval, uint_t cnt, uint_t flags);
-#define PD_TEMPONLY 0x1
/*
* The linkprop check() callback.
* - propstrp: property string array which keeps the property to be checked.
* - cnt: number of properties.
* - propval: return value; the property values of the given property strings.
- * - dofree: indicates whether the caller needs to free propvalp->vd_val.
+ *
+ * pd_check checks that the input values are valid. It does so by
+ * iteraring through the pd_modval list for the property. If
+ * the modifiable values cannot be expressed as a list, a pd_check
+ * specific to this property can be used. If the input values are
+ * verified to be valid, pd_check allocates a val_desc_t and fills it
+ * with either a val_desc_t found on the pd_modval list or something
+ * generated on the fly.
*/
-typedef dladm_status_t pd_checkf_t(datalink_id_t, char **propstrp,
- uint_t cnt, val_desc_t *propval, boolean_t *dofree);
-
+typedef dladm_status_t pd_checkf_t(struct prop_desc *pd,
+ datalink_id_t, char **propstrp,
+ uint_t cnt, val_desc_t *propval);
+
+typedef struct dld_public_prop_s {
+ dld_prop_id_t pp_id;
+ size_t pp_valsize;
+ char *pp_name;
+ char *pp_desc;
+} dld_public_prop_t;
+
+static dld_ioc_prop_t *dld_buf_alloc(size_t, datalink_id_t, const char *,
+ dladm_status_t *);
+static dladm_status_t dld_set_prop(datalink_id_t, const char *, char **,
+ uint_t, uint_t);
+static dladm_status_t dld_get_prop(datalink_id_t, const char *, char **,
+ uint_t *, dladm_prop_type_t);
static pd_getf_t do_get_zone, do_get_autopush, do_get_rate_mod,
do_get_rate_prop, do_get_channel_prop,
- do_get_powermode_prop, do_get_radio_prop;
+ do_get_powermode_prop, do_get_radio_prop,
+ dld_duplex_get, dld_speed_get, dld_status_get,
+ dld_binary_get, dld_uint64_get, dld_flowctl_get;
static pd_setf_t do_set_zone, do_set_autopush, do_set_rate_prop,
- do_set_powermode_prop, do_set_radio_prop;
-static pd_checkf_t do_check_zone, do_check_autopush, do_check_rate;
+ do_set_powermode_prop, do_set_radio_prop,
+ dld_set_public_prop;
+static pd_checkf_t do_check_zone, do_check_autopush, do_check_rate,
+ dld_defmtu_check;
typedef struct prop_desc {
/*
@@ -131,12 +170,9 @@ typedef struct prop_desc {
*/
pd_checkf_t *pd_check;
- /*
- * currently only PD_TEMPONLY is valid, which indicates the property
- * is temporary only.
- */
uint_t pd_flags;
-
+#define PD_TEMPONLY 0x1 /* property is temporary only */
+#define PD_CHECK_ALLOC 0x2 /* alloc vd_val as part of pd_check */
/*
* indicate link classes this property applies to.
*/
@@ -148,6 +184,97 @@ typedef struct prop_desc {
datalink_media_t pd_dmedia;
} prop_desc_t;
+#define DLD_PROPBUF_SIZE(v) sizeof (dld_ioc_prop_t) + (v) - 1
+
+
+static dld_public_prop_t dld_prop[] = {
+ { DLD_PROP_DUPLEX, sizeof (uint8_t),
+ "link_duplex", "link duplex mode" },
+
+ {DLD_PROP_SPEED, sizeof (uint8_t),
+ "ifspeed", "link speed (Mbps)" },
+
+ { DLD_PROP_STATUS, sizeof (uint8_t),
+ "link_up", "link up/down" },
+
+ { DLD_PROP_AUTONEG, sizeof (uint8_t),
+ "adv_autoneg_cap", "Advertised auto-negotiation" },
+
+ { DLD_PROP_DEFMTU, sizeof (uint64_t),
+ "default_mtu", "default frame mtu" },
+
+ { DLD_PROP_FLOWCTRL, sizeof (link_flowctrl_t),
+ "flowctrl", "flowcontrol" },
+
+ { DLD_PROP_ADV_1000FDX_CAP, sizeof (uint8_t),
+ "adv_1000fdx_cap", "Adv 1000 Mbps fdx" },
+
+ { DLD_PROP_EN_1000FDX_CAP, sizeof (uint8_t),
+ "en_1000fdx_cap", "Enable 1000 Mbps fdx" },
+
+ { DLD_PROP_ADV_1000HDX_CAP, sizeof (uint8_t),
+ "adv_1000hdx_cap", "Adv 1000 Mbps hdx" },
+
+ { DLD_PROP_EN_1000HDX_CAP, sizeof (uint8_t),
+ "en_1000hdx_cap", "Enable 1000 Mbps hdx" },
+
+ { DLD_PROP_ADV_100FDX_CAP, sizeof (uint8_t),
+ "adv_100fdx_cap", "Adv 100 Mbps fdx" },
+
+ { DLD_PROP_EN_100FDX_CAP, sizeof (uint8_t),
+ "en_100fdx_cap", "Enable 100 Mbps fdx" },
+
+ { DLD_PROP_ADV_100HDX_CAP, sizeof (uint8_t),
+ "adv_100hdx_cap", "Adv 100 Mbps hdx" },
+
+ { DLD_PROP_EN_100HDX_CAP, sizeof (uint8_t),
+ "en_100hdx_cap", "Enable 100 Mbps hdx" },
+
+ { DLD_PROP_ADV_10FDX_CAP, sizeof (uint8_t),
+ "adv_10fdx_cap", "Adv 10 Mbps fdx" },
+
+ { DLD_PROP_EN_10FDX_CAP, sizeof (uint8_t),
+ "en_10fdx_cap", "Enable 10 Mbps fdx" },
+
+ { DLD_PROP_ADV_10HDX_CAP, sizeof (uint8_t),
+ "adv_10hdx_cap", "Adv 10 Mbps hdx" },
+
+ { DLD_PROP_EN_10HDX_CAP, sizeof (uint8_t),
+ "en_10hdx_cap", "Enable 10 Mbps hdx" },
+
+ { DLD_PROP_PRIVATE, 0,
+ "driver-private", "" }
+};
+
+static val_desc_t link_duplex_vals[] = {
+ { "half", LINK_DUPLEX_HALF },
+ { "full", LINK_DUPLEX_HALF }
+};
+static val_desc_t link_speed_vals[] = {
+ { "10", 10 },
+ { "100", 100 },
+ { "1000", 1000 }
+};
+static val_desc_t link_status_vals[] = {
+ { "up", LINK_STATE_UP },
+ { "down", LINK_STATE_DOWN }
+};
+static val_desc_t link_01_vals[] = {
+ { "1", 1 },
+ { "0", 0 }
+};
+static val_desc_t link_flow_vals[] = {
+ { "no", LINK_FLOWCTRL_NONE },
+ { "tx", LINK_FLOWCTRL_TX },
+ { "rx", LINK_FLOWCTRL_RX },
+ { "bi", LINK_FLOWCTRL_BI }
+};
+static val_desc_t macdefaultmtu_vals[] = {
+ { "68-9000", NULL }
+};
+
+#define VALCNT(vals) (sizeof ((vals)) / sizeof (val_desc_t))
+
static val_desc_t dladm_wlan_radio_vals[] = {
{ "on", DLADM_WLAN_RADIO_ON },
{ "off", DLADM_WLAN_RADIO_OFF }
@@ -161,36 +288,128 @@ static val_desc_t dladm_wlan_powermode_vals[] = {
static prop_desc_t prop_table[] = {
- { "channel", { NULL, 0 }, NULL, 0, NULL, NULL,
+ { "channel", { NULL, 0 },
+ NULL, 0, NULL, NULL,
do_get_channel_prop, NULL, 0,
- DATALINK_CLASS_PHYS, DL_WIFI},
+ DATALINK_CLASS_PHYS, DL_WIFI },
{ "powermode", { "off", DLADM_WLAN_PM_OFF },
dladm_wlan_powermode_vals, VALCNT(dladm_wlan_powermode_vals),
do_set_powermode_prop, NULL,
do_get_powermode_prop, NULL, 0,
- DATALINK_CLASS_PHYS, DL_WIFI},
+ DATALINK_CLASS_PHYS, DL_WIFI },
{ "radio", { "on", DLADM_WLAN_RADIO_ON },
dladm_wlan_radio_vals, VALCNT(dladm_wlan_radio_vals),
do_set_radio_prop, NULL,
do_get_radio_prop, NULL, 0,
- DATALINK_CLASS_PHYS, DL_WIFI},
+ DATALINK_CLASS_PHYS, DL_WIFI },
{ "speed", { "", 0 }, NULL, 0,
do_set_rate_prop, do_get_rate_mod,
do_get_rate_prop, do_check_rate, 0,
- DATALINK_CLASS_PHYS, DL_WIFI},
+ DATALINK_CLASS_PHYS, DL_WIFI },
{ "autopush", { "", NULL }, NULL, 0,
do_set_autopush, NULL,
- do_get_autopush, do_check_autopush, 0,
- DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE},
+ do_get_autopush, do_check_autopush, PD_CHECK_ALLOC,
+ DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE },
{ "zone", { "", NULL }, NULL, 0,
do_set_zone, NULL,
do_get_zone, do_check_zone, PD_TEMPONLY,
- DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE}
+ DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE },
+
+ { "link_duplex", { "full", LINK_DUPLEX_FULL },
+ link_duplex_vals, VALCNT(link_duplex_vals),
+ NULL, NULL, dld_duplex_get, NULL,
+ 0, DATALINK_CLASS_PHYS, DL_ETHER },
+
+ { "ifspeed", { "1000", 1000 },
+ link_speed_vals, VALCNT(link_speed_vals),
+ NULL, NULL, dld_speed_get, NULL,
+ 0, DATALINK_CLASS_PHYS, DL_ETHER },
+
+ { "link_up", { "up", LINK_STATE_UP },
+ link_status_vals, VALCNT(link_status_vals),
+ NULL, NULL, dld_status_get, NULL,
+ 0, DATALINK_CLASS_PHYS, DL_ETHER },
+
+ { "adv_autoneg_cap", { "1", 1 },
+ link_01_vals, VALCNT(link_01_vals),
+ dld_set_public_prop, NULL, dld_binary_get, NULL,
+ 0, DATALINK_CLASS_PHYS, DL_ETHER },
+
+ { "default_mtu", { NULL, NULL },
+ macdefaultmtu_vals, VALCNT(macdefaultmtu_vals),
+ dld_set_public_prop, NULL, dld_uint64_get, dld_defmtu_check,
+ PD_CHECK_ALLOC, DATALINK_CLASS_PHYS, DL_ETHER },
+
+ { "flowctrl", { "bi", LINK_FLOWCTRL_BI },
+ link_flow_vals, VALCNT(link_flow_vals),
+ dld_set_public_prop, NULL, dld_flowctl_get, NULL,
+ 0, DATALINK_CLASS_PHYS, DL_ETHER },
+
+ { "adv_1000fdx_cap", { NULL, NULL },
+ link_01_vals, 0,
+ NULL, NULL, dld_binary_get, NULL,
+ 0, DATALINK_CLASS_PHYS, DL_ETHER },
+
+ { "en_1000fdx_cap", { NULL, NULL },
+ link_01_vals, VALCNT(link_01_vals),
+ dld_set_public_prop, NULL, dld_binary_get, NULL,
+ 0, DATALINK_CLASS_PHYS, DL_ETHER },
+
+ { "adv_1000hdx_cap", { NULL, NULL },
+ link_01_vals, VALCNT(link_01_vals),
+ NULL, NULL, dld_binary_get, NULL,
+ 0, DATALINK_CLASS_PHYS, DL_ETHER },
+
+ { "en_1000hdx_cap", { NULL, NULL },
+ link_01_vals, VALCNT(link_01_vals),
+ dld_set_public_prop, NULL, dld_binary_get, NULL,
+ 0, DATALINK_CLASS_PHYS, DL_ETHER },
+
+ { "adv_100fdx_cap", { NULL, NULL },
+ link_01_vals, VALCNT(link_01_vals),
+ NULL, NULL, dld_binary_get, NULL,
+ 0, DATALINK_CLASS_PHYS, DL_ETHER },
+
+ { "en_100fdx_cap", { NULL, NULL },
+ link_01_vals, VALCNT(link_01_vals),
+ dld_set_public_prop, NULL, dld_binary_get, NULL,
+ 0, DATALINK_CLASS_PHYS, DL_ETHER },
+
+ { "adv_100hdx_cap", { NULL, NULL },
+ link_01_vals, VALCNT(link_01_vals),
+ NULL, NULL, dld_binary_get, NULL,
+ 0, DATALINK_CLASS_PHYS, DL_ETHER },
+
+ { "en_100hdx_cap", { NULL, NULL },
+ link_01_vals, VALCNT(link_01_vals),
+ dld_set_public_prop, NULL, dld_binary_get, NULL,
+ 0, DATALINK_CLASS_PHYS, DL_ETHER },
+
+ { "adv_10fdx_cap", { NULL, NULL },
+ link_01_vals, VALCNT(link_01_vals),
+ NULL, NULL, dld_binary_get, NULL,
+ 0, DATALINK_CLASS_PHYS, DL_ETHER },
+
+ { "en_10fdx_cap", { NULL, NULL },
+ link_01_vals, VALCNT(link_01_vals),
+ dld_set_public_prop, NULL, dld_binary_get, NULL,
+ 0, DATALINK_CLASS_PHYS, DL_ETHER },
+
+ { "adv_10hdx_cap", { NULL, NULL },
+ link_01_vals, VALCNT(link_01_vals),
+ NULL, NULL, dld_binary_get, NULL,
+ 0, DATALINK_CLASS_PHYS, DL_ETHER },
+
+ { "en_10hdx_cap", { NULL, NULL },
+ link_01_vals, VALCNT(link_01_vals),
+ dld_set_public_prop, NULL, dld_binary_get, NULL,
+ 0, DATALINK_CLASS_PHYS, DL_ETHER }
+
};
#define DLADM_MAX_PROPS (sizeof (prop_table) / sizeof (prop_desc_t))
@@ -266,14 +485,19 @@ i_dladm_set_single_prop(datalink_id_t linkid, datalink_class_t class,
if (pdp->pd_set == NULL)
return (DLADM_STATUS_PROPRDONLY);
+ if (pdp->pd_flags & PD_CHECK_ALLOC)
+ needfree = B_TRUE;
+ else
+ needfree = B_FALSE;
if (prop_val != NULL) {
vdp = malloc(sizeof (val_desc_t) * val_cnt);
if (vdp == NULL)
return (DLADM_STATUS_NOMEM);
+
if (pdp->pd_check != NULL) {
- status = pdp->pd_check(linkid, prop_val, val_cnt, vdp,
- &needfree);
+ status = pdp->pd_check(pdp, linkid, prop_val, val_cnt,
+ vdp);
} else if (pdp->pd_optval != NULL) {
status = do_check_prop(pdp, prop_val, val_cnt, vdp);
} else {
@@ -294,10 +518,10 @@ i_dladm_set_single_prop(datalink_id_t linkid, datalink_class_t class,
(void) memcpy(vdp, &pdp->pd_defval, sizeof (val_desc_t));
cnt = 1;
}
- status = pdp->pd_set(linkid, vdp, cnt);
+ status = pdp->pd_set(pdp, linkid, vdp, cnt, flags);
if (needfree) {
for (i = 0; i < cnt; i++)
- free((void *)(((val_desc_t *)vdp + i)->vd_val));
+ free((void *)((val_desc_t *)vdp + i)->vd_val);
}
done:
free(vdp);
@@ -339,8 +563,15 @@ i_dladm_set_linkprop(datalink_id_t linkid, const char *prop_name,
status = s;
}
}
- if (!found)
- status = DLADM_STATUS_NOTFOUND;
+ if (!found) {
+ if (prop_name[0] == '_') {
+ /* other private properties */
+ status = dld_set_prop(linkid, prop_name, prop_val,
+ val_cnt, flags);
+ } else {
+ status = DLADM_STATUS_NOTFOUND;
+ }
+ }
return (status);
}
@@ -430,8 +661,17 @@ dladm_get_linkprop(datalink_id_t linkid, dladm_prop_type_t type,
if (strcasecmp(prop_name, prop_table[i].pd_name) == 0)
break;
- if (i == DLADM_MAX_PROPS)
- return (DLADM_STATUS_NOTFOUND);
+ if (i == DLADM_MAX_PROPS) {
+ if (prop_name[0] == '_') {
+ /*
+ * private property.
+ */
+ return (dld_get_prop(linkid, prop_name,
+ prop_val, val_cntp, type));
+ } else {
+ return (DLADM_STATUS_NOTFOUND);
+ }
+ }
pdp = &prop_table[i];
@@ -447,7 +687,7 @@ dladm_get_linkprop(datalink_id_t linkid, dladm_prop_type_t type,
switch (type) {
case DLADM_PROP_VAL_CURRENT:
- status = pdp->pd_get(linkid, prop_val, val_cntp);
+ status = pdp->pd_get(pdp, linkid, prop_val, val_cntp);
break;
case DLADM_PROP_VAL_DEFAULT:
@@ -461,7 +701,8 @@ dladm_get_linkprop(datalink_id_t linkid, dladm_prop_type_t type,
case DLADM_PROP_VAL_MODIFIABLE:
if (pdp->pd_getmod != NULL) {
- status = pdp->pd_getmod(linkid, prop_val, val_cntp);
+ status = pdp->pd_getmod(pdp, linkid, prop_val,
+ val_cntp);
break;
}
cnt = pdp->pd_noptval;
@@ -546,8 +787,10 @@ dladm_init_linkprop(datalink_id_t linkid)
return (DLADM_STATUS_OK);
}
+/* ARGSUSED */
static dladm_status_t
-do_get_zone(datalink_id_t linkid, char **prop_val, uint_t *val_cnt)
+do_get_zone(struct prop_desc *pd, datalink_id_t linkid,
+ char **prop_val, uint_t *val_cnt)
{
char zone_name[ZONENAME_MAX];
zoneid_t zid;
@@ -637,8 +880,10 @@ cleanup:
return (status);
}
+/* ARGSUSED */
static dladm_status_t
-do_set_zone(datalink_id_t linkid, val_desc_t *vdp, uint_t val_cnt)
+do_set_zone(prop_desc_t *pd, datalink_id_t linkid,
+ val_desc_t *vdp, uint_t val_cnt, uint_t flags)
{
dladm_status_t status;
zoneid_t zid_old, zid_new;
@@ -721,8 +966,8 @@ rollback1:
/* ARGSUSED */
static dladm_status_t
-do_check_zone(datalink_id_t linkid, char **prop_val, uint_t val_cnt,
- val_desc_t *vdp, boolean_t *needfreep)
+do_check_zone(struct prop_desc *pd, datalink_id_t linkid, char **prop_val,
+ uint_t val_cnt, val_desc_t *vdp)
{
zoneid_t zid;
@@ -746,12 +991,13 @@ do_check_zone(datalink_id_t linkid, char **prop_val, uint_t val_cnt,
}
vdp->vd_val = zid;
- *needfreep = B_FALSE;
return (DLADM_STATUS_OK);
}
+/* ARGSUSED */
static dladm_status_t
-do_get_autopush(datalink_id_t linkid, char **prop_val, uint_t *val_cnt)
+do_get_autopush(struct prop_desc *pd, datalink_id_t linkid,
+ char **prop_val, uint_t *val_cnt)
{
dld_ioc_ap_t dia;
int fd, i, len;
@@ -788,8 +1034,10 @@ done:
return (DLADM_STATUS_OK);
}
+/* ARGSUSED */
static dladm_status_t
-do_set_autopush(datalink_id_t linkid, val_desc_t *vdp, uint_t val_cnt)
+do_set_autopush(prop_desc_t *pd, datalink_id_t linkid,
+ val_desc_t *vdp, uint_t val_cnt, uint_t flags)
{
dld_ioc_ap_t dia;
struct dlautopush *dlap = (struct dlautopush *)vdp->vd_val;
@@ -862,8 +1110,8 @@ i_dladm_add_ap_module(const char *module, struct dlautopush *dlap)
*/
/* ARGSUSED */
static dladm_status_t
-do_check_autopush(datalink_id_t linkid, char **prop_val, uint_t val_cnt,
- val_desc_t *vdp, boolean_t *needfreep)
+do_check_autopush(struct prop_desc *pd, datalink_id_t linkid, char **prop_val,
+ uint_t val_cnt, val_desc_t *vdp)
{
char *module;
struct dlautopush *dlap;
@@ -890,13 +1138,13 @@ do_check_autopush(datalink_id_t linkid, char **prop_val, uint_t val_cnt,
}
vdp->vd_val = (uintptr_t)dlap;
- *needfreep = B_TRUE;
return (DLADM_STATUS_OK);
}
+/* ARGSUSED */
static dladm_status_t
-do_get_rate_common(datalink_id_t linkid, char **prop_val, uint_t *val_cnt,
- uint_t id)
+do_get_rate_common(struct prop_desc *pd, datalink_id_t linkid,
+ char **prop_val, uint_t *val_cnt, uint_t id)
{
wl_rates_t *wrp;
uint_t i;
@@ -937,16 +1185,18 @@ done:
}
static dladm_status_t
-do_get_rate_prop(datalink_id_t linkid, char **prop_val, uint_t *val_cnt)
+do_get_rate_prop(struct prop_desc *pd, datalink_id_t linkid,
+ char **prop_val, uint_t *val_cnt)
{
- return (do_get_rate_common(linkid, prop_val, val_cnt,
+ return (do_get_rate_common(pd, linkid, prop_val, val_cnt,
WL_DESIRED_RATES));
}
static dladm_status_t
-do_get_rate_mod(datalink_id_t linkid, char **prop_val, uint_t *val_cnt)
+do_get_rate_mod(struct prop_desc *pd, datalink_id_t linkid,
+ char **prop_val, uint_t *val_cnt)
{
- return (do_get_rate_common(linkid, prop_val, val_cnt,
+ return (do_get_rate_common(pd, linkid, prop_val, val_cnt,
WL_SUPPORTED_RATES));
}
@@ -978,8 +1228,10 @@ do_set_rate(datalink_id_t linkid, dladm_wlan_rates_t *rates)
return (status);
}
+/* ARGSUSED */
static dladm_status_t
-do_set_rate_prop(datalink_id_t linkid, val_desc_t *vdp, uint_t val_cnt)
+do_set_rate_prop(prop_desc_t *pd, datalink_id_t linkid,
+ val_desc_t *vdp, uint_t val_cnt, uint_t flags)
{
dladm_wlan_rates_t rates;
dladm_status_t status;
@@ -998,8 +1250,8 @@ done:
/* ARGSUSED */
static dladm_status_t
-do_check_rate(datalink_id_t linkid, char **prop_val, uint_t val_cnt,
- val_desc_t *vdp, boolean_t *needfreep)
+do_check_rate(struct prop_desc *pd, datalink_id_t linkid, char **prop_val,
+ uint_t val_cnt, val_desc_t *vdp)
{
int i;
uint_t modval_cnt = MAX_SUPPORT_RATES;
@@ -1022,19 +1274,15 @@ do_check_rate(datalink_id_t linkid, char **prop_val, uint_t val_cnt,
i * DLADM_STRSIZE;
}
- status = do_get_rate_mod(linkid, modval, &modval_cnt);
+ status = do_get_rate_mod(NULL, linkid, modval, &modval_cnt);
if (status != DLADM_STATUS_OK)
goto done;
for (i = 0; i < modval_cnt; i++) {
if (strcasecmp(*prop_val, modval[i]) == 0) {
- vdp->vd_val = (uint_t)(atof(*prop_val) * 2);
+ vdp->vd_val = (uintptr_t)(uint_t)
+ (atof(*prop_val) * 2);
status = DLADM_STATUS_OK;
-
- /*
- * Does not need the caller to free the vdp->vd_val
- */
- *needfreep = B_FALSE;
break;
}
}
@@ -1051,8 +1299,10 @@ do_get_phyconf(datalink_id_t linkid, wldp_t *gbuf)
return (i_dladm_wlan_get_ioctl(linkid, gbuf, WL_PHY_CONFIG));
}
+/* ARGSUSED */
static dladm_status_t
-do_get_channel_prop(datalink_id_t linkid, char **prop_val, uint_t *val_cnt)
+do_get_channel_prop(struct prop_desc *pd, datalink_id_t linkid,
+ char **prop_val, uint_t *val_cnt)
{
uint32_t channel;
wldp_t *gbuf;
@@ -1084,8 +1334,10 @@ do_get_powermode(datalink_id_t linkid, wldp_t *gbuf)
return (i_dladm_wlan_get_ioctl(linkid, gbuf, WL_POWER_MODE));
}
+/* ARGSUSED */
static dladm_status_t
-do_get_powermode_prop(datalink_id_t linkid, char **prop_val, uint_t *val_cnt)
+do_get_powermode_prop(struct prop_desc *pd, datalink_id_t linkid,
+ char **prop_val, uint_t *val_cnt)
{
wl_ps_mode_t *mode;
const char *s;
@@ -1147,7 +1399,8 @@ do_set_powermode(datalink_id_t linkid, dladm_wlan_powermode_t *pm)
/* ARGSUSED */
static dladm_status_t
-do_set_powermode_prop(datalink_id_t linkid, val_desc_t *vdp, uint_t val_cnt)
+do_set_powermode_prop(prop_desc_t *pd, datalink_id_t linkid,
+ val_desc_t *vdp, uint_t val_cnt, uint_t flags)
{
dladm_wlan_powermode_t powermode = (dladm_wlan_powermode_t)vdp->vd_val;
dladm_status_t status;
@@ -1166,8 +1419,10 @@ do_get_radio(datalink_id_t linkid, wldp_t *gbuf)
return (i_dladm_wlan_get_ioctl(linkid, gbuf, WL_RADIO));
}
+/* ARGSUSED */
static dladm_status_t
-do_get_radio_prop(datalink_id_t linkid, char **prop_val, uint_t *val_cnt)
+do_get_radio_prop(struct prop_desc *pd, datalink_id_t linkid,
+ char **prop_val, uint_t *val_cnt)
{
wl_radio_t radio;
const char *s;
@@ -1220,7 +1475,8 @@ do_set_radio(datalink_id_t linkid, dladm_wlan_radio_t *radio)
/* ARGSUSED */
static dladm_status_t
-do_set_radio_prop(datalink_id_t linkid, val_desc_t *vdp, uint_t val_cnt)
+do_set_radio_prop(prop_desc_t *pd, datalink_id_t linkid,
+ val_desc_t *vdp, uint_t val_cnt, uint_t fags)
{
dladm_wlan_radio_t radio = (dladm_wlan_radio_t)vdp->vd_val;
dladm_status_t status;
@@ -1305,3 +1561,410 @@ done:
dladm_destroy_conf(conf);
return (status);
}
+
+static dld_public_prop_t *
+dladm_name2prop(const char *prop_name)
+{
+ dld_public_prop_t *p;
+
+ for (p = dld_prop; p->pp_id != DLD_PROP_PRIVATE; p++) {
+ if (strcmp(p->pp_name, prop_name) == 0)
+ break;
+ }
+ return (p);
+}
+
+
+static dld_ioc_prop_t *
+dld_buf_alloc(size_t valsize, datalink_id_t linkid, const char *prop_name,
+ dladm_status_t *status)
+{
+ int dsize;
+ dld_ioc_prop_t *dip;
+ dld_public_prop_t *p;
+ char link[DLPI_LINKNAME_MAX];
+ uint32_t flags;
+
+ *status = DLADM_STATUS_OK;
+ p = dladm_name2prop(prop_name);
+ if (p->pp_id != DLD_PROP_PRIVATE)
+ valsize = p->pp_valsize;
+
+ dsize = DLD_PROPBUF_SIZE(valsize);
+ dip = malloc(dsize);
+ if (dip == NULL) {
+ *status = DLADM_STATUS_NOMEM;
+ return (NULL);
+ }
+ bzero(dip, dsize);
+ dip->pr_valsize = valsize;
+ (void) strlcpy(dip->pr_name, prop_name, DLD_LINKPROP_NAME_MAX);
+ dip->pr_version = DLD_PROP_VERSION;
+
+ if ((*status = dladm_datalink_id2info(linkid, &flags, NULL, NULL,
+ (char *)link, DLPI_LINKNAME_MAX)) != DLADM_STATUS_OK) {
+ free(dip);
+ return (NULL);
+ }
+
+ if (!(flags & DLADM_OPT_ACTIVE)) {
+ free(dip);
+ *status = DLADM_STATUS_TEMPONLY;
+ return (NULL);
+ }
+ (void) strlcpy(dip->pr_linkname, link, IFNAMSIZ);
+ dip->pr_num = p->pp_id;
+ return (dip);
+}
+
+/* ARGSUSED */
+static dladm_status_t
+dld_set_public_prop(prop_desc_t *pd, datalink_id_t linkid,
+ val_desc_t *vdp, uint_t val_cnt, uint_t flags)
+{
+ dld_ioc_prop_t *dip;
+ int fd, dsize;
+ dladm_status_t status = DLADM_STATUS_OK;
+ uint8_t u8;
+ uint16_t u16;
+ uint32_t u32;
+ void *val;
+
+ dip = dld_buf_alloc(0, linkid, pd->pd_name, &status);
+ if (dip == NULL)
+ return (status);
+
+ if (pd->pd_flags & PD_CHECK_ALLOC)
+ val = (void *)vdp->vd_val;
+ else {
+ /*
+ * Currently all 1/2/4-byte size properties are byte/word/int.
+ * No need (yet) to distinguish these from arrays of same size.
+ */
+ switch (dip->pr_valsize) {
+ case 1:
+ u8 = vdp->vd_val;
+ val = &u8;
+ break;
+ case 2:
+ u16 = vdp->vd_val;
+ val = &u16;
+ break;
+ case 4:
+ u32 = vdp->vd_val;
+ val = &u32;
+ break;
+ default:
+ val = &vdp->vd_val;
+ break;
+ }
+ }
+
+ (void) memcpy(dip->pr_val, val, dip->pr_valsize);
+ dsize = DLD_PROPBUF_SIZE(dip->pr_valsize);
+ if ((fd = open(DLD_CONTROL_DEV, O_RDWR)) < 0) {
+ status = dladm_errno2status(errno);
+ goto done;
+ }
+ if (i_dladm_ioctl(fd, DLDIOCSETPROP, dip, dsize) < 0)
+ status = dladm_errno2status(errno);
+
+ (void) close(fd);
+done:
+ return (status);
+}
+
+static dladm_status_t
+dld_get_public_prop(dld_ioc_prop_t *dip)
+{
+ int fd, dsize;
+ dladm_status_t status = DLADM_STATUS_OK;
+
+ dsize = DLD_PROPBUF_SIZE(dip->pr_valsize);
+
+ if ((fd = open(DLD_CONTROL_DEV, O_RDWR)) < 0) {
+ status = dladm_errno2status(errno);
+ goto done;
+ }
+ if (i_dladm_ioctl(fd, DLDIOCGETPROP, dip, dsize) < 0) {
+ status = dladm_errno2status(errno);
+ }
+done:
+ return (status);
+}
+
+
+/* ARGSUSED */
+static dladm_status_t
+dld_defmtu_check(struct prop_desc *pd, datalink_id_t linkid, char **prop_val,
+ uint_t val_cnt, val_desc_t *v)
+{
+ uint64_t mtu;
+
+ if (val_cnt != 1)
+ return (DLADM_STATUS_BADVAL);
+ mtu = atoll(prop_val[0]);
+ v->vd_val = (uintptr_t)malloc(sizeof (uint64_t));
+ if ((void *)v->vd_val == NULL)
+ return (DLADM_STATUS_NOMEM);
+ bcopy(&mtu, (void *)v->vd_val, sizeof (mtu));
+ return (DLADM_STATUS_OK);
+}
+
+/* ARGSUSED */
+static dladm_status_t
+dld_duplex_get(struct prop_desc *pd, datalink_id_t linkid,
+ char **prop_val, uint_t *val_cnt)
+{
+ link_duplex_t link_duplex;
+ dladm_status_t status;
+
+ if ((status = dladm_get_single_mac_stat(linkid, "link_duplex",
+ KSTAT_DATA_UINT32, &link_duplex)) != 0)
+ return (status);
+
+ switch (link_duplex) {
+ case LINK_DUPLEX_FULL:
+ (void) strcpy(*prop_val, "full");
+ break;
+ case LINK_DUPLEX_HALF:
+ (void) strcpy(*prop_val, "half");
+ break;
+ default:
+ (void) strcpy(*prop_val, "unknown");
+ break;
+ }
+ *val_cnt = 1;
+ return (DLADM_STATUS_OK);
+}
+
+/* ARGSUSED */
+static dladm_status_t
+dld_speed_get(struct prop_desc *pd, datalink_id_t linkid,
+ char **prop_val, uint_t *val_cnt)
+{
+ uint64_t ifspeed = 0;
+ dladm_status_t status;
+
+ if ((status = dladm_get_single_mac_stat(linkid, "ifspeed",
+ KSTAT_DATA_UINT64, &ifspeed)) != 0)
+ return (status);
+
+ (void) snprintf(*prop_val, DLADM_PROP_VAL_MAX,
+ "%llu", ifspeed / 1000000); /* Mbps */
+ *val_cnt = 1;
+ return (DLADM_STATUS_OK);
+}
+
+/* ARGSUSED */
+static dladm_status_t
+dld_status_get(struct prop_desc *pd, datalink_id_t linkid,
+ char **prop_val, uint_t *val_cnt)
+{
+ link_state_t link_state;
+ dladm_status_t status;
+
+ if ((status = dladm_get_single_mac_stat(linkid, "link_state",
+ KSTAT_DATA_UINT32, &link_state)) != 0)
+ return (status);
+
+ switch (link_state) {
+ case LINK_STATE_UP:
+ (void) strcpy(*prop_val, "up");
+ break;
+ case LINK_STATE_DOWN:
+ (void) strcpy(*prop_val, "down");
+ break;
+ default:
+ (void) strcpy(*prop_val, "unknown");
+ break;
+ }
+ *val_cnt = 1;
+ return (DLADM_STATUS_OK);
+}
+
+/* ARGSUSED */
+static dladm_status_t
+dld_binary_get(struct prop_desc *pd, datalink_id_t linkid,
+ char **prop_val, uint_t *val_cnt)
+{
+ dld_ioc_prop_t *dip;
+ dladm_status_t status;
+
+ if ((dip = dld_buf_alloc(0, linkid, pd->pd_name, &status)) == NULL)
+ return (status);
+ if ((status = dld_get_public_prop(dip)) != DLADM_STATUS_OK) {
+ free(dip);
+ return (status);
+ }
+ (void) snprintf(*prop_val, DLADM_PROP_VAL_MAX, "%x", dip->pr_val[0]);
+ free(dip);
+ *val_cnt = 1;
+ return (DLADM_STATUS_OK);
+}
+
+static dladm_status_t
+dld_uint64_get(struct prop_desc *pd, datalink_id_t linkid,
+ char **prop_val, uint_t *val_cnt)
+{
+ dld_ioc_prop_t *dip;
+ uint64_t v = 0;
+ uchar_t *cp;
+ dladm_status_t status;
+
+ if ((dip = dld_buf_alloc(0, linkid, pd->pd_name, &status)) == NULL)
+ return (status);
+ if ((status = dld_get_public_prop(dip)) != DLADM_STATUS_OK) {
+ free(dip);
+ return (status);
+ }
+ cp = (uchar_t *)dip->pr_val;
+ (void) memcpy(&v, cp, sizeof (v));
+ (void) snprintf(*prop_val, DLADM_PROP_VAL_MAX, "%" PRIu64, v);
+ free(dip);
+ *val_cnt = 1;
+ return (DLADM_STATUS_OK);
+}
+
+static dladm_status_t
+dld_flowctl_get(struct prop_desc *pd, datalink_id_t linkid,
+ char **prop_val, uint_t *val_cnt)
+{
+ dld_ioc_prop_t *dip;
+ link_flowctrl_t v;
+ dladm_status_t status;
+ uchar_t *cp;
+
+ if ((dip = dld_buf_alloc(0, linkid, pd->pd_name, &status)) == NULL)
+ return (status);
+
+ if ((status = dld_get_public_prop(dip)) != DLADM_STATUS_OK) {
+ free(dip);
+ return (status);
+ }
+ cp = (uchar_t *)dip->pr_val;
+ (void) memcpy(&v, cp, sizeof (v));
+ switch (v) {
+ case LINK_FLOWCTRL_NONE:
+ (void) sprintf(*prop_val, "no");
+ break;
+ case LINK_FLOWCTRL_RX:
+ (void) sprintf(*prop_val, "rx");
+ break;
+ case LINK_FLOWCTRL_TX:
+ (void) sprintf(*prop_val, "tx");
+ break;
+ case LINK_FLOWCTRL_BI:
+ (void) sprintf(*prop_val, "bi");
+ break;
+ }
+ free(dip);
+ *val_cnt = 1;
+ return (DLADM_STATUS_OK);
+}
+
+
+/* ARGSUSED */
+static dladm_status_t
+dld_set_prop(datalink_id_t linkid, const char *prop_name,
+ char **prop_val, uint_t val_cnt, uint_t flags)
+{
+ int fd, i, slen;
+ int bufsize = 0, dsize;
+ dld_ioc_prop_t *dip = NULL;
+ uchar_t *dp;
+ dld_public_prop_t *p;
+ dladm_status_t status;
+
+ if ((prop_name == NULL && prop_val != NULL) ||
+ (prop_val != NULL && val_cnt == 0))
+ return (DLADM_STATUS_BADARG);
+ p = dladm_name2prop(prop_name);
+ if (p->pp_id != DLD_PROP_PRIVATE)
+ return (DLADM_STATUS_BADARG);
+
+ /*
+ * private properties: all parsing is done in the kernel.
+ * allocate a enough space for each property + its separator (',').
+ */
+ for (i = 0; i < val_cnt; i++) {
+ bufsize += strlen(prop_val[i]) + 1;
+ }
+ dip = dld_buf_alloc(bufsize + 1, linkid, prop_name, &status);
+ if (dip == NULL)
+ return (status);
+
+ dp = (uchar_t *)dip->pr_val;
+ dsize = sizeof (dld_ioc_prop_t) + bufsize;
+ slen = 0;
+ for (i = 0; i < val_cnt; i++) {
+ int plen = 0;
+
+ plen = strlen(prop_val[i]);
+ bcopy(prop_val[i], dp, plen);
+ slen += plen;
+ /*
+ * add a "," separator and update dp.
+ */
+ if (i != (val_cnt -1))
+ dp[slen++] = ',';
+ dp += (plen + 1);
+ }
+ if ((fd = open(DLD_CONTROL_DEV, O_RDWR)) < 0) {
+ free(dip);
+ return (dladm_errno2status(errno));
+ }
+ if ((status = i_dladm_ioctl(fd, DLDIOCSETPROP, dip, dsize)) < 0) {
+ free(dip);
+ return (status);
+ }
+ free(dip);
+ (void) close(fd);
+ return (DLADM_STATUS_OK);
+}
+
+static dladm_status_t
+dld_get_prop(datalink_id_t linkid, const char *prop_name,
+ char **prop_val, uint_t *val_cnt, dladm_prop_type_t type)
+{
+ int fd;
+ dladm_status_t status = DLADM_STATUS_OK;
+ uint_t dsize;
+ dld_ioc_prop_t *dip = NULL;
+ dld_public_prop_t *p;
+ char tmp = '\0';
+
+ if ((prop_name == NULL && prop_val != NULL) ||
+ (prop_val != NULL && val_cnt == 0))
+ return (DLADM_STATUS_BADARG);
+
+ p = dladm_name2prop(prop_name);
+ if (p->pp_id != DLD_PROP_PRIVATE)
+ return (DLADM_STATUS_BADARG);
+
+ if (type == DLADM_PROP_VAL_DEFAULT ||
+ type == DLADM_PROP_VAL_MODIFIABLE) {
+ *prop_val = &tmp;
+ *val_cnt = 1;
+ return (DLADM_STATUS_OK);
+ }
+
+ /*
+ * private properties: all parsing is done in the kernel.
+ */
+ dip = dld_buf_alloc(1024, linkid, prop_name, &status);
+ if (dip == NULL)
+ return (status);
+ dsize = DLD_PROPBUF_SIZE(dip->pr_valsize);
+
+ if ((fd = open(DLD_CONTROL_DEV, O_RDWR)) < 0)
+ return (DLADM_STATUS_BADARG);
+
+ if ((status = i_dladm_ioctl(fd, DLDIOCGETPROP, dip, dsize)) < 0) {
+ status = dladm_errno2status(errno);
+ } else {
+ (void) strncpy(*prop_val, dip->pr_val, DLADM_PROP_VAL_MAX);
+ *val_cnt = 1;
+ }
+ return (status);
+}
diff --git a/usr/src/lib/libdladm/common/mapfile-vers b/usr/src/lib/libdladm/common/mapfile-vers
index 25ab048469..ce7f994420 100644
--- a/usr/src/lib/libdladm/common/mapfile-vers
+++ b/usr/src/lib/libdladm/common/mapfile-vers
@@ -38,6 +38,7 @@ SUNWprivate_1.1 {
dladm_valid_linkname;
dladm_mac_walk;
dladm_init_linkprop;
+ dladm_get_single_mac_stat;
dladm_get_linkprop;
dladm_set_linkprop;
dladm_walk_linkprop;
@@ -124,7 +125,8 @@ SUNWprivate_1.1 {
dladm_vnic_delete;
dladm_vnic_info;
dladm_vnic_str2macaddrtype;
-
+ dladm_kstat_value;
+ dladm_parselink;
local:
*;
};
diff --git a/usr/src/lib/libdlpi/common/libdlpi.c b/usr/src/lib/libdlpi/common/libdlpi.c
index f403135b6a..3849824ff0 100644
--- a/usr/src/lib/libdlpi/common/libdlpi.c
+++ b/usr/src/lib/libdlpi/common/libdlpi.c
@@ -368,16 +368,12 @@ dlpi_info(dlpi_handle_t dh, dlpi_info_t *infop, uint_t opt)
int
dlpi_parselink(const char *linkname, char *provider, uint_t *ppa)
{
- ifspec_t ifsp;
-
- if (linkname == NULL || !ifparse_ifspec(linkname, &ifsp))
- return (DLPI_ELINKNAMEINVAL);
+ dladm_status_t status;
- if (provider != NULL)
- (void) strlcpy(provider, ifsp.ifsp_devnm, DLPI_LINKNAME_MAX);
+ status = dladm_parselink(linkname, provider, ppa);
- if (ppa != NULL)
- *ppa = ifsp.ifsp_ppa;
+ if (status != DLADM_STATUS_OK)
+ return (DLPI_ELINKNAMEINVAL);
return (DLPI_SUCCESS);
}
diff --git a/usr/src/uts/common/io/aggr/aggr_grp.c b/usr/src/uts/common/io/aggr/aggr_grp.c
index 65105e298e..2668c23790 100644
--- a/usr/src/uts/common/io/aggr/aggr_grp.c
+++ b/usr/src/uts/common/io/aggr/aggr_grp.c
@@ -1520,9 +1520,11 @@ aggr_grp_max_sdu(aggr_grp_t *grp)
ASSERT(grp->lg_ports != NULL);
for (port = grp->lg_ports; port != NULL; port = port->lp_next) {
- const mac_info_t *port_mi = mac_info(port->lp_mh);
- if (max_sdu > port_mi->mi_sdu_max)
- max_sdu = port_mi->mi_sdu_max;
+ uint_t port_sdu_max;
+
+ mac_sdu_get(port->lp_mh, NULL, &port_sdu_max);
+ if (max_sdu > port_sdu_max)
+ max_sdu = port_sdu_max;
}
return (max_sdu);
@@ -1536,9 +1538,10 @@ aggr_grp_max_sdu(aggr_grp_t *grp)
static boolean_t
aggr_grp_sdu_check(aggr_grp_t *grp, aggr_port_t *port)
{
- const mac_info_t *port_mi = mac_info(port->lp_mh);
+ uint_t port_sdu_max;
- return (port_mi->mi_sdu_max >= grp->lg_max_sdu);
+ mac_sdu_get(port->lp_mh, NULL, &port_sdu_max);
+ return (port_sdu_max >= grp->lg_max_sdu);
}
/*
diff --git a/usr/src/uts/common/io/bge/bge_chip2.c b/usr/src/uts/common/io/bge/bge_chip2.c
index 1f29ac14a9..f4a46a15da 100644
--- a/usr/src/uts/common/io/bge/bge_chip2.c
+++ b/usr/src/uts/common/io/bge/bge_chip2.c
@@ -20,7 +20,7 @@
*/
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -1934,8 +1934,6 @@ bge_chip_id_init(bge_t *bgep)
int err;
uint_t i;
- ASSERT(bgep->bge_chip_state == BGE_CHIP_INITIAL);
-
sys_ok = dev_ok = B_FALSE;
cidp = &bgep->chipid;
@@ -1963,6 +1961,8 @@ bge_chip_id_init(bge_t *bgep)
cidp->mbuf_lo_water_rdma = bge_mbuf_lo_water_rdma;
cidp->mbuf_lo_water_rmac = bge_mbuf_lo_water_rmac;
cidp->mbuf_hi_water = bge_mbuf_hi_water;
+ cidp->rx_ticks_norm = bge_rx_ticks_norm;
+ cidp->rx_count_norm = bge_rx_count_norm;
if (cidp->rx_rings == 0 || cidp->rx_rings > BGE_RECV_RINGS_MAX)
cidp->rx_rings = BGE_RECV_RINGS_DEFAULT;
@@ -2649,10 +2649,10 @@ bge_chip_enable_engine(bge_t *bgep, bge_regno_t regno, uint32_t morebits)
* Reprogram the Ethernet, Transmit, and Receive MAC
* modes to match the param_* variables
*/
-static void bge_sync_mac_modes(bge_t *bgep);
+void bge_sync_mac_modes(bge_t *bgep);
#pragma no_inline(bge_sync_mac_modes)
-static void
+void
bge_sync_mac_modes(bge_t *bgep)
{
uint32_t macmode;
@@ -2741,7 +2741,7 @@ bge_chip_sync(bge_t *bgep)
int retval = DDI_SUCCESS;
BGE_TRACE(("bge_chip_sync($%p)",
- (void *)bgep));
+ (void *)bgep));
ASSERT(mutex_owned(bgep->genlock));
@@ -2945,7 +2945,9 @@ bge_chip_stop(bge_t *bgep, boolean_t fault)
if (fault) {
if (bgep->bge_chip_state != BGE_CHIP_FAULT) {
bgep->bge_chip_state = BGE_CHIP_FAULT;
- ddi_fm_service_impact(bgep->devinfo, DDI_SERVICE_LOST);
+ if (!bgep->manual_reset)
+ ddi_fm_service_impact(bgep->devinfo,
+ DDI_SERVICE_LOST);
if (bgep->bge_dma_error) {
/*
* need to free buffers in case the fault was
@@ -3926,10 +3928,10 @@ bge_status_sync(bge_t *bgep, uint64_t bits, uint64_t *flags)
return (retval);
}
-static void bge_wake_factotum(bge_t *bgep);
+void bge_wake_factotum(bge_t *bgep);
#pragma inline(bge_wake_factotum)
-static void
+void
bge_wake_factotum(bge_t *bgep)
{
mutex_enter(bgep->softintrlock);
@@ -4464,8 +4466,10 @@ bge_chip_factotum(caddr_t arg)
bgep->asf_status = ASF_STAT_RUN;
}
#endif
- ddi_fm_service_impact(bgep->devinfo,
- DDI_SERVICE_RESTORED);
+ if (!bgep->manual_reset) {
+ ddi_fm_service_impact(bgep->devinfo,
+ DDI_SERVICE_RESTORED);
+ }
}
}
break;
@@ -4507,6 +4511,9 @@ bge_chip_factotum(caddr_t arg)
*/
if (linkchg)
mac_link_update(bgep->mh, bgep->link_state);
+ if (bgep->manual_reset) {
+ bgep->manual_reset = B_FALSE;
+ }
return (result);
}
diff --git a/usr/src/uts/common/io/bge/bge_impl.h b/usr/src/uts/common/io/bge/bge_impl.h
index 8b2bbaebc7..2da4240765 100644
--- a/usr/src/uts/common/io/bge/bge_impl.h
+++ b/usr/src/uts/common/io/bge/bge_impl.h
@@ -20,7 +20,7 @@
*/
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -63,6 +63,7 @@ extern "C" {
#include <sys/pattr.h>
#include <sys/disp.h>
+#include <sys/cmn_err.h>
#include <sys/ddi.h>
#include <sys/sunddi.h>
@@ -616,6 +617,9 @@ typedef struct {
uint64_t hw_mac_addr; /* from chip register */
bge_mac_addr_t vendor_addr; /* transform of same */
boolean_t msi_enabled; /* default to true */
+
+ uint32_t rx_ticks_norm;
+ uint32_t rx_count_norm;
} chip_id_t;
#define CHIP_FLAG_SUPPORTED 0x80
@@ -696,7 +700,6 @@ enum {
PARAM_LINK_RX_PAUSE,
PARAM_LINK_TX_PAUSE,
- PARAM_LOOP_MODE,
PARAM_MSI_CNT,
PARAM_DRAIN_MAX,
@@ -916,6 +919,7 @@ typedef struct bge {
boolean_t send_hw_tcp_csum;
boolean_t recv_hw_tcp_csum;
boolean_t promisc;
+ boolean_t manual_reset;
/*
* Miscellaneous operating variables (not synchronised)
@@ -960,6 +964,17 @@ typedef struct bge {
uint32_t asf_status;
timeout_id_t asf_timeout_id;
#endif
+ uint32_t param_en_pause:1,
+ param_en_asym_pause:1,
+ param_en_1000hdx:1,
+ param_en_1000fdx:1,
+ param_en_100fdx:1,
+ param_en_100hdx:1,
+ param_en_10fdx:1,
+ param_en_10hdx:1,
+ param_pad_to_32:24;
+
+ uint32_t param_loop_mode;
} bge_t;
/*
@@ -1009,7 +1024,6 @@ typedef struct bge {
#define param_link_rx_pause nd_params[PARAM_LINK_RX_PAUSE].ndp_val
#define param_link_tx_pause nd_params[PARAM_LINK_TX_PAUSE].ndp_val
-#define param_loop_mode nd_params[PARAM_LOOP_MODE].ndp_val
#define param_msi_cnt nd_params[PARAM_MSI_CNT].ndp_val
#define param_drain_max nd_params[PARAM_DRAIN_MAX].ndp_val
@@ -1220,6 +1234,7 @@ void bge_chip_cyclic(void *arg);
enum ioc_reply bge_chip_ioctl(bge_t *bgep, queue_t *wq, mblk_t *mp,
struct iocblk *iocp);
uint_t bge_intr(caddr_t arg1, caddr_t arg2);
+void bge_sync_mac_modes(bge_t *);
extern uint32_t bge_rx_ticks_norm;
extern uint32_t bge_tx_ticks_norm;
extern uint32_t bge_rx_count_norm;
@@ -1260,6 +1275,7 @@ int bge_alloc_bufs(bge_t *bgep);
void bge_free_bufs(bge_t *bgep);
void bge_intr_enable(bge_t *bgep);
void bge_intr_disable(bge_t *bgep);
+int bge_reprogram(bge_t *);
/* bge_phys.c */
int bge_phys_init(bge_t *bgep);
diff --git a/usr/src/uts/common/io/bge/bge_kstats.c b/usr/src/uts/common/io/bge/bge_kstats.c
index 98141d92ce..32af1a2b13 100644
--- a/usr/src/uts/common/io/bge/bge_kstats.c
+++ b/usr/src/uts/common/io/bge/bge_kstats.c
@@ -20,7 +20,7 @@
*/
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -600,31 +600,6 @@ bge_setup_named_kstat(bge_t *bgep, int instance, char *name,
return (ksp);
}
-/*
- * Create kstats corresponding to NDD parameters
- */
-static kstat_t *
-bge_setup_params_kstat(bge_t *bgep, int instance, char *name,
- int (*update)(kstat_t *, int))
-{
- kstat_t *ksp;
- kstat_named_t *knp;
- int i;
-
- ksp = kstat_create(BGE_DRIVER_NAME, instance, name, "net",
- KSTAT_TYPE_NAMED, PARAM_COUNT, KSTAT_FLAG_PERSISTENT);
- if (ksp != NULL) {
- ksp->ks_private = bgep;
- ksp->ks_update = update;
- for (knp = ksp->ks_data, i = 0; i < PARAM_COUNT; ++knp, ++i)
- kstat_named_init(knp, bgep->nd_params[i].ndp_name+1,
- KSTAT_DATA_UINT64);
- kstat_install(ksp);
- }
-
- return (ksp);
-}
-
void
bge_init_kstats(bge_t *bgep, int instance)
{
diff --git a/usr/src/uts/common/io/bge/bge_main2.c b/usr/src/uts/common/io/bge/bge_main2.c
index f80a750652..7a13f85e50 100644
--- a/usr/src/uts/common/io/bge/bge_main2.c
+++ b/usr/src/uts/common/io/bge/bge_main2.c
@@ -28,6 +28,7 @@
#include "bge_impl.h"
#include <sys/sdt.h>
+#include <sys/dld.h>
/*
* This is the string displayed by modinfo, etc.
@@ -127,8 +128,17 @@ static int bge_m_unicst_add(void *, mac_multi_addr_t *);
static int bge_m_unicst_remove(void *, mac_addr_slot_t);
static int bge_m_unicst_modify(void *, mac_multi_addr_t *);
static int bge_m_unicst_get(void *, mac_multi_addr_t *);
-
-#define BGE_M_CALLBACK_FLAGS (MC_RESOURCES | MC_IOCTL | MC_GETCAPAB)
+static int bge_m_setprop(void *, const char *, mac_prop_id_t,
+ uint_t, const void *);
+static int bge_m_getprop(void *, const char *, mac_prop_id_t,
+ uint_t, void *);
+static int bge_set_priv_prop(bge_t *, const char *, uint_t,
+ const void *);
+static int bge_get_priv_prop(bge_t *, const char *, uint_t,
+ void *);
+
+#define BGE_M_CALLBACK_FLAGS\
+ (MC_RESOURCES | MC_IOCTL | MC_GETCAPAB | MC_SETPROP | MC_GETPROP)
static mac_callbacks_t bge_m_callbacks = {
BGE_M_CALLBACK_FLAGS,
@@ -141,7 +151,11 @@ static mac_callbacks_t bge_m_callbacks = {
bge_m_tx,
bge_m_resources,
bge_m_ioctl,
- bge_m_getcapab
+ bge_m_getcapab,
+ NULL,
+ NULL,
+ bge_m_setprop,
+ bge_m_getprop
};
/*
@@ -834,6 +848,439 @@ bge_m_unicst_get(void *arg, mac_multi_addr_t *maddr)
return (0);
}
+extern void bge_wake_factotum(bge_t *);
+
+static boolean_t
+bge_param_locked(mac_prop_id_t pr_num)
+{
+ /*
+ * All adv_* parameters are locked (read-only) while
+ * the device is in any sort of loopback mode ...
+ */
+ switch (pr_num) {
+ case DLD_PROP_ADV_1000FDX_CAP:
+ case DLD_PROP_EN_1000FDX_CAP:
+ case DLD_PROP_ADV_1000HDX_CAP:
+ case DLD_PROP_EN_1000HDX_CAP:
+ case DLD_PROP_ADV_100FDX_CAP:
+ case DLD_PROP_EN_100FDX_CAP:
+ case DLD_PROP_ADV_100HDX_CAP:
+ case DLD_PROP_EN_100HDX_CAP:
+ case DLD_PROP_ADV_10FDX_CAP:
+ case DLD_PROP_EN_10FDX_CAP:
+ case DLD_PROP_ADV_10HDX_CAP:
+ case DLD_PROP_EN_10HDX_CAP:
+ case DLD_PROP_AUTONEG:
+ case DLD_PROP_FLOWCTRL:
+ return (B_TRUE);
+ }
+ return (B_FALSE);
+}
+/*
+ * callback functions for set/get of properties
+ */
+static int
+bge_m_setprop(void *barg, const char *pr_name, mac_prop_id_t pr_num,
+ uint_t pr_valsize, const void *pr_val)
+{
+ bge_t *bgep = barg;
+ int err = 0;
+ uint64_t cur_mtu, new_mtu;
+ uint_t maxsdu;
+ link_flowctrl_t fl;
+
+ mutex_enter(bgep->genlock);
+ if (bgep->param_loop_mode != BGE_LOOP_NONE &&
+ bge_param_locked(pr_num)) {
+ /*
+ * All adv_* parameters are locked (read-only)
+ * while the device is in any sort of loopback mode.
+ */
+ mutex_exit(bgep->genlock);
+ return (EBUSY);
+ }
+ switch (pr_num) {
+ case DLD_PROP_EN_1000FDX_CAP:
+ bgep->param_en_1000fdx = *(uint8_t *)pr_val;
+ bgep->param_adv_1000fdx = *(uint8_t *)pr_val;
+ goto reprogram;
+ case DLD_PROP_EN_1000HDX_CAP:
+ bgep->param_en_1000hdx = *(uint8_t *)pr_val;
+ bgep->param_adv_1000hdx = *(uint8_t *)pr_val;
+ goto reprogram;
+ case DLD_PROP_EN_100FDX_CAP:
+ bgep->param_en_100fdx = *(uint8_t *)pr_val;
+ bgep->param_adv_100fdx = *(uint8_t *)pr_val;
+ goto reprogram;
+ case DLD_PROP_EN_100HDX_CAP:
+ bgep->param_en_100hdx = *(uint8_t *)pr_val;
+ bgep->param_adv_100hdx = *(uint8_t *)pr_val;
+ goto reprogram;
+ case DLD_PROP_EN_10FDX_CAP:
+ bgep->param_en_10fdx = *(uint8_t *)pr_val;
+ bgep->param_adv_10fdx = *(uint8_t *)pr_val;
+ goto reprogram;
+ case DLD_PROP_EN_10HDX_CAP:
+ bgep->param_en_10hdx = *(uint8_t *)pr_val;
+ bgep->param_adv_10hdx = *(uint8_t *)pr_val;
+reprogram:
+ if (err == 0 && bge_reprogram(bgep) == IOC_INVAL)
+ err = EINVAL;
+ break;
+ case DLD_PROP_ADV_1000FDX_CAP:
+ case DLD_PROP_ADV_1000HDX_CAP:
+ case DLD_PROP_ADV_100FDX_CAP:
+ case DLD_PROP_ADV_100HDX_CAP:
+ case DLD_PROP_ADV_10FDX_CAP:
+ case DLD_PROP_ADV_10HDX_CAP:
+ case DLD_PROP_STATUS:
+ case DLD_PROP_SPEED:
+ case DLD_PROP_DUPLEX:
+ err = EINVAL; /* read-only prop. Can't set this */
+ break;
+ case DLD_PROP_AUTONEG:
+ bgep->param_adv_autoneg = *(uint8_t *)pr_val;
+ if (bge_reprogram(bgep) == IOC_INVAL)
+ err = EINVAL;
+ break;
+ case DLD_PROP_DEFMTU:
+ cur_mtu = bgep->chipid.default_mtu;
+ bcopy(pr_val, &new_mtu, sizeof (new_mtu));
+ if (new_mtu == cur_mtu) {
+ err = 0;
+ break;
+ }
+ if (new_mtu < BGE_DEFAULT_MTU ||
+ new_mtu > BGE_MAXIMUM_MTU) {
+ err = EINVAL;
+ break;
+ }
+ if ((new_mtu > BGE_DEFAULT_MTU) &&
+ (bgep->chipid.flags & CHIP_FLAG_NO_JUMBO)) {
+ err = EINVAL;
+ break;
+ }
+ if (bgep->bge_mac_state == BGE_MAC_STARTED) {
+ err = EBUSY;
+ break;
+ }
+ bgep->chipid.default_mtu = new_mtu;
+ if (bge_chip_id_init(bgep)) {
+ err = EINVAL;
+ break;
+ }
+ maxsdu = bgep->chipid.ethmax_size -
+ sizeof (struct ether_header);
+ err = mac_maxsdu_update(bgep->mh, maxsdu);
+ if (err == 0) {
+ bgep->bge_dma_error = B_TRUE;
+ bgep->manual_reset = B_TRUE;
+ bge_chip_stop(bgep, B_TRUE);
+ bge_wake_factotum(bgep);
+ err = 0;
+ }
+ break;
+ case DLD_PROP_FLOWCTRL:
+ bcopy(pr_val, &fl, sizeof (fl));
+ switch (fl) {
+ default:
+ err = EINVAL;
+ break;
+ case LINK_FLOWCTRL_NONE:
+ bgep->param_adv_pause = 0;
+ bgep->param_adv_asym_pause = 0;
+
+ bgep->param_link_rx_pause = B_FALSE;
+ bgep->param_link_tx_pause = B_FALSE;
+ break;
+ case LINK_FLOWCTRL_RX:
+ if (!((bgep->param_lp_pause == 0) &&
+ (bgep->param_lp_asym_pause == 1))) {
+ err = EINVAL;
+ break;
+ }
+ bgep->param_adv_pause = 1;
+ bgep->param_adv_asym_pause = 1;
+
+ bgep->param_link_rx_pause = B_TRUE;
+ bgep->param_link_tx_pause = B_FALSE;
+ break;
+ case LINK_FLOWCTRL_TX:
+ if (!((bgep->param_lp_pause == 1) &&
+ (bgep->param_lp_asym_pause == 1))) {
+ err = EINVAL;
+ break;
+ }
+ bgep->param_adv_pause = 0;
+ bgep->param_adv_asym_pause = 1;
+
+ bgep->param_link_rx_pause = B_FALSE;
+ bgep->param_link_tx_pause = B_TRUE;
+ break;
+ case LINK_FLOWCTRL_BI:
+ if (bgep->param_lp_pause != 1) {
+ err = EINVAL;
+ break;
+ }
+ bgep->param_adv_pause = 1;
+
+ bgep->param_link_rx_pause = B_TRUE;
+ bgep->param_link_tx_pause = B_TRUE;
+ break;
+ }
+
+ if (err == 0) {
+ if (bge_reprogram(bgep) == IOC_INVAL)
+ err = EINVAL;
+ }
+
+ break;
+ default:
+ err = bge_set_priv_prop(bgep, pr_name, pr_valsize,
+ pr_val);
+ break;
+ }
+ mutex_exit(bgep->genlock);
+ return (err);
+}
+static int
+bge_m_getprop(void *barg, const char *pr_name, mac_prop_id_t pr_num,
+ uint_t pr_valsize, void *pr_val)
+{
+ bge_t *bgep = barg;
+ int err = 0;
+ link_flowctrl_t fl;
+
+ bzero(pr_val, pr_valsize);
+ switch (pr_num) {
+ case DLD_PROP_DUPLEX:
+ if (pr_valsize < sizeof (uint8_t))
+ return (EINVAL);
+ *(uint8_t *)pr_val = bgep->param_link_duplex;
+ break;
+ case DLD_PROP_SPEED:
+ if (pr_valsize < sizeof (uint_t))
+ return (EINVAL);
+ bcopy(&(bgep->param_link_speed), pr_val,
+ sizeof (bgep->param_link_speed));
+ break;
+ case DLD_PROP_STATUS:
+ if (pr_valsize < sizeof (uint8_t))
+ return (EINVAL);
+ *(uint8_t *)pr_val = bgep->param_link_up;
+ break;
+ case DLD_PROP_AUTONEG:
+ if (pr_valsize < sizeof (uint8_t))
+ return (EINVAL);
+ *(uint8_t *)pr_val = bgep->param_adv_autoneg;
+ break;
+ case DLD_PROP_DEFMTU: {
+ uint64_t tmp = 0;
+
+ if (pr_valsize < sizeof (uint64_t))
+ return (EINVAL);
+ tmp = bgep->chipid.default_mtu;
+ bcopy(&tmp, pr_val, sizeof (tmp));
+ break;
+ }
+ case DLD_PROP_FLOWCTRL:
+ if (pr_valsize < sizeof (link_flowctrl_t))
+ return (EINVAL);
+ if (bgep->param_link_rx_pause &&
+ !bgep->param_link_tx_pause)
+ fl = LINK_FLOWCTRL_RX;
+
+ if (!bgep->param_link_rx_pause &&
+ !bgep->param_link_tx_pause)
+ fl = LINK_FLOWCTRL_NONE;
+
+ if (!bgep->param_link_rx_pause &&
+ bgep->param_link_tx_pause)
+ fl = LINK_FLOWCTRL_TX;
+
+ if (bgep->param_link_rx_pause &&
+ bgep->param_link_tx_pause)
+ fl = LINK_FLOWCTRL_BI;
+ bcopy(&fl, pr_val, sizeof (fl));
+ break;
+ case DLD_PROP_ADV_1000FDX_CAP:
+ if (pr_valsize < sizeof (uint8_t))
+ return (EINVAL);
+ *(uint8_t *)pr_val = bgep->param_adv_1000fdx;
+ break;
+ case DLD_PROP_EN_1000FDX_CAP:
+ if (pr_valsize < sizeof (uint8_t))
+ return (EINVAL);
+ *(uint8_t *)pr_val = bgep->param_en_1000fdx;
+ break;
+ case DLD_PROP_ADV_1000HDX_CAP:
+ if (pr_valsize < sizeof (uint8_t))
+ return (EINVAL);
+ *(uint8_t *)pr_val = bgep->param_adv_1000hdx;
+ break;
+ case DLD_PROP_EN_1000HDX_CAP:
+ if (pr_valsize < sizeof (uint8_t))
+ return (EINVAL);
+ *(uint8_t *)pr_val = bgep->param_en_1000hdx;
+ break;
+ case DLD_PROP_ADV_100FDX_CAP:
+ if (pr_valsize < sizeof (uint8_t))
+ return (EINVAL);
+ *(uint8_t *)pr_val = bgep->param_adv_100fdx;
+ break;
+ case DLD_PROP_EN_100FDX_CAP:
+ if (pr_valsize < sizeof (uint8_t))
+ return (EINVAL);
+ *(uint8_t *)pr_val = bgep->param_en_100fdx;
+ break;
+ case DLD_PROP_ADV_100HDX_CAP:
+ if (pr_valsize < sizeof (uint8_t))
+ return (EINVAL);
+ *(uint8_t *)pr_val = bgep->param_adv_100hdx;
+ break;
+ case DLD_PROP_EN_100HDX_CAP:
+ if (pr_valsize < sizeof (uint8_t))
+ return (EINVAL);
+ *(uint8_t *)pr_val = bgep->param_en_100hdx;
+ break;
+ case DLD_PROP_ADV_10FDX_CAP:
+ if (pr_valsize < sizeof (uint8_t))
+ return (EINVAL);
+ *(uint8_t *)pr_val = bgep->param_adv_10fdx;
+ break;
+ case DLD_PROP_EN_10FDX_CAP:
+ if (pr_valsize < sizeof (uint8_t))
+ return (EINVAL);
+ *(uint8_t *)pr_val = bgep->param_en_10fdx;
+ break;
+ case DLD_PROP_ADV_10HDX_CAP:
+ if (pr_valsize < sizeof (uint8_t))
+ return (EINVAL);
+ *(uint8_t *)pr_val = bgep->param_adv_10hdx;
+ break;
+ case DLD_PROP_EN_10HDX_CAP:
+ if (pr_valsize < sizeof (uint8_t))
+ return (EINVAL);
+ *(uint8_t *)pr_val = bgep->param_en_10hdx;
+ break;
+ default:
+ err = bge_get_priv_prop(bgep, pr_name, pr_valsize,
+ pr_val);
+ return (err);
+ }
+ return (0);
+}
+
+/* ARGSUSED */
+static int
+bge_set_priv_prop(bge_t *bgep, const char *pr_name, uint_t pr_valsize,
+ const void *pr_val)
+{
+ int err = 0;
+ long result;
+
+ if (strcmp(pr_name, "_drain_max") == 0) {
+
+ /*
+ * on the Tx side, we need to update the h/w register for
+ * real packet transmission per packet. The drain_max parameter
+ * is used to reduce the register access. This parameter
+ * controls the max number of packets that we will hold before
+ * updating the bge h/w to trigger h/w transmit. The bge
+ * chipset usually has a max of 512 Tx descriptors, thus
+ * the upper bound on drain_max is 512.
+ */
+ if (pr_val == NULL) {
+ err = EINVAL;
+ return (err);
+ }
+ (void) ddi_strtol(pr_val, (char **)NULL, 0, &result);
+ if (result > 512 || result < 1)
+ err = EINVAL;
+ else {
+ bgep->param_drain_max = (uint32_t)result;
+ if (bge_reprogram(bgep) == IOC_INVAL)
+ err = EINVAL;
+ }
+ return (err);
+ }
+ if (strcmp(pr_name, "_msi_cnt") == 0) {
+
+ if (pr_val == NULL) {
+ err = EINVAL;
+ return (err);
+ }
+ (void) ddi_strtol(pr_val, (char **)NULL, 0, &result);
+ if (result > 7 || result < 0)
+ err = EINVAL;
+ else {
+ bgep->param_msi_cnt = (uint32_t)result;
+ if (bge_reprogram(bgep) == IOC_INVAL)
+ err = EINVAL;
+ }
+ return (err);
+ }
+ if (strcmp(pr_name, "_intr_coalesce_blank_time") == 0) {
+ if (ddi_strtol(pr_val, (char **)NULL, 0, &result) != 0) {
+ return (EINVAL);
+ }
+
+ bgep->chipid.rx_ticks_norm = result;
+ return (0);
+ }
+
+ if (strcmp(pr_name, "_intr_coalesce_pkt_cnt") == 0) {
+ if (ddi_strtol(pr_val, (char **)NULL, 0, &result) != 0)
+ return (EINVAL);
+
+ bgep->chipid.rx_count_norm = result;
+ return (0);
+ }
+ return (EINVAL);
+}
+
+static int
+bge_get_priv_prop(bge_t *bge, const char *pr_name, uint_t pr_valsize,
+ void *pr_val)
+{
+ char valstr[MAXNAMELEN];
+ int err = EINVAL;
+ uint_t strsize;
+
+
+ if (strcmp(pr_name, "_drain_max") == 0) {
+ (void) sprintf(valstr, "%d", bge->param_drain_max);
+ err = 0;
+ goto done;
+ }
+ if (strcmp(pr_name, "_msi_cnt") == 0) {
+ (void) sprintf(valstr, "%d", bge->param_msi_cnt);
+ err = 0;
+ goto done;
+ }
+
+ if (strcmp(pr_name, "_intr_coalesce_blank_time") == 0) {
+ (void) sprintf(valstr, "%d", bge->chipid.rx_ticks_norm);
+ err = 0;
+ goto done;
+ }
+
+ if (strcmp(pr_name, "_intr_coalesce_pkt_cnt") == 0) {
+ (void) sprintf(valstr, "%d", bge->chipid.rx_count_norm);
+ err = 0;
+ goto done;
+ }
+
+done:
+ strsize = (uint_t)strlen(valstr);
+ if (pr_valsize < strsize) {
+ err = ENOBUFS;
+ } else {
+ (void) strlcpy(pr_val, valstr, pr_valsize);
+ }
+ return (err);
+}
+
/*
* Compute the index of the required bit in the multicast hash map.
* This must mirror the way the hardware actually does it!
@@ -1262,22 +1709,8 @@ bge_m_ioctl(void *arg, queue_t *wq, mblk_t *mp)
switch (status) {
case IOC_RESTART_REPLY:
case IOC_RESTART_ACK:
- if (bge_phys_update(bgep) != DDI_SUCCESS) {
- ddi_fm_service_impact(bgep->devinfo,
- DDI_SERVICE_DEGRADED);
- status = IOC_INVAL;
- }
-#ifdef BGE_IPMI_ASF
- if (bge_chip_sync(bgep, B_TRUE) == DDI_FAILURE) {
-#else
- if (bge_chip_sync(bgep) == DDI_FAILURE) {
-#endif
- ddi_fm_service_impact(bgep->devinfo,
- DDI_SERVICE_DEGRADED);
+ if (bge_reprogram(bgep) == IOC_INVAL)
status = IOC_INVAL;
- }
- if (bgep->intr_type == DDI_INTR_TYPE_MSI)
- bge_chip_msi_trig(bgep);
break;
}
@@ -1331,15 +1764,13 @@ bge_m_ioctl(void *arg, queue_t *wq, mblk_t *mp)
}
static void
-bge_m_resources(void *arg)
+bge_resources_add(bge_t *bgep, time_t time, uint_t pkt_cnt)
{
- bge_t *bgep = arg;
+
recv_ring_t *rrp;
mac_rx_fifo_t mrf;
int ring;
- mutex_enter(bgep->genlock);
-
/*
* Register Rx rings as resources and save mac
* resource id for future reference
@@ -1347,15 +1778,25 @@ bge_m_resources(void *arg)
mrf.mrf_type = MAC_RX_FIFO;
mrf.mrf_blank = bge_chip_blank;
mrf.mrf_arg = (void *)bgep;
- mrf.mrf_normal_blank_time = bge_rx_ticks_norm;
- mrf.mrf_normal_pkt_count = bge_rx_count_norm;
+ mrf.mrf_normal_blank_time = time;
+ mrf.mrf_normal_pkt_count = pkt_cnt;
for (ring = 0; ring < bgep->chipid.rx_rings; ring++) {
rrp = &bgep->recv[ring];
rrp->handle = mac_resource_add(bgep->mh,
(mac_resource_t *)&mrf);
}
+}
+static void
+bge_m_resources(void *arg)
+{
+ bge_t *bgep = arg;
+
+ mutex_enter(bgep->genlock);
+
+ bge_resources_add(bgep, bgep->chipid.rx_ticks_norm,
+ bgep->chipid.rx_count_norm);
mutex_exit(bgep->genlock);
}
@@ -2520,6 +2961,9 @@ bge_attach(dev_info_t *devinfo, ddi_attach_cmd_t cmd)
ddi_set_driver_private(devinfo, bgep);
bgep->bge_guard = BGE_GUARD;
bgep->devinfo = devinfo;
+ bgep->param_drain_max = 64;
+ bgep->param_msi_cnt = 0;
+ bgep->param_loop_mode = 0;
/*
* Initialize more fields in BGE private data
@@ -3241,3 +3685,27 @@ bge_intr_disable(bge_t *bgep)
}
}
}
+
+int
+bge_reprogram(bge_t *bgep)
+{
+ int status = 0;
+
+ ASSERT(mutex_owned(bgep->genlock));
+
+ if (bge_phys_update(bgep) != DDI_SUCCESS) {
+ ddi_fm_service_impact(bgep->devinfo, DDI_SERVICE_DEGRADED);
+ status = IOC_INVAL;
+ }
+#ifdef BGE_IPMI_ASF
+ if (bge_chip_sync(bgep, B_TRUE) == DDI_FAILURE) {
+#else
+ if (bge_chip_sync(bgep) == DDI_FAILURE) {
+#endif
+ ddi_fm_service_impact(bgep->devinfo, DDI_SERVICE_DEGRADED);
+ status = IOC_INVAL;
+ }
+ if (bgep->intr_type == DDI_INTR_TYPE_MSI)
+ bge_chip_msi_trig(bgep);
+ return (status);
+}
diff --git a/usr/src/uts/common/io/bge/bge_ndd.c b/usr/src/uts/common/io/bge/bge_ndd.c
index ca993b64f7..280f3b6bcb 100644
--- a/usr/src/uts/common/io/bge/bge_ndd.c
+++ b/usr/src/uts/common/io/bge/bge_ndd.c
@@ -20,7 +20,7 @@
*/
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -30,7 +30,6 @@
#define BGE_DBG BGE_DBG_NDD /* debug flag for this code */
-
/*
* Property names
*/
@@ -112,15 +111,6 @@ static const nd_param_t nd_template[] = {
{ PARAM_LINK_RX_PAUSE, 0, 1, 0, "-link_rx_pause" },
{ PARAM_LINK_TX_PAUSE, 0, 1, 0, "-link_tx_pause" },
-/* Loopback status */
-{ PARAM_LOOP_MODE, 0, 5, 0, "-loop_mode" },
-
-/* MSI count */
-{ PARAM_MSI_CNT, 0, 7, 0, "+msi_cnt" },
-
-/* Performance tuning */
-{ PARAM_DRAIN_MAX, 1, 512, 64, "+drain_max" },
-
/* Terminator */
{ PARAM_COUNT, 0, 0, 0, NULL }
};
@@ -146,6 +136,27 @@ bge_param_get(queue_t *q, mblk_t *mp, caddr_t cp, cred_t *credp)
}
/*
+ * synchronize the adv* and en* parameters.
+ *
+ * See comments in <sys/dld.h> for details of the *_en_*
+ * parameters. The usage of ndd for setting adv parameters will
+ * synchronize all the en parameters with the bge parameters,
+ * implicitly disabling any settings made via dladm.
+ */
+static void
+bge_param_sync(bge_t *bgep)
+{
+ bgep->param_en_pause = bgep->param_adv_pause;
+ bgep->param_en_asym_pause = bgep->param_adv_asym_pause;
+ bgep->param_en_1000fdx = bgep->param_adv_1000fdx;
+ bgep->param_en_1000hdx = bgep->param_adv_1000hdx;
+ bgep->param_en_100fdx = bgep->param_adv_100fdx;
+ bgep->param_en_100hdx = bgep->param_adv_100hdx;
+ bgep->param_en_10fdx = bgep->param_adv_10fdx;
+ bgep->param_en_10hdx = bgep->param_adv_10hdx;
+}
+
+/*
* Validates the request to set a BGE parameter to a specific value.
* If the request is OK, the parameter is set. Also the <info> field
* is incremented to show that the parameter was touched, even though
@@ -251,7 +262,7 @@ bge_param_register(bge_t *bgep)
nd_fail:
BGE_DEBUG(("bge_param_register: FAILED at index %d [info %d]",
- tmplp-nd_template, tmplp->ndp_info));
+ tmplp-nd_template, tmplp->ndp_info));
nd_free(nddpp);
return (DDI_FAILURE);
}
@@ -280,8 +291,8 @@ bge_nd_init(bge_t *bgep)
*/
if (BGE_PROP_EXISTS(bgep->devinfo, supported_net)) {
if (ddi_prop_lookup_string_array(DDI_DEV_T_ANY, bgep->devinfo,
- DDI_PROP_DONTPASS, supported_net,
- &options, &noptions) == DDI_PROP_SUCCESS) {
+ DDI_PROP_DONTPASS, supported_net,
+ &options, &noptions) == DDI_PROP_SUCCESS) {
bgep->param_adv_autoneg = 0;
bgep->param_adv_1000fdx = 0;
@@ -342,7 +353,7 @@ bge_nd_init(bge_t *bgep)
speed = BGE_PROP_GET_INT(dip, transfer_speed_propname);
bge_log(bgep, "%s property is %d",
- transfer_speed_propname, speed);
+ transfer_speed_propname, speed);
switch (speed) {
case 1000:
@@ -401,9 +412,9 @@ bge_nd_init(bge_t *bgep)
speed = BGE_PROP_GET_INT(dip, speed_propname);
duplex = BGE_PROP_GET_INT(dip, duplex_propname);
bge_log(bgep, "%s property is %d",
- speed_propname, speed);
+ speed_propname, speed);
bge_log(bgep, "%s property is %d",
- duplex_propname, duplex);
+ duplex_propname, duplex);
switch (speed) {
case 1000:
@@ -446,15 +457,17 @@ bge_nd_init(bge_t *bgep)
}
BGE_DEBUG(("bge_nd_init: autoneg %d"
- "pause %d asym_pause %d "
- "1000fdx %d 1000hdx %d "
- "100fdx %d 100hdx %d "
- "10fdx %d 10hdx %d ",
- bgep->param_adv_autoneg,
- bgep->param_adv_pause, bgep->param_adv_asym_pause,
- bgep->param_adv_1000fdx, bgep->param_adv_1000hdx,
- bgep->param_adv_100fdx, bgep->param_adv_100hdx,
- bgep->param_adv_10fdx, bgep->param_adv_10hdx));
+ "pause %d asym_pause %d "
+ "1000fdx %d 1000hdx %d "
+ "100fdx %d 100hdx %d "
+ "10fdx %d 10hdx %d ",
+ bgep->param_adv_autoneg,
+ bgep->param_adv_pause, bgep->param_adv_asym_pause,
+ bgep->param_adv_1000fdx, bgep->param_adv_1000hdx,
+ bgep->param_adv_100fdx, bgep->param_adv_100hdx,
+ bgep->param_adv_10fdx, bgep->param_adv_10hdx));
+
+ bge_param_sync(bgep);
return (0);
}
@@ -468,7 +481,7 @@ bge_nd_ioctl(bge_t *bgep, queue_t *wq, mblk_t *mp, struct iocblk *iocp)
int cmd;
BGE_TRACE(("bge_nd_ioctl($%p, $%p, $%p, $%p)",
- (void *)bgep, (void *)wq, (void *)mp, (void *)iocp));
+ (void *)bgep, (void *)wq, (void *)mp, (void *)iocp));
ASSERT(mutex_owned(bgep->genlock));
@@ -513,6 +526,8 @@ bge_nd_ioctl(bge_t *bgep, queue_t *wq, mblk_t *mp, struct iocblk *iocp)
info = ndp->ndp_info;
ok = nd_getset(wq, bgep->nd_data_p, mp);
+ bge_param_sync(bgep);
+
/*
* If nd_getset() returns B_FALSE, the command was
* not valid (e.g. unknown name), so we just tell
@@ -526,8 +541,8 @@ bge_nd_ioctl(bge_t *bgep, queue_t *wq, mblk_t *mp, struct iocblk *iocp)
* So, we also drop out in that case ...
*/
BGE_DEBUG(("bge_nd_ioctl: set %s err %d autoneg %d info %d/%d",
- ok ? "OK" : "FAIL", iocp->ioc_error,
- ndp->ndp_val, info, ndp->ndp_info));
+ ok ? "OK" : "FAIL", iocp->ioc_error,
+ ndp->ndp_val, info, ndp->ndp_info));
if (!ok)
return (IOC_INVAL);
if (iocp->ioc_error)
diff --git a/usr/src/uts/common/io/bge/bge_recv2.c b/usr/src/uts/common/io/bge/bge_recv2.c
index 78a5913ae2..06282b461b 100644
--- a/usr/src/uts/common/io/bge/bge_recv2.c
+++ b/usr/src/uts/common/io/bge/bge_recv2.c
@@ -20,7 +20,7 @@
*/
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -211,8 +211,8 @@ bge_receive_packet(bge_t *bgep, bge_rbd_t *hw_rbd_p)
ehp->ether_tpid = ntohs(ETHERTYPE_VLAN);
ehp->ether_tci = ntohs(hw_rbd.vlan_tci);
bcopy(((uchar_t *)(DMA_VPTR(srbdp->pbuf))) + 2 * ETHERADDRL,
- dp + 2 * ETHERADDRL + VLAN_TAGSZ,
- len - 2 * ETHERADDRL);
+ dp + 2 * ETHERADDRL + VLAN_TAGSZ,
+ len - 2 * ETHERADDRL);
} else {
#endif
mp->b_rptr = dp = mp->b_rptr + BGE_HEADROOM;
@@ -312,7 +312,7 @@ bge_receive_ring(bge_t *bgep, recv_ring_t *rrp)
slot = rrp->rx_next;
while ((slot != *rrp->prod_index_p) && /* Note: volatile */
- (recv_cnt < BGE_MAXPKT_RCVED)) {
+ (recv_cnt < BGE_MAXPKT_RCVED)) {
if ((mp = bge_receive_packet(bgep, &hw_rbd_p[slot])) != NULL) {
*tail = mp;
tail = &mp->b_next;
diff --git a/usr/src/uts/common/io/dld/dld_drv.c b/usr/src/uts/common/io/dld/dld_drv.c
index 2b394c051d..e09b6eff13 100644
--- a/usr/src/uts/common/io/dld/dld_drv.c
+++ b/usr/src/uts/common/io/dld/dld_drv.c
@@ -431,8 +431,8 @@ drv_ioc_attr(dld_ctl_str_t *ctls, mblk_t *mp)
dls_devnet_rele_tmp(dlh);
goto failed;
}
+ mac_sdu_get(dvp->dv_dlp->dl_mh, NULL, &diap->dia_max_sdu);
- diap->dia_max_sdu = dvp->dv_dlp->dl_mip->mi_sdu_max;
dls_vlan_rele(dvp);
dls_devnet_rele_tmp(dlh);
@@ -507,6 +507,72 @@ failed:
}
/*
+ * DLDIOCSETPROP
+ */
+static void
+drv_ioc_prop_common(dld_ctl_str_t *ctls, mblk_t *mp, boolean_t set)
+{
+ int err = EINVAL, dsize;
+ queue_t *q = ctls->cs_wq;
+ dld_ioc_prop_t *dipp;
+ dls_dl_handle_t dlh;
+ dls_vlan_t *dvp;
+ datalink_id_t linkid;
+ mac_prop_t macprop;
+
+ if ((err = miocpullup(mp, sizeof (dld_ioc_prop_t))) != 0)
+ goto done;
+ dipp = (dld_ioc_prop_t *)mp->b_cont->b_rptr;
+
+ dsize = sizeof (dld_ioc_prop_t) + dipp->pr_valsize - 1;
+ if ((err = miocpullup(mp, dsize)) != 0)
+ goto done;
+ dipp = (dld_ioc_prop_t *)mp->b_cont->b_rptr;
+
+ if ((err = dls_mgmt_get_linkid(dipp->pr_linkname, &linkid)) != 0)
+ goto done;
+
+ if ((err = dls_devnet_hold_tmp(linkid, &dlh)) != 0)
+ goto done;
+
+ if ((err = dls_vlan_hold(dls_devnet_mac(dlh),
+ dls_devnet_vid(dlh), &dvp, B_FALSE, B_FALSE)) != 0) {
+ dls_devnet_rele_tmp(dlh);
+ goto done;
+ }
+
+ macprop.mp_name = dipp->pr_name;
+ macprop.mp_id = dipp->pr_num;
+
+ if (set)
+ err = mac_set_prop(dvp->dv_dlp->dl_mh, &macprop,
+ dipp->pr_val, dipp->pr_valsize);
+ else
+ err = mac_get_prop(dvp->dv_dlp->dl_mh, &macprop,
+ dipp->pr_val, dipp->pr_valsize);
+
+ dls_vlan_rele(dvp);
+ dls_devnet_rele_tmp(dlh);
+done:
+ if (err == 0)
+ miocack(q, mp, dsize, 0);
+ else
+ miocnak(q, mp, 0, err);
+}
+
+static void
+drv_ioc_setprop(dld_ctl_str_t *ctls, mblk_t *mp)
+{
+ drv_ioc_prop_common(ctls, mp, B_TRUE);
+}
+
+static void
+drv_ioc_getprop(dld_ctl_str_t *ctls, mblk_t *mp)
+{
+ drv_ioc_prop_common(ctls, mp, B_FALSE);
+}
+
+/*
* DLDIOC_CREATE_VLAN
*/
static void
@@ -900,6 +966,12 @@ drv_ioc(dld_ctl_str_t *ctls, mblk_t *mp)
case DLDIOC_SECOBJ_UNSET:
drv_ioc_secobj_unset(ctls, mp);
return;
+ case DLDIOCSETPROP:
+ drv_ioc_setprop(ctls, mp);
+ return;
+ case DLDIOCGETPROP:
+ drv_ioc_getprop(ctls, mp);
+ return;
case DLDIOC_CREATE_VLAN:
drv_ioc_create_vlan(ctls, mp);
return;
diff --git a/usr/src/uts/common/io/dld/dld_proto.c b/usr/src/uts/common/io/dld/dld_proto.c
index 78543294d4..f572c3c322 100644
--- a/usr/src/uts/common/io/dld/dld_proto.c
+++ b/usr/src/uts/common/io/dld/dld_proto.c
@@ -238,6 +238,8 @@ proto_info_req(dld_str_t *dsp, union DL_primitives *udlp, mblk_t *mp)
minfop = &minfo;
} else {
minfop = (mac_info_t *)dsp->ds_mip;
+ /* We can only get the sdu if we're attached. */
+ mac_sdu_get(dsp->ds_mh, &dlp->dl_min_sdu, &dlp->dl_max_sdu);
}
/*
@@ -255,12 +257,6 @@ proto_info_req(dld_str_t *dsp, union DL_primitives *udlp, mblk_t *mp)
sap_length = sizeof (uint16_t);
dlp->dl_sap_length = NEG(sap_length);
- /*
- * Set the minimum and maximum payload sizes.
- */
- dlp->dl_min_sdu = minfop->mi_sdu_min;
- dlp->dl_max_sdu = minfop->mi_sdu_max;
-
addr_length = minfop->mi_addr_length;
/*
@@ -1322,6 +1318,7 @@ dld_wput_proto_data(dld_str_t *dsp, mblk_t *mp)
mblk_t *bp, *payload;
uint32_t start, stuff, end, value, flags;
t_uscalar_t dl_err;
+ uint_t max_sdu;
if (MBLKL(mp) < sizeof (dl_unitdata_req_t) || mp->b_cont == NULL) {
dl_err = DL_BADPRIM;
@@ -1358,7 +1355,8 @@ dld_wput_proto_data(dld_str_t *dsp, mblk_t *mp)
size += MBLKL(bp);
}
- if (size > dsp->ds_mip->mi_sdu_max)
+ mac_sdu_get(dsp->ds_mh, NULL, &max_sdu);
+ if (size > max_sdu)
goto baddata;
/*
diff --git a/usr/src/uts/common/io/dld/dld_str.c b/usr/src/uts/common/io/dld/dld_str.c
index f89e4a5f94..bb39729813 100644
--- a/usr/src/uts/common/io/dld/dld_str.c
+++ b/usr/src/uts/common/io/dld/dld_str.c
@@ -1008,6 +1008,7 @@ str_mdata_raw_put(dld_str_t *dsp, mblk_t *mp)
size_t size;
mac_header_info_t mhi;
uint_t pri, vid;
+ uint_t max_sdu;
/*
* Certain MAC type plugins provide an illusion for raw DLPI
@@ -1042,12 +1043,13 @@ str_mdata_raw_put(dld_str_t *dsp, mblk_t *mp)
if (dls_header_info(dsp->ds_dc, mp, &mhi) != 0)
goto discard;
+ mac_sdu_get(dsp->ds_mh, NULL, &max_sdu);
/*
* If LSO is enabled, check the size against lso_max. Otherwise,
- * compare the packet size with sdu_max.
+ * compare the packet size with max_sdu.
*/
- if (size > (dsp->ds_lso ? dsp->ds_lso_max : dsp->ds_mip->mi_sdu_max)
- + mhi.mhi_hdrsize)
+ max_sdu = dsp->ds_lso ? dsp->ds_lso_max : max_sdu;
+ if (size > max_sdu + mhi.mhi_hdrsize)
goto discard;
if (is_ethernet) {
@@ -1473,6 +1475,31 @@ dld_str_rx_unitdata(void *arg, mac_resource_handle_t mrh, mblk_t *mp,
}
/*
+ * DL_NOTIFY_IND: DL_NOTE_SDU_SIZE
+ */
+static void
+str_notify_sdu_size(dld_str_t *dsp, uint_t max_sdu)
+{
+ mblk_t *mp;
+ dl_notify_ind_t *dlip;
+
+ if (!(dsp->ds_notifications & DL_NOTE_SDU_SIZE))
+ return;
+
+ if ((mp = mexchange(dsp->ds_wq, NULL, sizeof (dl_notify_ind_t),
+ M_PROTO, 0)) == NULL)
+ return;
+
+ bzero(mp->b_rptr, sizeof (dl_notify_ind_t));
+ dlip = (dl_notify_ind_t *)mp->b_rptr;
+ dlip->dl_primitive = DL_NOTIFY_IND;
+ dlip->dl_notification = DL_NOTE_SDU_SIZE;
+ dlip->dl_data = max_sdu;
+
+ qreply(dsp->ds_wq, mp);
+}
+
+/*
* Generate DL_NOTIFY_IND messages to notify the DLPI consumer of the
* current state of the interface.
*/
@@ -1857,12 +1884,20 @@ str_notify(void *arg, mac_notify_type_t type)
str_notify_capab_reneg(dsp);
break;
+ case MAC_NOTE_SDU_SIZE: {
+ uint_t max_sdu;
+ mac_sdu_get(dsp->ds_mh, NULL, &max_sdu);
+ str_notify_sdu_size(dsp, max_sdu);
+ break;
+ }
+
case MAC_NOTE_FASTPATH_FLUSH:
str_notify_fastpath_flush(dsp);
break;
case MAC_NOTE_MARGIN:
break;
+
default:
ASSERT(B_FALSE);
break;
diff --git a/usr/src/uts/common/io/gld.c b/usr/src/uts/common/io/gld.c
index d14b0eff00..0aa1ae890a 100644
--- a/usr/src/uts/common/io/gld.c
+++ b/usr/src/uts/common/io/gld.c
@@ -204,7 +204,7 @@ extern void gld_sr_dump(gld_mac_info_t *);
* Allocate and zero-out "number" structures each of type "structure" in
* kernel memory.
*/
-#define GETSTRUCT(structure, number) \
+#define GLD_GETSTRUCT(structure, number) \
(kmem_zalloc((uint_t)(sizeof (structure) * (number)), KM_NOSLEEP))
#define abs(a) ((a) < 0 ? -(a) : a)
@@ -574,7 +574,7 @@ gld_register(dev_info_t *devinfo, char *devname, gld_mac_info_t *macinfo)
*/
if (glddev == NULL) {
/* first occurrence of this device name (major number) */
- glddev = GETSTRUCT(glddev_t, 1);
+ glddev = GLD_GETSTRUCT(glddev_t, 1);
if (glddev == NULL) {
mutex_exit(&gld_device_list.gld_devlock);
return (DDI_FAILURE);
@@ -584,9 +584,9 @@ gld_register(dev_info_t *devinfo, char *devname, gld_mac_info_t *macinfo)
glddev->gld_major = major;
glddev->gld_nextminor = GLD_MIN_CLONE_MINOR;
glddev->gld_mac_next = glddev->gld_mac_prev =
- (gld_mac_info_t *)&glddev->gld_mac_next;
+ (gld_mac_info_t *)&glddev->gld_mac_next;
glddev->gld_str_next = glddev->gld_str_prev =
- (gld_t *)&glddev->gld_str_next;
+ (gld_t *)&glddev->gld_str_next;
mutex_init(&glddev->gld_devlock, NULL, MUTEX_DRIVER, NULL);
/* allow increase of number of supported multicast addrs */
@@ -806,9 +806,9 @@ late_failure:
ddi_remove_minor_node(devinfo, NULL);
GLDM_LOCK_DESTROY(macinfo);
if (mac_pvt->curr_macaddr != NULL)
- kmem_free(mac_pvt->curr_macaddr, macinfo->gldm_addrlen);
+ kmem_free(mac_pvt->curr_macaddr, macinfo->gldm_addrlen);
if (mac_pvt->statistics != NULL)
- kmem_free(mac_pvt->statistics, sizeof (struct gld_stats));
+ kmem_free(mac_pvt->statistics, sizeof (struct gld_stats));
kmem_free(macinfo->gldm_mac_pvt, sizeof (gld_mac_pvt_t));
macinfo->gldm_mac_pvt = NULL;
@@ -3243,13 +3243,13 @@ gld_addudind(gld_t *gld, mblk_t *mp, pktinfo_t *pktinfo, boolean_t tagged)
dludindp->dl_primitive = DL_UNITDATA_IND;
dludindp->dl_src_addr_length =
dludindp->dl_dest_addr_length = macinfo->gldm_addrlen +
- abs(macinfo->gldm_saplen);
+ abs(macinfo->gldm_saplen);
dludindp->dl_dest_addr_offset = sizeof (dl_unitdata_ind_t);
dludindp->dl_src_addr_offset = dludindp->dl_dest_addr_offset +
- dludindp->dl_dest_addr_length;
+ dludindp->dl_dest_addr_length;
dludindp->dl_group_address = (pktinfo->isMulticast ||
- pktinfo->isBroadcast);
+ pktinfo->isBroadcast);
nmp->b_wptr = nmp->b_rptr + dludindp->dl_dest_addr_offset;
@@ -4001,14 +4001,14 @@ gld_notify_req(queue_t *q, mblk_t *mp)
#ifdef GLD_DEBUG
if (gld_debug & GLDTRACE)
cmn_err(CE_NOTE, "gld_notify_req(%p %p)",
- (void *)q, (void *)mp);
+ (void *)q, (void *)mp);
#endif
if (gld->gld_state == DL_UNATTACHED) {
#ifdef GLD_DEBUG
if (gld_debug & GLDERRS)
cmn_err(CE_NOTE, "gld_notify_req: wrong state (%d)",
- gld->gld_state);
+ gld->gld_state);
#endif
return (DL_OUTSTATE);
}
@@ -4205,7 +4205,7 @@ gld_bind(queue_t *q, mblk_t *mp)
#ifdef GLD_DEBUG
if (gld_debug & GLDERRS)
cmn_err(CE_NOTE, "gld_bind: bound or not attached (%d)",
- gld->gld_state);
+ gld->gld_state);
#endif
return (DL_OUTSTATE);
}
@@ -4285,7 +4285,7 @@ gld_unbind(queue_t *q, mblk_t *mp)
#ifdef GLD_DEBUG
if (gld_debug & GLDERRS)
cmn_err(CE_NOTE, "gld_unbind: wrong state (%d)",
- gld->gld_state);
+ gld->gld_state);
#endif
return (DL_OUTSTATE);
}
@@ -4516,7 +4516,7 @@ gld_unitdata(queue_t *q, mblk_t *mp)
#ifdef GLD_DEBUG
if (gld_debug & GLDERRS)
cmn_err(CE_NOTE, "gld_unitdata: wrong state (%d)",
- gld->gld_state);
+ gld->gld_state);
#endif
dluderrorind(q, mp, mp->b_rptr + dlp->dl_dest_addr_offset,
dlp->dl_dest_addr_length, DL_OUTSTATE, 0);
@@ -4539,7 +4539,7 @@ gld_unitdata(queue_t *q, mblk_t *mp)
#ifdef GLD_DEBUG
if (gld_debug & GLDERRS)
cmn_err(CE_NOTE, "gld_unitdata: bad msglen (%d)",
- (int)msglen);
+ (int)msglen);
#endif
dluderrorind(q, mp, mp->b_rptr + dlp->dl_dest_addr_offset,
dlp->dl_dest_addr_length, DL_BADDATA, 0);
@@ -4886,8 +4886,8 @@ gld_enable_multi(queue_t *q, mblk_t *mp)
/* does this address appear in current table? */
if (gld->gld_mcast == NULL) {
/* no mcast addresses -- allocate table */
- gld->gld_mcast = GETSTRUCT(gld_mcast_t *,
- glddev->gld_multisize);
+ gld->gld_mcast = GLD_GETSTRUCT(gld_mcast_t *,
+ glddev->gld_multisize);
if (gld->gld_mcast == NULL) {
GLDM_UNLOCK(macinfo);
dlerrorack(q, mp, DL_ENABMULTI_REQ, DL_SYSERR, ENOSR);
@@ -4898,7 +4898,7 @@ gld_enable_multi(queue_t *q, mblk_t *mp)
for (i = 0; i < gld->gld_multicnt; i++) {
if (gld->gld_mcast[i] &&
mac_eq(gld->gld_mcast[i]->gldm_addr,
- maddr, macinfo->gldm_addrlen)) {
+ maddr, macinfo->gldm_addrlen)) {
/* this is a match -- just succeed */
ASSERT(gld->gld_mcast[i]->gldm_refcnt);
GLDM_UNLOCK(macinfo);
@@ -4913,8 +4913,8 @@ gld_enable_multi(queue_t *q, mblk_t *mp)
*/
mcast = NULL;
if (mac_pvt->mcast_table == NULL) {
- mac_pvt->mcast_table = GETSTRUCT(gld_mcast_t,
- glddev->gld_multisize);
+ mac_pvt->mcast_table = GLD_GETSTRUCT(gld_mcast_t,
+ glddev->gld_multisize);
if (mac_pvt->mcast_table == NULL) {
GLDM_UNLOCK(macinfo);
dlerrorack(q, mp, DL_ENABMULTI_REQ, DL_SYSERR, ENOSR);
@@ -5685,7 +5685,7 @@ nextminor:
;
}
cmn_err(CE_WARN, "GLD ran out of minor numbers for %s",
- device->gld_name);
+ device->gld_name);
return (0);
}
diff --git a/usr/src/uts/common/io/ipw/ipw2100.c b/usr/src/uts/common/io/ipw/ipw2100.c
index 34fcc32a6e..10e5c7f65c 100644
--- a/usr/src/uts/common/io/ipw/ipw2100.c
+++ b/usr/src/uts/common/io/ipw/ipw2100.c
@@ -51,6 +51,7 @@
#include <sys/devops.h>
#include <sys/dlpi.h>
#include <sys/mac.h>
+#include <net/if.h>
#include <sys/mac_wifi.h>
#include <sys/varargs.h>
#include <sys/policy.h>
diff --git a/usr/src/uts/common/io/ipw/ipw2100_impl.h b/usr/src/uts/common/io/ipw/ipw2100_impl.h
index b0800d8e80..269ed55eb5 100644
--- a/usr/src/uts/common/io/ipw/ipw2100_impl.h
+++ b/usr/src/uts/common/io/ipw/ipw2100_impl.h
@@ -1,5 +1,5 @@
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -166,12 +166,7 @@ struct ipw2100_softc {
kcondvar_t sc_scan_cv; /* used for active scan */
kthread_t *sc_mf_thread;
uint32_t sc_mfthread_switch; /* 0/1 indicate off/on */
-
int if_flags;
-#define IFF_DEBUG (0x0004)
-#define IFF_PROMISC (0x0100)
-#define IFF_SIMPLEX (0x0800)
-
};
/*
diff --git a/usr/src/uts/common/io/mac/mac.c b/usr/src/uts/common/io/mac/mac.c
index d12bfdf021..3bc71547de 100644
--- a/usr/src/uts/common/io/mac/mac.c
+++ b/usr/src/uts/common/io/mac/mac.c
@@ -53,6 +53,7 @@
#include <sys/cpuvar.h>
#include <sys/atomic.h>
#include <sys/sdt.h>
+#include <inet/nd.h>
#define IMPL_HASHSZ 67 /* prime */
@@ -1004,6 +1005,17 @@ mac_promisc_get(mac_handle_t mh, mac_promisc_type_t ptype)
}
void
+mac_sdu_get(mac_handle_t mh, uint_t *min_sdu, uint_t *max_sdu)
+{
+ mac_impl_t *mip = (mac_impl_t *)mh;
+
+ if (min_sdu != NULL)
+ *min_sdu = mip->mi_sdu_min;
+ if (max_sdu != NULL)
+ *max_sdu = mip->mi_sdu_max;
+}
+
+void
mac_resources(mac_handle_t mh)
{
mac_impl_t *mip = (mac_impl_t *)mh;
@@ -1020,7 +1032,20 @@ void
mac_ioctl(mac_handle_t mh, queue_t *wq, mblk_t *bp)
{
mac_impl_t *mip = (mac_impl_t *)mh;
+ int cmd;
+ if (mip->mi_callbacks->mc_callbacks & (MC_SETPROP|MC_GETPROP)) {
+ cmd = ((struct iocblk *)bp->b_rptr)->ioc_cmd;
+ if (cmd == ND_SET || cmd == ND_GET) {
+ /*
+ * ndd ioctls are Obsolete
+ */
+ cmn_err(CE_WARN,
+ "The ndd commands are obsolete and may be removed "
+ "in a future release of Solaris. "
+ "Use dladm(1M) to manage driver tunables\n");
+ }
+ }
/*
* Call the driver to handle the ioctl. The driver may not support
* any ioctls, in which case we reply with a NAK on its behalf.
@@ -1511,10 +1536,10 @@ mac_register(mac_register_t *mregp, mac_handle_t *mhp)
mip->mi_margin = mregp->m_margin;
mip->mi_info.mi_media = mtype->mt_type;
mip->mi_info.mi_nativemedia = mtype->mt_nativetype;
- mip->mi_info.mi_sdu_min = mregp->m_min_sdu;
if (mregp->m_max_sdu <= mregp->m_min_sdu)
goto fail;
- mip->mi_info.mi_sdu_max = mregp->m_max_sdu;
+ mip->mi_sdu_min = mregp->m_min_sdu;
+ mip->mi_sdu_max = mregp->m_max_sdu;
mip->mi_info.mi_addr_length = mip->mi_type->mt_addr_length;
/*
* If the media supports a broadcast address, cache a pointer to it
@@ -1667,6 +1692,9 @@ mac_register(mac_register_t *mregp, mac_handle_t *mhp)
goto fail;
}
+ DTRACE_PROBE2(mac__register, struct devnames *, dnp,
+ (mac_impl_t *), mip);
+
/*
* Mark the MAC to be ready for open.
*/
@@ -2817,3 +2845,43 @@ done:
mutex_exit(&i_mactype_lock);
return (err);
}
+
+int
+mac_set_prop(mac_handle_t mh, mac_prop_t *macprop, void *val, uint_t valsize)
+{
+ int err = ENOTSUP;
+ mac_impl_t *mip = (mac_impl_t *)mh;
+
+ if (mip->mi_callbacks->mc_callbacks & MC_SETPROP) {
+ err = mip->mi_callbacks->mc_setprop(mip->mi_driver,
+ macprop->mp_name, macprop->mp_id, valsize, val);
+ }
+ return (err);
+}
+
+int
+mac_get_prop(mac_handle_t mh, mac_prop_t *macprop, void *val, uint_t valsize)
+{
+ int err = ENOTSUP;
+ mac_impl_t *mip = (mac_impl_t *)mh;
+
+ if (mip->mi_callbacks->mc_callbacks & MC_GETPROP) {
+ err = mip->mi_callbacks->mc_getprop(mip->mi_driver,
+ macprop->mp_name, macprop->mp_id, valsize, val);
+ }
+ return (err);
+}
+
+int
+mac_maxsdu_update(mac_handle_t mh, uint_t sdu_max)
+{
+ mac_impl_t *mip = (mac_impl_t *)mh;
+
+ if (sdu_max <= mip->mi_sdu_min)
+ return (EINVAL);
+ mip->mi_sdu_max = sdu_max;
+
+ /* Send a MAC_NOTE_SDU_SIZE notification. */
+ i_mac_notify(mip, MAC_NOTE_SDU_SIZE);
+ return (0);
+}
diff --git a/usr/src/uts/common/io/nge/nge_kstats.c b/usr/src/uts/common/io/nge/nge_kstats.c
index 66350d6125..28069a836b 100644
--- a/usr/src/uts/common/io/nge/nge_kstats.c
+++ b/usr/src/uts/common/io/nge/nge_kstats.c
@@ -243,31 +243,6 @@ nge_setup_named_kstat(nge_t *ngep, int instance, char *name,
return (ksp);
}
-/*
- * Create kstats corresponding to NDD parameters
- */
-static kstat_t *
-nge_setup_params_kstat(nge_t *ngep, int instance, char *name,
- int (*update)(kstat_t *, int))
-{
- kstat_t *ksp;
- kstat_named_t *knp;
- int i;
-
- ksp = kstat_create(NGE_DRIVER_NAME, instance, name, "net",
- KSTAT_TYPE_NAMED, PARAM_COUNT, KSTAT_FLAG_PERSISTENT);
- if (ksp != NULL) {
- ksp->ks_private = ngep;
- ksp->ks_update = update;
- for (knp = ksp->ks_data, i = 0; i < PARAM_COUNT; ++knp, ++i)
- kstat_named_init(knp, ngep->nd_params[i].ndp_name+1,
- KSTAT_DATA_UINT64);
- kstat_install(ksp);
- }
-
- return (ksp);
-}
-
void
nge_init_kstats(nge_t *ngep, int instance)
{
diff --git a/usr/src/uts/common/io/strplumb.c b/usr/src/uts/common/io/strplumb.c
index 6f20d98a5a..4eaf8e20ac 100644
--- a/usr/src/uts/common/io/strplumb.c
+++ b/usr/src/uts/common/io/strplumb.c
@@ -71,6 +71,7 @@
#include <sys/ddi_implfuncs.h>
#include <sys/dld.h>
+#include <sys/mac.h>
/*
* Debug Macros
diff --git a/usr/src/uts/common/io/vnic/vnic_dev.c b/usr/src/uts/common/io/vnic/vnic_dev.c
index 676bcc1e6f..7d98003a17 100644
--- a/usr/src/uts/common/io/vnic/vnic_dev.c
+++ b/usr/src/uts/common/io/vnic/vnic_dev.c
@@ -729,7 +729,6 @@ vnic_dev_create(datalink_id_t vnic_id, datalink_id_t linkid, int mac_len,
mac_register_t *mac;
int err;
vnic_mac_t *vnic_mac;
- const mac_info_t *lower_mac_info;
mac_multi_addr_t maddr;
mac_txinfo_t tx_info;
@@ -796,9 +795,7 @@ vnic_dev_create(datalink_id_t vnic_id, datalink_id_t linkid, int mac_len,
mac->m_src_addr = vnic->vn_addr;
mac->m_callbacks = &vnic_m_callbacks;
- lower_mac_info = mac_info(vnic_mac->va_mh);
- mac->m_min_sdu = lower_mac_info->mi_sdu_min;
- mac->m_max_sdu = lower_mac_info->mi_sdu_max;
+ mac_sdu_get(vnic_mac->va_mh, &mac->m_min_sdu, &mac->m_max_sdu);
/*
* As the current margin size of the underlying mac is used to
diff --git a/usr/src/uts/common/sys/dld.h b/usr/src/uts/common/sys/dld.h
index 8cc70e52f9..ad3530c1a3 100644
--- a/usr/src/uts/common/sys/dld.h
+++ b/usr/src/uts/common/sys/dld.h
@@ -34,11 +34,11 @@
#include <sys/types.h>
#include <sys/stream.h>
-#include <sys/mac.h>
-#include <sys/dls.h>
#include <sys/conf.h>
#include <sys/sad.h>
#include <net/if.h>
+#include <sys/ddi.h>
+#include <sys/sunddi.h>
#ifdef __cplusplus
extern "C" {
@@ -94,6 +94,8 @@ extern "C" {
#define DLDIOC_ATTR (DLDIOC | 0x03)
+typedef uint32_t datalink_id_t;
+
typedef struct dld_ioc_attr {
datalink_id_t dia_linkid;
uint_t dia_max_sdu;
@@ -109,6 +111,8 @@ typedef struct dld_ioc_vlan_attr {
} dld_ioc_vlan_attr_t;
#define DLDIOC_PHYS_ATTR (DLDIOC | 0x05)
+#define DLPI_LINKNAME_MAX 32
+
typedef struct dld_ioc_phys_attr {
datalink_id_t dip_linkid;
/*
@@ -223,7 +227,63 @@ struct dlautopush {
char dap_aplist[MAXAPUSH][FMNAMESZ+1];
};
+/*
+ * Encodings for public properties.
+ * A most significant bit value of 1 indicates private property, intended
+ * to allow private property implementations to use internal encodings
+ * if desired.
+ *
+ * Note that there are 2 sets of parameters: the *_EN_*
+ * values are those that the Administrator configures for autonegotiation.
+ * The _ADV_* values are those that are currently exposed over the wire.
+ */
+typedef enum {
+ DLD_PROP_DUPLEX = 0x00000001,
+ DLD_PROP_SPEED,
+ DLD_PROP_STATUS,
+ DLD_PROP_AUTONEG,
+ DLD_PROP_EN_AUTONEG,
+ DLD_PROP_DEFMTU,
+ DLD_PROP_NDD_LEGACY,
+ DLD_PROP_FLOWCTRL,
+ DLD_PROP_ADV_1000FDX_CAP,
+ DLD_PROP_EN_1000FDX_CAP,
+ DLD_PROP_ADV_1000HDX_CAP,
+ DLD_PROP_EN_1000HDX_CAP,
+ DLD_PROP_ADV_100FDX_CAP,
+ DLD_PROP_EN_100FDX_CAP,
+ DLD_PROP_ADV_100HDX_CAP,
+ DLD_PROP_EN_100HDX_CAP,
+ DLD_PROP_ADV_10FDX_CAP,
+ DLD_PROP_EN_10FDX_CAP,
+ DLD_PROP_ADV_10HDX_CAP,
+ DLD_PROP_EN_10HDX_CAP,
+ DLD_PROP_PRIVATE = -1
+} dld_prop_id_t;
+
+/*
+ * to figure out r/w status of legacy ndd props.
+ */
+#define DLD_NDD_READ 0x01
+#define DLD_NDD_WRITE 0x10
+
+#define DLDIOCSETPROP (DLDIOC | 0x14)
+#define DLDIOCGETPROP (DLDIOC | 0x15)
+#define DLD_LINKPROP_NAME_MAX 256
+#define DLD_PROP_VERSION 1
+
+typedef struct dld_ioc_prop_s {
+ int pr_version;
+ uint_t pr_flags; /* private to libdladm */
+ char pr_linkname[DLPI_LINKNAME_MAX]; /* interface name */
+ dld_prop_id_t pr_num;
+ char pr_name[DLD_LINKPROP_NAME_MAX];
+ uint_t pr_valsize; /* sizeof pr_val */
+ char pr_val[1];
+} dld_ioc_prop_t;
+
#ifdef _KERNEL
+typedef dld_prop_id_t mac_prop_id_t;
int dld_getinfo(dev_info_t *, ddi_info_cmd_t, void *, void **);
int dld_open(queue_t *, dev_t *, int, int, cred_t *);
int dld_close(queue_t *);
diff --git a/usr/src/uts/common/sys/mac.h b/usr/src/uts/common/sys/mac.h
index 4fd83059c4..b83f5cb981 100644
--- a/usr/src/uts/common/sys/mac.h
+++ b/usr/src/uts/common/sys/mac.h
@@ -32,6 +32,7 @@
#include <sys/ddi.h>
#include <sys/sunddi.h>
#include <sys/stream.h>
+#include <sys/dld.h>
/*
* MAC Services Module
@@ -84,11 +85,17 @@ typedef enum {
LINK_DUPLEX_FULL
} link_duplex_t;
-typedef uint32_t datalink_id_t;
#define DATALINK_INVALID_LINKID 0
#define DATALINK_ALL_LINKID 0
#define DATALINK_MAX_LINKID 0xffffffff
+typedef enum {
+ LINK_FLOWCTRL_NONE = 0,
+ LINK_FLOWCTRL_RX,
+ LINK_FLOWCTRL_TX,
+ LINK_FLOWCTRL_BI
+} link_flowctrl_t;
+
/*
* Maximum MAC address length
*/
@@ -177,8 +184,6 @@ enum mac_driver_stat {
typedef struct mac_info_s {
uint_t mi_media;
uint_t mi_nativemedia;
- uint_t mi_sdu_min;
- uint_t mi_sdu_max;
uint_t mi_addr_length;
uint8_t *mi_unicst_addr;
uint8_t *mi_brdcst_addr;
@@ -292,6 +297,10 @@ typedef mblk_t *(*mac_tx_t)(void *, mblk_t *);
typedef boolean_t (*mac_getcapab_t)(void *, mac_capab_t, void *);
typedef int (*mac_open_t)(void *);
typedef void (*mac_close_t)(void *);
+typedef int (*mac_set_prop_t)(void *, const char *, mac_prop_id_t,
+ uint_t, const void *);
+typedef int (*mac_get_prop_t)(void *, const char *, mac_prop_id_t,
+ uint_t, void *);
/*
* Drivers must set all of these callbacks except for mc_resources,
@@ -315,6 +324,8 @@ typedef struct mac_callbacks_s {
mac_getcapab_t mc_getcapab; /* Get capability information */
mac_open_t mc_open; /* Open the device */
mac_close_t mc_close; /* Close the device */
+ mac_set_prop_t mc_setprop;
+ mac_get_prop_t mc_getprop;
} mac_callbacks_t;
/*
@@ -328,6 +339,8 @@ typedef struct mac_callbacks_s {
#define MC_GETCAPAB 0x004
#define MC_OPEN 0x008
#define MC_CLOSE 0x010
+#define MC_SETPROP 0x020
+#define MC_GETPROP 0x040
#define MAC_MAX_MINOR 1000
@@ -367,6 +380,7 @@ typedef enum {
MAC_NOTE_RESOURCE,
MAC_NOTE_DEVPROMISC,
MAC_NOTE_FASTPATH_FLUSH,
+ MAC_NOTE_SDU_SIZE,
MAC_NOTE_VNIC,
MAC_NOTE_MARGIN,
MAC_NNOTE /* must be the last entry */
@@ -534,6 +548,11 @@ typedef struct mactype_register_s {
size_t mtr_statcount;
} mactype_register_t;
+typedef struct mac_prop_s {
+ mac_prop_id_t mp_id;
+ char *mp_name;
+} mac_prop_t;
+
/*
* Client interface functions.
*/
@@ -560,6 +579,7 @@ extern boolean_t mac_unicst_verify(mac_handle_t,
extern int mac_unicst_set(mac_handle_t, const uint8_t *);
extern void mac_unicst_get(mac_handle_t, uint8_t *);
extern void mac_dest_get(mac_handle_t, uint8_t *);
+extern void mac_sdu_get(mac_handle_t, uint_t *, uint_t *);
extern void mac_resources(mac_handle_t);
extern void mac_ioctl(mac_handle_t, queue_t *, mblk_t *);
extern const mac_txinfo_t *mac_tx_get(mac_handle_t);
@@ -626,6 +646,7 @@ extern void mac_tx_update(mac_handle_t);
extern void mac_resource_update(mac_handle_t);
extern mac_resource_handle_t mac_resource_add(mac_handle_t,
mac_resource_t *);
+extern int mac_maxsdu_update(mac_handle_t, uint_t);
extern int mac_pdata_update(mac_handle_t, void *,
size_t);
extern void mac_multicst_refresh(mac_handle_t,
@@ -650,6 +671,10 @@ extern mactype_register_t *mactype_alloc(uint_t);
extern void mactype_free(mactype_register_t *);
extern int mactype_register(mactype_register_t *);
extern int mactype_unregister(const char *);
+extern int mac_set_prop(mac_handle_t, mac_prop_t *,
+ void *, uint_t);
+extern int mac_get_prop(mac_handle_t, mac_prop_t *,
+ void *, uint_t);
#endif /* _KERNEL */
diff --git a/usr/src/uts/common/sys/mac_impl.h b/usr/src/uts/common/sys/mac_impl.h
index c0acfc5c37..6e39232224 100644
--- a/usr/src/uts/common/sys/mac_impl.h
+++ b/usr/src/uts/common/sys/mac_impl.h
@@ -152,6 +152,8 @@ typedef struct mac_impl_s {
uint_t mi_devpromisc;
uint8_t mi_addr[MAXMACADDRLEN];
uint8_t mi_dstaddr[MAXMACADDRLEN];
+ uint_t mi_sdu_min;
+ uint_t mi_sdu_max;
mac_multicst_addr_t *mi_mmap;
krwlock_t mi_notify_lock;
diff --git a/usr/src/uts/common/xen/io/xnbo.c b/usr/src/uts/common/xen/io/xnbo.c
index 91714e9117..833cf96576 100644
--- a/usr/src/uts/common/xen/io/xnbo.c
+++ b/usr/src/uts/common/xen/io/xnbo.c
@@ -245,6 +245,7 @@ xnbo_open_mac(xnb_t *xnbp, char *mac)
const mac_info_t *mi;
char *xsname;
void (*rx_fn)(void *, mac_resource_handle_t, mblk_t *);
+ uint_t max_sdu;
xsname = xvdi_get_xsname(xnbp->xnb_devinfo);
@@ -271,9 +272,11 @@ xnbo_open_mac(xnb_t *xnbp, char *mac)
xnbo_close_mac(xnbop);
return (B_FALSE);
}
- if (mi->mi_sdu_max > XNBMAXPKT) {
- cmn_err(CE_WARN, "xnbo_open_mac: "
- "mac device SDU too big (%d)", mi->mi_sdu_max);
+
+ mac_sdu_get(xnbop->o_mh, NULL, &max_sdu);
+ if (max_sdu > XNBMAXPKT) {
+ cmn_err(CE_WARN, "xnbo_open_mac: mac device SDU too big (%d)",
+ max_sdu);
xnbo_close_mac(xnbop);
return (B_FALSE);
}
diff --git a/usr/src/uts/intel/mac/Makefile b/usr/src/uts/intel/mac/Makefile
index 8e34b910a9..12bd648ee0 100644
--- a/usr/src/uts/intel/mac/Makefile
+++ b/usr/src/uts/intel/mac/Makefile
@@ -2,9 +2,8 @@
# CDDL HEADER START
#
# The contents of this file are subject to the terms of the
-# Common Development and Distribution License, Version 1.0 only
-# (the "License"). You may not use this file except in compliance
-# with the License.
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
# or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
# CDDL HEADER END
#
#
-# Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
#ident "%Z%%M% %I% %E% SMI"
@@ -54,6 +53,7 @@ include $(UTSBASE)/intel/Makefile.intel
ALL_TARGET = $(BINARY)
LINT_TARGET = $(MODULE).lint
INSTALL_TARGET = $(BINARY) $(ROOTMODULE)
+LINTTAGS += -erroff=E_BAD_PTR_CAST_ALIGN
#
# Overrides.
diff --git a/usr/src/uts/sparc/mac/Makefile b/usr/src/uts/sparc/mac/Makefile
index ecf5b2cfa2..d343e0bc74 100644
--- a/usr/src/uts/sparc/mac/Makefile
+++ b/usr/src/uts/sparc/mac/Makefile
@@ -2,9 +2,8 @@
# CDDL HEADER START
#
# The contents of this file are subject to the terms of the
-# Common Development and Distribution License, Version 1.0 only
-# (the "License"). You may not use this file except in compliance
-# with the License.
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
# or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
# CDDL HEADER END
#
#
-# Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+# Copyright 2008 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
#ident "%Z%%M% %I% %E% SMI"
@@ -55,6 +54,7 @@ include $(UTSBASE)/sparc/Makefile.sparc
ALL_TARGET = $(BINARY)
LINT_TARGET = $(MODULE).lint
INSTALL_TARGET = $(BINARY) $(ROOTMODULE)
+LINTTAGS += -erroff=E_BAD_PTR_CAST_ALIGN
#
# Overrides.
diff --git a/usr/src/uts/sun/io/hme.c b/usr/src/uts/sun/io/hme.c
index f57bcd697b..b5d91a728a 100644
--- a/usr/src/uts/sun/io/hme.c
+++ b/usr/src/uts/sun/io/hme.c
@@ -2341,7 +2341,7 @@ _info(struct modinfo *modinfop)
* Allocate and zero-out "number" structures
* each of type "structure" in kernel memory.
*/
-#define GETSTRUCT(structure, number) \
+#define HME_GETSTRUCT(structure, number) \
((structure *)kmem_zalloc(\
(size_t)(sizeof (structure) * (number)), KM_SLEEP))
@@ -2763,7 +2763,7 @@ hmeattach(dev_info_t *dip, ddi_attach_cmd_t cmd)
/*
* Allocate soft device data structure
*/
- hmep = GETSTRUCT(struct hme, 1);
+ hmep = HME_GETSTRUCT(struct hme, 1);
/*
* Might as well set up elements of data structure