summaryrefslogtreecommitdiff
path: root/usr/src
diff options
context:
space:
mode:
authorericheng <none@none>2005-08-01 12:58:24 -0700
committerericheng <none@none>2005-08-01 12:58:24 -0700
commit210db2243d3b5ca39c96a4c34c6d9453ddfbeaa9 (patch)
treea9b505b9cd0c944c476713e42180c724a44833a6 /usr/src
parentd01412971af32f806ad2e91e40c00b485e893b2c (diff)
downloadillumos-gate-210db2243d3b5ca39c96a4c34c6d9453ddfbeaa9.tar.gz
PSARC 2005/365 Nemo drivers interface simplification
6246540 race condition between aggr driver detach and create-aggr 6253542 dld breaks autopush, PPPoE, ipfilter for bge and xge 6261226 Nemo should use modhash 6272908 in.rarpd no longer works for GLDv3 interfaces 6303082 ill_tx fastpath lacks flow control --HG-- rename : usr/src/cmd/dladm/datalink.conf => deleted_files/usr/src/cmd/dladm/datalink.conf rename : usr/src/cmd/rcm_daemon/common/mac_rcm.c => deleted_files/usr/src/cmd/rcm_daemon/common/mac_rcm.c rename : usr/src/cmd/svc/milestone/aggregation => deleted_files/usr/src/cmd/svc/milestone/aggregation rename : usr/src/cmd/svc/milestone/aggregation.xml => deleted_files/usr/src/cmd/svc/milestone/aggregation.xml rename : usr/src/cmd/svc/milestone/datalink => deleted_files/usr/src/cmd/svc/milestone/datalink rename : usr/src/cmd/svc/milestone/datalink-init => deleted_files/usr/src/cmd/svc/milestone/datalink-init rename : usr/src/cmd/svc/milestone/datalink-init.xml => deleted_files/usr/src/cmd/svc/milestone/datalink-init.xml rename : usr/src/cmd/svc/milestone/datalink.xml => deleted_files/usr/src/cmd/svc/milestone/datalink.xml rename : usr/src/pkgdefs/SUNWcnetr/postinstall => deleted_files/usr/src/pkgdefs/SUNWcnetr/postinstall rename : usr/src/pkgdefs/common_files/i.datalinkconf => deleted_files/usr/src/pkgdefs/common_files/i.datalinkconf rename : usr/src/uts/common/io/dld/dld_ioc.c => deleted_files/usr/src/uts/common/io/dld/dld_ioc.c rename : usr/src/uts/common/io/dld/dld_minor.c => deleted_files/usr/src/uts/common/io/dld/dld_minor.c rename : usr/src/uts/common/io/dld/dld_node.c => deleted_files/usr/src/uts/common/io/dld/dld_node.c rename : usr/src/uts/common/io/dld/dld_ppa.c => deleted_files/usr/src/uts/common/io/dld/dld_ppa.c rename : usr/src/uts/common/os/ght.c => deleted_files/usr/src/uts/common/os/ght.c rename : usr/src/uts/common/sys/ght.h => deleted_files/usr/src/uts/common/sys/ght.h rename : usr/src/uts/intel/ght/Makefile => deleted_files/usr/src/uts/intel/ght/Makefile rename : usr/src/uts/sparc/ght/Makefile => deleted_files/usr/src/uts/sparc/ght/Makefile
Diffstat (limited to 'usr/src')
-rw-r--r--usr/src/cmd/devfsadm/devfsadm.c110
-rw-r--r--usr/src/cmd/dladm/Makefile2
-rw-r--r--usr/src/cmd/dladm/datalink.conf31
-rw-r--r--usr/src/cmd/dladm/dladm.c541
-rw-r--r--usr/src/cmd/rcm_daemon/Makefile.com13
-rw-r--r--usr/src/cmd/rcm_daemon/common/ip_rcm.c47
-rw-r--r--usr/src/cmd/rcm_daemon/common/mac_rcm.c1446
-rw-r--r--usr/src/cmd/rcm_daemon/common/network_rcm.c105
-rw-r--r--usr/src/cmd/svc/milestone/Makefile6
-rw-r--r--usr/src/cmd/svc/milestone/aggregation40
-rw-r--r--usr/src/cmd/svc/milestone/aggregation.xml73
-rw-r--r--usr/src/cmd/svc/milestone/datalink37
-rw-r--r--usr/src/cmd/svc/milestone/datalink-init44
-rw-r--r--usr/src/cmd/svc/milestone/datalink-init.xml83
-rw-r--r--usr/src/cmd/svc/milestone/datalink.xml88
-rw-r--r--usr/src/cmd/svc/milestone/net-physical5
-rw-r--r--usr/src/cmd/svc/seed/Makefile5
-rw-r--r--usr/src/cmd/truss/codes.c8
-rw-r--r--usr/src/lib/Makefile2
-rw-r--r--usr/src/lib/libdladm/common/libdladm.c589
-rw-r--r--usr/src/lib/libdladm/common/libdladm.h34
-rw-r--r--usr/src/lib/libdladm/spec/dladm.spec48
-rw-r--r--usr/src/lib/libdlpi/common/libdlpi.c6
-rw-r--r--usr/src/lib/liblaadm/common/liblaadm.c89
-rw-r--r--usr/src/lib/libmacadm/Makefile.com2
-rw-r--r--usr/src/lib/libmacadm/common/libmacadm.c31
-rw-r--r--usr/src/lib/libmacadm/common/libmacadm.h2
-rw-r--r--usr/src/lib/libmacadm/spec/macadm.spec2
-rw-r--r--usr/src/pkgdefs/SUNWckr/prototype_i3862
-rw-r--r--usr/src/pkgdefs/SUNWckr/prototype_sparc1
-rw-r--r--usr/src/pkgdefs/SUNWcnetr/Makefile4
-rw-r--r--usr/src/pkgdefs/SUNWcnetr/pkginfo.tmpl2
-rw-r--r--usr/src/pkgdefs/SUNWcnetr/postinstall46
-rw-r--r--usr/src/pkgdefs/SUNWcnetr/prototype_com3
-rw-r--r--usr/src/pkgdefs/SUNWcsr/postinstall26
-rw-r--r--usr/src/pkgdefs/SUNWcsr/prototype_com6
-rw-r--r--usr/src/pkgdefs/SUNWcsu/prototype_com1
-rw-r--r--usr/src/pkgdefs/SUNWhea/prototype_com1
-rw-r--r--usr/src/pkgdefs/common_files/i.datalinkconf69
-rw-r--r--usr/src/tools/scripts/bfu.sh113
-rw-r--r--usr/src/uts/common/Makefile.files5
-rw-r--r--usr/src/uts/common/inet/ip.h2
-rw-r--r--usr/src/uts/common/inet/tcp/tcp.c10
-rw-r--r--usr/src/uts/common/io/aggr/aggr_ctl.c258
-rw-r--r--usr/src/uts/common/io/aggr/aggr_dev.c148
-rw-r--r--usr/src/uts/common/io/aggr/aggr_grp.c171
-rw-r--r--usr/src/uts/common/io/bge/bge_main.c43
-rw-r--r--usr/src/uts/common/io/dld/dld_drv.c384
-rw-r--r--usr/src/uts/common/io/dld/dld_ioc.c396
-rw-r--r--usr/src/uts/common/io/dld/dld_minor.c113
-rw-r--r--usr/src/uts/common/io/dld/dld_node.c544
-rw-r--r--usr/src/uts/common/io/dld/dld_ppa.c373
-rw-r--r--usr/src/uts/common/io/dld/dld_proto.c2016
-rw-r--r--usr/src/uts/common/io/dld/dld_str.c1211
-rw-r--r--usr/src/uts/common/io/dls/dls.c11
-rw-r--r--usr/src/uts/common/io/dls/dls_link.c463
-rw-r--r--usr/src/uts/common/io/dls/dls_mod.c1
-rw-r--r--usr/src/uts/common/io/dls/dls_stat.c1
-rw-r--r--usr/src/uts/common/io/dls/dls_vlan.c241
-rw-r--r--usr/src/uts/common/io/mac/mac.c274
-rw-r--r--usr/src/uts/common/io/strplumb.c70
-rw-r--r--usr/src/uts/common/os/ght.c527
-rw-r--r--usr/src/uts/common/sys/Makefile1
-rw-r--r--usr/src/uts/common/sys/aggr.h7
-rw-r--r--usr/src/uts/common/sys/aggr_impl.h10
-rw-r--r--usr/src/uts/common/sys/dld.h47
-rw-r--r--usr/src/uts/common/sys/dld_impl.h209
-rw-r--r--usr/src/uts/common/sys/dls.h9
-rw-r--r--usr/src/uts/common/sys/dls_impl.h20
-rw-r--r--usr/src/uts/common/sys/ght.h90
-rw-r--r--usr/src/uts/common/sys/mac.h4
-rw-r--r--usr/src/uts/common/sys/mac_impl.h2
-rw-r--r--usr/src/uts/intel/Makefile.intel1
-rw-r--r--usr/src/uts/intel/aggr/Makefile2
-rw-r--r--usr/src/uts/intel/bge/Makefile2
-rw-r--r--usr/src/uts/intel/dld/Makefile2
-rw-r--r--usr/src/uts/intel/dls/Makefile2
-rw-r--r--usr/src/uts/intel/ght/Makefile82
-rw-r--r--usr/src/uts/intel/ia32/ml/modstubs.s18
-rw-r--r--usr/src/uts/intel/mac/Makefile2
-rw-r--r--usr/src/uts/sparc/Makefile.sparc2
-rw-r--r--usr/src/uts/sparc/aggr/Makefile2
-rw-r--r--usr/src/uts/sparc/dld/Makefile2
-rw-r--r--usr/src/uts/sparc/dls/Makefile2
-rw-r--r--usr/src/uts/sparc/ght/Makefile84
-rw-r--r--usr/src/uts/sparc/mac/Makefile2
-rw-r--r--usr/src/uts/sparc/ml/modstubs.s18
87 files changed, 3373 insertions, 8274 deletions
diff --git a/usr/src/cmd/devfsadm/devfsadm.c b/usr/src/cmd/devfsadm/devfsadm.c
index 1017ed31df..152d3f6390 100644
--- a/usr/src/cmd/devfsadm/devfsadm.c
+++ b/usr/src/cmd/devfsadm/devfsadm.c
@@ -1936,7 +1936,7 @@ check_minor_type(di_node_t node, di_minor_t minor, void *arg)
if ((dcip->dci_flags & DCA_CHECK_TYPE) &&
(nt = di_minor_nodetype(minor)) &&
- (strcmp(nt, DDI_NT_NET) == 0 || strcmp(nt, DDI_NT_MAC) == 0)) {
+ (strcmp(nt, DDI_NT_NET) == 0)) {
dcip->dci_flags |= DCA_NOTIFY_RCM;
dcip->dci_flags &= ~DCA_CHECK_TYPE;
}
@@ -7589,83 +7589,15 @@ lookup_nvpair(nvlist_t *nvl, char *name, data_type_t type)
return (NULL);
}
-/*
- * Send the specified event to RCM if the given nvlist contains a minor
- * node of the specified type.
- */
-static void
-notify_event(nvlist_t *nvl, char *minor_node_type, char *event)
-{
- nvpair_t *nvp, *mnvp;
- char *path, *driver, *type;
- int instance;
- int err;
- boolean_t do_notify = B_FALSE;
- uint_t nminor;
- char *minor_byte_array;
- nvlist_t *mnvl;
-
- nvp = NULL;
- while (!do_notify && ((nvp = nvlist_next_nvpair(nvl, nvp)) != NULL)) {
- if (strcmp(nvpair_name(nvp), RCM_NV_MINOR_DATA) != 0)
- continue;
- if (nvpair_value_byte_array(nvp,
- (uchar_t **)&minor_byte_array, &nminor) != 0)
- goto error;
- if (nvlist_unpack(minor_byte_array,
- nminor, &mnvl, 0) != 0)
- goto error;
-
- mnvp = NULL;
- while (!do_notify &&
- ((mnvp = nvlist_next_nvpair(mnvl, mnvp)) != NULL)) {
- if (strcmp(nvpair_name(mnvp),
- RCM_NV_MINOR_NODE_TYPE) == 0) {
- if (nvpair_value_string(mnvp, &type) != 0) {
- nvlist_free(mnvl);
- goto error;
- }
- do_notify = (strcmp(type,
- minor_node_type) == 0);
- }
- }
-
- nvlist_free(mnvl);
- }
-
- if (!do_notify)
- return;
-
- if (librcm_notify_event(rcm_hdl, event, 0, nvl, NULL) == RCM_SUCCESS)
- return;
-
-error:
- err = errno;
-
- if (((nvp = lookup_nvpair(nvl,
- RCM_NV_DEVFS_PATH, DATA_TYPE_STRING)) == NULL) ||
- (nvpair_value_string(nvp, &path) != 0))
- path = "unknown";
-
- if (((nvp = lookup_nvpair(nvl,
- RCM_NV_DRIVER_NAME, DATA_TYPE_STRING)) == NULL) ||
- (nvpair_value_string(nvp, &driver) != 0))
- driver = "unknown";
-
- if (((nvp = lookup_nvpair(nvl,
- RCM_NV_INSTANCE, DATA_TYPE_INT32)) == NULL) ||
- (nvpair_value_int32(nvp, &instance) != 0))
- instance = -1;
-
- err_print(RCM_NOTIFY_FAILED, path, driver,
- instance, strerror(err));
-}
-
/*ARGSUSED*/
static void
process_rcm_events(void *arg)
{
struct rcm_eventq *ev, *ev_next;
+ nvpair_t *nvp;
+ char *path, *driver;
+ int instance;
+ int err;
int need_to_exit;
for (;;) {
@@ -7686,12 +7618,32 @@ process_rcm_events(void *arg)
* we do not know whether the failure occurred in
* librcm, rcm_daemon or rcm modules or scripts.
*/
-
- notify_event(ev->nvl, DDI_NT_NET,
- RCM_RESOURCE_NETWORK_NEW);
-
- notify_event(ev->nvl, DDI_NT_MAC,
- RCM_RESOURCE_MAC_NEW);
+ if (librcm_notify_event(rcm_hdl,
+ RCM_RESOURCE_NETWORK_NEW, 0, ev->nvl, NULL)
+ != RCM_SUCCESS) {
+
+ err = errno;
+
+ if (((nvp = lookup_nvpair(ev->nvl,
+ RCM_NV_DEVFS_PATH, DATA_TYPE_STRING))
+ == NULL) ||
+ (nvpair_value_string(nvp, &path) != 0))
+ path = "unknown";
+
+ if (((nvp = lookup_nvpair(ev->nvl,
+ RCM_NV_DRIVER_NAME, DATA_TYPE_STRING))
+ == NULL) ||
+ (nvpair_value_string(nvp, &driver) != 0))
+ driver = "unknown";
+ if (((nvp = lookup_nvpair(ev->nvl,
+ RCM_NV_INSTANCE, DATA_TYPE_INT32))
+ == NULL) ||
+ (nvpair_value_int32(nvp, &instance) != 0))
+ instance = -1;
+
+ err_print(RCM_NOTIFY_FAILED, path, driver,
+ instance, strerror(err));
+ }
ev_next = ev->next;
nvlist_free(ev->nvl);
diff --git a/usr/src/cmd/dladm/Makefile b/usr/src/cmd/dladm/Makefile
index ae3f9167e4..0923fece9c 100644
--- a/usr/src/cmd/dladm/Makefile
+++ b/usr/src/cmd/dladm/Makefile
@@ -29,7 +29,7 @@
PROG= dladm
ROOTFS_PROG= $(PROG)
-CONFIGFILES= datalink.conf aggregation.conf
+CONFIGFILES= aggregation.conf
POFILE= $(PROG).po
diff --git a/usr/src/cmd/dladm/datalink.conf b/usr/src/cmd/dladm/datalink.conf
deleted file mode 100644
index 5cb5189578..0000000000
--- a/usr/src/cmd/dladm/datalink.conf
+++ /dev/null
@@ -1,31 +0,0 @@
-#
-# 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.
-#
-# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
-# See the License for the specific language governing permissions
-# and limitations under the License.
-#
-# When distributing Covered Code, include this CDDL HEADER in each
-# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
-# If applicable, add the following below this CDDL HEADER, with the
-# fields enclosed by brackets "[]" replaced with your own identifying
-# information: Portions Copyright [yyyy] [name of copyright owner]
-#
-# CDDL HEADER END
-#
-#
-# Copyright 2005 Sun Microsystems, Inc. All rights reserved.
-# Use is subject to license terms.
-#
-# ident "%Z%%M% %I% %E% SMI"
-#
-# DO NOT EDIT OR PARSE THIS FILE!
-#
-# Use the dladm(1m) command to change the contents of this file.
-
diff --git a/usr/src/cmd/dladm/dladm.c b/usr/src/cmd/dladm/dladm.c
index 404a1c3e92..f74eab440c 100644
--- a/usr/src/cmd/dladm/dladm.c
+++ b/usr/src/cmd/dladm/dladm.c
@@ -96,11 +96,7 @@ static port_state_t port_states[] = {
#define NPORTSTATES (sizeof (port_states) / sizeof (port_state_t))
-static void do_create_vlan(int, char **);
-static void do_delete_vlan(int, char **);
static void do_show_link(int, char **);
-static void do_up_link(int, char **);
-static void do_init_link(int, char **);
static void do_create_aggr(int, char **);
static void do_delete_aggr(int, char **);
static void do_add_aggr(int, char **);
@@ -129,11 +125,8 @@ typedef struct cmd {
} cmd_t;
static cmd_t cmds[] = {
- { "create-vlan", do_create_vlan },
- { "delete-vlan", do_delete_vlan },
{ "show-link", do_show_link },
- { "up-link", do_up_link },
- { "init-link", do_init_link },
+ { "show-dev", do_show_dev },
{ "create-aggr", do_create_aggr },
{ "delete-aggr", do_delete_aggr },
@@ -142,9 +135,7 @@ static cmd_t cmds[] = {
{ "modify-aggr", do_modify_aggr },
{ "show-aggr", do_show_aggr },
{ "up-aggr", do_up_aggr },
- { "down-aggr", do_down_aggr },
-
- { "show-dev", do_show_dev }
+ { "down-aggr", do_down_aggr }
};
static const struct option longopts[] = {
@@ -176,9 +167,7 @@ static void
usage(void)
{
(void) fprintf(stderr, gettext(
- "usage: dladm create-vlan [-t] [-R <root-dir>] -v <vlan> -d <dev>\n"
- " delete-vlan [-t] [-R <root-dir>] -v <vlan> -d <dev>\n"
- " create-aggr [-t] [-R <root-dir>] [-P <policy>]\n"
+ "usage: dladm create-aggr [-t] [-R <root-dir>] [-P <policy>]\n"
" [-l <mode>] [-T <time>]\n"
" [-u <address>] -d <dev> ... <key>\n"
" delete-aggr [-t] [-R <root-dir>] <key>\n"
@@ -224,269 +213,6 @@ main(int argc, char *argv[])
return (0);
}
-static void
-do_create_vlan(int argc, char *argv[])
-{
- char name[MAXNAMELEN];
- char driver[MAXNAMELEN];
- int instance;
- dladm_attr_t dlattr;
- int value;
- char option;
- boolean_t v_arg = B_FALSE;
- boolean_t d_arg = B_FALSE;
- boolean_t t_arg = B_FALSE;
- char *altroot = NULL;
- char *endp = NULL;
- dladm_diag_t diag = 0;
-
- bzero(&dlattr, sizeof (dladm_attr_t));
-
- opterr = 0;
- while ((option = getopt_long(argc, argv, ":d:R:tv:", longopts,
- NULL)) != -1) {
- switch (option) {
- case 'v':
- if (v_arg) {
- (void) fprintf(stderr, gettext("%s: the option "
- "-v cannot be specified more than once\n"),
- progname);
- usage();
- }
-
- v_arg = B_TRUE;
-
- errno = 0;
- value = (int)strtol(optarg, &endp, 10);
- if (errno != 0 || value < 1 || value > 4094 ||
- *endp != '\0') {
- (void) fprintf(stderr,
- gettext("%s: illegal VLAN identifier"
- " '%d'\n"), progname, value);
- exit(1);
- }
-
- dlattr.da_vid = (uint16_t)value;
-
- break;
- case 'd':
- if (d_arg) {
- (void) fprintf(stderr, gettext(
- "%s: the option -d cannot be specified "
- "more than once\n"), progname);
- usage();
- }
-
- d_arg = B_TRUE;
-
- if (strlcpy(dlattr.da_dev, optarg, MAXNAMELEN) >=
- MAXNAMELEN) {
- (void) fprintf(stderr,
- gettext("%s: device name too long\n"),
- progname);
- exit(1);
- }
- break;
- case 't':
- t_arg = B_TRUE;
- break;
- case 'R':
- altroot = optarg;
- break;
- case ':':
- (void) fprintf(stderr,
- gettext("%s: option requires a value '-%c'\n"),
- progname, optopt);
- exit(1);
- break;
- case '?':
- default:
- (void) fprintf(stderr,
- gettext("%s: unrecognized option '-%c'\n"),
- progname, optopt);
- exit(1);
- break;
- }
- }
-
- if (optind != argc) {
- usage();
- }
-
- if (dlattr.da_dev[0] == '\0') {
- (void) fprintf(stderr,
- gettext("%s: no device specified\n"),
- progname);
- exit(1);
- }
-
- if (dlattr.da_vid == 0) {
- (void) fprintf(stderr,
- gettext("%s: no VLAN ID specified\n"),
- progname);
- exit(1);
- }
-
- if (dlpi_if_parse(dlattr.da_dev, driver, &instance) < 0 ||
- instance < 0) {
- (void) fprintf(stderr,
- gettext("%s: badly formatted device '%s'\n"),
- progname, dlattr.da_dev);
- exit(1);
- }
-
- (void) snprintf(name, MAXNAMELEN, "%s%d", driver,
- (dlattr.da_vid * 1000) + instance);
-
- /*
- * For aggregations, the da_dev is always AGGR_DEV, and the
- * aggregation key (the instance integer extracted above by
- * dlpi_if_parse) is da_port.
- */
- if (strcmp(driver, AGGR_DRIVER) == 0) {
- (void) strlcpy(dlattr.da_dev, AGGR_DEV, MAXNAMELEN);
- dlattr.da_port = instance;
- }
-
- if (dladm_link(name, &dlattr, (t_arg ? DLADM_LINK_TEMP : 0),
- altroot, &diag) < 0) {
- PRINT_ERR_DIAG("%s: link operation failed: %s", diag,
- dladm_diag);
- exit(1);
- }
-
- if (dladm_sync() < 0) {
- (void) fprintf(stderr,
- gettext("%s: sync operation failed"),
- progname);
- perror(" ");
- exit(1);
- }
-}
-
-static void
-do_delete_vlan(int argc, char *argv[])
-{
- char option;
- boolean_t t_arg = B_FALSE;
- boolean_t v_arg = B_FALSE;
- boolean_t d_arg = B_FALSE;
- char device[MAXNAMELEN];
- char name[MAXNAMELEN];
- char driver[MAXNAMELEN];
- int instance;
- int vid;
- char *altroot = NULL;
- char *endp = NULL;
- dladm_diag_t diag = 0;
-
- opterr = 0;
- while ((option = getopt_long(argc, argv, ":R:td:v:", longopts,
- NULL)) != -1) {
- switch (option) {
- case 'v':
- if (v_arg) {
- (void) fprintf(stderr, gettext("%s: the option "
- "-v cannot be specified more than once\n"),
- progname);
- usage();
- }
-
- v_arg = B_TRUE;
-
- errno = 0;
- vid = (int)strtol(optarg, &endp, 10);
- if (errno != 0 || vid < 1 || vid > 4094 ||
- *endp != '\0') {
- (void) fprintf(stderr,
- gettext("%s: illegal VLAN identifier"
- " '%d'\n"), progname, vid);
- exit(1);
- }
-
- break;
- case 'd':
- if (d_arg) {
- (void) fprintf(stderr, gettext(
- "%s: the option -d cannot be specified "
- "more than once\n"), progname);
- usage();
- }
-
- d_arg = B_TRUE;
-
- if (strlcpy(device, optarg, MAXNAMELEN) >=
- MAXNAMELEN) {
- (void) fprintf(stderr,
- gettext("%s: device name too long\n"),
- progname);
- exit(1);
- }
- break;
- case 't':
- t_arg = B_TRUE;
- break;
- case 'R':
- altroot = optarg;
- break;
- case ':':
- (void) fprintf(stderr,
- gettext("%s: option requires a value '-%c'\n"),
- progname, optopt);
- exit(1);
- break;
- case '?':
- default:
- (void) fprintf(stderr,
- gettext("%s: unrecognized option '-%c'\n"),
- progname, optopt);
- exit(1);
- break;
- }
- }
-
- if (optind != argc)
- usage();
-
- if (d_arg == B_FALSE) {
- (void) fprintf(stderr,
- gettext("%s: no device specified\n"),
- progname);
- exit(1);
- }
-
- if (v_arg == B_FALSE) {
- (void) fprintf(stderr,
- gettext("%s: no VLAN ID specified\n"),
- progname);
- exit(1);
- }
-
- if (dlpi_if_parse(device, driver, &instance) < 0 ||
- instance < 0) {
- (void) fprintf(stderr,
- gettext("%s: badly formatted device '%s'\n"),
- progname, device);
- exit(1);
- }
-
- (void) snprintf(name, MAXNAMELEN, "%s%d", driver,
- (vid * 1000) + instance);
-
- if (dladm_unlink(name, t_arg, altroot, &diag) < 0) {
- PRINT_ERR_DIAG("%s: unlink operation failed: %s", diag,
- dladm_diag);
- exit(1);
- }
-
- if (dladm_sync() < 0) {
- (void) fprintf(stderr,
- gettext("%s: sync operation failed"),
- progname);
- perror(" ");
- exit(1);
- }
-}
static void
do_create_aggr(int argc, char *argv[])
@@ -1009,35 +735,6 @@ do_modify_aggr(int argc, char *argv[])
}
static void
-do_up_link(int argc, char *argv[])
-{
- char *name = NULL;
- dladm_diag_t diag = 0;
-
- /* get link name (optional last argument) */
- if (argc == 2)
- name = argv[1];
- else if (argc > 2)
- usage();
-
- if (dladm_up(name, &diag) < 0) {
- if (name != NULL) {
- (void) fprintf(stderr,
- gettext("%s: could not bring up link '%s' : %s"),
- progname, name, strerror(errno));
- if (diag != 0)
- (void) fprintf(stderr, " (%s)",
- dladm_diag(diag));
- (void) fprintf(stderr, "\n");
- } else {
- PRINT_ERR_DIAG("%s: could not bring links up: %s",
- diag, dladm_diag);
- }
- exit(1);
- }
-}
-
-static void
do_up_aggr(int argc, char *argv[])
{
uint16_t key = 0;
@@ -1112,114 +809,118 @@ do_down_aggr(int argc, char *argv[])
}
}
+#define TYPE_WIDTH 10
+
static void
-create(void *arg, const char *dev, uint_t port)
+print_link_parseable(const char *name, dladm_attr_t *dap, boolean_t legacy)
{
- dladm_attr_t dlattr;
- dladm_diag_t diag;
- int flags;
-
- if (port != 0)
- return;
+ char type[TYPE_WIDTH];
- if (strlcpy(dlattr.da_dev, dev, MAXNAMELEN) >= MAXNAMELEN) {
- (void) fprintf(stderr,
- gettext("%s: device name too long\n"),
- progname);
- exit(1);
+ if (!legacy) {
+ if (dap->da_vid != 0) {
+ (void) snprintf(type, TYPE_WIDTH, "vlan %u",
+ dap->da_vid);
+ } else {
+ (void) snprintf(type, TYPE_WIDTH, "non-vlan");
+ }
+ if (strcmp(dap->da_dev, AGGR_DEV) == 0) {
+ (void) printf("%s type=%s mtu=%d key=%u\n",
+ name, type, dap->da_max_sdu, dap->da_port);
+ } else {
+ (void) printf("%s type=%s mtu=%d device=%s\n",
+ name, type, dap->da_max_sdu, dap->da_dev);
+ }
+ } else {
+ (void) printf("%s type=legacy mtu=%d device=%s\n",
+ name, dap->da_max_sdu, name);
}
-
- dlattr.da_port = 0;
- dlattr.da_vid = 0;
-
- flags = DLADM_LINK_FORCED;
- if (arg != NULL)
- flags |= DLADM_LINK_TEMP;
-
- (void) dladm_link(dlattr.da_dev, &dlattr, flags, NULL, &diag);
}
-/* ARGSUSED */
static void
-do_init_link(int argc, char *argv[])
+print_link(const char *name, dladm_attr_t *dap, boolean_t legacy)
{
- if (argc != 1 && strcmp(argv[1], "-t") != 0)
- usage();
+ char type[TYPE_WIDTH];
- (void) macadm_walk(create, (void *)(argc > 1), B_FALSE);
+ if (!legacy) {
+ if (dap->da_vid != 0) {
+ (void) snprintf(type, TYPE_WIDTH, gettext("vlan %u"),
+ dap->da_vid);
+ } else {
+ (void) snprintf(type, TYPE_WIDTH, gettext("non-vlan"));
+ }
+ if (strcmp(dap->da_dev, AGGR_DEV) == 0) {
+ (void) printf(gettext("%-9s\ttype: %s\tmtu: %d"
+ "\taggregation: key %u\n"), name, type,
+ dap->da_max_sdu, dap->da_port);
+ } else {
+ (void) printf(gettext("%-9s\ttype: %s\tmtu: "
+ "%d\tdevice: %s\n"), name, type, dap->da_max_sdu,
+ dap->da_dev);
+ }
+ } else {
+ (void) printf(gettext("%-9s\ttype: legacy\tmtu: "
+ "%d\tdevice: %s\n"), name, dap->da_max_sdu, name);
+ }
}
-#define TYPE_WIDTH 10
-#define MAC_WIDTH 23
-#define MTU_WIDTH 11
-#define STATE_WIDTH 15
+static int
+get_if_info(const char *name, dladm_attr_t *dlattrp, boolean_t *legacy)
+{
+ int err;
+
+ if ((err = dladm_info(name, dlattrp)) == 0) {
+ *legacy = B_FALSE;
+ } else if (err < 0 && errno == ENODEV) {
+ int fd;
+ dlpi_if_attr_t dia;
+ dl_info_ack_t dlia;
+
+ /*
+ * A return value of ENODEV means that the specified
+ * device is not gldv3.
+ */
+ if ((fd = dlpi_if_open(name, &dia, B_FALSE)) != -1 &&
+ dlpi_info(fd, -1, &dlia, NULL, NULL, NULL, NULL,
+ NULL, NULL) != -1) {
+ (void) dlpi_close(fd);
+
+ *legacy = B_TRUE;
+ bzero(dlattrp, sizeof (*dlattrp));
+ dlattrp->da_max_sdu = (uint_t)dlia.dl_max_sdu;
+ } else {
+ errno = ENOENT;
+ return (-1);
+ }
+ } else {
+ /*
+ * If the return value is not ENODEV, this means that
+ * user is either passing in a bogus interface name
+ * or a vlan interface name that doesn't exist yet.
+ */
+ errno = ENOENT;
+ return (-1);
+ }
+ return (0);
+}
/* ARGSUSED */
static void
show_link(void *arg, const char *name)
{
dladm_attr_t dlattr;
- char type[TYPE_WIDTH];
- int fd;
- dlpi_if_attr_t dia;
- dl_info_ack_t dlia;
- t_uscalar_t dl_max_sdu;
+ boolean_t legacy = B_TRUE;
show_link_state_t *state = (show_link_state_t *)arg;
- if ((fd = dlpi_if_open(name, &dia, B_FALSE)) != -1 &&
- dlpi_info(fd, -1, &dlia, NULL, NULL, NULL, NULL,
- NULL, NULL) != -1) {
- (void) dlpi_close(fd);
- dl_max_sdu = dlia.dl_max_sdu;
- } else {
- (void) fprintf(stderr,
- gettext("%s: invalid device '%s'\n"),
+ if (get_if_info(name, &dlattr, &legacy) < 0) {
+ (void) fprintf(stderr, gettext("%s: invalid device '%s'\n"),
progname, name);
exit(1);
}
- if (dladm_info(name, &dlattr) < 0) {
- if (!state->ls_parseable) {
- (void) printf(gettext("%-9s\ttype: legacy"
- "\tmtu: %d\tdevice: %s\n"),
- name, (int)dl_max_sdu, name);
- } else {
- (void) printf("%s type=legacy mtu=%d device=%s\n",
- name, (int)dl_max_sdu, name);
- }
+ if (state->ls_parseable) {
+ print_link_parseable(name, &dlattr, legacy);
} else {
- if (dlattr.da_vid != 0) {
- (void) snprintf(type, TYPE_WIDTH,
- state->ls_parseable ? "vlan %u" :
- gettext("vlan %u"), dlattr.da_vid);
- } else {
- (void) snprintf(type, TYPE_WIDTH,
- state->ls_parseable ? "non-vlan" :
- gettext("non-vlan"));
- }
-
- if (strcmp(dlattr.da_dev, AGGR_DEV) == 0) {
- if (!state->ls_parseable) {
- (void) printf(gettext("%-9s\ttype: %s"
- "\tmtu: %d\taggregation: key %u\n"),
- name, type, (int)dl_max_sdu,
- dlattr.da_port);
- } else {
- (void) printf("%s type=%s mtu=%d key=%u\n",
- name, type, (int)dl_max_sdu,
- dlattr.da_port);
- }
- } else {
- if (!state->ls_parseable) {
- (void) printf(gettext("%-9s\ttype: %s"
- "\tmtu: %d\tdevice: %s\n"),
- name, type, (int)dl_max_sdu,
- dlattr.da_dev);
- } else {
- (void) printf("%s type=%s mtu=%d device=%s\n",
- name, type, (int)dl_max_sdu, dlattr.da_dev);
- }
- }
+ print_link(name, &dlattr, legacy);
}
}
@@ -1502,36 +1203,34 @@ kstat_value(kstat_t *ksp, const char *name, uint8_t type, void *buf)
}
static void
-show_dev(void *arg, const char *dev, uint_t port)
+show_dev(void *arg, const char *dev)
{
- show_mac_state_t *state = (show_mac_state_t *)arg;
+ show_mac_state_t *state = (show_mac_state_t *)arg;
/* aggregations are already managed by a set of subcommands */
if (strcmp(dev, AGGR_DEV) == 0)
return;
(void) printf("%s", dev);
- if (port != 0)
- (void) printf("/%d", port);
if (!state->ms_parseable) {
(void) printf(gettext("\t\tlink: %s"),
- mac_link_state(dev, port));
+ mac_link_state(dev, 0));
(void) printf(gettext("\tspeed: %-5u Mbps"),
- (unsigned int)(mac_ifspeed(dev, port) / 1000000ull));
+ (unsigned int)(mac_ifspeed(dev, 0) / 1000000ull));
(void) printf(gettext("\tduplex: %s\n"),
- mac_link_duplex(dev, port));
+ mac_link_duplex(dev, 0));
} else {
- (void) printf(" link=%s", mac_link_state(dev, port));
+ (void) printf(" link=%s", mac_link_state(dev, 0));
(void) printf(" speed=%u",
- (unsigned int)(mac_ifspeed(dev, port) / 1000000ull));
- (void) printf(" duplex=%s\n", mac_link_duplex(dev, port));
+ (unsigned int)(mac_ifspeed(dev, 0) / 1000000ull));
+ (void) printf(" duplex=%s\n", mac_link_duplex(dev, 0));
}
}
/*ARGSUSED*/
static void
-show_dev_stats(void *arg, const char *dev, uint_t port)
+show_dev_stats(void *arg, const char *dev)
{
show_mac_state_t *state = (show_mac_state_t *)arg;
pktsum_t stats, diff_stats;
@@ -1548,12 +1247,10 @@ show_dev_stats(void *arg, const char *dev, uint_t port)
bzero(&state->ms_prevstats, sizeof (state->ms_prevstats));
}
- get_mac_stats(dev, port, &stats);
+ get_mac_stats(dev, 0, &stats);
stats_diff(&diff_stats, &stats, &state->ms_prevstats);
(void) printf("%s", dev);
- if (port != 0)
- (void) printf("/%d", port);
(void) printf("\t\t%-10llu", diff_stats.ipackets);
(void) printf("%-12llu", diff_stats.rbytes);
(void) printf("%-8u", diff_stats.ierrors);
@@ -1648,10 +1345,11 @@ do_show_link(int argc, char *argv[])
return;
}
- if (name == NULL)
+ if (name == NULL) {
(void) dladm_walk(show_link, &state);
- else
+ } else {
show_link(&state, name);
+ }
}
static void
@@ -1886,29 +1584,22 @@ do_show_dev(int argc, char *argv[])
if (dev == NULL)
(void) macadm_walk(show_dev, &state, B_TRUE);
else
- show_dev(&state, dev, 0);
+ show_dev(&state, dev);
}
/* ARGSUSED */
static void
link_stats(const char *link, uint32_t interval)
{
- show_link_state_t state;
+ dladm_attr_t dlattr;
+ boolean_t legacy;
+ show_link_state_t state;
- if (link != NULL) {
- dlpi_if_attr_t dia;
- int fd;
-
- if ((fd = dlpi_if_open(link, &dia, B_FALSE)) != -1) {
- (void) dlpi_close(fd);
- } else {
- (void) fprintf(stderr,
- gettext("%s: invalid device '%s'\n"),
- progname, link);
- exit(1);
- }
+ if (link != NULL && get_if_info(link, &dlattr, &legacy) < 0) {
+ (void) fprintf(stderr, gettext("%s: invalid device '%s'\n"),
+ progname, link);
+ exit(1);
}
-
bzero(&state, sizeof (state));
/*
@@ -1932,7 +1623,6 @@ link_stats(const char *link, uint32_t interval)
(void) sleep(interval);
}
-
}
/* ARGSUSED */
@@ -1988,11 +1678,10 @@ dev_stats(const char *dev, uint32_t interval)
(void) printf("opackets obytes oerrors\n");
state.ms_donefirst = B_FALSE;
- if (dev == NULL) {
+ if (dev == NULL)
(void) macadm_walk(show_dev_stats, &state, B_TRUE);
- } else {
- show_dev_stats(&state, dev, 0);
- }
+ else
+ show_dev_stats(&state, dev);
if (interval == 0)
break;
diff --git a/usr/src/cmd/rcm_daemon/Makefile.com b/usr/src/cmd/rcm_daemon/Makefile.com
index 8dd9114270..532f96f1b2 100644
--- a/usr/src/cmd/rcm_daemon/Makefile.com
+++ b/usr/src/cmd/rcm_daemon/Makefile.com
@@ -57,8 +57,7 @@ COMMON_MOD_SRC = \
$(COMMON)/pool_rcm.c \
$(COMMON)/mpxio_rcm.c \
$(COMMON)/ip_anon_rcm.c \
- $(COMMON)/svm_rcm.c \
- $(COMMON)/mac_rcm.c
+ $(COMMON)/svm_rcm.c
sparc_MOD_SRC = $(COMMON)/ttymux_rcm.c
@@ -72,8 +71,7 @@ COMMON_MOD_OBJ = \
pool_rcm.o \
mpxio_rcm.o \
ip_anon_rcm.o \
- svm_rcm.o \
- mac_rcm.o
+ svm_rcm.o
sparc_MOD_OBJ = ttymux_rcm.o
@@ -89,8 +87,7 @@ COMMON_RCM_MODS = \
SUNW_pool_rcm.so \
SUNW_mpxio_rcm.so \
SUNW_ip_anon_rcm.so \
- SUNW_svm_rcm.so \
- SUNW_mac_rcm.so
+ SUNW_svm_rcm.so
sparc_RCM_MODS = SUNW_ttymux_rcm.so
@@ -111,9 +108,7 @@ LINTFLAGS += -u -erroff=E_FUNC_ARG_UNUSED
LDLIBS_MODULES =
SUNW_pool_rcm.so := LDLIBS_MODULES += -L$(ROOT)/usr/lib -lpool
SUNW_svm_rcm.so := LDLIBS_MODULES += -L$(ROOT)/usr/lib -lmeta
-SUNW_mac_rcm.so := LDLIBS_MODULES += -L$(ROOT)/lib -ldladm -llaadm
-SUNW_ip_rcm.so := LDLIBS_MODULES += -L$(ROOT)/lib -ldladm -ldlpi
-SUNW_network_rcm.so := LDLIBS_MODULES += -L$(ROOT)/lib -ldlpi
+SUNW_network_rcm.so := LDLIBS_MODULES += -L$(ROOT)/lib -llaadm
LDLIBS += -lgen -lelf -lcmd -lrcm -lnvpair -ldevinfo -lnsl -lsocket -lrt
diff --git a/usr/src/cmd/rcm_daemon/common/ip_rcm.c b/usr/src/cmd/rcm_daemon/common/ip_rcm.c
index acc3e49c77..95ed823a74 100644
--- a/usr/src/cmd/rcm_daemon/common/ip_rcm.c
+++ b/usr/src/cmd/rcm_daemon/common/ip_rcm.c
@@ -54,8 +54,6 @@
#include <libdevinfo.h>
#include <sys/systeminfo.h>
#include <netdb.h>
-#include <libdladm.h>
-#include <libdlpi.h>
#include <ipmp_mpathd.h>
#include "rcm_module.h"
@@ -87,8 +85,6 @@
#define RCM_STR_SUNW_IP "SUNW_ip/" /* IP address export prefix */
#define RCM_SIZE_SUNW_IP 9 /* strlen("SUNW_ip/") + 1 */
-#define MAXINTSTR 11 /* max integer string len */
-
/* ifconfig(1M) */
#define USR_SBIN_IFCONFIG "/usr/sbin/ifconfig" /* ifconfig command */
#define CFGFILE_FMT_IPV4 "/etc/hostname." /* IPV4 config file */
@@ -2034,18 +2030,6 @@ ip_ipmp_undo_offline(ip_cache_t *node)
}
/*
- * is_virtual() - Determine whether the specified device is a virtual
- * device managed by dld.
- */
-static boolean_t
-is_virtual(char *ifname)
-{
- dladm_attr_t attr;
-
- return (dladm_info(ifname, &attr) == 0);
-}
-
-/*
* getdlpi_style() - Determine the DLPI provider style of the interface
*/
static int
@@ -2084,7 +2068,7 @@ get_ppa(char *rsrc)
if (m == 1) {
return (-1);
}
- return (is_virtual(rsrc) ? p : VLAN_GET_PPA(p)); /* VLAN support */
+ return (VLAN_GET_PPA(p)); /* VLAN support */
}
/*
@@ -3014,8 +2998,6 @@ process_minor(char *devfs_path, char *name, int instance,
struct ni_list **pp;
char *cname;
size_t cnamelen;
- char dev_name[MAXPATHLEN];
- boolean_t virtual = B_FALSE;
rcm_log_message(RCM_TRACE1, "IP: process_minor\n");
@@ -3028,31 +3010,8 @@ process_minor(char *devfs_path, char *name, int instance,
rcm_log_message(RCM_TRACE1, "IP: Examining %s (%s)\n",
devfs_path, mdata->minor_name);
- /*
- * Virtual DDI_NT_NET nodes created by dld are exposed by devfs
- * for non-VLAN as well as VLANs. Determine if we're dealing
- * with a virtual device.
- */
- if (strncmp("/pseudo", devfs_path, strlen("/pseudo")) == 0) {
- rcm_log_message(RCM_TRACE1, "IP: pseudo node %s (%s)\n",
- devfs_path, mdata->minor_name);
- if (strcmp(name, "dld") == 0) {
- if (dlpi_if_parse(mdata->minor_name, dev_name,
- &instance) < 0 || instance < 0) {
- /* dld always also creates a style-2 */
- rcm_log_message(RCM_DEBUG, "IP: ignoring "
- "\"%s\" (style 1)\n", devfs_path);
- return;
- }
- name = dev_name;
- virtual = B_TRUE;
- rcm_log_message(RCM_TRACE1, "IP: virtual datalink "
- "%s%d\n", name, instance);
- }
- }
-
/* Sanity check, instances > 999 are illegal */
- if (!virtual && instance > 999) {
+ if (instance > 999) {
errno = EINVAL;
rcm_log_message(RCM_ERROR, _("IP: invalid instance %d(%s)\n"),
instance, strerror(errno));
@@ -3077,7 +3036,7 @@ process_minor(char *devfs_path, char *name, int instance,
}
(void) memcpy(nip->type, name, cnamelen);
- cnamelen += MAXINTSTR;
+ cnamelen += 3;
if ((cname = (char *)malloc(cnamelen)) == NULL) {
free(nip->type);
free(nip);
diff --git a/usr/src/cmd/rcm_daemon/common/mac_rcm.c b/usr/src/cmd/rcm_daemon/common/mac_rcm.c
deleted file mode 100644
index bfb90c1019..0000000000
--- a/usr/src/cmd/rcm_daemon/common/mac_rcm.c
+++ /dev/null
@@ -1,1446 +0,0 @@
-/*
- * 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.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-/*
- * This RCM module adds support to the RCM framework for datalinks
- * managed by dladm(1M).
- */
-#include <alloca.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <assert.h>
-#include <string.h>
-#include <synch.h>
-#include <libintl.h>
-#include <errno.h>
-#include <libdevinfo.h>
-#include <sys/types.h>
-#include <libdladm.h>
-#include <liblaadm.h>
-#include <net/if.h>
-#include "rcm_module.h"
-
-#define _KERNEL
-#include <sys/sysmacros.h>
-#undef _KERNEL
-
-#define CACHE_STALE 1 /* flags */
-#define CACHE_NEW 2 /* flags */
-
-typedef enum mac_op {
- MAC_OP_SUSPEND = 0,
- MAC_OP_OFFLINE = 1,
- MAC_OP_ONLINE = 2,
- MAC_OP_REMOVE = 3,
- MAC_OP_RESUME = 4
-} mac_op_t;
-
-char *mac_op_str[] = {
- "SUSPEND",
- "OFFLINE",
- "ONLINE",
- "REMOVE",
- "RESUME"
-};
-
-/* devfsadm post-attach nvpair values */
-#define PROP_NV_DDI_MAC "ddi_mac"
-
-typedef struct mac_cache {
- char *resource;
- char *driver;
- int instance;
- int flags;
- struct mac_cache *next;
- struct mac_cache *prev;
-} mac_cache_t;
-
-static mac_cache_t cache_head;
-static mac_cache_t cache_tail;
-static mutex_t cache_lock;
-static int events_registered = 0;
-
-struct devfs_minor_data {
- int32_t minor_type;
- char *minor_name;
- char *minor_node_type;
-};
-
-/* module interface routines */
-static int mac_register(rcm_handle_t *);
-static int mac_unregister(rcm_handle_t *);
-static int mac_getinfo(rcm_handle_t *, char *, id_t, uint_t, char **,
- char **, nvlist_t *, rcm_info_t **);
-static int mac_suspend(rcm_handle_t *, char *, id_t, timespec_t *,
- uint_t, char **, rcm_info_t **);
-static int mac_resume(rcm_handle_t *, char *, id_t, uint_t, char **,
- rcm_info_t **);
-static int mac_offline(rcm_handle_t *, char *, id_t, uint_t, char **,
- rcm_info_t **);
-static int mac_online(rcm_handle_t *, char *, id_t, uint_t, char **,
- rcm_info_t **);
-static int mac_remove(rcm_handle_t *, char *, id_t, uint_t, char **,
- rcm_info_t **);
-static int mac_notify_event(rcm_handle_t *, char *, id_t, uint_t,
- char **, nvlist_t *, rcm_info_t **);
-
-/* module private routines */
-static void free_cache(void);
-static void update_cache(rcm_handle_t *hd);
-static int devfs_entry(di_node_t node, di_minor_t minor, void *arg);
-static void cache_remove(mac_cache_t *node);
-static mac_cache_t *cache_lookup(const char *resource);
-static void free_node(mac_cache_t *);
-static void cache_insert(mac_cache_t *);
-static int process_nvlist(nvlist_t *);
-
-/*
- * Module-Private data
- */
-static struct rcm_mod_ops mac_ops = {
- RCM_MOD_OPS_VERSION,
- mac_register,
- mac_unregister,
- mac_getinfo,
- mac_suspend,
- mac_resume,
- mac_offline,
- mac_online,
- mac_remove,
- NULL, /* request_capacity_change */
- NULL, /* notify_capacity_change */
- mac_notify_event
-};
-
-/*
- * Module Interface Routines
- */
-
-/*
- * rcm_mod_init()
- *
- * Update registrations, and return the ops structure.
- */
-struct rcm_mod_ops *
-rcm_mod_init()
-{
- cache_head.next = &cache_tail;
- cache_head.prev = NULL;
- cache_tail.prev = &cache_head;
- cache_tail.next = NULL;
- (void) mutex_init(&cache_lock, NULL, NULL);
-
- /* Return the ops vectors */
- return (&mac_ops);
-}
-
-/*
- * rcm_mod_info()
- *
- * Return a string describing this module.
- */
-const char *
-rcm_mod_info()
-{
- return ("Network namespace module %I%");
-}
-
-/*
- * rcm_mod_fini()
- *
- * Destroy the cache.
- */
-int
-rcm_mod_fini()
-{
- free_cache();
- (void) mutex_destroy(&cache_lock);
- return (RCM_SUCCESS);
-}
-
-/*
- * mac_register()
- *
- * Make sure the cache is properly sync'ed, and its registrations
- * are in order.
- *
- * Locking: the cache is locked by update_cache, and is held
- * throughout update_cache's execution because it reads and
- * possibly modifies cache links continuously.
- */
-static int
-mac_register(rcm_handle_t *hd)
-{
- if (!events_registered) {
- if (rcm_register_event(hd, RCM_RESOURCE_MAC_NEW, 0, NULL) !=
- RCM_SUCCESS) {
- rcm_log_message(RCM_ERROR,
- gettext("MAC: failed to register for events %s\n"),
- RCM_RESOURCE_MAC_NEW);
- return (RCM_FAILURE);
- } else {
- rcm_log_message(RCM_TRACE1, "MAC: registered "
- " for events %s\n", RCM_RESOURCE_MAC_NEW);
- events_registered++;
- }
- }
- update_cache(hd);
- return (RCM_SUCCESS);
-}
-
-/*
- * mac_unregister()
- *
- * Manually walk through the cache, unregistering all the networks.
- *
- * Locking: the cache is locked throughout the execution of this routine
- * because it reads and modifies cache links continuously.
- */
-static int
-mac_unregister(rcm_handle_t *hd)
-{
- mac_cache_t *probe;
-
- /* Walk the cache, unregistering everything */
- (void) mutex_lock(&cache_lock);
- probe = cache_head.next;
- while (probe != &cache_tail) {
- (void) rcm_unregister_interest(hd, probe->resource, 0);
- cache_remove(probe);
- free_node(probe);
- probe = cache_head.next;
- }
- (void) mutex_unlock(&cache_lock);
- if (events_registered) {
- (void) rcm_unregister_event(hd, RCM_RESOURCE_MAC_NEW, 0);
- events_registered--;
- }
- return (RCM_SUCCESS);
-}
-
-typedef struct mac_dl_walker_state {
- char *ws_dev_name;
- uint_t ws_n_datalinks;
- char **ws_datalink;
- char **ws_paths;
-} mac_dl_walker_state_t;
-
-/*
- * Adds a datalink of the specified name to the list hanging off
- * the specified state. Invoked by mac_dl_walker_db() and mac_dl_walker().
- */
-static void
-mac_add_datalink(mac_dl_walker_state_t *state, const char *name)
-{
- char dl_path[MAXPATHLEN];
-
- (void) snprintf(dl_path, sizeof (dl_path), "/devices/pseudo/dld@0:%s",
- name);
- rcm_log_message(RCM_DEBUG, "MAC: found datalink \"%s\"\n", dl_path);
-
- state->ws_n_datalinks++;
-
- state->ws_datalink = realloc(state->ws_datalink,
- (state->ws_n_datalinks + 1) * sizeof (char *));
- if (state->ws_datalink == NULL)
- return;
- state->ws_datalink[state->ws_n_datalinks-1] = strdup(name);
- state->ws_datalink[state->ws_n_datalinks] = NULL;
-
- state->ws_paths = realloc(state->ws_paths,
- (state->ws_n_datalinks + 1) * sizeof (char *));
- if (state->ws_paths == NULL)
- return;
- state->ws_paths[state->ws_n_datalinks-1] = strdup(dl_path);
- state->ws_paths[state->ws_n_datalinks] = NULL;
-}
-
-/*
- * Invoked for each DDI_NT_NET node found by the dladm library.
- */
-static
-void
-mac_dl_walker(void *arg, const char *name)
-{
- dladm_attr_t dl_attr;
- mac_dl_walker_state_t *state = (mac_dl_walker_state_t *)arg;
-
- rcm_log_message(RCM_DEBUG, "MAC: walker: DDI_NT_NET \"%s\"\n", name);
-
- if ((state->ws_datalink == NULL) || (state->ws_paths == NULL))
- return;
-
- if (dladm_info(name, &dl_attr) < 0) {
- rcm_log_message(RCM_DEBUG, "MAC: dladm_info failed "
- "(legacy)\n");
- return;
- }
-
- /*
- * We have a virtual data link that is defined on top
- * of a MAC port. Ignore it unless the MAC port was
- * registered by the device being acted upon.
- */
- rcm_log_message(RCM_DEBUG, "MAC: rsrc \"%s\" matches link \"%s\"?\n",
- state->ws_dev_name, dl_attr.da_dev);
- if (strcmp(state->ws_dev_name, dl_attr.da_dev) != 0) {
- rcm_log_message(RCM_DEBUG, "MAC: no match\n");
- return;
- }
-
- mac_add_datalink(state, name);
-}
-
-/*
- * Allocate and return a list of strings containing the virtual
- * data links that are currently configured on top of a device.
- */
-static int
-mac_list_datalinks(char *dev_name, char ***paths, char ***names)
-{
- mac_dl_walker_state_t dl_state;
-
- /*
- * Use the instance and driver from the cache node to find
- * matching mac ports.
- */
- dl_state.ws_dev_name = dev_name;
- dl_state.ws_n_datalinks = 0;
-
- dl_state.ws_datalink = calloc(1, sizeof (char *));
- dl_state.ws_paths = calloc(1, sizeof (char *));
- if ((dl_state.ws_datalink == NULL) || (dl_state.ws_paths == NULL)) {
- rcm_log_message(RCM_ERROR, gettext("MAC: malloc failure"));
- goto bail;
- }
-
- (void) dladm_walk(mac_dl_walker, &dl_state);
-
- if ((dl_state.ws_datalink == NULL) || (dl_state.ws_paths == NULL)) {
- rcm_log_message(RCM_ERROR, gettext("MAC: malloc failure"));
- goto bail;
- }
-
- if (paths != NULL)
- *paths = dl_state.ws_paths;
- if (names != NULL)
- *names = dl_state.ws_datalink;
-
- return (dl_state.ws_n_datalinks);
-
-bail:
- free(dl_state.ws_datalink);
- free(dl_state.ws_paths);
- return (-1);
-}
-
-/*
- * Invoked for each virtual datalink defined in database.
- */
-static void
-mac_dl_walker_db(void *arg, const char *name, dladm_attr_t *dl_attr)
-{
- mac_dl_walker_state_t *state = arg;
-
- rcm_log_message(RCM_DEBUG, "MAC: DB walker: \"%s\"\n", name);
-
- if ((state->ws_datalink == NULL) || (state->ws_paths == NULL))
- return;
-
- /*
- * We have a virtual data link that is defined on top
- * of a MAC port. Ignore it unless the MAC port was
- * registered by the device being acted upon.
- */
- rcm_log_message(RCM_DEBUG, "MAC: DB rsrc \"%s\" matches link "
- "\"%s\"?\n", state->ws_dev_name, dl_attr->da_dev);
- if (strcmp(state->ws_dev_name, dl_attr->da_dev) != 0) {
- rcm_log_message(RCM_DEBUG, "MAC: no match\n");
- return;
- }
-
- mac_add_datalink(state, name);
-}
-
-/*
- * Allocate and return a list of strings containing the virtual
- * data links that are configured on top of a device.
- */
-static int
-mac_list_datalinks_db(char *dev_name, char ***paths, char ***names)
-{
- mac_dl_walker_state_t dl_state;
-
- /*
- * Use the instance and driver from the cache node to find
- * matching mac ports.
- */
- dl_state.ws_dev_name = dev_name;
- dl_state.ws_n_datalinks = 0;
-
- dl_state.ws_datalink = calloc(1, sizeof (char *));
- dl_state.ws_paths = calloc(1, sizeof (char *));
- if ((dl_state.ws_datalink == NULL) || (dl_state.ws_paths == NULL)) {
- rcm_log_message(RCM_ERROR, gettext("MAC: malloc failure"));
- goto bail;
- }
-
- (void) dladm_db_walk(mac_dl_walker_db, &dl_state);
-
- if ((dl_state.ws_datalink == NULL) || (dl_state.ws_paths == NULL)) {
- rcm_log_message(RCM_ERROR, gettext("MAC: malloc failure"));
- goto bail;
- }
-
- if (paths != NULL)
- *paths = dl_state.ws_paths;
- if (names != NULL)
- *names = dl_state.ws_datalink;
-
- return (dl_state.ws_n_datalinks);
-
-bail:
- free(dl_state.ws_datalink);
- free(dl_state.ws_paths);
- return (-1);
-}
-
-/*
- * Link aggregation walker state.
- */
-typedef struct mac_aggr_walker_state {
- char *as_dev_name;
- uint_t as_n_aggr;
- uint32_t *as_aggr;
-} mac_aggr_walker_state_t;
-
-/*
- * Link aggregation walker.
- */
-static int
-mac_list_aggr_walker(void *arg, laadm_grp_attr_sys_t *grp)
-{
- mac_aggr_walker_state_t *state = (mac_aggr_walker_state_t *)arg;
- laadm_port_attr_sys_t *port;
- int i, j;
-
- rcm_log_message(RCM_TRACE1, "MAC: aggr sys walker: key %u\n",
- grp->lg_key);
-
- if (state->as_aggr == NULL)
- return (0);
-
- /*
- * Add an entry for each aggregated MAC port that was registered
- * by the device being acted upon by RCM.
- */
- for (i = 0; i < grp->lg_nports; i++) {
- port = &grp->lg_ports[i];
-
- rcm_log_message(RCM_TRACE1, "MAC: aggr (%d) port %s/%d\n",
- grp->lg_key, port->lp_devname, port->lp_port);
-
- if (strcmp(port->lp_devname, state->as_dev_name) != 0)
- continue;
-
- /*
- * Found matching port. Add aggregation key to list
- * if it not already there, since multiple ports of
- * the same device could be added to the same
- * aggregation.
- */
- for (j = 0; j < state->as_n_aggr; j++) {
- if (state->as_aggr[j] == grp->lg_key)
- break;
- }
- if (j < state->as_n_aggr)
- /* aggregation group already in list */
- continue;
-
- state->as_n_aggr++;
- state->as_aggr = realloc(state->as_aggr,
- (state->as_n_aggr + 1) * sizeof (uint32_t));
- if (state->as_aggr == NULL)
- return (0);
- state->as_aggr[state->as_n_aggr-1] = grp->lg_key;
- state->as_aggr[state->as_n_aggr] = 0;
- }
-
- return (0);
-}
-
-/*
- * Allocate and return a list of key values of aggregations that
- * are currently configured on top of the MAC ports registered
- * by a device.
- */
-static int
-mac_list_aggr(char *dev_name, uint32_t **aggr)
-{
- mac_aggr_walker_state_t ag_state;
- int rv;
-
- ag_state.as_dev_name = dev_name;
- ag_state.as_n_aggr = 0;
-
- ag_state.as_aggr = calloc(1, sizeof (uint32_t));
- if (ag_state.as_aggr == NULL) {
- rcm_log_message(RCM_ERROR, gettext("MAC: malloc failure"));
- return (-1);
- }
-
- rv = laadm_walk_sys(mac_list_aggr_walker, &ag_state);
- if (rv != 0) {
- rcm_log_message(RCM_ERROR,
- gettext("MAC: cannot list aggregations "
- "(%s)\n"), strerror(errno));
- free(ag_state.as_aggr);
- return (-1);
- }
-
- if (ag_state.as_aggr == NULL) {
- rcm_log_message(RCM_ERROR, gettext("MAC: malloc failure"));
- return (-1);
- }
-
- if (aggr != NULL)
- *aggr = ag_state.as_aggr;
-
- return (ag_state.as_n_aggr);
-}
-
-static void
-mac_list_free(char **list)
-{
- int i;
-
- if (list == NULL)
- return;
-
- for (i = 0; list[i] != NULL; i++)
- free(list[i]);
-
- free(list);
-}
-
-static int
-mac_dl_down_list(char **list)
-{
- int i;
- dladm_diag_t diag;
-
- if (list == NULL)
- return (RCM_SUCCESS);
-
- for (i = 0; list[i] != NULL; i++) {
- rcm_log_message(RCM_DEBUG, "MAC: dl_down() for \"%s\"\n",
- list[i]);
- if (dladm_down(list[i], &diag) != 0) {
- char diag_str[256];
-
- if (diag != 0) {
- (void) snprintf(diag_str, sizeof (diag_str),
- " (%s)", dladm_diag(diag));
- } else {
- diag_str[0] = '\0';
- }
-
- rcm_log_message(RCM_ERROR,
- gettext("MAC: failed to bring "
- "down link %s%s"), list[i], diag_str);
- goto error;
- }
- }
-
- return (RCM_SUCCESS);
-
-error:
- /* bring data links back up */
- for (i--; i >= 0; i--) {
- dladm_diag_t diag;
- (void) dladm_up(list[i], &diag);
- }
- return (RCM_FAILURE);
-}
-
-static int
-mac_dl_up_list(char **list)
-{
- int i;
- dladm_diag_t diag;
-
- if (list == NULL)
- return (RCM_SUCCESS);
-
- for (i = 0; list[i] != NULL; i++) {
- rcm_log_message(RCM_DEBUG, "MAC: dl_up() for \"%s\"\n",
- list[i]);
- if (dladm_up(list[i], &diag) != 0) {
- char diag_str[256];
-
- if (diag != 0) {
- (void) snprintf(diag_str, sizeof (diag_str),
- " (%s)", dladm_diag(diag));
- } else {
- diag_str[0] = '\0';
- }
-
- rcm_log_message(RCM_ERROR,
- gettext("MAC: failed to bring "
- "up link %s%s\n"), list[i], diag_str);
- goto error;
- }
- }
-
- return (RCM_SUCCESS);
-
-error:
- /* bring data links down */
- for (i--; i >= 0; i--) {
- dladm_diag_t diag;
- (void) dladm_down(list[i], &diag);
- }
- return (RCM_FAILURE);
-}
-
-/*
- * Since all we do is pass operations thru, we provide a general
- * routine for passing through operations.
- */
-/*ARGSUSED*/
-static int
-mac_propagate(rcm_handle_t *hd, mac_op_t op, const char *rsrc, uint_t flag,
- char **reason, rcm_info_t **dependent_reason, void *arg)
-{
- mac_cache_t *node;
- int rv = RCM_SUCCESS;
- int ndep, naggr;
- char **dl_paths = NULL;
- char **dl_names = NULL;
- char dev_name[MAXNAMELEN];
- uint32_t *aggr = NULL;
-
- /*
- * Lock the cache just long enough to extract information about this
- * resource.
- */
- (void) mutex_lock(&cache_lock);
- node = cache_lookup(rsrc);
- if (node == NULL) {
- rcm_log_message(RCM_WARNING,
- gettext("MAC: unrecognized resource %s\n"), rsrc);
- (void) mutex_unlock(&cache_lock);
- return (RCM_SUCCESS);
- }
-
- (void) snprintf(dev_name, sizeof (dev_name), "%s%d", node->driver,
- node->instance);
- rcm_log_message(RCM_DEBUG, "MAC: mac_propagate() %s for \"%s\" (%s)\n",
- mac_op_str[op], rsrc, dev_name);
-
- /*
- * We need to propagate the notification to the MAC clients
- * that are configured on top of the MACs of the specified
- * device. These MAC clients can be virtual links,
- * or link aggregation groups.
- */
-
- /*
- * Remove notifications are unconditional in the RCM state model,
- * so it's safe to remove the node from the cache at this point.
- * And we need to remove it so that we will recognize it as a new
- * resource following the reattachment of the resource.
- */
- if (op == MAC_OP_REMOVE) {
- cache_remove(node);
- free_node(node);
- }
- (void) mutex_unlock(&cache_lock);
-
- /*
- * Obtain the list of virtual datalinks configured on currently
- * active on top of the MAC ports registered by the device.
- */
- if ((op == MAC_OP_SUSPEND) || (op == MAC_OP_OFFLINE) ||
- (op == MAC_OP_RESUME))
- ndep = mac_list_datalinks(dev_name, &dl_paths, &dl_names);
- else
- ndep = mac_list_datalinks_db(dev_name, &dl_paths, &dl_names);
-
- if (ndep == -1) {
- rv = RCM_FAILURE;
- goto done;
- } else if ((ndep == 0) && (op != MAC_OP_OFFLINE)) {
- goto done;
- }
-
- switch (op) {
- case MAC_OP_SUSPEND:
- rv = rcm_request_suspend_list(hd, dl_paths, flag,
- (timespec_t *)arg, dependent_reason);
- break;
-
- case MAC_OP_OFFLINE:
- /* refuse operation if aggregation defined on a MAC port */
- naggr = mac_list_aggr(dev_name, &aggr);
- if (naggr == -1) {
- rv = RCM_FAILURE;
- break;
- } else if (naggr > 0) {
- /*
- * Active link aggregation(s) defined on at least
- * one of the MAC ports registered by the device
- * being offlined.
- */
- char *errstr;
- char errgrp[64];
- int i;
-
- errstr = strdup(gettext(
- "Resource is in use by aggregation"));
- if (errstr == NULL) {
- rcm_log_message(RCM_ERROR,
- gettext("MAC: malloc failure"));
- rv = RCM_FAILURE;
- goto done;
- }
-
- for (i = 0; i < naggr; i++) {
- (void) snprintf(errgrp, sizeof (errgrp), " %d",
- aggr[i]);
- errstr = realloc(errstr, strlen(errstr) +
- strlen(errgrp) + 1);
- if (errstr == NULL) {
- rcm_log_message(RCM_ERROR,
- gettext("MAC: malloc failure"));
- rv = RCM_FAILURE;
- goto done;
- }
- (void) strcat(errstr, errgrp);
- }
- *reason = errstr;
- rcm_log_message(RCM_ERROR, "MAC: %s %s\n",
- dev_name, *reason);
- errno = EBUSY;
- rv = RCM_FAILURE;
- break;
- }
-
- if (ndep == 0)
- break;
-
- /* propagate offline request */
- rv = rcm_request_offline_list(hd, dl_paths, flag,
- dependent_reason);
- if (rv != RCM_SUCCESS)
- break;
- if (flag & RCM_QUERY)
- break;
- rv = mac_dl_down_list(dl_names);
- break;
-
- case MAC_OP_REMOVE:
- rv = rcm_notify_remove_list(hd, dl_paths, flag,
- dependent_reason);
- break;
-
- case MAC_OP_ONLINE:
- rv = mac_dl_up_list(dl_names);
- if (rv != RCM_SUCCESS)
- break;
- rv = rcm_notify_online_list(hd, dl_paths, flag,
- dependent_reason);
- break;
-
- case MAC_OP_RESUME:
- rv = rcm_notify_resume_list(hd, dl_paths, flag,
- dependent_reason);
- break;
-
- default:
- rcm_log_message(RCM_WARNING,
- gettext("MAC: bad RCM operation %d\n"), op);
- errno = EINVAL;
- return (RCM_FAILURE);
- }
-
-done:
- if (rv != RCM_SUCCESS) {
- rcm_log_message(RCM_WARNING,
- gettext("MAC: %s operation failed\n"),
- mac_op_str[op]);
- }
-
- mac_list_free(dl_paths);
- mac_list_free(dl_names);
- free(aggr);
-
- return (rv);
-}
-
-
-/*
- * mac_offline()
- *
- * Determine dependents of the resource being offlined, and offline
- * them all.
- */
-static int
-mac_offline(rcm_handle_t *hd, char *rsrc, id_t id, uint_t flags,
- char **reason, rcm_info_t **dependent_reason)
-{
- rcm_log_message(RCM_TRACE1, "MAC: offline(%s)\n", rsrc);
-
- return (mac_propagate(hd, MAC_OP_OFFLINE, rsrc, flags, reason,
- dependent_reason, NULL));
-}
-
-/*
- * mac_online()
- *
- * Remount the previously offlined filesystem, and online its dependents.
- */
-static int
-mac_online(rcm_handle_t *hd, char *rsrc, id_t id, uint_t flag, char **reason,
- rcm_info_t **dependent_reason)
-{
- rcm_log_message(RCM_DEBUG, "MAC: online(%s)\n", rsrc);
-
- return (mac_propagate(hd, MAC_OP_ONLINE, rsrc, flag, reason,
- dependent_reason, NULL));
-}
-
-/*
- * mac_getinfo()
- *
- * Gather usage information for this resource.
- *
- * Locking: the cache is locked while this routine looks up the
- * resource and extracts copies of any piece of information it needs.
- * The cache is then unlocked, and this routine performs the rest of
- * its functions without touching any part of the cache.
- */
-/*ARGSUSED*/
-static int
-mac_getinfo(rcm_handle_t *hd, char *rsrc, id_t id, uint_t flag,
- char **info, char **errstr, nvlist_t *proplist, rcm_info_t **depend_info)
-{
- int len;
- char nic[LIFNAMSIZ];
- const char *info_fmt;
- mac_cache_t *node;
- char **dl_paths;
-
- rcm_log_message(RCM_TRACE1, "MAC: getinfo(%s)\n", rsrc);
-
- info_fmt = "MAC %s";
-
- (void) mutex_lock(&cache_lock);
- node = cache_lookup(rsrc);
- if (!node) {
- rcm_log_message(RCM_WARNING,
- gettext("MAC: unrecognized resource %s\n"), rsrc);
- (void) mutex_unlock(&cache_lock);
- errno = ENOENT;
- return (RCM_FAILURE);
- }
-
- (void) snprintf(nic, sizeof (nic), "%s%d", node->driver,
- node->instance);
-
- len = strlen(info_fmt) + strlen(nic) + 1;
- if ((*info = (char *)malloc(len)) == NULL) {
- rcm_log_message(RCM_ERROR, gettext("MAC: malloc failure"));
- return (RCM_FAILURE);
- }
-
- /* Fill in the string */
- (void) snprintf(*info, len, info_fmt, nic);
-
- if (flag & RCM_INCLUDE_DEPENDENT) {
- char dev_name[MAXNAMELEN];
- int ndep;
-
- rcm_log_message(RCM_DEBUG, "MAC: getting dependents\n");
- /* get list of configured datalinks */
- (void) snprintf(dev_name, sizeof (dev_name), "%s%d",
- node->driver, node->instance);
- ndep = mac_list_datalinks(dev_name, &dl_paths, NULL);
- if (ndep != 0) {
- (void) rcm_get_info_list(hd, dl_paths, flag,
- depend_info);
- mac_list_free(dl_paths);
- }
- }
-
- (void) mutex_unlock(&cache_lock);
-
- return (RCM_SUCCESS);
-}
-
-/*
- * mac_suspend()
- *
- * Notify all dependents that the resource is being suspended.
- * Since no real operation is involved, QUERY or not doesn't matter.
- *
- * Locking: the cache is only used to retrieve some information about
- * this resource, so it is only locked during that retrieval.
- */
-static int
-mac_suspend(rcm_handle_t *hd, char *rsrc, id_t id, timespec_t *interval,
- uint_t flag, char **reason, rcm_info_t **dependent_reason)
-{
- rcm_log_message(RCM_TRACE1, "MAC: suspend(%s)\n", rsrc);
-
- return (mac_propagate(hd, MAC_OP_SUSPEND, rsrc, flag, reason,
- dependent_reason, (void *)interval));
-}
-
-/*
- * mac_resume()
- *
- * Resume all the dependents of a suspended network.
- *
- * Locking: the cache is only used to retrieve some information about
- * this resource, so it is only locked during that retrieval.
- */
-static int
-mac_resume(rcm_handle_t *hd, char *rsrc, id_t id, uint_t flag, char **info,
- rcm_info_t **dependent_info)
-{
- rcm_log_message(RCM_TRACE1, "MAC: resume(%s)\n", rsrc);
-
- return (mac_propagate(hd, MAC_OP_RESUME, rsrc, flag, info,
- dependent_info, NULL));
-}
-
-/*
- * mac_remove()
- *
- * This is another NO-OP for us, we propagate the information. We
- * don't need to remove it from our cache. We don't unregister
- * interest at this point either; the network device name is still
- * around. This way we don't have to change this logic when we
- * gain the ability to learn about DR attach operations.
- */
-static int
-mac_remove(rcm_handle_t *hd, char *rsrc, id_t id, uint_t flag, char **info,
- rcm_info_t **dependent_info)
-{
- rcm_log_message(RCM_TRACE1, "MAC: remove(%s)\n", rsrc);
-
- return (mac_propagate(hd, MAC_OP_REMOVE, rsrc, flag, info,
- dependent_info, NULL));
-}
-
-/*
- * Process post-attach notifications sent by devfs for devices
- * that created DDI_NT_MAC minor nodes. Bring up the links
- * that are configured on top of the corresponding MAC ports.
- */
-/*ARGSUSED*/
-static int
-mac_notify_event(rcm_handle_t *hd, char *rsrc, id_t id, uint_t flag,
- char **errstr, nvlist_t *nvl, rcm_info_t **result)
-{
- rcm_log_message(RCM_DEBUG, "MAC: notify_event(%s)\n", rsrc);
-
- if (strcmp(rsrc, RCM_RESOURCE_MAC_NEW) != 0) {
- rcm_log_message(RCM_WARNING,
- gettext("MAC: unrecognized event for %s\n"), rsrc);
- return (RCM_FAILURE);
- }
-
- /* update cache to reflect attached nodes */
- update_cache(hd);
-
- /* Process the nvlist for the event */
- if (process_nvlist(nvl) != 0) {
- rcm_log_message(RCM_WARNING,
- gettext("MAC: Error processing resource attributes(%s)\n"),
- rsrc);
- rcm_log_message(RCM_WARNING,
- gettext("MAC: One or more devices may not be "
- "configured.\n"));
- }
-
- return (RCM_SUCCESS);
-}
-
-/*
- * Cache management routines. Note that the cache is implemented as a
- * trivial linked list, and is only required because RCM doesn't
- * provide enough state about our own registrations back to us. This
- * linked list implementation probably clobbers the CPU cache pretty
- * well.
- */
-
-/*
- * cache_lookup()
- *
- * Get a cache node for a resource. Call with cache lock held.
- */
-static mac_cache_t *
-cache_lookup(const char *resource)
-{
- mac_cache_t *probe;
-
- probe = cache_head.next;
- while (probe != &cache_tail) {
- if (probe->resource &&
- (strcmp(resource, probe->resource) == 0)) {
- return (probe);
- }
- probe = probe->next;
- }
- return (NULL);
-}
-
-/*
- * free_node()
- *
- * Free a node. Make sure it isn't in the list!
- */
-static void
-free_node(mac_cache_t *node)
-{
- if (node != NULL) {
- free(node->resource);
- free(node->driver);
- free(node);
- }
-}
-
-/*
- * cache_insert()
- *
- * Call with the cache_lock held.
- */
-static void
-cache_insert(mac_cache_t *node)
-{
- /* insert at the head for best performance */
- node->next = cache_head.next;
- node->prev = &cache_head;
-
- node->next->prev = node;
- cache_head.next = node;
-}
-
-/*
- * cache_remove()
- *
- * Call with the cache_lock held.
- */
-static void
-cache_remove(mac_cache_t *node)
-{
- node->next->prev = node->prev;
- node->prev->next = node->next;
- node->next = NULL;
- node->prev = NULL;
-}
-
-/*
- * di_walk_minor() walker. Invoked for each DDI_NT_MAC device.
- */
-/*ARGSUSED*/
-static int
-devfs_entry(di_node_t node, di_minor_t minor, void *arg)
-{
- char *devfspath;
- char resource[MAXPATHLEN];
- char *name;
- char *cp;
- uint_t port_num;
- int instance;
- mac_cache_t *probe;
-
- cp = di_minor_nodetype(minor);
- if ((cp == NULL) || (strcmp(cp, DDI_NT_MAC) != 0)) {
- /* doesn't look like a MAC device */
- return (DI_WALK_CONTINUE);
- }
-
- /*
- * We need to register interest for devices that
- * can be unconfigured, suspended, etc, and registered
- * one or more MAC ports with the kernel.
- *
- * In our cache, we keep one entry per device that registered
- * MAC ports. Each cache entry is also associated with a
- * list of MAC ports that have been registered by the
- * device associated with that cache entry.
- */
-
- name = di_driver_name(node);
- if (name == NULL) {
- /* what else can we do? */
- return (DI_WALK_CONTINUE);
- }
- rcm_log_message(RCM_DEBUG, "MAC: node driver name: \"%s\"\n", name);
-
- instance = di_instance(node);
- rcm_log_message(RCM_DEBUG, "MAC: node instance: %d\n", instance);
-
- port_num = getminor(di_minor_devt(minor));
- rcm_log_message(RCM_DEBUG, "MAC: port number: %u\n", port_num);
-
- devfspath = di_devfs_path(node);
- if (devfspath == NULL) {
- /* no devfs path?!? */
- rcm_log_message(RCM_DEBUG, "MAC: missing devfs path\n");
- return (DI_WALK_CONTINUE);
- }
-
- if (strncmp("/pseudo", devfspath, strlen("/pseudo")) == 0) {
- /* ignore pseudo devices, they are not NICs */
- rcm_log_message(RCM_DEBUG, "MAC: ignoring pseudo device %s\n",
- devfspath);
- di_devfs_path_free(devfspath);
- return (DI_WALK_CONTINUE);
- }
-
- (void) snprintf(resource, sizeof (resource), "/devices%s", devfspath);
- di_devfs_path_free(devfspath);
-
- probe = cache_lookup(resource);
- if (probe != NULL) {
- rcm_log_message(RCM_DEBUG, "MAC: %s already registered\n",
- resource);
- probe->flags &= ~(CACHE_STALE);
- } else {
- rcm_log_message(RCM_DEBUG, "MAC: %s is new resource\n",
- resource);
- probe = calloc(1, sizeof (mac_cache_t));
- if (probe == NULL) {
- rcm_log_message(RCM_ERROR,
- gettext("MAC: malloc failure"));
- return (DI_WALK_CONTINUE);
- }
-
- probe->resource = strdup(resource);
- probe->instance = instance;
- probe->driver = strdup(name);
-
- if (probe->resource == NULL || probe->driver == NULL) {
- free_node(probe);
- return (DI_WALK_CONTINUE);
- }
-
- probe->flags |= CACHE_NEW;
- cache_insert(probe);
- }
-
- return (DI_WALK_CONTINUE);
-}
-
-static void
-update_cache(rcm_handle_t *hd)
-{
- mac_cache_t *probe;
- di_node_t root;
- int rv;
-
- (void) mutex_lock(&cache_lock);
-
- /* first we walk the entire cache, marking each entry stale */
- probe = cache_head.next;
- while (probe != &cache_tail) {
- probe->flags |= CACHE_STALE;
- probe = probe->next;
- }
-
- root = di_init("/", DINFOSUBTREE | DINFOMINOR);
- if (root == DI_NODE_NIL) {
- goto done;
- }
-
- (void) di_walk_minor(root, DDI_NT_MAC, DI_CHECK_ALIAS, NULL,
- devfs_entry);
-
- di_fini(root);
-
- probe = cache_head.next;
- while (probe != &cache_tail) {
- mac_cache_t *freeit;
-
- if (probe->flags & CACHE_STALE) {
- (void) rcm_unregister_interest(hd, probe->resource, 0);
- rcm_log_message(RCM_DEBUG, "MAC: unregistered %s\n",
- probe->resource);
- freeit = probe;
- probe = probe->next;
- cache_remove(freeit);
- free_node(freeit);
- continue;
- }
-
- if (!(probe->flags & CACHE_NEW)) {
- probe = probe->next;
- continue;
- }
-
- rcm_log_message(RCM_DEBUG, "MAC: registering %s\n",
- probe->resource);
- rv = rcm_register_interest(hd, probe->resource, 0, NULL);
- if (rv != RCM_SUCCESS) {
- rcm_log_message(RCM_ERROR,
- gettext("MAC: failed to register %s\n"),
- probe->resource);
- } else {
- rcm_log_message(RCM_DEBUG,
- "MAC: registered %s\n", probe->resource);
- probe->flags &= ~(CACHE_NEW);
- }
- probe = probe->next;
- }
-
-done:
- (void) mutex_unlock(&cache_lock);
-}
-
-static void
-free_cache(void)
-{
- mac_cache_t *probe;
-
- (void) mutex_lock(&cache_lock);
- probe = cache_head.next;
- while (probe != &cache_tail) {
- cache_remove(probe);
- free_node(probe);
- probe = cache_head.next;
- }
- (void) mutex_unlock(&cache_lock);
-}
-
-/*
- * Walker state and function used to bring up the virtual datalinks
- * that are configured on top of a MAC port for which we received
- * a post-attach notification.
- */
-
-typedef struct dl_evt_walker_state {
- char ws_dev_name[MAXNAMELEN];
- int ws_port_num;
-} dl_evt_walker_state_t;
-
-static void
-dl_evt_walker(void *arg, const char *name, dladm_attr_t *dl_attr)
-{
- dl_evt_walker_state_t *state = (dl_evt_walker_state_t *)arg;
- int rc;
- dladm_diag_t diag;
-
- rcm_log_message(RCM_DEBUG, "MAC: dl evt walker match %s/%d with "
- "config %s/%d?\n", dl_attr->da_dev, dl_attr->da_port,
- state->ws_dev_name, state->ws_port_num);
-
- if ((strcmp(state->ws_dev_name, dl_attr->da_dev) != 0) ||
- (state->ws_port_num != dl_attr->da_port)) {
- /* no match */
- rcm_log_message(RCM_DEBUG, "MAC: no dl match, skip entry\n");
- return;
- }
-
- /* we have a match, bring up the datalink */
- rc = dladm_up(name, &diag);
- if (rc != 0) {
- char diag_str[256];
-
- if (diag != 0) {
- (void) snprintf(diag_str, sizeof (diag_str), " (%s)",
- dladm_diag(diag));
- } else {
- diag_str[0] = '\0';
- }
-
- rcm_log_message(RCM_ERROR,
- gettext("MAC: error (%s) configuring "
- "virtual datalink %s%s\n"), strerror(rc), name, diag_str);
- }
-}
-
-/*
- * Process a notification received for a MAC minor node. Bring up
- * each link that is configured on top of the MAC port.
- */
-static void
-process_minor(char *devfs_path, char *name, int instance,
- struct devfs_minor_data *mdata)
-{
- dl_evt_walker_state_t state;
-
- rcm_log_message(RCM_TRACE1, "MAC: process_minor\n");
-
- if ((mdata->minor_node_type != NULL) &&
- strcmp(mdata->minor_node_type, PROP_NV_DDI_MAC) != 0) {
- /* Process MAC devices only */
- return;
- }
-
- rcm_log_message(RCM_TRACE1, "MAC: Examining %s (%s)\n",
- devfs_path, mdata->minor_name);
-
- if (strncmp("/pseudo", devfs_path, strlen("/pseudo")) == 0) {
- rcm_log_message(RCM_TRACE1, "MAC: ignoring pseudo %s (%s)\n",
- devfs_path, mdata->minor_name);
- return;
- }
-
- rcm_log_message(RCM_TRACE1, "MAC: process MAC minor "
- "(dev=%s, name=%s, inst=%d, port=\"%s\")\n",
- devfs_path, name, instance, mdata->minor_name);
-
- (void) snprintf(state.ws_dev_name, sizeof (state.ws_dev_name), "%s%d",
- name, instance);
- state.ws_port_num = atoi(mdata->minor_name);
- (void) dladm_db_walk(dl_evt_walker, &state);
-}
-
-/*
- * Process a post-attached notification nvlist sent by devfs.
- */
-static int
-process_nvlist(nvlist_t *nvl)
-{
- nvpair_t *nvp = NULL;
- char *driver_name;
- char *devfs_path;
- int32_t instance;
- char *minor_byte_array;
- uint_t nminor;
- struct devfs_minor_data *mdata = NULL;
- nvlist_t *mnvl = NULL;
- nvpair_t *mnvp = NULL;
-
- rcm_log_message(RCM_TRACE1, "MAC: process_nvlist\n");
-
- while ((nvp = nvlist_next_nvpair(nvl, nvp)) != NULL) {
- /* Get driver name */
- if (strcmp(nvpair_name(nvp), RCM_NV_DRIVER_NAME) == 0) {
- if (nvpair_value_string(nvp, &driver_name) != 0) {
- rcm_log_message(RCM_WARNING,
- gettext("MAC: cannot get driver name\n"));
- return (-1);
- }
- }
- /* Get instance */
- if (strcmp(nvpair_name(nvp), RCM_NV_INSTANCE) == 0) {
- if (nvpair_value_int32(nvp, &instance) != 0) {
- rcm_log_message(RCM_WARNING, gettext(
- "MAC: cannot get device instance\n"));
- return (-1);
- }
- }
- /* Get devfs_path */
- if (strcmp(nvpair_name(nvp), RCM_NV_DEVFS_PATH) == 0) {
- if (nvpair_value_string(nvp, &devfs_path) != 0) {
- rcm_log_message(RCM_WARNING,
- gettext("MAC: cannot get device path\n"));
- return (-1);
- }
- }
- /* Get minor data */
- if (strcmp(nvpair_name(nvp), RCM_NV_MINOR_DATA) == 0) {
- if (nvpair_value_byte_array(nvp,
- (uchar_t **)&minor_byte_array, &nminor) != 0) {
- rcm_log_message(RCM_WARNING, gettext(
- "MAC: cannot get device minor data\n"));
- return (-1);
- }
- if (nvlist_unpack(minor_byte_array,
- nminor, &mnvl, 0) != 0) {
- rcm_log_message(RCM_WARNING, gettext(
- "MAC: cannot get minor node data\n"));
- return (-1);
- }
- mdata = (struct devfs_minor_data *)calloc(1,
- sizeof (struct devfs_minor_data));
- if (mdata == NULL) {
- rcm_log_message(RCM_WARNING,
- gettext("MAC: calloc error(%s)\n"),
- strerror(errno));
- goto bail;
- }
- /* Enumerate minor node data */
- while ((mnvp = nvlist_next_nvpair(mnvl, mnvp)) !=
- NULL) {
- /* Get minor type */
- if (strcmp(nvpair_name(mnvp),
- RCM_NV_MINOR_TYPE) == 0) {
- if (nvpair_value_int32(mnvp,
- &mdata->minor_type) != 0) {
- rcm_log_message(RCM_WARNING,
- gettext("MAC: cannot get "
- "minor type \n"));
- goto bail;
- }
- }
- /* Get minor name */
- if (strcmp(nvpair_name(mnvp),
- RCM_NV_MINOR_NAME) == 0) {
- if (nvpair_value_string(mnvp,
- &mdata->minor_name) != 0) {
- rcm_log_message(RCM_WARNING,
- gettext("MAC: cannot get "
- "minor name \n"));
- goto bail;
- }
- }
- /* Get minor node type */
- if (strcmp(nvpair_name(mnvp),
- RCM_NV_MINOR_NODE_TYPE) == 0) {
- if (nvpair_value_string(mnvp,
- &mdata->minor_node_type) != 0) {
- rcm_log_message(RCM_WARNING,
- gettext("MAC: cannot get "
- "minor node type \n"));
- goto bail;
- }
- }
- }
- process_minor(devfs_path, driver_name, instance,
- mdata);
- nvlist_free(mnvl);
- }
- }
-
- rcm_log_message(RCM_TRACE1, "MAC: process_nvlist success\n");
- return (0);
-
-bail:
- if (mnvl != NULL)
- nvlist_free(mnvl);
- if (mdata != NULL)
- free(mdata);
- return (-1);
-}
diff --git a/usr/src/cmd/rcm_daemon/common/network_rcm.c b/usr/src/cmd/rcm_daemon/common/network_rcm.c
index 6072ff510a..85325a3409 100644
--- a/usr/src/cmd/rcm_daemon/common/network_rcm.c
+++ b/usr/src/cmd/rcm_daemon/common/network_rcm.c
@@ -40,9 +40,9 @@
#include <libintl.h>
#include <errno.h>
#include <libdevinfo.h>
-#include <ctype.h>
#include <sys/types.h>
-#include <libdlpi.h>
+#include <net/if.h>
+#include <liblaadm.h>
#include "rcm_module.h"
/*
@@ -70,8 +70,6 @@
*/
#define NET_DELIMITER ""
-#define DLD_NAME "dld"
-
typedef struct net_cache
{
char *resource;
@@ -114,6 +112,7 @@ static void cache_remove(net_cache_t *node);
static net_cache_t *cache_lookup(const char *resource);
static void free_node(net_cache_t *);
static void cache_insert(net_cache_t *);
+static boolean_t is_aggregated(char *driver, int ppa);
/*
* Module-Private data
@@ -285,6 +284,18 @@ net_passthru(rcm_handle_t *hd, int op, const char *rsrc, uint_t flag,
(timespec_t *)arg, dependent_reason);
break;
case NET_OFFLINE:
+ if (is_aggregated(node->driver, node->ppa)) {
+ /* device is aggregated */
+ *reason = strdup(gettext(
+ "Resource is in use by aggregation"));
+ if (*reason == NULL) {
+ rcm_log_message(RCM_ERROR,
+ gettext("NET: malloc failure"));
+ }
+ errno = EBUSY;
+ return (RCM_FAILURE);
+ }
+
rv = rcm_request_offline(hd, exported, flag, dependent_reason);
break;
case NET_ONLINE:
@@ -727,7 +738,6 @@ devfs_entry(di_node_t node, di_minor_t minor, void *arg)
char ifname [MAXPATHLEN]; /* should be big enough! */
char *devfspath;
char resource[MAXPATHLEN];
- char dev_name[MAXPATHLEN];
char *name;
char *cp;
int instance;
@@ -747,6 +757,9 @@ devfs_entry(di_node_t node, di_minor_t minor, void *arg)
instance = di_instance(node);
+ (void) snprintf(ifname, sizeof (ifname), "SUNW_network/%s%s%d",
+ name, NET_DELIMITER, instance);
+
devfspath = di_devfs_path(node);
if (!devfspath) {
/* no devfs path?!? */
@@ -755,39 +768,16 @@ devfs_entry(di_node_t node, di_minor_t minor, void *arg)
}
if (strncmp("/pseudo", devfspath, strlen("/pseudo")) == 0) {
- char *minor_name;
-
- if (strcmp(DLD_NAME, name) != 0) {
- /* ignore pseudo devices, probably not really NICs */
- rcm_log_message(RCM_DEBUG, "NET: ignoring pseudo "
- "device %s\n", devfspath);
- di_devfs_path_free(devfspath);
- return (DI_WALK_CONTINUE);
- }
-
- /* we have a virtual datalink created by dld */
- di_devfs_path_free(devfspath);
- devfspath = di_devfs_minor_path(minor);
- rcm_log_message(RCM_DEBUG, "NET: virtual datalink \"%s\"\n",
+ /* ignore pseudo devices, probably not really NICs */
+ rcm_log_message(RCM_DEBUG, "NET: ignoring pseudo device %s\n",
devfspath);
-
- minor_name = di_minor_name(minor);
- if (dlpi_if_parse(minor_name, dev_name, &instance) < 0 ||
- instance < 0) {
- rcm_log_message(RCM_DEBUG, "NET: ignoring \"%s\" "
- "(style 1)\n", devfspath);
- di_devfs_path_free(devfspath);
- return (DI_WALK_CONTINUE);
- }
- name = dev_name;
+ di_devfs_path_free(devfspath);
+ return (DI_WALK_CONTINUE);
}
(void) snprintf(resource, sizeof (resource), "/devices%s", devfspath);
di_devfs_path_free(devfspath);
- (void) snprintf(ifname, sizeof (ifname), "SUNW_network/%s%s%d",
- name, NET_DELIMITER, instance);
-
probe = cache_lookup(resource);
if (probe != NULL) {
rcm_log_message(RCM_DEBUG, "NET: %s already registered\n",
@@ -907,3 +897,54 @@ free_cache(void)
}
(void) mutex_unlock(&cache_lock);
}
+
+/*
+ * is_aggregated() checks whether a NIC being removed is part of an
+ * aggregation.
+ */
+
+typedef struct aggr_walker_state_s {
+ uint_t naggr;
+ char dev_name[LIFNAMSIZ];
+} aggr_walker_state_t;
+
+static int
+aggr_walker(void *arg, laadm_grp_attr_sys_t *grp)
+{
+ aggr_walker_state_t *state = arg;
+ laadm_port_attr_sys_t *port;
+ int i;
+
+ for (i = 0; i < grp->lg_nports; i++) {
+ port = &grp->lg_ports[i];
+
+ rcm_log_message(RCM_TRACE1, "MAC: aggr (%d) port %s/%d\n",
+ grp->lg_key, port->lp_devname, port->lp_port);
+
+ if (strcmp(port->lp_devname, state->dev_name) != 0)
+ continue;
+
+ /* found matching MAC port */
+ state->naggr++;
+ }
+
+ return (0);
+}
+
+static boolean_t
+is_aggregated(char *driver, int ppa)
+{
+ aggr_walker_state_t state;
+
+ state.naggr = 0;
+ (void) snprintf(state.dev_name, sizeof (state.dev_name), "%s%d",
+ driver, ppa);
+
+ if (laadm_walk_sys(aggr_walker, &state) != 0) {
+ rcm_log_message(RCM_ERROR, gettext("NET: cannot walk "
+ "aggregations (%s)\n"), strerror(errno));
+ return (B_FALSE);
+ }
+
+ return (state.naggr > 0);
+}
diff --git a/usr/src/cmd/svc/milestone/Makefile b/usr/src/cmd/svc/milestone/Makefile
index eebdf29046..be0440da40 100644
--- a/usr/src/cmd/svc/milestone/Makefile
+++ b/usr/src/cmd/svc/milestone/Makefile
@@ -43,9 +43,6 @@ FSSVCS= \
FSMANIFESTS= $(FSSVCS:%=$(ROOTSVCSYSTEMFILESYSTEM)/%)
NETSVCS= \
- datalink.xml \
- datalink-init.xml \
- aggregation.xml \
network-initial.xml \
network-loopback.xml \
network-physical.xml \
@@ -94,11 +91,8 @@ MANIFEST= $(FSSVCS) $(NETSVCS) $(MAINMILESTONES) $(SYSTEMSVCS) \
$(SYSDEVSVCS) $(SYSTEMSVCSVCS)
SVCMETHOD=\
- aggregation \
boot-archive \
console-login \
- datalink \
- datalink-init \
devices-local \
fs-local \
fs-minimal \
diff --git a/usr/src/cmd/svc/milestone/aggregation b/usr/src/cmd/svc/milestone/aggregation
deleted file mode 100644
index 88317277e3..0000000000
--- a/usr/src/cmd/svc/milestone/aggregation
+++ /dev/null
@@ -1,40 +0,0 @@
-#!/sbin/sh
-#
-# 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.
-#
-# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
-# See the License for the specific language governing permissions
-# and limitations under the License.
-#
-# When distributing Covered Code, include this CDDL HEADER in each
-# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
-# If applicable, add the following below this CDDL HEADER, with the
-# fields enclosed by brackets "[]" replaced with your own identifying
-# information: Portions Copyright [yyyy] [name of copyright owner]
-#
-# CDDL HEADER END
-#
-#
-# Copyright 2005 Sun Microsystems, Inc. All rights reserved.
-# Use is subject to license terms.
-#
-# ident "%Z%%M% %I% %E% SMI"
-
-if [ `/sbin/zonename` != "global" ]; then
- exit 0
-fi
-
-case "$1" in
-'start')
- /sbin/dladm up-aggr
- ;;
-'stop')
- /sbin/dladm down-aggr
- ;;
-esac
diff --git a/usr/src/cmd/svc/milestone/aggregation.xml b/usr/src/cmd/svc/milestone/aggregation.xml
deleted file mode 100644
index d7f38fafed..0000000000
--- a/usr/src/cmd/svc/milestone/aggregation.xml
+++ /dev/null
@@ -1,73 +0,0 @@
-<?xml version="1.0"?>
-<!DOCTYPE service_bundle SYSTEM "/usr/share/lib/xml/dtd/service_bundle.dtd.1">
-<!--
- Copyright 2005 Sun Microsystems, Inc. All rights reserved.
- Use is subject to license terms.
-
- 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.
-
- You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- or http://www.opensolaris.org/os/licensing.
- See the License for the specific language governing permissions
- and limitations under the License.
-
- When distributing Covered Code, include this CDDL HEADER in each
- file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- If applicable, add the following below this CDDL HEADER, with the
- fields enclosed by brackets "[]" replaced with your own identifying
- information: Portions Copyright [yyyy] [name of copyright owner]
-
- CDDL HEADER END
-
- ident "%Z%%M% %I% %E% SMI"
--->
-
-<service_bundle type='manifest' name='SUNWcsr:net-aggregation'>
-
-<service
- name='network/aggregation'
- type='service'
- version='1'>
-
- <create_default_instance enabled='true' />
-
- <single_instance/>
-
- <exec_method
- type='method'
- name='start'
- exec='/lib/svc/method/aggregation %m'
- timeout_seconds='30' />
-
- <exec_method
- type='method'
- name='stop'
- exec='/lib/svc/method/aggregation %m'
- timeout_seconds='30' />
-
- <property_group name='startd' type='framework'>
- <propval name='duration' type='astring'
- value='transient' />
- </property_group>
-
- <stability value='Evolving' />
-
- <template>
- <common_name>
- <loctext xml:lang='C'>
- network aggregations
- </loctext>
- </common_name>
- <documentation>
- <manpage title='dladm' section='1M'
- manpath='/usr/share/man' />
- </documentation>
- </template>
-</service>
-
-</service_bundle>
diff --git a/usr/src/cmd/svc/milestone/datalink b/usr/src/cmd/svc/milestone/datalink
deleted file mode 100644
index 5bc22b5a06..0000000000
--- a/usr/src/cmd/svc/milestone/datalink
+++ /dev/null
@@ -1,37 +0,0 @@
-#!/sbin/sh
-#
-# 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.
-#
-# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
-# See the License for the specific language governing permissions
-# and limitations under the License.
-#
-# When distributing Covered Code, include this CDDL HEADER in each
-# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
-# If applicable, add the following below this CDDL HEADER, with the
-# fields enclosed by brackets "[]" replaced with your own identifying
-# information: Portions Copyright [yyyy] [name of copyright owner]
-#
-# CDDL HEADER END
-#
-#
-# Copyright 2005 Sun Microsystems, Inc. All rights reserved.
-# Use is subject to license terms.
-#
-# ident "%Z%%M% %I% %E% SMI"
-
-if [ `/sbin/zonename` != "global" ]; then
- exit 0
-fi
-
-v1=`svcprop -p system/reconfigure system/svc/restarter:default`
-if [ "$v1" = "true" -o -f /etc/.UNCONFIGURED ]; then
- /sbin/dladm init-link -t > /dev/msglog 2>&1
-fi
-/sbin/dladm up-link
diff --git a/usr/src/cmd/svc/milestone/datalink-init b/usr/src/cmd/svc/milestone/datalink-init
deleted file mode 100644
index 6217e2003c..0000000000
--- a/usr/src/cmd/svc/milestone/datalink-init
+++ /dev/null
@@ -1,44 +0,0 @@
-#!/sbin/sh
-#
-# 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.
-#
-# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
-# See the License for the specific language governing permissions
-# and limitations under the License.
-#
-# When distributing Covered Code, include this CDDL HEADER in each
-# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
-# If applicable, add the following below this CDDL HEADER, with the
-# fields enclosed by brackets "[]" replaced with your own identifying
-# information: Portions Copyright [yyyy] [name of copyright owner]
-#
-# CDDL HEADER END
-#
-#
-# Copyright 2005 Sun Microsystems, Inc. All rights reserved.
-# Use is subject to license terms.
-#
-# ident "%Z%%M% %I% %E% SMI"
-
-#
-# Populate the /etc/links file during a reconfiguration reboot
-#
-
-if [ `/sbin/zonename` != "global" ]; then
- exit 0
-fi
-
-svcprop -p system/reconfigure system/svc/restarter:default | (
- read v1
- if [ "$v1" = "true" ]; then
- /sbin/dladm init-link > /dev/msglog 2>&1
- fi
-)
-
-exit 0
diff --git a/usr/src/cmd/svc/milestone/datalink-init.xml b/usr/src/cmd/svc/milestone/datalink-init.xml
deleted file mode 100644
index 2729eaddc2..0000000000
--- a/usr/src/cmd/svc/milestone/datalink-init.xml
+++ /dev/null
@@ -1,83 +0,0 @@
-<?xml version="1.0"?>
-<!DOCTYPE service_bundle SYSTEM "/usr/share/lib/xml/dtd/service_bundle.dtd.1">
-<!--
- Copyright 2005 Sun Microsystems, Inc. All rights reserved.
- Use is subject to license terms.
-
- 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.
-
- You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- or http://www.opensolaris.org/os/licensing.
- See the License for the specific language governing permissions
- and limitations under the License.
-
- When distributing Covered Code, include this CDDL HEADER in each
- file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- If applicable, add the following below this CDDL HEADER, with the
- fields enclosed by brackets "[]" replaced with your own identifying
- information: Portions Copyright [yyyy] [name of copyright owner]
-
- CDDL HEADER END
-
- ident "%Z%%M% %I% %E% SMI"
--->
-
-<service_bundle type='manifest' name='SUNWcsr:datalink-init'>
-
-<service
- name='network/datalink-init'
- type='service'
- version='1'>
-
- <create_default_instance enabled='true' />
-
- <single_instance/>
-
- <dependency
- name='usr'
- grouping='require_all'
- restart_on='none'
- type='service'>
- <service_fmri value='svc:/system/filesystem/usr' />
- </dependency>
-
- <exec_method
- type='method'
- name='start'
- exec='/lib/svc/method/datalink-init'
- timeout_seconds='6000' />
-
- <exec_method
- type='method'
- name='refresh'
- exec='/lib/svc/method/datalink-init'
- timeout_seconds='6000' />
-
- <exec_method
- type='method'
- name='stop'
- exec=':true'
- timeout_seconds='3' />
-
- <property_group name='startd' type='framework'>
- <propval name='duration' type='astring'
- value='transient' />
- </property_group>
-
- <stability value='Evolving' />
-
- <template>
- <common_name>
- <loctext xml:lang='C'>
- Solaris datalink initialization
- </loctext>
- </common_name>
- </template>
-</service>
-
-</service_bundle>
diff --git a/usr/src/cmd/svc/milestone/datalink.xml b/usr/src/cmd/svc/milestone/datalink.xml
deleted file mode 100644
index 37153eb52d..0000000000
--- a/usr/src/cmd/svc/milestone/datalink.xml
+++ /dev/null
@@ -1,88 +0,0 @@
-<?xml version="1.0"?>
-<!DOCTYPE service_bundle SYSTEM "/usr/share/lib/xml/dtd/service_bundle.dtd.1">
-<!--
- Copyright 2005 Sun Microsystems, Inc. All rights reserved.
- Use is subject to license terms.
-
- 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.
-
- You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- or http://www.opensolaris.org/os/licensing.
- See the License for the specific language governing permissions
- and limitations under the License.
-
- When distributing Covered Code, include this CDDL HEADER in each
- file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- If applicable, add the following below this CDDL HEADER, with the
- fields enclosed by brackets "[]" replaced with your own identifying
- information: Portions Copyright [yyyy] [name of copyright owner]
-
- CDDL HEADER END
-
- ident "%Z%%M% %I% %E% SMI"
--->
-
-<service_bundle type='manifest' name='SUNWcsr:datalink'>
-
-<service
- name='network/datalink'
- type='service'
- version='1'>
-
- <create_default_instance enabled='true' />
-
- <single_instance/>
-
- <dependency
- name='aggregation'
- grouping='optional_all'
- restart_on='none'
- type='service'>
- <service_fmri value='svc:/network/aggregation' />
- </dependency>
-
- <dependent
- name='data_network'
- grouping='optional_all'
- restart_on='none'>
- <service_fmri value='svc:/network/physical' />
- </dependent>
-
- <exec_method
- type='method'
- name='start'
- exec='/lib/svc/method/datalink'
- timeout_seconds='600' />
-
- <exec_method
- type='method'
- name='stop'
- exec=':true'
- timeout_seconds='3' />
-
- <property_group name='startd' type='framework'>
- <propval name='duration' type='astring'
- value='transient' />
- </property_group>
-
- <stability value='Evolving' />
-
- <template>
- <common_name>
- <loctext xml:lang='C'>
- network datalinks
- </loctext>
- </common_name>
- <documentation>
- <manpage title='dladm' section='1M'
- manpath='/usr/share/man' />
- </documentation>
- </template>
-</service>
-
-</service_bundle>
diff --git a/usr/src/cmd/svc/milestone/net-physical b/usr/src/cmd/svc/milestone/net-physical
index 73775643be..d5702f6331 100644
--- a/usr/src/cmd/svc/milestone/net-physical
+++ b/usr/src/cmd/svc/milestone/net-physical
@@ -61,6 +61,11 @@ SUNW_NO_MPATHD=; export SUNW_NO_MPATHD
smf_netstrategy
#
+# Bring up link aggregations
+#
+/sbin/dladm up-aggr
+
+#
# If the system was net booted by DHCP, hand DHCP management off to the
# DHCP agent (ifconfig communicates to the DHCP agent through the
# loopback interface).
diff --git a/usr/src/cmd/svc/seed/Makefile b/usr/src/cmd/svc/seed/Makefile
index aa3d728fc2..262a2c835c 100644
--- a/usr/src/cmd/svc/seed/Makefile
+++ b/usr/src/cmd/svc/seed/Makefile
@@ -53,7 +53,6 @@ INSTALLSEED = $(ROOT)/usr/sadm/install
#
COMMON_DESCRIPTIONS = \
../milestone/boot-archive.xml \
- ../milestone/datalink.xml \
../milestone/devices-local.xml \
../milestone/identity.xml \
../milestone/local-fs.xml \
@@ -75,9 +74,7 @@ COMMON_DESCRIPTIONS = \
#
GLOBAL_ZONE_DESCRIPTIONS = \
../milestone/console-login.xml \
- ../milestone/datalink-init.xml \
../milestone/multi-user-server.xml \
- ../milestone/aggregation.xml \
../../cmd-inet/usr.lib/inetd/inetd-upgrade.xml \
../../utmpd/utmp.xml \
../../lvm/util/metainit.xml \
@@ -89,14 +86,12 @@ GLOBAL_ZONE_DESCRIPTIONS = \
NONGLOBAL_ZONE_DESCRIPTIONS = \
../milestone/console-login.xml \
../milestone/multi-user-server.xml \
- ../milestone/aggregation.xml \
../../utmpd/utmp.xml
#
# Additional manifests for the install miniroot.
#
MINIROOT_DESCRIPTIONS= \
- ../milestone/datalink-init.xml \
../milestone/sysconfig.xml \
../../cmd-inet/usr.lib/inetd/inetd.xml \
../../cmd-inet/usr.sbin/login.xml \
diff --git a/usr/src/cmd/truss/codes.c b/usr/src/cmd/truss/codes.c
index b2e7ca4dd0..c0a20c6a64 100644
--- a/usr/src/cmd/truss/codes.c
+++ b/usr/src/cmd/truss/codes.c
@@ -852,13 +852,9 @@ const struct ioc {
"laioc_add_rem"},
{ (uint_t)LAIOC_MODIFY, "LAIOC_MODIFY", "laioc_modify"},
- /* dld data-link configuration ioctls */
- { (uint_t)DLDIOCCREATE, "DLDIOCCREATE",
- "dld_ioc_create"},
- { (uint_t)DLDIOCDESTROY, "DLDIOCDESTROY",
- "dld_ioc_destroy"},
+ /* dld data-link ioctls */
{ (uint_t)DLDIOCATTR, "DLDIOCATTR", "dld_ioc_attr"},
-
+ { (uint_t)DLDIOCVLAN, "DLDIOCVLAN", "dld_ioc_vlan"},
{ (uint_t)0, NULL, NULL }
};
diff --git a/usr/src/lib/Makefile b/usr/src/lib/Makefile
index d25f6b0ccf..9375332e21 100644
--- a/usr/src/lib/Makefile
+++ b/usr/src/lib/Makefile
@@ -399,7 +399,7 @@ libefi: libuuid
libelfsign: libike libcryptoutil pkcs11
libinetcfg: libnsl libsocket libdevinfo
libnsl: libmd5 libscf
-libmacadm: libdevinfo
+libmacadm: libdevinfo libdladm libdlpi
libuuid: libsocket
libinetutil: libsocket
libsecdb: libcmd libnsl
diff --git a/usr/src/lib/libdladm/common/libdladm.c b/usr/src/lib/libdladm/common/libdladm.c
index 27c99135a8..8d97e4d708 100644
--- a/usr/src/lib/libdladm/common/libdladm.c
+++ b/usr/src/lib/libdladm/common/libdladm.c
@@ -28,7 +28,6 @@
#include <stdio.h>
#include <sys/types.h>
-#include <sys/stat.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
@@ -38,428 +37,27 @@
#include <libdevinfo.h>
#include <libdlpi.h>
#include <libdladm.h>
-#include <libintl.h>
#include <sys/dld.h>
#include <net/if.h>
-#define DLADM_DB "/etc/datalink.conf"
-#define DLADM_DB_TMP "/etc/datalink.conf.new"
-#define DLADM_DB_LOCK "/tmp/datalink.conf.lock"
-#define DLADM_DB_PERMS S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH
-
-#define MAXLINELEN 1024
-#define LISTSZ 1024
-#define MAXPATHLEN 1024
-
-#define BLANK_LINE(s) ((s[0] == '\0') || (s[0] == '#') || (s[0] == '\n'))
-
-typedef struct i_dladm_walk {
- int fd;
- boolean_t found;
- const char *name;
-} i_dladm_walk_t;
-
-/*
- * Open and lock the aggregation configuration file lock. The lock is
- * acquired as a reader (F_RDLCK) or writer (F_WRLCK).
- */
-static int
-i_dladm_lock_db(short type)
-{
- int lock_fd;
- struct flock lock;
-
- if ((lock_fd = open(DLADM_DB_LOCK, O_RDWR | O_CREAT | O_TRUNC,
- DLADM_DB_PERMS)) < 0)
- return (-1);
-
- lock.l_type = type;
- lock.l_whence = SEEK_SET;
- lock.l_start = 0;
- lock.l_len = 0;
-
- if (fcntl(lock_fd, F_SETLKW, &lock) < 0) {
- (void) close(lock_fd);
- (void) unlink(DLADM_DB_LOCK);
- return (-1);
- }
- return (lock_fd);
-}
-
-/*
- * Unlock and close the specified file.
- */
-static void
-i_dladm_unlock_db(int fd)
-{
- struct flock lock;
-
- if (fd < 0)
- return;
-
- lock.l_type = F_UNLCK;
- lock.l_whence = SEEK_SET;
- lock.l_start = 0;
- lock.l_len = 0;
-
- (void) fcntl(fd, F_SETLKW, &lock);
- (void) close(fd);
- (void) unlink(DLADM_DB_LOCK);
-}
-
-/*
- * Parse a line of the configuration file, returns -1 if an error
- * occured.
- */
-static int
-i_dladm_db_decode(char *buf, char *name, dladm_attr_t *dap)
-{
- char *attr[DLADM_NATTR + 1];
- char *endp = NULL;
- char *lasts = NULL;
- uint_t i;
-
- attr[0] = strtok_r(buf, " \t\n", &lasts);
- for (i = 1; i < DLADM_NATTR + 1; i++) {
- if ((attr[i] = strtok_r(NULL, " \t\n", &lasts)) == NULL)
- return (-1);
- }
-
- if (i != DLADM_NATTR + 1) {
- errno = EINVAL;
- return (-1);
- }
-
- (void) strlcpy(name, attr[0], IFNAMSIZ);
- (void) strlcpy(dap->da_dev, attr[1], MAXNAMELEN);
-
- errno = 0;
- dap->da_port = (int)strtol(attr[2], &endp, 10);
- if (errno != 0 || *endp != '\0') {
- return (-1);
- }
-
- errno = 0;
- dap->da_vid = (int)strtol(attr[3], &endp, 10);
- if (errno != 0 || *endp != '\0') {
- return (-1);
- }
-
- return (0);
-}
-
-/*
- * Add a datalink of the specified name and attributes to
- * the configuration repository.
- */
-static int
-i_dladm_db_add(const char *name, dladm_attr_t *dap, const char *root,
- dladm_diag_t *diag)
-{
- FILE *fp;
- int lock_fd, retval = -1;
- char line[MAXLINELEN];
- char dl_name[IFNAMSIZ];
- dladm_attr_t da;
- char *db_file;
- char db_file_buf[MAXPATHLEN];
-
- if (root == NULL) {
- db_file = DLADM_DB;
- } else {
- (void) snprintf(db_file_buf, MAXPATHLEN, "%s%s", root,
- DLADM_DB);
- db_file = db_file_buf;
- }
-
- if ((lock_fd = i_dladm_lock_db(F_WRLCK)) < 0)
- return (-1);
-
- if ((fp = fopen(db_file, "r+")) == NULL &&
- (fp = fopen(db_file, "w")) == NULL) {
- *diag = DLADM_DIAG_REPOSITORY_OPENFAIL;
- i_dladm_unlock_db(lock_fd);
- return (-1);
- }
-
- while (fgets(line, MAXLINELEN, fp) != NULL) {
- /* skip comments and blank lines */
- if (BLANK_LINE(line))
- continue;
-
- /* skip corrupted lines */
- if (i_dladm_db_decode(line, dl_name, &da) < 0)
- continue;
-
- if (strcmp(dl_name, name) == 0) {
- errno = EEXIST;
- goto failed;
- }
-
- if (strcmp(da.da_dev, dap->da_dev) == 0 &&
- da.da_port == dap->da_port &&
- da.da_vid == dap->da_vid) {
- errno = EEXIST;
- goto failed;
- }
- }
-
- (void) snprintf(line, MAXPATHLEN, "%s\t%s\t%u\t%u\n",
- name, dap->da_dev, dap->da_port, dap->da_vid);
-
- if (fputs(line, fp) == EOF) {
- *diag = DLADM_DIAG_REPOSITORY_WRITEFAIL;
- goto failed;
- }
-
- if (fflush(fp) == EOF)
- goto failed;
-
- retval = 0;
-
-failed:
- (void) fclose(fp);
- i_dladm_unlock_db(lock_fd);
- return (retval);
-}
-
-/*
- * Remove the datalink of the specified name from the configuration repository.
- */
-static int
-i_dladm_db_remove(const char *name, const char *root)
-{
- FILE *fp;
- FILE *nfp;
- int nfd, lock_fd;
- char line[MAXLINELEN];
- char copy[MAXLINELEN];
- char dl_name[IFNAMSIZ];
- dladm_attr_t da;
- boolean_t found = B_FALSE;
- char *db_file, *tmp_db_file;
- char db_file_buf[MAXPATHLEN];
- char tmp_db_file_buf[MAXPATHLEN];
-
- if (root == NULL) {
- db_file = DLADM_DB;
- tmp_db_file = DLADM_DB_TMP;
- } else {
- (void) snprintf(db_file_buf, MAXPATHLEN, "%s%s", root,
- DLADM_DB);
- (void) snprintf(tmp_db_file_buf, MAXPATHLEN, "%s%s", root,
- DLADM_DB_TMP);
- db_file = db_file_buf;
- tmp_db_file = tmp_db_file_buf;
- }
-
- if ((lock_fd = i_dladm_lock_db(F_WRLCK)) < 0)
- return (-1);
-
- if ((fp = fopen(db_file, "r")) == NULL) {
- i_dladm_unlock_db(lock_fd);
- return (-1);
- }
-
- if ((nfd = open(tmp_db_file, O_WRONLY | O_CREAT | O_TRUNC,
- DLADM_DB_PERMS)) < 0) {
- (void) fclose(fp);
- i_dladm_unlock_db(lock_fd);
- return (-1);
- }
-
- if ((nfp = fdopen(nfd, "w")) == NULL) {
- (void) close(nfd);
- (void) fclose(fp);
- (void) unlink(tmp_db_file);
- i_dladm_unlock_db(lock_fd);
- return (-1);
- }
-
- while (fgets(line, MAXLINELEN, fp) != NULL) {
- (void) strlcpy(copy, line, MAXLINELEN);
-
- /* skip comments */
- if (!BLANK_LINE(line)) {
- if (i_dladm_db_decode(line, dl_name, &da) < 0) {
- continue;
- }
-
- if (strcmp(dl_name, name) == 0) {
- found = B_TRUE;
- continue;
- }
- }
-
- if (fputs(copy, nfp) == EOF)
- goto failed;
- }
-
- if (!found) {
- errno = ENOENT;
- goto failed;
- }
-
- if (fflush(nfp) == EOF)
- goto failed;
-
- (void) fclose(fp);
- (void) fclose(nfp);
- if (rename(tmp_db_file, db_file) < 0) {
- (void) unlink(tmp_db_file);
- i_dladm_unlock_db(lock_fd);
- return (-1);
- }
-
- i_dladm_unlock_db(lock_fd);
- return (0);
-
-failed:
- (void) fclose(fp);
- (void) fclose(nfp);
- (void) unlink(tmp_db_file);
- i_dladm_unlock_db(lock_fd);
-
- return (-1);
-}
-
-/*
- * For each datalink in the configuration repository, invoke the specified
- * callback. If the datalink name is specified, the callback is invoked
- * only for datalink of the matching name.
- */
-static void
-i_dladm_db_walk(void (*fn)(void *, const char *, dladm_attr_t *),
- const char *name, void *arg)
-{
- FILE *fp;
- int lock_fd;
- char line[MAXLINELEN];
- char dl_name[IFNAMSIZ];
- dladm_attr_t da;
-
- lock_fd = i_dladm_lock_db(F_RDLCK);
-
- if ((fp = fopen(DLADM_DB, "r")) == NULL) {
- i_dladm_unlock_db(lock_fd);
- return;
- }
-
- while (fgets(line, MAXLINELEN, fp) != NULL) {
- /* skip comments */
- if (BLANK_LINE(line))
- continue;
-
- if (i_dladm_db_decode(line, dl_name, &da) < 0)
- continue;
-
- if (name != NULL && strcmp(name, dl_name) != 0)
- continue;
-
- fn(arg, dl_name, &da);
- }
-
- (void) fclose(fp);
- i_dladm_unlock_db(lock_fd);
-}
-
-/*
- * For each datalink in the configuration repository, invoke the
- * specified callback.
- */
-void
-dladm_db_walk(void (*fn)(void *, const char *, dladm_attr_t *),
- void *arg)
-{
- i_dladm_db_walk(fn, NULL, arg);
-}
-
/*
* Issue an ioctl to the specified file descriptor attached to the
* DLD control driver interface.
*/
static int
-i_dladm_ioctl(int fd, char *ic_dp, int ic_cmd, int ic_len)
+i_dladm_ioctl(int fd, int ic_cmd, void *ic_dp, int ic_len)
{
struct strioctl iocb;
iocb.ic_cmd = ic_cmd;
iocb.ic_timout = 0;
iocb.ic_len = ic_len;
- iocb.ic_dp = ic_dp;
+ iocb.ic_dp = (char *)ic_dp;
return (ioctl(fd, I_STR, &iocb));
}
/*
- * Issue a DLDIOCCREATE ioctl command.
- */
-static int
-i_dladm_create(int fd, const char *name, dladm_attr_t *dap)
-{
- dld_ioc_create_t dic;
-
- if (strlen(name) >= IFNAMSIZ) {
- errno = EINVAL;
- return (-1);
- }
-
- (void) strlcpy(dic.dic_name, name, IFNAMSIZ);
- (void) strlcpy(dic.dic_dev, dap->da_dev, MAXNAMELEN);
- dic.dic_port = dap->da_port;
- dic.dic_vid = dap->da_vid;
-
- return (i_dladm_ioctl(fd, (char *)&dic, DLDIOCCREATE, sizeof (dic)));
-}
-
-/*
- * Datalink bringup callback. Brings up the specified datalink.
- */
-static void
-i_dladm_up(void *arg, const char *name, dladm_attr_t *dap)
-{
- i_dladm_walk_t *wp = arg;
-
- wp->found = B_TRUE;
- (void) i_dladm_create(wp->fd, name, dap);
-}
-
-/*
- * Bring down the datalink of the specified name.
- */
-static int
-i_dladm_destroy(int fd, const char *name)
-{
- dld_ioc_destroy_t did;
-
- if (strlen(name) >= IFNAMSIZ) {
- errno = EINVAL;
- return (-1);
- }
-
- (void) strlcpy(did.did_name, name, IFNAMSIZ);
-
- return (i_dladm_ioctl(fd, (char *)&did, DLDIOCDESTROY, sizeof (did)));
-}
-
-/*
- * Bring down one or all currently active datalinks.
- */
-/*ARGSUSED*/
-static void
-i_dladm_down(void *arg, const char *name)
-{
- i_dladm_walk_t *wp = (i_dladm_walk_t *)arg;
-
- wp->found = B_TRUE;
-
- if (wp->name != NULL && strcmp(name, wp->name) != 0)
- return;
-
- (void) i_dladm_destroy(wp->fd, name);
-}
-
-/*
* Return the attributes of the specified datalink from the DLD driver.
*/
static int
@@ -474,10 +72,11 @@ i_dladm_info(int fd, const char *name, dladm_attr_t *dap)
(void) strlcpy(dia.dia_name, name, IFNAMSIZ);
- if (i_dladm_ioctl(fd, (char *)&dia, DLDIOCATTR, sizeof (dia)) < 0)
+ if (i_dladm_ioctl(fd, DLDIOCATTR, &dia, sizeof (dia)) < 0)
return (-1);
(void) strlcpy(dap->da_dev, dia.dia_dev, MAXNAMELEN);
+ dap->da_max_sdu = dia.dia_max_sdu;
dap->da_port = dia.dia_port;
dap->da_vid = dia.dia_vid;
@@ -581,7 +180,7 @@ dladm_walk(void (*fn)(void *, const char *), void *arg)
i_dladm_nt_net_count);
if (count == 0)
- return (0);
+ return (dladm_walk_vlan(fn, arg));
if ((array = malloc(count * sizeof (char *))) == NULL)
goto done;
@@ -610,136 +209,56 @@ dladm_walk(void (*fn)(void *, const char *), void *arg)
done:
free(array);
- return (0);
+ return (dladm_walk_vlan(fn, arg));
}
/*
- * Create the link of specified name and attributes. Adds it to the
- * configuration repository if DLADM_LINK_TEMP is not set. Errors
- * will be ignored if DLADM_LINK_FORCED is set.
+ * Invoke the specified callback function for each vlan managed by dld
*/
int
-dladm_link(const char *name, dladm_attr_t *dap, int flags,
- const char *root, dladm_diag_t *diag)
+dladm_walk_vlan(void (*fn)(void *, const char *), void *arg)
{
- int fd;
- boolean_t tempop = (flags & DLADM_LINK_TEMP);
- boolean_t forced = (flags & DLADM_LINK_FORCED);
+ int fd, bufsize, rc, i;
+ int nvlan = 512;
+ dld_ioc_vlan_t *iocp = NULL;
+ dld_vlan_info_t *dvip;
- if ((fd = open(DLD_CONTROL_DEV, O_RDWR)) < 0) {
- *diag = DLADM_DIAG_DEVICE_OPENFAIL;
+ if ((fd = open(DLD_CONTROL_DEV, O_RDWR)) < 0)
return (-1);
- }
-
- if (!tempop) {
- if (i_dladm_db_add(name, dap, root, diag) < 0 && !forced)
- goto failed;
- }
-
- if (i_dladm_create(fd, name, dap) < 0 && !forced) {
- if (errno == EINVAL) {
- *diag = DLADM_DIAG_INVALID_INTFNAME;
- }
- if (!tempop)
- (void) i_dladm_db_remove(name, root);
- goto failed;
- }
-
- (void) close(fd);
- return (0);
-failed:
- (void) close(fd);
- return (-1);
-}
+ for (;;) {
+ bufsize = sizeof (dld_ioc_vlan_t) +
+ nvlan * sizeof (dld_vlan_info_t);
-/*
- * Instantiate the datalink of specified name. Brings up all datalinks
- * if name is NULL.
- */
-int
-dladm_up(const char *name, dladm_diag_t *diag)
-{
- i_dladm_walk_t walk;
+ iocp = (dld_ioc_vlan_t *)calloc(1, bufsize);
+ if (iocp == NULL)
+ goto done;
- if ((walk.fd = open(DLD_CONTROL_DEV, O_RDWR)) < 0) {
- *diag =
- DLADM_DIAG_DEVICE_OPENFAIL;
- return (-1);
- }
+ rc = i_dladm_ioctl(fd, DLDIOCVLAN, iocp, bufsize);
+ if (rc == 0)
+ break;
- walk.found = B_FALSE;
- i_dladm_db_walk(i_dladm_up, name, (void *)&walk);
- if (name != NULL && !walk.found) {
- (void) close(walk.fd);
- errno = ENOENT;
- return (-1);
+ if (errno == ENOSPC) {
+ nvlan *= 2;
+ free(iocp);
+ continue;
+ }
+ goto done;
}
- (void) close(walk.fd);
- return (0);
-}
-
-/*
- * Deletes the link of specified name.
- */
-int
-dladm_unlink(const char *name, boolean_t tempop, const char *root,
- dladm_diag_t *diag)
-{
- int fd;
+ dvip = (dld_vlan_info_t *)(iocp + 1);
- if ((fd = open(DLD_CONTROL_DEV, O_RDWR)) < 0) {
- *diag = DLADM_DIAG_DEVICE_OPENFAIL;
- return (-1);
- }
-
- if (i_dladm_destroy(fd, name) < 0) {
- if (errno == EINVAL)
- *diag = DLADM_DIAG_INVALID_LINKNAME;
- goto failed;
+ for (i = 0; i < iocp->div_count; i++) {
+ if (dvip[i].dvi_vid != 0)
+ (*fn)(arg, dvip[i].dvi_name);
}
- if (!tempop)
- (void) i_dladm_db_remove(name, root);
+done:
+ free(iocp);
(void) close(fd);
return (0);
-
-failed:
- (void) close(fd);
- return (-1);
}
-/*
- * Brings down the datalink of specified name. Brings down all datalinks
- * if name == NULL.
- */
-int
-dladm_down(const char *name, dladm_diag_t *diag)
-{
- i_dladm_walk_t walk;
-
- if ((walk.fd = open(DLD_CONTROL_DEV, O_RDWR)) < 0) {
- *diag = DLADM_DIAG_DEVICE_OPENFAIL;
- return (-1);
- }
- walk.found = B_FALSE;
- walk.name = name;
-
- if (dladm_walk(i_dladm_down, (void *)&walk) < 0) {
- (void) close(walk.fd);
- return (-1);
- }
-
- if (name != NULL && !walk.found) {
- (void) close(walk.fd);
- errno = ENOENT;
- return (-1);
- }
-
- (void) close(walk.fd);
- return (0);
-}
/*
* Returns the current attributes of the specified datalink.
@@ -762,43 +281,3 @@ failed:
(void) close(fd);
return (-1);
}
-
-/*
- * Causes the nodes corresponding to created or deleted datalinks to
- * be created or deleted.
- */
-int
-dladm_sync(void)
-{
- di_devlink_handle_t hdl;
-
- if ((hdl = di_devlink_init(DLD_DRIVER_NAME, DI_MAKE_LINK)) == NULL)
- return (-1);
-
- if (di_devlink_fini(&hdl) < 0)
- return (-1);
-
- return (0);
-}
-
-const char *
-dladm_diag(dladm_diag_t diag) {
- switch (diag) {
- case DLADM_DIAG_INVALID_LINKNAME:
- return (gettext("invalid datalink name"));
- case DLADM_DIAG_INVALID_INTFNAME:
- return (gettext("invalid interface name"));
- case DLADM_DIAG_CORRUPT_REPOSITORY:
- return (gettext("configuration repository corrupt"));
- case DLADM_DIAG_REPOSITORY_OPENFAIL:
- return (gettext("configuration repository open failed"));
- case DLADM_DIAG_REPOSITORY_WRITEFAIL:
- return (gettext("write to configuration repository failed"));
- case DLADM_DIAG_REPOSITORY_CLOSEFAIL:
- return (gettext("configuration repository close failed"));
- case DLADM_DIAG_DEVICE_OPENFAIL:
- return (gettext("dld device open fail"));
- default:
- return (gettext("unknown diagnostic"));
- }
-}
diff --git a/usr/src/lib/libdladm/common/libdladm.h b/usr/src/lib/libdladm/common/libdladm.h
index 32c1a08736..8ae84bc51b 100644
--- a/usr/src/lib/libdladm/common/libdladm.h
+++ b/usr/src/lib/libdladm/common/libdladm.h
@@ -41,44 +41,14 @@ typedef struct dladm_attr dladm_attr_t;
struct dladm_attr {
char da_dev[MAXNAMELEN];
+ uint_t da_max_sdu;
uint_t da_port;
uint16_t da_vid;
};
-/* number of attributes per devices in database file */
-#define DLADM_NATTR 3
-
-/*
- * Diagnostic codes. These supplement error messages.
- */
-typedef enum {
- DLADM_DIAG_INVALID_LINKNAME = 1,
- DLADM_DIAG_INVALID_INTFNAME = 2,
- DLADM_DIAG_CORRUPT_REPOSITORY = 3,
- DLADM_DIAG_REPOSITORY_OPENFAIL = 4,
- DLADM_DIAG_REPOSITORY_WRITEFAIL = 5,
- DLADM_DIAG_REPOSITORY_CLOSEFAIL = 6,
- DLADM_DIAG_DEVICE_OPENFAIL = 7
-} dladm_diag_t;
-
-/*
- * Flags recognized by dladm_link()
- */
-#define DLADM_LINK_TEMP 0x01
-#define DLADM_LINK_FORCED 0x02
-
-extern int dladm_link(const char *, dladm_attr_t *,
- int, const char *, dladm_diag_t *);
-extern int dladm_up(const char *, dladm_diag_t *);
-extern int dladm_unlink(const char *, boolean_t, const char *,
- dladm_diag_t *);
-extern int dladm_down(const char *, dladm_diag_t *);
extern int dladm_walk(void (*)(void *, const char *), void *);
+extern int dladm_walk_vlan(void (*)(void *, const char *), void *);
extern int dladm_info(const char *, dladm_attr_t *);
-extern void dladm_db_walk(void (*)(void *, const char *,
- dladm_attr_t *), void *);
-extern int dladm_sync(void);
-extern const char *dladm_diag(dladm_diag_t);
#ifdef __cplusplus
}
diff --git a/usr/src/lib/libdladm/spec/dladm.spec b/usr/src/lib/libdladm/spec/dladm.spec
index 3bb89fb4a7..6aca5746ee 100644
--- a/usr/src/lib/libdladm/spec/dladm.spec
+++ b/usr/src/lib/libdladm/spec/dladm.spec
@@ -25,32 +25,6 @@
#pragma ident "%Z%%M% %I% %E% SMI"
#
-function dladm_link
-include <libdladm.h>
-declaration int dladm_link(const char *, dladm_attr_t *, \
- int, const char *, dladm_diag_t *)
-version SUNWprivate_1.1
-end
-
-function dladm_up
-include <libdladm.h>
-declaration int dladm_up(const char *, dladm_diag_t *)
-version SUNWprivate_1.1
-end
-
-function dladm_unlink
-include <libdladm.h>
-declaration int dladm_unlink(const char *, boolean_t, const char *, \
- dladm_diag_t *)
-version SUNWprivate_1.1
-end
-
-function dladm_down
-include <libdladm.h>
-declaration int dladm_down(const char *, dladm_diag_t *)
-version SUNWprivate_1.1
-end
-
function dladm_walk
include <libdladm.h>
declaration int dladm_walk(void (*fn)(void *, const char *), \
@@ -58,27 +32,15 @@ declaration int dladm_walk(void (*fn)(void *, const char *), \
version SUNWprivate_1.1
end
-function dladm_info
-include <libdladm.h>
-declaration int dladm_info(const char *, dladm_attr_t *)
-version SUNWprivate_1.1
-end
-
-function dladm_db_walk
+function dladm_walk_vlan
include <libdladm.h>
-declaration int dladm_db_walk(void (*)(void *, const char *,
- dladm_attr_t *), void *)
-version SUNWprivate_1.1
-end
-
-function dladm_sync
-include <libdladm.h>
-declaration void dladm_sync(void)
+declaration int dladm_walk_vlan(void (*fn)(void *, const char *), \
+ void *)
version SUNWprivate_1.1
end
-function dladm_diag
+function dladm_info
include <libdladm.h>
-declaration const char * dladm_diag(dladm_diag_t)
+declaration int dladm_info(const char *, dladm_attr_t *)
version SUNWprivate_1.1
end
diff --git a/usr/src/lib/libdlpi/common/libdlpi.c b/usr/src/lib/libdlpi/common/libdlpi.c
index 2ae1ccc349..59d213fffc 100644
--- a/usr/src/lib/libdlpi/common/libdlpi.c
+++ b/usr/src/lib/libdlpi/common/libdlpi.c
@@ -178,12 +178,6 @@ dlpi_open(const char *provider)
if ((fd = open(devname, O_RDWR)) != -1)
return (fd);
- (void) snprintf(devname, MAXPATHLEN, "/devices/pseudo/dld@0:%s",
- provider);
-
- if ((fd = open(devname, O_RDWR)) != -1)
- return (fd);
-
(void) snprintf(path, MAXPATHLEN, "/devices/pseudo/clone@0:%s",
provider);
diff --git a/usr/src/lib/liblaadm/common/liblaadm.c b/usr/src/lib/liblaadm/common/liblaadm.c
index 4eafc61f7c..6add61fcb8 100644
--- a/usr/src/lib/liblaadm/common/liblaadm.c
+++ b/usr/src/lib/liblaadm/common/liblaadm.c
@@ -185,6 +185,18 @@ typedef struct add_db_state {
static int i_laadm_fput_grp(FILE *, laadm_grp_attr_db_t *);
+static int
+i_laadm_strioctl(int fd, int cmd, void *ptr, int ilen)
+{
+ struct strioctl str;
+
+ str.ic_cmd = cmd;
+ str.ic_timout = 0;
+ str.ic_len = ilen;
+ str.ic_dp = ptr;
+
+ return (ioctl(fd, I_STR, &str));
+}
/*
* Open and lock the aggregation configuration file lock. The lock is
@@ -261,8 +273,7 @@ laadm_walk_sys(int (*fn)(void *, laadm_grp_attr_sys_t *), void *arg)
}
tryagain:
- ioc->li_bufsize = bufsize;
- rc = ioctl(fd, LAIOC_INFO, ioc);
+ rc = i_laadm_strioctl(fd, LAIOC_INFO, ioc, bufsize);
if (rc != 0) {
if (errno == ENOSPC) {
@@ -501,19 +512,18 @@ failed:
static int
i_laadm_add_rem_sys(laadm_grp_attr_db_t *attr, int cmd, laadm_diag_t *diag)
{
- int i, rc, fd;
- laioc_add_t ioc;
+ int i, rc, fd, len;
+ laioc_add_rem_t *iocp;
laioc_port_t *ports;
- ioc.la_key = attr->lt_key;
- ioc.la_nports = attr->lt_nports;
-
- ioc.la_ports = malloc(attr->lt_nports * sizeof (laioc_port_t));
- if (ioc.la_ports == NULL)
+ len = sizeof (*iocp) + attr->lt_nports * sizeof (laioc_port_t);
+ iocp = malloc(len);
+ if (iocp == NULL)
goto failed;
- /* LINTED E_BAD_PTR_CAST_ALIGN */
- ports = (laioc_port_t *)ioc.la_ports;
+ iocp->la_key = attr->lt_key;
+ iocp->la_nports = attr->lt_nports;
+ ports = (laioc_port_t *)(iocp + 1);
for (i = 0; i < attr->lt_nports; i++) {
if (strlcpy(ports[i].lp_devname,
@@ -528,17 +538,17 @@ i_laadm_add_rem_sys(laadm_grp_attr_db_t *attr, int cmd, laadm_diag_t *diag)
goto failed;
}
- rc = ioctl(fd, cmd, &ioc);
+ rc = i_laadm_strioctl(fd, cmd, iocp, len);
if ((rc < 0) && (errno == EINVAL))
*diag = LAADM_DIAG_INVALID_INTFNAME;
(void) close(fd);
- free(ioc.la_ports);
+ free(iocp);
return (rc);
failed:
- free(ioc.la_ports);
+ free(iocp);
return (-1);
}
@@ -575,7 +585,7 @@ i_laadm_modify_sys(uint32_t key, uint32_t mask, laadm_modify_attr_t *attr,
return (-1);
}
- rc = ioctl(fd, LAIOC_MODIFY, &ioc);
+ rc = i_laadm_strioctl(fd, LAIOC_MODIFY, &ioc, sizeof (ioc));
if ((rc < 0) && (errno == EINVAL))
*diag = LAADM_DIAG_INVALID_MACADDR;
@@ -590,28 +600,29 @@ i_laadm_modify_sys(uint32_t key, uint32_t mask, laadm_modify_attr_t *attr,
static int
i_laadm_create_sys(int fd, laadm_grp_attr_db_t *attr, laadm_diag_t *diag)
{
- int i, rc;
- laioc_create_t ioc;
+ int i, rc, len;
+ laioc_create_t *iocp;
laioc_port_t *ports;
- ioc.lc_key = attr->lt_key;
- ioc.lc_nports = attr->lt_nports;
- ioc.lc_policy = attr->lt_policy;
- ioc.lc_lacp_mode = attr->lt_lacp_mode;
- ioc.lc_lacp_timer = attr->lt_lacp_timer;
-
- ioc.lc_ports = malloc(attr->lt_nports * sizeof (laioc_port_t));
- if (ioc.lc_ports == NULL)
+ len = sizeof (*iocp) + attr->lt_nports * sizeof (laioc_port_t);
+ iocp = malloc(len);
+ if (iocp == NULL)
return (-1);
- /* LINTED E_BAD_PTR_CAST_ALIGN */
- ports = (laioc_port_t *)ioc.lc_ports;
+ iocp->lc_key = attr->lt_key;
+ iocp->lc_nports = attr->lt_nports;
+ iocp->lc_policy = attr->lt_policy;
+ iocp->lc_lacp_mode = attr->lt_lacp_mode;
+ iocp->lc_lacp_timer = attr->lt_lacp_timer;
+
+ ports = (laioc_port_t *)(iocp + 1);
for (i = 0; i < attr->lt_nports; i++) {
if (strlcpy(ports[i].lp_devname,
attr->lt_ports[i].lp_devname,
MAXNAMELEN) >= MAXNAMELEN) {
- free(ioc.lc_ports);
+ errno = EINVAL;
+ free(iocp);
return (-1);
}
ports[i].lp_port = attr->lt_ports[i].lp_port;
@@ -622,18 +633,18 @@ i_laadm_create_sys(int fd, laadm_grp_attr_db_t *attr, laadm_diag_t *diag)
(attr->lt_mac[0] & 0x01))) {
errno = EINVAL;
*diag = LAADM_DIAG_INVALID_MACADDR;
- free(ioc.lc_ports);
+ free(iocp);
return (-1);
}
- bcopy(attr->lt_mac, ioc.lc_mac, ETHERADDRL);
- ioc.lc_mac_fixed = attr->lt_mac_fixed;
+ bcopy(attr->lt_mac, iocp->lc_mac, ETHERADDRL);
+ iocp->lc_mac_fixed = attr->lt_mac_fixed;
- rc = ioctl(fd, LAIOC_CREATE, &ioc);
+ rc = i_laadm_strioctl(fd, LAIOC_CREATE, iocp, len);
if (rc < 0)
*diag = LAADM_DIAG_INVALID_INTFNAME;
- free(ioc.lc_ports);
+ free(iocp);
return (rc);
}
@@ -700,7 +711,7 @@ i_laadm_delete_sys(int fd, laadm_grp_attr_sys_t *attr)
ioc.ld_key = attr->lg_key;
- return (ioctl(fd, LAIOC_DELETE, &ioc));
+ return (i_laadm_strioctl(fd, LAIOC_DELETE, &ioc, sizeof (ioc)));
}
/*
@@ -1486,9 +1497,17 @@ laadm_create(uint32_t key, uint32_t nports, laadm_port_attr_db_t *ports,
return (-1);
} else {
laadm_up_t up;
+ int rc;
+
up.lu_key = key;
up.lu_found = B_FALSE;
- return (i_laadm_up((void *)&up, &attr, diag));
+ up.lu_fd = open(LAADM_DEV, O_RDWR);
+ if (up.lu_fd < 0)
+ return (-1);
+
+ rc = i_laadm_up((void *)&up, &attr, diag);
+ (void) close(up.lu_fd);
+ return (rc);
}
/* bring up the link aggregation group */
diff --git a/usr/src/lib/libmacadm/Makefile.com b/usr/src/lib/libmacadm/Makefile.com
index 95e9cf09f4..b3d7635878 100644
--- a/usr/src/lib/libmacadm/Makefile.com
+++ b/usr/src/lib/libmacadm/Makefile.com
@@ -37,7 +37,7 @@ include ../../Makefile.rootfs
LIBS = $(DYNLIB) $(LINTLIB)
-LDLIBS += -ldevinfo -lc
+LDLIBS += -ldevinfo -ldladm -ldlpi -lc
$(LINTLIB) := SRCS = $(SRCDIR)/$(LINTSRC)
SRCDIR = ../common
diff --git a/usr/src/lib/libmacadm/common/libmacadm.c b/usr/src/lib/libmacadm/common/libmacadm.c
index 2dd66131aa..053d1c5011 100644
--- a/usr/src/lib/libmacadm/common/libmacadm.c
+++ b/usr/src/lib/libmacadm/common/libmacadm.c
@@ -33,6 +33,8 @@
#include <stropts.h>
#include <sys/dld.h>
#include <libdevinfo.h>
+#include <libdladm.h>
+#include <libdlpi.h>
#define _KERNEL
#include <sys/sysmacros.h>
@@ -48,24 +50,39 @@
typedef struct macadm_walk {
void *mw_arg;
- void (*mw_fn)(void *, const char *, uint_t);
+ void (*mw_fn)(void *, const char *);
} macadm_walk_t;
/*
- * Local callback invoked for each DDI_NT_MAC node.
+ * Local callback invoked for each DDI_NT_NET node.
*/
+/* ARGSUSED */
static int
i_macadm_apply(di_node_t node, di_minor_t minor, void *arg)
{
macadm_walk_t *mwp = arg;
char dev[MAXNAMELEN];
- uint_t port;
+ dladm_attr_t dlattr;
+ int fd;
(void) snprintf(dev, MAXNAMELEN, "%s%d",
di_driver_name(node), di_instance(node));
- port = getminor(di_minor_devt(minor));
- mwp->mw_fn(mwp->mw_arg, dev, port);
+ /*
+ * We need to be able to report devices that are
+ * reported by the walker, but have not yet attached
+ * to the system. Attempting to opening them will
+ * cause them to temporarely attach and be known
+ * by dld.
+ */
+ if ((fd = dlpi_open(dev)) == -1 && errno != EPERM)
+ return (DI_WALK_CONTINUE);
+ if (fd != 0)
+ (void) dlpi_close(fd);
+
+ /* invoke callback only for non-legacy devices */
+ if (dladm_info(dev, &dlattr) == 0)
+ mwp->mw_fn(mwp->mw_arg, dev);
return (DI_WALK_CONTINUE);
}
@@ -74,7 +91,7 @@ i_macadm_apply(di_node_t node, di_minor_t minor, void *arg)
* Invoke the specified callback for each DDI_NT_MAC node.
*/
int
-macadm_walk(void (*fn)(void *, const char *, uint_t), void *arg,
+macadm_walk(void (*fn)(void *, const char *), void *arg,
boolean_t use_cache)
{
di_node_t root;
@@ -94,7 +111,7 @@ macadm_walk(void (*fn)(void *, const char *, uint_t), void *arg,
mw.mw_fn = fn;
mw.mw_arg = arg;
- (void) di_walk_minor(root, DDI_NT_MAC, 0, &mw, i_macadm_apply);
+ (void) di_walk_minor(root, DDI_NT_NET, 0, &mw, i_macadm_apply);
di_fini(root);
return (0);
diff --git a/usr/src/lib/libmacadm/common/libmacadm.h b/usr/src/lib/libmacadm/common/libmacadm.h
index a5ae05ef7c..2f21b53d55 100644
--- a/usr/src/lib/libmacadm/common/libmacadm.h
+++ b/usr/src/lib/libmacadm/common/libmacadm.h
@@ -36,7 +36,7 @@
extern "C" {
#endif
-extern int macadm_walk(void (*)(void *, const char *, uint_t),
+extern int macadm_walk(void (*)(void *, const char *),
void *, boolean_t);
#ifdef __cplusplus
diff --git a/usr/src/lib/libmacadm/spec/macadm.spec b/usr/src/lib/libmacadm/spec/macadm.spec
index 5bab70293a..32cbe46145 100644
--- a/usr/src/lib/libmacadm/spec/macadm.spec
+++ b/usr/src/lib/libmacadm/spec/macadm.spec
@@ -28,7 +28,7 @@
function macadm_walk
include <libmacadm.h>
declaration int macadm_walk( \
- void (*fn)(void *, const char *, uint_t), \
+ void (*fn)(void *, const char *), \
void *, boolean_t);
version SUNWprivate_1.1
end
diff --git a/usr/src/pkgdefs/SUNWckr/prototype_i386 b/usr/src/pkgdefs/SUNWckr/prototype_i386
index bb47ae02e6..a7041ad90e 100644
--- a/usr/src/pkgdefs/SUNWckr/prototype_i386
+++ b/usr/src/pkgdefs/SUNWckr/prototype_i386
@@ -149,7 +149,6 @@ f none kernel/misc/ctf 755 root sys
l none kernel/misc/des=../../kernel/crypto/des
f none kernel/misc/dls 755 root sys
f none kernel/misc/fssnap_if 755 root sys
-f none kernel/misc/ght 755 root sys
f none kernel/misc/gld 755 root sys
f none kernel/misc/hpcsvc 755 root sys
f none kernel/misc/i2o_msg 755 root sys
@@ -314,7 +313,6 @@ f none kernel/misc/amd64/ctf 755 root sys
l none kernel/misc/amd64/des=../../../kernel/crypto/amd64/des
f none kernel/misc/amd64/dls 755 root sys
f none kernel/misc/amd64/fssnap_if 755 root sys
-f none kernel/misc/amd64/ght 755 root sys
f none kernel/misc/amd64/gld 755 root sys
f none kernel/misc/amd64/hpcsvc 755 root sys
f none kernel/misc/amd64/ipc 755 root sys
diff --git a/usr/src/pkgdefs/SUNWckr/prototype_sparc b/usr/src/pkgdefs/SUNWckr/prototype_sparc
index 71ae7c662f..957f64a0b8 100644
--- a/usr/src/pkgdefs/SUNWckr/prototype_sparc
+++ b/usr/src/pkgdefs/SUNWckr/prototype_sparc
@@ -154,7 +154,6 @@ f none kernel/misc/sparcv9/dada 755 root sys
l none kernel/misc/sparcv9/des=../../../kernel/crypto/sparcv9/des
f none kernel/misc/sparcv9/dls 755 root sys
f none kernel/misc/sparcv9/fssnap_if 755 root sys
-f none kernel/misc/sparcv9/ght 755 root sys
f none kernel/misc/sparcv9/gld 755 root sys
f none kernel/misc/sparcv9/hpcsvc 755 root sys
f none kernel/misc/sparcv9/ipc 755 root sys
diff --git a/usr/src/pkgdefs/SUNWcnetr/Makefile b/usr/src/pkgdefs/SUNWcnetr/Makefile
index c8a4f49fbf..99b31cc824 100644
--- a/usr/src/pkgdefs/SUNWcnetr/Makefile
+++ b/usr/src/pkgdefs/SUNWcnetr/Makefile
@@ -28,11 +28,11 @@
include ../Makefile.com
-DATAFILES += i.ipsecalgsbase i.preserve i.sock2path i.datalinkconf
+DATAFILES += i.ipsecalgsbase i.preserve i.sock2path
.KEEP_STATE:
-all: $(FILES) postinstall
+all: $(FILES)
install: all pkg
diff --git a/usr/src/pkgdefs/SUNWcnetr/pkginfo.tmpl b/usr/src/pkgdefs/SUNWcnetr/pkginfo.tmpl
index 5b1bf64231..ee6f722581 100644
--- a/usr/src/pkgdefs/SUNWcnetr/pkginfo.tmpl
+++ b/usr/src/pkgdefs/SUNWcnetr/pkginfo.tmpl
@@ -41,7 +41,7 @@ DESC="core software for network infrastructure configuration"
VENDOR="Sun Microsystems, Inc."
HOTLINE="Please contact your local service provider"
EMAIL=""
-CLASSES="none ipsecalgsbase preserve sock2path datalinkconf"
+CLASSES="none ipsecalgsbase preserve sock2path"
BASEDIR=/
SUNW_PKGVERS="1.0"
SUNW_PKG_ALLZONES="true"
diff --git a/usr/src/pkgdefs/SUNWcnetr/postinstall b/usr/src/pkgdefs/SUNWcnetr/postinstall
deleted file mode 100644
index 9473d07cd6..0000000000
--- a/usr/src/pkgdefs/SUNWcnetr/postinstall
+++ /dev/null
@@ -1,46 +0,0 @@
-#
-# 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.
-#
-# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
-# See the License for the specific language governing permissions
-# and limitations under the License.
-#
-# When distributing Covered Code, include this CDDL HEADER in each
-# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
-# If applicable, add the following below this CDDL HEADER, with the
-# fields enclosed by brackets "[]" replaced with your own identifying
-# information: Portions Copyright [yyyy] [name of copyright owner]
-#
-# CDDL HEADER END
-#
-#
-# Copyright 2005 Sun Microsystems, Inc. All rights reserved.
-# Use is subject to license terms.
-#
-#ident "%Z%%M% %I% %E% SMI"
-#
-
-if [ ! -r $PKG_INSTALL_ROOT/etc/svc/volatile/repository_door ]; then
- #
- # smf(5) is not presently running for the destination environment.
- # Which means we're likely in an upgrade situation and need
- # to add a svcadm clear for the network/physical service since
- # it is likely to go into maintenance on first reboot due to
- # the network/datalink service
- #
-
- UPGRADE=$BASEDIR/var/svc/profile/upgrade
-
-cat >> $UPGRADE <<-EOF
-
-svcadm clear svc:/network/physical:default
-
-EOF
-
-fi
diff --git a/usr/src/pkgdefs/SUNWcnetr/prototype_com b/usr/src/pkgdefs/SUNWcnetr/prototype_com
index 9456e9678a..636fadd79e 100644
--- a/usr/src/pkgdefs/SUNWcnetr/prototype_com
+++ b/usr/src/pkgdefs/SUNWcnetr/prototype_com
@@ -39,11 +39,9 @@
# packaging files
i pkginfo
i copyright
-i postinstall
i i.ipsecalgsbase
i i.preserve
i i.sock2path
-i i.datalinkconf
#
# source locations relative to the prototype file
#
@@ -51,7 +49,6 @@ i i.datalinkconf
#
d none etc 755 root sys
e preserve etc/aggregation.conf 644 root sys
-e datalinkconf etc/datalink.conf 644 root sys
d none etc/default 755 root sys
e preserve etc/default/dhcpagent 644 root sys
e preserve etc/default/inetinit 644 root sys
diff --git a/usr/src/pkgdefs/SUNWcsr/postinstall b/usr/src/pkgdefs/SUNWcsr/postinstall
index 225d1819eb..9ff3d11ad5 100644
--- a/usr/src/pkgdefs/SUNWcsr/postinstall
+++ b/usr/src/pkgdefs/SUNWcsr/postinstall
@@ -101,6 +101,32 @@ cat >> $BASEDIR/var/svc/profile/upgrade <<\_DEL_BIND8
_DEL_BIND8
#
+# Remove stale GLD services
+#
+SVCCFG_REPOSITORY=$PKG_INSTALL_ROOT/etc/svc/repository.db
+export SVCCFG_REPOSITORY
+if [ ! -r $PKG_INSTALL_ROOT/etc/svc/volatile/repository_door ]; then
+ #
+ # smf(5) is not presently running for the destination environment.
+ # It is safe to remove the manifests from the repository.
+ #
+ svccfg delete svc:/network/aggregation
+ svccfg delete svc:/network/datalink-init
+ svccfg delete svc:/network/datalink
+else
+ #
+ # Local package install. Need to disable the services first
+ # before deleting.
+ #
+ svcadm disable -s svc:/network/aggregation
+ svccfg delete svc:/network/aggregation
+ svcadm disable -s svc:/network/datalink-init
+ svccfg delete svc:/network/datalink-init
+ svcadm disable -s svc:/network/datalink
+ svccfg delete svc:/network/datalink
+fi
+
+#
# svc:/network/rpc/keyserv is expected to be off on systems that don't
# set domainname. On systems that do define a default domain, leave the
# setting as previously set.
diff --git a/usr/src/pkgdefs/SUNWcsr/prototype_com b/usr/src/pkgdefs/SUNWcsr/prototype_com
index 77a82a5a41..154aef85a3 100644
--- a/usr/src/pkgdefs/SUNWcsr/prototype_com
+++ b/usr/src/pkgdefs/SUNWcsr/prototype_com
@@ -328,11 +328,8 @@ f none lib/svc/bin/svc.configd 0555 root sys
f none lib/svc/bin/svc.startd 0555 root sys
d none lib/svc/capture 0755 root bin
d none lib/svc/method 0755 root bin
-f none lib/svc/method/aggregation 0555 root bin
f none lib/svc/method/boot-archive 0555 root bin
f none lib/svc/method/console-login 0555 root bin
-f none lib/svc/method/datalink 0555 root bin
-f none lib/svc/method/datalink-init 0555 root bin
f none lib/svc/method/devices-local 0555 root bin
f none lib/svc/method/fs-local 0555 root bin
f none lib/svc/method/fs-minimal 0555 root bin
@@ -463,9 +460,6 @@ f manifest var/svc/manifest/milestone/network.xml 0444 root sys
f manifest var/svc/manifest/milestone/single-user.xml 0444 root sys
f manifest var/svc/manifest/milestone/sysconfig.xml 0444 root sys
d none var/svc/manifest/network 755 root sys
-f manifest var/svc/manifest/network/aggregation.xml 0444 root sys
-f manifest var/svc/manifest/network/datalink.xml 0444 root sys
-f manifest var/svc/manifest/network/datalink-init.xml 0444 root sys
f manifest var/svc/manifest/network/inetd.xml 0444 root sys
f manifest var/svc/manifest/network/inetd-upgrade.xml 0444 root sys
f manifest var/svc/manifest/network/network-initial.xml 0444 root sys
diff --git a/usr/src/pkgdefs/SUNWcsu/prototype_com b/usr/src/pkgdefs/SUNWcsu/prototype_com
index 45475ebf21..1e7210d9a3 100644
--- a/usr/src/pkgdefs/SUNWcsu/prototype_com
+++ b/usr/src/pkgdefs/SUNWcsu/prototype_com
@@ -577,7 +577,6 @@ f none usr/lib/rcm/modules/SUNW_network_rcm.so 555 root bin
f none usr/lib/rcm/modules/SUNW_swap_rcm.so 555 root bin
f none usr/lib/rcm/modules/SUNW_cluster_rcm.so 555 root bin
f none usr/lib/rcm/modules/SUNW_ip_anon_rcm.so 555 root bin
-f none usr/lib/rcm/modules/SUNW_mac_rcm.so 555 root bin
f none usr/lib/rcm/modules/SUNW_mpxio_rcm.so 555 root bin
f none usr/lib/rcm/rcm_daemon 555 root bin
d none usr/lib/rcm/scripts 755 root bin
diff --git a/usr/src/pkgdefs/SUNWhea/prototype_com b/usr/src/pkgdefs/SUNWhea/prototype_com
index b29958df97..afc3165640 100644
--- a/usr/src/pkgdefs/SUNWhea/prototype_com
+++ b/usr/src/pkgdefs/SUNWhea/prototype_com
@@ -657,7 +657,6 @@ f none usr/include/sys/fss.h 644 root bin
f none usr/include/sys/fsspriocntl.h 644 root bin
f none usr/include/sys/fx.h 644 root bin
f none usr/include/sys/fxpriocntl.h 644 root bin
-f none usr/include/sys/ght.h 644 root bin
f none usr/include/sys/gld.h 644 root bin
f none usr/include/sys/gldpriv.h 644 root bin
d none usr/include/sys/hotplug 755 root bin
diff --git a/usr/src/pkgdefs/common_files/i.datalinkconf b/usr/src/pkgdefs/common_files/i.datalinkconf
deleted file mode 100644
index ff9e170279..0000000000
--- a/usr/src/pkgdefs/common_files/i.datalinkconf
+++ /dev/null
@@ -1,69 +0,0 @@
-#!/bin/sh
-#
-# 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.
-#
-# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
-# See the License for the specific language governing permissions
-# and limitations under the License.
-#
-# When distributing Covered Code, include this CDDL HEADER in each
-# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
-# If applicable, add the following below this CDDL HEADER, with the
-# fields enclosed by brackets "[]" replaced with your own identifying
-# information: Portions Copyright [yyyy] [name of copyright owner]
-#
-# CDDL HEADER END
-#
-#
-# Copyright 2005 Sun Microsystems, Inc. All rights reserved.
-# Use is subject to license terms.
-#
-# ident "%Z%%M% %I% %E% SMI"
-
-while read src dest
-do
- if [ ! -f $dest ] ; then
- cp $src $dest
- fi
-
- drivers="bge xge"
- conf=$dest
-
- ls -1 $PKG_INSTALL_ROOT/etc | \
- egrep -e '^hostname.|^hostname6.|^dhcp.' | \
- cut -d . -f2 | sort -u > /tmp/ifnames.$$
-
- for driver in $drivers
- do
- grep $driver /tmp/ifnames.$$ | \
- while read ifname
- do
- devnum=`echo $ifname | sed "s/$driver//g`
- if [ "$driver$devnum" != $ifname -o \
- -n "`echo $devnum | tr -d '[0-9]'`" ]; then
- echo "skipping invalid interface $ifname"
- continue
- fi
-
- vid=`expr $devnum / 1000`
- inst=`expr $devnum % 1000`
-
- awk '{ print $1 }' $conf | grep $ifname > /dev/null
- if [ $? -ne 0 ]; then
- # An entry for that interface does not exist
- printf \
- "$ifname\t$driver$inst\t0\t$vid\n" \
- >> $conf
- fi
- done
- done
-
- rm -f /tmp/ifnames.$$
-done
-exit 0
diff --git a/usr/src/tools/scripts/bfu.sh b/usr/src/tools/scripts/bfu.sh
index f845949a50..227b8acc42 100644
--- a/usr/src/tools/scripts/bfu.sh
+++ b/usr/src/tools/scripts/bfu.sh
@@ -84,7 +84,6 @@ all_zones_files="
etc/cron.d/at.deny
etc/cron.d/cron.deny
etc/crypto/pkcs11.conf
- etc/datalink.conf
etc/default/*
etc/dfs/dfstab
etc/dumpdates
@@ -318,9 +317,6 @@ superfluous_local_zone_files="
var/adm/pool
var/fm
var/log/pool
- var/svc/manifest/network/aggregation.xml
- var/svc/manifest/network/datalink-init.xml
- var/svc/manifest/network/datalink.xml
var/svc/manifest/network/ipfilter.xml
var/svc/manifest/network/pfil.xml
var/svc/manifest/platform
@@ -432,15 +428,6 @@ smf_inetd_conversions="
walld
"
-enable_next_boot () {
- if [ -x /tmp/bfubin/svccfg ]; then
- svcadm disable -t $1
- [ $? = 0 ] || echo "warning: unable to temporarily disable $1"
- svccfg -s $1 setprop general/enabled = true
- [ $? = 0 ] || echo "warning: unable to enable $1 for next boot"
- fi
-}
-
smf_inetd_disable() {
inetconf=$rootprefix/etc/inet/inetd.conf
inettmp=/tmp/inetd.tmp.$$
@@ -986,6 +973,9 @@ smf_obsolete_rc_files="
smf_obsolete_manifests="
var/svc/manifest/network/tftp.xml
var/svc/manifest/network/lp.xml
+ var/svc/manifest/network/aggregation.xml
+ var/svc/manifest/network/datalink.xml
+ var/svc/manifest/network/datalink-init.xml
"
# smf services whose manifests have been renamed
@@ -997,6 +987,9 @@ smf_renamed_manifests="
# Obsolete smf methods
smf_obsolete_methods="
lib/svc/method/print-server
+ lib/svc/method/aggregation
+ lib/svc/method/datalink
+ lib/svc/method/datalink-init
"
smf_cleanup () {
@@ -1628,52 +1621,6 @@ EOFA
EOF
fi
- # If we're in the global zone, and using an alternate root, see if
- # we are in an smf root. If so, import datalink and aggregation svcs.
- # If we're not bfu'ing an alternate root, and we're post-smf,
- # import datalink and aggregation. This is to get them
- # in the repository before reboot. If we're bfu'ing from pre-smf,
- # this isn't an issue, as they are in the seed repository.
- if [[ $zone = global &&
- -f $rootprefix/var/svc/manifest/network/datalink.xml ]]; then
- if [[ -n $rootprefix ]]; then
- if [ -x /usr/sbin/svccfg ]; then
- SVCCFG_REPOSITORY=$rootprefix/etc/svc/repository.db
- sed -e "s/enabled='true'/enabled='false'/" \
- $rootprefix/var/svc/manifest/network/aggregation.xml \
- | svccfg import -
- sed -e "s/enabled='true'/enabled='false'/" \
- $rootprefix/var/svc/manifest/network/datalink.xml \
- | svccfg import -
- sed -e "s/enabled='true'/enabled='false'/" \
- $rootprefix/var/svc/manifest/network/datalink-init.xml \
- | svccfg import -
- else
- echo "Warning: This system does not have SMF, so I"
- echo "cannot ensure the pre-import of datalink and"
- echo "network aggregation. If they do not work"
- echo "reboot your alternate root to fix it."
- fi
- elif [ -x /tmp/bfubin/svccfg ]; then
- sed -e "s/enabled='true'/enabled='false'/" \
- /var/svc/manifest/network/aggregation.xml | \
- svccfg import -
- sed -e "s/enabled='true'/enabled='false'/" \
- /var/svc/manifest/network/datalink.xml | \
- svccfg import -
- sed -e "s/enabled='true'/enabled='false'/" \
- /var/svc/manifest/network/datalink-init.xml | \
- svccfg import -
- fi
-
- #
- # Make sure the services are enabled after reboot.
- #
- enable_next_boot svc:/network/aggregation:default
- enable_next_boot svc:/network/datalink:default
- enable_next_boot svc:/network/datalink-init:default
- fi
-
# Enable new NFS status and nlockmgr services if client is enabled
cat >> $rootprefix/var/svc/profile/upgrade <<-EOF
cl="svc:/network/nfs/client:default"
@@ -2320,49 +2267,6 @@ if [ $multiboot_archives = yes ]; then
done
fi
-create_datalink_conf()
-{
- # /etc/datalink.conf needs to be populated.
- drivers="bge xge"
- conf=$rootprefix/etc/datalink.conf
-
- if [ ! -f $conf ]; then
- # nothing to do if we bfu'ed from an archive that doesn't
- # provide /etc/datalink.conf
- return
- fi
-
- ls -1 $rootprefix/etc | egrep -e '^hostname.|^hostname6.|^dhcp.' | \
- cut -d . -f2 | sort -u > /tmp/ifnames.$$
-
- for driver in $drivers
- do
- grep $driver /tmp/ifnames.$$ | \
- while read ifname
- do
- devnum=`echo $ifname | sed "s/$driver//g"`
- if [ "$driver$devnum" != $ifname -o \
- -n "`echo $devnum | tr -d '[0-9]'`" ]; then
- echo "skipping invalid interface $ifname"
- continue
- fi
-
- vid=`expr $devnum / 1000`
- inst=`expr $devnum % 1000`
-
- awk '{ print $1 }' $conf | grep $ifname > /dev/null
- if [ $? -ne 0 ]; then
- # An entry for that interface does not exist
- printf \
- "$ifname\t$driver$inst\t0\t$vid\n" \
- >> $conf
- fi
- done
- done
-
- rm -f /tmp/ifnames.$$
-}
-
remove_initd_links()
{
# If we're delivering a new version of an existing /etc/init.d script,
@@ -5631,11 +5535,6 @@ mondo_loop() {
# Cleanup old Kerberos mechanisms
cleanup_kerberos_mechanisms
- # Fix network datalink configuration
- if [ $zone = global ]; then
- create_datalink_conf
- fi
-
print "\nRestoring configuration files.\n"
cd $root
diff --git a/usr/src/uts/common/Makefile.files b/usr/src/uts/common/Makefile.files
index c748139976..e802144a19 100644
--- a/usr/src/uts/common/Makefile.files
+++ b/usr/src/uts/common/Makefile.files
@@ -487,8 +487,7 @@ CLONE_OBJS += clone.o
CN_OBJS += cons.o
-DLD_OBJS += dld_drv.o dld_ioc.o dld_minor.o dld_node.o dld_ppa.o \
- dld_proto.o dld_str.o
+DLD_OBJS += dld_drv.o dld_proto.o dld_str.o
DLS_OBJS += dls.o dls_link.o dls_mod.o dls_stat.o dls_vlan.o
@@ -499,8 +498,6 @@ MAC_OBJS += mac.o mac_mod.o mac_stat.o
AGGR_OBJS += aggr_dev.o aggr_ctl.o aggr_grp.o aggr_port.o \
aggr_send.o aggr_recv.o aggr_lacp.o
-GHT_OBJS += ght.o
-
TAVOR_OBJS += tavor.o tavor_agents.o tavor_cfg.o tavor_ci.o tavor_cmd.o \
tavor_cq.o tavor_event.o tavor_ioctl.o tavor_misc.o \
tavor_mr.o tavor_qp.o tavor_qpmod.o tavor_rsrc.o \
diff --git a/usr/src/uts/common/inet/ip.h b/usr/src/uts/common/inet/ip.h
index 45cba93039..9709a106f3 100644
--- a/usr/src/uts/common/inet/ip.h
+++ b/usr/src/uts/common/inet/ip.h
@@ -2959,7 +2959,7 @@ struct ill_zerocopy_capab_s {
* include mac.h in this file.
*/
typedef void (*ip_mac_blank_t)(void *, time_t, uint_t);
-typedef mblk_t *(*ip_mac_tx_t)(void *, mblk_t *);
+typedef void (*ip_mac_tx_t)(void *, mblk_t *);
struct ill_rx_ring {
ip_mac_blank_t rr_blank; /* Driver interrupt blanking func */
diff --git a/usr/src/uts/common/inet/tcp/tcp.c b/usr/src/uts/common/inet/tcp/tcp.c
index 236e0e3d70..a4874f27b2 100644
--- a/usr/src/uts/common/inet/tcp/tcp.c
+++ b/usr/src/uts/common/inet/tcp/tcp.c
@@ -18759,15 +18759,7 @@ tcp_send_data(tcp_t *tcp, queue_t *q, mblk_t *mp)
ASSERT(ill_poll->ill_tx != NULL);
ASSERT(ill_poll->ill_tx_handle != NULL);
- mp = ill_poll->ill_tx(ill_poll->ill_tx_handle, mp);
- /*
- * Driver couldn't send it. Drop it here and the connections
- * will automatically slow down when no ack comes back. We
- * should make this a better mechanism but this is a very
- * rare case.
- */
- if (mp != NULL)
- freemsg(mp);
+ ill_poll->ill_tx(ill_poll->ill_tx_handle, mp);
} else {
putnext(ire->ire_stq, mp);
}
diff --git a/usr/src/uts/common/io/aggr/aggr_ctl.c b/usr/src/uts/common/io/aggr/aggr_ctl.c
index a545363fb4..8606ecd1ee 100644
--- a/usr/src/uts/common/io/aggr/aggr_ctl.c
+++ b/usr/src/uts/common/io/aggr/aggr_ctl.c
@@ -33,64 +33,49 @@
#include <sys/ddi.h>
#include <sys/aggr.h>
#include <sys/aggr_impl.h>
+#include <sys/strsun.h>
-static int aggr_ioc_create(int, void *, int);
-static int aggr_ioc_delete(int, void *, int);
-static int aggr_ioc_info(int, void *, int);
-static int aggr_ioc_add_remove(int, void *, int);
-static int aggr_ioc_status(int, void *, int);
-static int aggr_ioc_modify(int, void *, int);
+static int aggr_ioc_create(mblk_t *, int);
+static int aggr_ioc_delete(mblk_t *, int);
+static int aggr_ioc_info(mblk_t *, int);
+static int aggr_ioc_add(mblk_t *, int);
+static int aggr_ioc_remove(mblk_t *, int);
+static int aggr_ioc_status(mblk_t *, int);
+static int aggr_ioc_modify(mblk_t *, int);
typedef struct ioc_cmd_s {
int ic_cmd;
- int (*ic_func)(int, void *, int);
+ int (*ic_func)(mblk_t *, int);
} ioc_cmd_t;
static ioc_cmd_t ioc_cmd[] = {
{LAIOC_CREATE, aggr_ioc_create},
{LAIOC_DELETE, aggr_ioc_delete},
{LAIOC_INFO, aggr_ioc_info},
- {LAIOC_ADD, aggr_ioc_add_remove},
- {LAIOC_REMOVE, aggr_ioc_add_remove},
+ {LAIOC_ADD, aggr_ioc_add},
+ {LAIOC_REMOVE, aggr_ioc_remove},
{LAIOC_MODIFY, aggr_ioc_modify}};
-/*ARGSUSED*/
-int
-aggr_open(dev_t *devp, int flag, int otyp, cred_t *cred_p)
-{
- /* only the control interface can be opened */
- if (getminor(*devp) != AGGR_MINOR_CTL)
- return (ENOSYS);
- return (0);
-}
-
-/*ARGSUSED*/
-int
-aggr_close(dev_t dev, int flag, int otyp, cred_t *cred_p)
-{
- return (0);
-}
+#define IOC_CMD_SZ (sizeof (ioc_cmd) / sizeof (ioc_cmd_t))
/*
* Process a LAIOC_MODIFY request.
*/
-/* ARGSUSED */
static int
-aggr_ioc_modify(int cmd, void *arg, int mode)
+aggr_ioc_modify(mblk_t *mp, int mode)
{
- STRUCT_DECL(laioc_modify, modify_arg);
+ STRUCT_HANDLE(laioc_modify, modify_arg);
uint32_t policy;
boolean_t mac_fixed;
uchar_t mac_addr[ETHERADDRL];
uint8_t modify_mask_arg, modify_mask = 0;
- uint32_t key;
+ uint32_t rc, key;
aggr_lacp_mode_t lacp_mode;
aggr_lacp_timer_t lacp_timer;
- STRUCT_INIT(modify_arg, mode);
-
- if (copyin(arg, STRUCT_BUF(modify_arg), STRUCT_SIZE(modify_arg)) != 0)
- return (EFAULT);
+ STRUCT_SET_HANDLE(modify_arg, mode, (void *)mp->b_cont->b_rptr);
+ if (MBLKL(mp->b_cont) < STRUCT_SIZE(modify_arg))
+ return (EINVAL);
key = STRUCT_FGET(modify_arg, lu_key);
modify_mask_arg = STRUCT_FGET(modify_arg, lu_modify_mask);
@@ -116,18 +101,21 @@ aggr_ioc_modify(int cmd, void *arg, int mode)
lacp_timer = STRUCT_FGET(modify_arg, lu_lacp_timer);
}
- return (aggr_grp_modify(key, NULL, modify_mask, policy, mac_fixed,
- mac_addr, lacp_mode, lacp_timer));
+ rc = aggr_grp_modify(key, NULL, modify_mask, policy, mac_fixed,
+ mac_addr, lacp_mode, lacp_timer);
+
+ freemsg(mp->b_cont);
+ mp->b_cont = NULL;
+ return (rc);
}
/*
* Process a LAIOC_CREATE request.
*/
-/* ARGSUSED */
static int
-aggr_ioc_create(int cmd, void *arg, int mode)
+aggr_ioc_create(mblk_t *mp, int mode)
{
- STRUCT_DECL(laioc_create, create_arg);
+ STRUCT_HANDLE(laioc_create, create_arg);
uint16_t nports;
laioc_port_t *ports = NULL;
uint32_t policy;
@@ -135,12 +123,11 @@ aggr_ioc_create(int cmd, void *arg, int mode)
uchar_t mac_addr[ETHERADDRL];
aggr_lacp_mode_t lacp_mode;
aggr_lacp_timer_t lacp_timer;
- int rc;
+ int rc, len;
- STRUCT_INIT(create_arg, mode);
-
- if (copyin(arg, STRUCT_BUF(create_arg), STRUCT_SIZE(create_arg)) != 0)
- return (EFAULT);
+ STRUCT_SET_HANDLE(create_arg, mode, (void *)mp->b_cont->b_rptr);
+ if ((len = MBLKL(mp->b_cont)) < STRUCT_SIZE(create_arg))
+ return (EINVAL);
nports = STRUCT_FGET(create_arg, lc_nports);
if (nports > AGGR_MAX_PORTS)
@@ -150,13 +137,10 @@ aggr_ioc_create(int cmd, void *arg, int mode)
lacp_mode = STRUCT_FGET(create_arg, lc_lacp_mode);
lacp_timer = STRUCT_FGET(create_arg, lc_lacp_timer);
- ports = kmem_alloc(nports * sizeof (laioc_port_t), KM_SLEEP);
+ if (len < STRUCT_SIZE(create_arg) + (nports * sizeof (laioc_port_t)))
+ return (EINVAL);
- if (copyin(STRUCT_FGETP(create_arg, lc_ports), ports,
- nports * sizeof (laioc_port_t)) != 0) {
- rc = EFAULT;
- goto bail;
- }
+ ports = (laioc_port_t *)(STRUCT_BUF(create_arg) + 1);
bcopy(STRUCT_FGET(create_arg, lc_mac), mac_addr, ETHERADDRL);
mac_fixed = STRUCT_FGET(create_arg, lc_mac_fixed);
@@ -164,28 +148,31 @@ aggr_ioc_create(int cmd, void *arg, int mode)
rc = aggr_grp_create(STRUCT_FGET(create_arg, lc_key),
nports, ports, policy, mac_fixed, mac_addr, lacp_mode, lacp_timer);
-bail:
- kmem_free(ports, nports * sizeof (laioc_port_t));
+ freemsg(mp->b_cont);
+ mp->b_cont = NULL;
return (rc);
}
-/* ARGSUSED */
static int
-aggr_ioc_delete(int cmd, void *arg, int mode)
+aggr_ioc_delete(mblk_t *mp, int mode)
{
- STRUCT_DECL(laioc_delete, delete_arg);
+ STRUCT_HANDLE(laioc_delete, delete_arg);
+ int rc;
- STRUCT_INIT(delete_arg, mode);
+ STRUCT_SET_HANDLE(delete_arg, mode, (void *)mp->b_cont->b_rptr);
+ if (STRUCT_SIZE(delete_arg) > MBLKL(mp))
+ return (EINVAL);
- if (copyin(arg, STRUCT_BUF(delete_arg), STRUCT_SIZE(delete_arg)) != 0)
- return (EFAULT);
+ rc = aggr_grp_delete(STRUCT_FGET(delete_arg, ld_key));
- return (aggr_grp_delete(STRUCT_FGET(delete_arg, ld_key)));
+ freemsg(mp->b_cont);
+ mp->b_cont = NULL;
+ return (rc);
}
typedef struct aggr_ioc_info_state {
uint32_t bytes_left;
- uchar_t *where; /* in user buffer */
+ uchar_t *where;
} aggr_ioc_info_state_t;
static int
@@ -207,9 +194,7 @@ aggr_ioc_info_new_grp(void *arg, uint32_t key, uchar_t *mac,
grp.lg_lacp_mode = lacp_mode;
grp.lg_lacp_timer = lacp_timer;
- if (copyout(&grp, state->where, sizeof (grp)) != 0)
- return (EFAULT);
-
+ bcopy(&grp, state->where, sizeof (grp));
state->where += sizeof (grp);
state->bytes_left -= sizeof (grp);
@@ -232,9 +217,7 @@ aggr_ioc_info_new_port(void *arg, char *devname, uint32_t portnum,
port.lp_state = portstate;
port.lp_lacp_state = *lacp_state;
- if (copyout(&port, state->where, sizeof (port)) != 0)
- return (EFAULT);
-
+ bcopy(&port, state->where, sizeof (port));
state->where += sizeof (port);
state->bytes_left -= sizeof (port);
@@ -243,125 +226,130 @@ aggr_ioc_info_new_port(void *arg, char *devname, uint32_t portnum,
/*ARGSUSED*/
static int
-aggr_ioc_info(int cmd, void *arg, int mode)
+aggr_ioc_info(mblk_t *mp, int mode)
{
- laioc_info_t info_arg;
+ laioc_info_t *info_argp;
uint32_t ngroups, group_key;
- int rc;
+ int rc, len;
aggr_ioc_info_state_t state;
- if (copyin(arg, &info_arg, sizeof (info_arg)) != 0)
- return (EFAULT);
+ if ((len = MBLKL(mp->b_cont)) < sizeof (*info_argp))
+ return (EINVAL);
+ info_argp = (laioc_info_t *)mp->b_cont->b_rptr;
/*
* Key of the group to return. If zero, the call returns information
* regarding all groups currently defined.
*/
- group_key = info_arg.li_group_key;
+ group_key = info_argp->li_group_key;
- state.bytes_left = info_arg.li_bufsize - sizeof (laioc_info_t);
- state.where = (uchar_t *)arg + sizeof (laioc_info_t);
+ state.bytes_left = len - sizeof (laioc_info_t);
+ state.where = (uchar_t *)(info_argp + 1);
rc = aggr_grp_info(&ngroups, group_key, &state, aggr_ioc_info_new_grp,
aggr_ioc_info_new_port);
- if (rc == 0) {
- info_arg.li_ngroups = ngroups;
- if (copyout(&info_arg, arg, sizeof (info_arg)) != 0)
- return (EFAULT);
- }
+ if (rc == 0)
+ info_argp->li_ngroups = ngroups;
+
return (rc);
}
-/*ARGSUSED*/
static int
-aggr_ioc_add_remove(int cmd, void *arg, int mode)
+aggr_ioc_add(mblk_t *mp, int mode)
{
- STRUCT_DECL(laioc_add_rem, add_rem_arg);
- uint16_t nports;
+ STRUCT_HANDLE(laioc_add_rem, add_arg);
+ uint32_t nports;
laioc_port_t *ports = NULL;
- int rc;
-
- STRUCT_INIT(add_rem_arg, mode);
+ int rc, len;
- if (copyin(arg, STRUCT_BUF(add_rem_arg), STRUCT_SIZE(add_rem_arg)) != 0)
- return (EFAULT);
+ STRUCT_SET_HANDLE(add_arg, mode, (void *)mp->b_cont->b_rptr);
+ if ((len = MBLKL(mp->b_cont)) < STRUCT_SIZE(add_arg))
+ return (EINVAL);
- nports = STRUCT_FGET(add_rem_arg, la_nports);
+ nports = STRUCT_FGET(add_arg, la_nports);
if (nports > AGGR_MAX_PORTS)
return (EINVAL);
- ports = kmem_alloc(nports * sizeof (laioc_port_t), KM_SLEEP);
+ if (len < STRUCT_SIZE(add_arg) + (nports * sizeof (laioc_port_t)))
+ return (EINVAL);
- if (copyin(STRUCT_FGETP(add_rem_arg, la_ports), ports,
- nports * sizeof (laioc_port_t)) != 0) {
- rc = EFAULT;
- goto bail;
- }
+ ports = (laioc_port_t *)(STRUCT_BUF(add_arg) + 1);
- switch (cmd) {
- case LAIOC_ADD:
- rc = aggr_grp_add_ports(STRUCT_FGET(add_rem_arg, la_key),
- nports, ports);
- break;
- case LAIOC_REMOVE:
- rc = aggr_grp_rem_ports(STRUCT_FGET(add_rem_arg, la_key),
- nports, ports);
- break;
- default:
- rc = EINVAL;
- }
+ rc = aggr_grp_add_ports(STRUCT_FGET(add_arg, la_key),
+ nports, ports);
-bail:
- if (ports != NULL)
- kmem_free(ports, nports * sizeof (laioc_port_t));
+ freemsg(mp->b_cont);
+ mp->b_cont = NULL;
return (rc);
}
-/*ARGSUSED*/
static int
-aggr_ioc_remove(void *arg, int mode)
+aggr_ioc_remove(mblk_t *mp, int mode)
{
- STRUCT_DECL(laioc_add_rem, rem_arg);
- uint16_t nports;
+ STRUCT_HANDLE(laioc_add_rem, rem_arg);
+ uint32_t nports;
laioc_port_t *ports = NULL;
- int rc;
-
- STRUCT_INIT(rem_arg, mode);
+ int rc, len;
- if (copyin(arg, STRUCT_BUF(rem_arg), STRUCT_SIZE(rem_arg)) != 0)
- return (EFAULT);
+ STRUCT_SET_HANDLE(rem_arg, mode, (void *)mp->b_cont->b_rptr);
+ if ((len = MBLKL(mp->b_cont)) < STRUCT_SIZE(rem_arg))
+ return (EINVAL);
nports = STRUCT_FGET(rem_arg, la_nports);
if (nports > AGGR_MAX_PORTS)
return (EINVAL);
- ports = kmem_alloc(nports * sizeof (laioc_port_t), KM_SLEEP);
+ if (len < STRUCT_SIZE(rem_arg) + (nports * sizeof (laioc_port_t)))
+ return (EINVAL);
- if (copyin(STRUCT_FGETP(rem_arg, la_ports), ports,
- nports * sizeof (laioc_port_t)) != 0) {
- rc = EFAULT;
- goto bail;
- }
+ ports = (laioc_port_t *)(STRUCT_BUF(rem_arg) + 1);
rc = aggr_grp_rem_ports(STRUCT_FGET(rem_arg, la_key),
nports, ports);
-bail:
- if (ports != NULL)
- kmem_free(ports, nports * sizeof (laioc_port_t));
+ freemsg(mp->b_cont);
+ mp->b_cont = NULL;
return (rc);
}
-/*ARGSUSED*/
-int
-aggr_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *cr, int *rv)
+void
+aggr_ioctl(queue_t *wq, mblk_t *mp)
{
- int i;
+ struct iocblk *iocp = (struct iocblk *)mp->b_rptr;
+ int i, err = EINVAL;
+ mblk_t *nmp;
+
+ if (mp->b_cont == NULL)
+ goto done;
+
+ /*
+ * Construct contiguous message
+ */
+ if ((nmp = msgpullup(mp->b_cont, -1)) == NULL) {
+ err = ENOMEM;
+ goto done;
+ }
+
+ freemsg(mp->b_cont);
+ mp->b_cont = nmp;
+
+ for (i = 0; i < IOC_CMD_SZ; i++) {
+ if (iocp->ioc_cmd == ioc_cmd[i].ic_cmd) {
+ err = ioc_cmd[i].ic_func(mp, (int)iocp->ioc_flag);
+ break;
+ }
+ }
+
+ if (err == 0) {
+ int len = 0;
- for (i = 0; i < sizeof (ioc_cmd) / sizeof (ioc_cmd_t); i++) {
- if (cmd == ioc_cmd[i].ic_cmd)
- return (ioc_cmd[i].ic_func(cmd, (void *)arg, mode));
+ if (mp->b_cont != NULL) {
+ len = MBLKL(mp->b_cont);
+ }
+ miocack(wq, mp, len, 0);
+ return;
}
- return (EINVAL);
+done:
+ miocnak(wq, mp, 0, err);
}
diff --git a/usr/src/uts/common/io/aggr/aggr_dev.c b/usr/src/uts/common/io/aggr/aggr_dev.c
index 97107495b6..148374f0e0 100644
--- a/usr/src/uts/common/io/aggr/aggr_dev.c
+++ b/usr/src/uts/common/io/aggr/aggr_dev.c
@@ -38,17 +38,21 @@
#include <sys/ksynch.h>
#include <sys/kmem.h>
#include <sys/stream.h>
+#include <sys/strsun.h>
#include <sys/modctl.h>
#include <sys/ddi.h>
#include <sys/sunddi.h>
#include <sys/atomic.h>
#include <sys/stat.h>
+#include <sys/dld_impl.h>
#include <sys/aggr.h>
#include <sys/aggr_impl.h>
+#include <inet/common.h>
/* module description */
#define AGGR_LINKINFO "Link Aggregation MAC"
+#define AGGR_DRIVER_NAME "aggr"
/* device info ptr, only one for instance 0 */
dev_info_t *aggr_dip;
@@ -58,51 +62,74 @@ static int aggr_dev_fini(void);
static int aggr_getinfo(dev_info_t *, ddi_info_cmd_t, void *, void **);
static int aggr_attach(dev_info_t *, ddi_attach_cmd_t);
static int aggr_detach(dev_info_t *, ddi_detach_cmd_t);
+static int aggr_open(queue_t *, dev_t *, int, int, cred_t *);
+static int aggr_close(queue_t *);
+static void aggr_wput(queue_t *, mblk_t *);
-static struct cb_ops aggr_cb_ops = {
- aggr_open, /* open */
- aggr_close, /* close */
- nulldev, /* strategy */
- nulldev, /* print */
- nodev, /* dump */
- nodev, /* read */
- nodev, /* write */
- aggr_ioctl, /* ioctl */
- nodev, /* devmap */
- nodev, /* mmap */
- nodev, /* segmap */
- nochpoll, /* poll */
- ddi_prop_op, /* cb_prop_op */
- 0, /* streamtab */
- D_NEW | D_MP /* driver compatibility flag */
+/*
+ * mi_hiwat is set to 1 because of the flow control mechanism implemented
+ * in dld. refer to the comments in dld_str.c for details.
+ */
+static struct module_info aggr_module_info = {
+ 0,
+ AGGR_DRIVER_NAME,
+ 0,
+ INFPSZ,
+ 1,
+ 0
+};
+
+static struct qinit aggr_r_qinit = { /* read queues */
+ NULL,
+ NULL,
+ aggr_open,
+ aggr_close,
+ NULL,
+ &aggr_module_info
+};
+
+static struct qinit aggr_w_qinit = { /* write queues */
+ (pfi_t)dld_wput,
+ (pfi_t)dld_wsrv,
+ NULL,
+ NULL,
+ NULL,
+ &aggr_module_info
+};
+
+/*
+ * Entry points for aggr control node
+ */
+static struct qinit aggr_w_ctl_qinit = {
+ (pfi_t)aggr_wput,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ &aggr_module_info
};
-static struct dev_ops aggr_ops = {
- DEVO_REV, /* devo_rev */
- 0, /* refcnt */
- aggr_getinfo, /* getinfo */
- nulldev, /* identify */
- nulldev, /* probe */
- aggr_attach, /* attach */
- aggr_detach, /* detach */
- nodev, /* reset */
- &aggr_cb_ops, /* driver operations */
- NULL, /* bus operations */
- nodev /* dev power */
+static struct streamtab aggr_streamtab = {
+ &aggr_r_qinit,
+ &aggr_w_qinit
};
-static struct modldrv modldrv = {
- &mod_driverops,
- AGGR_LINKINFO,
- &aggr_ops
+DDI_DEFINE_STREAM_OPS(aggr_dev_ops, nulldev, nulldev, aggr_attach, aggr_detach,
+ nodev, aggr_getinfo, D_MP, &aggr_streamtab);
+
+static struct modldrv aggr_modldrv = {
+ &mod_driverops, /* Type of module. This one is a driver */
+ AGGR_LINKINFO, /* short description */
+ &aggr_dev_ops /* driver specific ops */
};
-static struct modlinkage modlinkage = {
+static struct modlinkage modlinkage = {
MODREV_1,
- &modldrv,
+ &aggr_modldrv,
NULL
};
+
int
_init(void)
{
@@ -116,7 +143,6 @@ _init(void)
}
aggr_dip = NULL;
-
return (0);
}
@@ -142,6 +168,53 @@ _info(struct modinfo *modinfop)
return (mod_info(&modlinkage, modinfop));
}
+static int
+aggr_open(queue_t *q, dev_t *devp, int flag, int sflag, cred_t *credp)
+{
+ if (q->q_ptr != NULL)
+ return (EBUSY);
+
+ if (getminor(*devp) == AGGR_MINOR_CTL) {
+ dld_str_t *dsp;
+
+ dsp = dld_str_create(q, DLD_CONTROL, getmajor(*devp),
+ DL_STYLE1);
+ if (dsp == NULL)
+ return (ENOSR);
+
+ /*
+ * The aggr control node uses its own set of entry points.
+ */
+ WR(q)->q_qinfo = &aggr_w_ctl_qinit;
+ *devp = makedevice(getmajor(*devp), dsp->ds_minor);
+ qprocson(q);
+ return (0);
+ }
+ return (dld_open(q, devp, flag, sflag, credp));
+}
+
+static int
+aggr_close(queue_t *q)
+{
+ dld_str_t *dsp = q->q_ptr;
+
+ if (dsp->ds_type == DLD_CONTROL) {
+ qprocsoff(q);
+ dld_str_destroy(dsp);
+ return (0);
+ }
+ return (dld_close(q));
+}
+
+static void
+aggr_wput(queue_t *q, mblk_t *mp)
+{
+ if (DB_TYPE(mp) == M_IOCTL)
+ aggr_ioctl(q, mp);
+ else
+ freemsg(mp);
+}
+
static void
aggr_dev_init(void)
{
@@ -216,8 +289,11 @@ aggr_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
{
switch (cmd) {
case DDI_DETACH:
+ if (aggr_grp_count() > 0)
+ return (DDI_FAILURE);
+
aggr_dip = NULL;
- ddi_remove_minor_node(dip, NULL);
+ ddi_remove_minor_node(dip, AGGR_DEVNAME_CTL);
return (DDI_SUCCESS);
diff --git a/usr/src/uts/common/io/aggr/aggr_grp.c b/usr/src/uts/common/io/aggr/aggr_grp.c
index c51e1c5fbf..091d6c4550 100644
--- a/usr/src/uts/common/io/aggr/aggr_grp.c
+++ b/usr/src/uts/common/io/aggr/aggr_grp.c
@@ -31,7 +31,7 @@
*
* An instance of the structure aggr_grp_t is allocated for each
* link aggregation group. When created, aggr_grp_t objects are
- * entered into the aggr_grp_hash hash table maintained by the GHT
+ * entered into the aggr_grp_hash hash table maintained by the modhash
* module. The hash key is the port number associated with the link
* aggregation group. The port number associated with a group corresponds
* the key associated with the group.
@@ -52,7 +52,7 @@
#include <sys/sunddi.h>
#include <sys/atomic.h>
#include <sys/stat.h>
-#include <sys/ght.h>
+#include <sys/modhash.h>
#include <sys/strsun.h>
#include <sys/dlpi.h>
@@ -75,10 +75,13 @@ static void aggr_stats_op(enum mac_stat, uint64_t *, uint64_t *, boolean_t);
static void aggr_grp_capab_set(aggr_grp_t *);
static boolean_t aggr_grp_capab_check(aggr_grp_t *, aggr_port_t *);
-static kmem_cache_t *aggr_grp_cache;
-static ght_t aggr_grp_hash;
+static kmem_cache_t *aggr_grp_cache;
+static mod_hash_t *aggr_grp_hash;
+static krwlock_t aggr_grp_lock;
+static uint_t aggr_grp_cnt;
#define GRP_HASHSZ 64
+#define GRP_HASH_KEY(key) ((mod_hash_key_t)(uintptr_t)key)
static uchar_t aggr_zero_mac[] = {0, 0, 0, 0, 0, 0};
static uchar_t aggr_brdcst_mac[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
@@ -126,28 +129,39 @@ aggr_grp_destructor(void *buf, void *arg)
void
aggr_grp_init(void)
{
- int err;
-
aggr_grp_cache = kmem_cache_create("aggr_grp_cache",
sizeof (aggr_grp_t), 0, aggr_grp_constructor,
aggr_grp_destructor, NULL, NULL, NULL, 0);
- err = ght_scalar_create("aggr_grp_hash", GRP_HASHSZ,
- &aggr_grp_hash);
- ASSERT(err == 0);
+ aggr_grp_hash = mod_hash_create_idhash("aggr_grp_hash",
+ GRP_HASHSZ, mod_hash_null_valdtor);
+ rw_init(&aggr_grp_lock, NULL, RW_DEFAULT, NULL);
+ aggr_grp_cnt = 0;
}
int
aggr_grp_fini(void)
{
- int err;
+ if (aggr_grp_cnt > 0)
+ return (EBUSY);
- if ((err = ght_destroy(aggr_grp_hash)) != 0)
- return (err);
+ rw_destroy(&aggr_grp_lock);
+ mod_hash_destroy_idhash(aggr_grp_hash);
kmem_cache_destroy(aggr_grp_cache);
return (0);
}
+uint_t
+aggr_grp_count(void)
+{
+ uint_t count;
+
+ rw_enter(&aggr_grp_lock, RW_READER);
+ count = aggr_grp_cnt;
+ rw_exit(&aggr_grp_lock);
+ return (count);
+}
+
/*
* Attach a port to a link aggregation group.
*
@@ -390,21 +404,18 @@ int
aggr_grp_add_ports(uint32_t key, uint_t nports, laioc_port_t *ports)
{
int rc, i, nadded = 0;
- ghte_t hte;
aggr_grp_t *grp = NULL;
aggr_port_t *port;
/* get group corresponding to key */
- ght_lock(aggr_grp_hash, GHT_READ);
- if ((rc = ght_find(aggr_grp_hash, GHT_SCALAR_TO_KEY(key),
- &hte)) == ENOENT) {
- ght_unlock(aggr_grp_hash);
- return (rc);
+ rw_enter(&aggr_grp_lock, RW_READER);
+ if (mod_hash_find(aggr_grp_hash, GRP_HASH_KEY(key),
+ (mod_hash_val_t *)&grp) != 0) {
+ rw_exit(&aggr_grp_lock);
+ return (ENOENT);
}
- ASSERT(rc == 0);
- grp = (aggr_grp_t *)GHT_VAL(hte);
AGGR_GRP_REFHOLD(grp);
- ght_unlock(aggr_grp_hash);
+ rw_exit(&aggr_grp_lock);
AGGR_LACP_LOCK(grp);
rw_enter(&grp->lg_lock, RW_WRITER);
@@ -479,18 +490,17 @@ aggr_grp_modify(uint32_t key, aggr_grp_t *grp_arg, uint8_t update_mask,
aggr_lacp_mode_t lacp_mode, aggr_lacp_timer_t lacp_timer)
{
int rc = 0;
- ghte_t hte;
aggr_grp_t *grp = NULL;
boolean_t mac_addr_changed = B_FALSE;
if (grp_arg == NULL) {
/* get group corresponding to key */
- ght_lock(aggr_grp_hash, GHT_READ);
- if ((rc = ght_find(aggr_grp_hash, GHT_SCALAR_TO_KEY(key),
- &hte)) == ENOENT)
+ rw_enter(&aggr_grp_lock, RW_READER);
+ if (mod_hash_find(aggr_grp_hash, GRP_HASH_KEY(key),
+ (mod_hash_val_t *)&grp) != 0) {
+ rc = ENOENT;
goto bail;
- ASSERT(rc == 0);
- grp = (aggr_grp_t *)GHT_VAL(hte);
+ }
AGGR_LACP_LOCK(grp);
rw_enter(&grp->lg_lock, RW_WRITER);
} else {
@@ -551,7 +561,7 @@ bail:
rw_exit(&grp->lg_lock);
AGGR_LACP_UNLOCK(grp);
}
- ght_unlock(aggr_grp_hash);
+ rw_exit(&aggr_grp_lock);
/* pass new unicast address up to MAC layer */
if (grp != NULL && mac_addr_changed && !grp->lg_closing)
mac_unicst_update(&grp->lg_mac, grp->lg_addr);
@@ -574,7 +584,6 @@ aggr_grp_create(uint32_t key, uint_t nports, laioc_port_t *ports,
{
aggr_grp_t *grp = NULL;
aggr_port_t *port;
- ghte_t hte;
mac_t *mac;
mac_info_t *mip;
int err;
@@ -584,12 +593,13 @@ aggr_grp_create(uint32_t key, uint_t nports, laioc_port_t *ports,
if (nports == 0)
return (EINVAL);
- ght_lock(aggr_grp_hash, GHT_WRITE);
+ rw_enter(&aggr_grp_lock, RW_WRITER);
/* does a group with the same key already exist? */
- err = ght_find(aggr_grp_hash, GHT_SCALAR_TO_KEY(key), &hte);
- if (err != ENOENT) {
- ght_unlock(aggr_grp_hash);
+ err = mod_hash_find(aggr_grp_hash, GRP_HASH_KEY(key),
+ (mod_hash_val_t *)&grp);
+ if (err == 0) {
+ rw_exit(&aggr_grp_lock);
return (EEXIST);
}
@@ -688,18 +698,14 @@ aggr_grp_create(uint32_t key, uint_t nports, laioc_port_t *ports,
aggr_lacp_set_mode(grp, lacp_mode, lacp_timer);
/* add new group to hash table */
- hte = ght_alloc(aggr_grp_hash, KM_SLEEP);
- GHT_KEY(hte) = GHT_SCALAR_TO_KEY(key);
- GHT_VAL(hte) = GHT_PTR_TO_VAL(grp);
- grp->lg_hte = hte;
-
- err = ght_insert(hte);
+ err = mod_hash_insert(aggr_grp_hash, GRP_HASH_KEY(key),
+ (mod_hash_val_t)grp);
ASSERT(err == 0);
+ aggr_grp_cnt++;
rw_exit(&grp->lg_lock);
AGGR_LACP_UNLOCK(grp);
- ght_unlock(aggr_grp_hash);
-
+ rw_exit(&aggr_grp_lock);
return (0);
bail:
@@ -719,7 +725,7 @@ bail:
kmem_cache_free(aggr_grp_cache, grp);
}
- ght_unlock(aggr_grp_hash);
+ rw_exit(&aggr_grp_lock);
return (err);
}
@@ -837,22 +843,20 @@ int
aggr_grp_rem_ports(uint32_t key, uint_t nports, laioc_port_t *ports)
{
int rc = 0, i;
- ghte_t hte;
aggr_grp_t *grp = NULL;
aggr_port_t *port;
boolean_t notify = B_FALSE, grp_mac_addr_changed;
/* get group corresponding to key */
- ght_lock(aggr_grp_hash, GHT_READ);
- if ((rc = ght_find(aggr_grp_hash, GHT_SCALAR_TO_KEY(key),
- &hte)) == ENOENT) {
- ght_unlock(aggr_grp_hash);
- return (rc);
+ rw_enter(&aggr_grp_lock, RW_READER);
+ if (mod_hash_find(aggr_grp_hash, GRP_HASH_KEY(key),
+ (mod_hash_val_t *)&grp) != 0) {
+ rw_exit(&aggr_grp_lock);
+ return (ENOENT);
}
- ASSERT(rc == 0);
- grp = (aggr_grp_t *)GHT_VAL(hte);
AGGR_GRP_REFHOLD(grp);
- ght_unlock(aggr_grp_hash);
+ rw_exit(&aggr_grp_lock);
+
AGGR_LACP_LOCK(grp);
rw_enter(&grp->lg_lock, RW_WRITER);
@@ -907,22 +911,17 @@ bail:
int
aggr_grp_delete(uint32_t key)
{
- int err;
- ghte_t hte;
- aggr_grp_t *grp;
+ aggr_grp_t *grp = NULL;
aggr_port_t *port, *cport;
+ mod_hash_val_t val;
- ght_lock(aggr_grp_hash, GHT_WRITE);
+ rw_enter(&aggr_grp_lock, RW_WRITER);
- err = ght_find(aggr_grp_hash, GHT_SCALAR_TO_KEY(key), &hte);
- if (err == ENOENT) {
- ght_unlock(aggr_grp_hash);
- return (err);
+ if (mod_hash_find(aggr_grp_hash, GRP_HASH_KEY(key),
+ (mod_hash_val_t *)&grp) != 0) {
+ rw_exit(&aggr_grp_lock);
+ return (ENOENT);
}
- ASSERT(err == 0);
-
- grp = (aggr_grp_t *)GHT_VAL(hte);
-
AGGR_LACP_LOCK(grp);
rw_enter(&grp->lg_lock, RW_WRITER);
grp->lg_closing = B_TRUE;
@@ -935,7 +934,7 @@ aggr_grp_delete(uint32_t key)
if (mac_unregister(&grp->lg_mac)) {
rw_exit(&grp->lg_lock);
AGGR_LACP_UNLOCK(grp);
- ght_unlock(aggr_grp_hash);
+ rw_exit(&aggr_grp_lock);
return (EBUSY);
}
@@ -955,10 +954,13 @@ aggr_grp_delete(uint32_t key)
rw_exit(&grp->lg_lock);
AGGR_LACP_UNLOCK(grp);
- ght_remove(hte);
- ght_free(hte);
+ (void) mod_hash_remove(aggr_grp_hash, GRP_HASH_KEY(key), &val);
+ ASSERT(grp == (aggr_grp_t *)val);
+
+ ASSERT(aggr_grp_cnt > 0);
+ aggr_grp_cnt--;
- ght_unlock(aggr_grp_hash);
+ rw_exit(&aggr_grp_lock);
AGGR_GRP_REFRELE(grp);
return (0);
@@ -976,17 +978,18 @@ aggr_grp_free(aggr_grp_t *grp)
* their ports that must be passed up to user-space.
*/
-static boolean_t
-aggr_grp_info_walker(void *arg, ghte_t hte)
+/*ARGSUSED*/
+static uint_t
+aggr_grp_info_walker(mod_hash_key_t key, mod_hash_val_t *val, void *arg)
{
aggr_grp_t *grp;
aggr_port_t *port;
aggr_grp_info_state_t *state = arg;
if (state->ls_rc != 0)
- return (B_FALSE); /* terminate walk */
+ return (MH_WALK_TERMINATE); /* terminate walk */
- grp = (aggr_grp_t *)GHT_VAL(hte);
+ grp = (aggr_grp_t *)val;
rw_enter(&grp->lg_lock, RW_READER);
@@ -1018,7 +1021,7 @@ aggr_grp_info_walker(void *arg, ghte_t hte)
bail:
rw_exit(&grp->lg_lock);
- return (state->ls_rc == 0);
+ return ((state->ls_rc == 0) ? MH_WALK_CONTINUE : MH_WALK_TERMINATE);
}
int
@@ -1029,9 +1032,9 @@ aggr_grp_info(uint_t *ngroups, uint32_t group_key, void *fn_arg,
aggr_grp_info_state_t state;
int rc = 0;
- ght_lock(aggr_grp_hash, GHT_READ);
+ rw_enter(&aggr_grp_lock, RW_READER);
- *ngroups = ght_count(aggr_grp_hash);
+ *ngroups = aggr_grp_cnt;
bzero(&state, sizeof (state));
state.ls_group_key = group_key;
@@ -1039,13 +1042,13 @@ aggr_grp_info(uint_t *ngroups, uint32_t group_key, void *fn_arg,
state.ls_new_port_fn = new_port_fn;
state.ls_fn_arg = fn_arg;
- ght_walk(aggr_grp_hash, aggr_grp_info_walker, &state);
+ mod_hash_walk(aggr_grp_hash, aggr_grp_info_walker, &state);
if ((rc = state.ls_rc) == 0 && group_key != 0 &&
!state.ls_group_found)
rc = ENOENT;
- ght_unlock(aggr_grp_hash);
+ rw_exit(&aggr_grp_lock);
return (rc);
}
@@ -1059,16 +1062,6 @@ typedef struct aggr_grp_walker_state_s {
} aggr_grp_walker_state_t;
void
-aggr_grp_walker(void *arg, ghte_t hte)
-{
- aggr_grp_walker_state_t *state = arg;
- aggr_grp_t *grp;
-
- grp = (aggr_grp_t *)GHT_VAL(hte);
- state->ws_walker_fn(grp, state->ws_arg);
-}
-
-void
aggr_grp_walk(aggr_grp_walker_fn_t walker, void *arg)
{
aggr_grp_walker_state_t state;
@@ -1076,9 +1069,9 @@ aggr_grp_walk(aggr_grp_walker_fn_t walker, void *arg)
state.ws_walker_fn = walker;
state.ws_arg = arg;
- ght_lock(aggr_grp_hash, GHT_READ);
- ght_walk(aggr_grp_hash, aggr_grp_info_walker, &state);
- ght_unlock(aggr_grp_hash);
+ rw_enter(&aggr_grp_lock, RW_READER);
+ mod_hash_walk(aggr_grp_hash, aggr_grp_info_walker, &state);
+ rw_exit(&aggr_grp_lock);
}
static void
diff --git a/usr/src/uts/common/io/bge/bge_main.c b/usr/src/uts/common/io/bge/bge_main.c
index 3a96a2e09e..e1dcafecf9 100644
--- a/usr/src/uts/common/io/bge/bge_main.c
+++ b/usr/src/uts/common/io/bge/bge_main.c
@@ -2075,40 +2075,8 @@ bge_detach(dev_info_t *devinfo, ddi_detach_cmd_t cmd)
#undef BGE_DBG
#define BGE_DBG BGE_DBG_INIT /* debug flag for this code */
-static struct cb_ops bge_cb_ops = {
- nulldev, /* cb_open */
- nulldev, /* cb_close */
- nodev, /* cb_strategy */
- nodev, /* cb_print */
- nodev, /* cb_dump */
- nodev, /* cb_read */
- nodev, /* cb_write */
- nodev, /* cb_ioctl */
- nodev, /* cb_devmap */
- nodev, /* cb_mmap */
- nodev, /* cb_segmap */
- nochpoll, /* cb_chpoll */
- ddi_prop_op, /* cb_prop_op */
- NULL, /* cb_stream */
- D_MP, /* cb_flag */
- CB_REV, /* cb_rev */
- nodev, /* cb_aread */
- nodev /* cb_awrite */
-};
-
-static struct dev_ops bge_dev_ops = {
- DEVO_REV, /* devo_rev */
- 0, /* devo_refcnt */
- nulldev, /* devo_getinfo */
- nulldev, /* devo_identify */
- nulldev, /* devo_probe */
- bge_attach, /* devo_attach */
- bge_detach, /* devo_detach */
- nodev, /* devo_reset */
- &bge_cb_ops, /* devo_cb_ops */
- (struct bus_ops *)NULL, /* devo_bus_ops */
- NULL /* devo_power */
-};
+DDI_DEFINE_STREAM_OPS(bge_dev_ops, nulldev, nulldev, bge_attach, bge_detach,
+ nodev, NULL, D_MP, NULL);
static struct modldrv bge_modldrv = {
&mod_driverops, /* Type of module. This one is a driver */
@@ -2132,9 +2100,12 @@ _init(void)
{
int status;
+ mac_init_ops(&bge_dev_ops, "bge");
status = mod_install(&modlinkage);
if (status == DDI_SUCCESS)
mutex_init(bge_log_mutex, NULL, MUTEX_DRIVER, NULL);
+ else
+ mac_fini_ops(&bge_dev_ops);
return (status);
}
@@ -2144,8 +2115,10 @@ _fini(void)
int status;
status = mod_remove(&modlinkage);
- if (status == DDI_SUCCESS)
+ if (status == DDI_SUCCESS) {
+ mac_fini_ops(&bge_dev_ops);
mutex_destroy(bge_log_mutex);
+ }
return (status);
}
diff --git a/usr/src/uts/common/io/dld/dld_drv.c b/usr/src/uts/common/io/dld/dld_drv.c
index e502f99874..5d34f79f7e 100644
--- a/usr/src/uts/common/io/dld/dld_drv.c
+++ b/usr/src/uts/common/io/dld/dld_drv.c
@@ -30,20 +30,23 @@
* Data-Link Driver
*/
-#include <sys/types.h>
-#include <sys/stream.h>
#include <sys/conf.h>
-#include <sys/stat.h>
-#include <sys/ddi.h>
-#include <sys/sunddi.h>
-#include <sys/dlpi.h>
+#include <sys/mkdev.h>
#include <sys/modctl.h>
-#include <sys/kmem.h>
-#include <inet/common.h>
-
-#include <sys/dls.h>
+#include <sys/stat.h>
+#include <sys/strsun.h>
#include <sys/dld.h>
#include <sys/dld_impl.h>
+#include <sys/dls_impl.h>
+#include <inet/common.h>
+
+/*
+ * dld control node state, one per open control node session.
+ */
+typedef struct dld_ctl_str_s {
+ minor_t cs_minor;
+ queue_t *cs_wq;
+} dld_ctl_str_t;
static void drv_init(void);
static int drv_fini(void);
@@ -52,6 +55,11 @@ static int drv_getinfo(dev_info_t *, ddi_info_cmd_t, void *, void **);
static int drv_attach(dev_info_t *, ddi_attach_cmd_t);
static int drv_detach(dev_info_t *, ddi_detach_cmd_t);
+/*
+ * The following entry points are private to dld and are used for control
+ * operations only. The entry points exported to mac drivers are defined
+ * in dld_str.c. Refer to the comment on top of dld_str.c for details.
+ */
static int drv_open(queue_t *, dev_t *, int, int, cred_t *);
static int drv_close(queue_t *);
@@ -59,13 +67,8 @@ static void drv_uw_put(queue_t *, mblk_t *);
static void drv_uw_srv(queue_t *);
dev_info_t *dld_dip; /* dev_info_t for the driver */
-uint32_t dld_opt; /* Global options */
-boolean_t dld_open; /* Flag to note that the control */
- /* node is open */
-boolean_t dld_aul = B_TRUE; /* Set to B_FALSE to prevent driver */
- /* unloading */
-
-static kmutex_t drv_lock; /* Needs no initialization */
+uint32_t dld_opt = 0; /* Global options */
+static vmem_t *dld_ctl_vmem; /* for control minor numbers */
static struct module_info drv_info = {
0, /* mi_idnum */
@@ -104,7 +107,7 @@ static struct streamtab drv_stream = {
};
DDI_DEFINE_STREAM_OPS(drv_ops, nulldev, nulldev, drv_attach, drv_detach,
- nodev, drv_getinfo, D_MP | D_MTQPAIR | D_MTPUTSHARED, &drv_stream);
+ nodev, drv_getinfo, D_MP, &drv_stream);
/*
* Module linkage information for the kernel.
@@ -129,13 +132,11 @@ _init(void)
{
int err;
+ drv_init();
+
if ((err = mod_install(&drv_modlinkage)) != 0)
return (err);
-#ifdef DEBUG
- cmn_err(CE_NOTE, "!%s loaded", DLD_INFO);
-#endif /* DEBUG */
-
return (0);
}
@@ -144,15 +145,13 @@ _fini(void)
{
int err;
- if (!dld_aul)
- return (ENOTSUP);
-
if ((err = mod_remove(&drv_modlinkage)) != 0)
return (err);
-#ifdef DEBUG
- cmn_err(CE_NOTE, "!%s unloaded", DLD_INFO);
-#endif /* DEBUG */
+ if (drv_fini() != 0) {
+ (void) mod_install(&drv_modlinkage);
+ return (DDI_FAILURE);
+ }
return (err);
}
@@ -165,15 +164,14 @@ _info(struct modinfo *modinfop)
/*
- * Initialize compoment modules.
+ * Initialize component modules.
*/
static void
drv_init(void)
{
- dld_minor_init();
- dld_node_init();
+ dld_ctl_vmem = vmem_create("dld_ctl", (void *)1, MAXMIN, 1,
+ NULL, NULL, NULL, 1, VM_SLEEP | VMC_IDENTIFIER);
dld_str_init();
- dld_ppa_init();
}
static int
@@ -181,18 +179,10 @@ drv_fini(void)
{
int err;
- if ((err = dld_ppa_fini()) != 0)
+ if ((err = dld_str_fini()) != 0)
return (err);
- err = dld_str_fini();
- ASSERT(err == 0);
-
- err = dld_node_fini();
- ASSERT(err == 0);
-
- err = dld_minor_fini();
- ASSERT(err == 0);
-
+ vmem_destroy(dld_ctl_vmem);
return (0);
}
@@ -227,34 +217,17 @@ static void
drv_set_opt(dev_info_t *dip)
{
if (ddi_prop_get_int(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
- DLD_PROP_NO_STYLE1, 0) != 0) {
-#ifdef DEBUG
- cmn_err(CE_NOTE, "%s: ON", DLD_PROP_NO_STYLE1);
-#endif /* DEBUG */
- dld_opt |= DLD_OPT_NO_STYLE1;
- }
-
- if (ddi_prop_get_int(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
DLD_PROP_NO_FASTPATH, 0) != 0) {
-#ifdef DEBUG
- cmn_err(CE_NOTE, "%s: ON", DLD_PROP_NO_FASTPATH);
-#endif /* DEBUG */
dld_opt |= DLD_OPT_NO_FASTPATH;
}
if (ddi_prop_get_int(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
DLD_PROP_NO_POLL, 0) != 0) {
-#ifdef DEBUG
- cmn_err(CE_NOTE, "%s: ON", DLD_PROP_NO_POLL);
-#endif /* DEBUG */
dld_opt |= DLD_OPT_NO_POLL;
}
if (ddi_prop_get_int(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
DLD_PROP_NO_ZEROCOPY, 0) != 0) {
-#ifdef DEBUG
- cmn_err(CE_NOTE, "%s: ON", DLD_PROP_NO_ZEROCOPY);
-#endif /* DEBUG */
dld_opt |= DLD_OPT_NO_ZEROCOPY;
}
}
@@ -270,7 +243,6 @@ drv_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
ASSERT(ddi_get_instance(dip) == 0);
- drv_init();
drv_set_opt(dip);
/*
@@ -298,9 +270,6 @@ drv_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
if (cmd != DDI_DETACH)
return (DDI_FAILURE);
- if (drv_fini() != 0)
- return (DDI_FAILURE);
-
ASSERT(dld_dip == dip);
/*
@@ -313,83 +282,41 @@ drv_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
}
/*
- * qi_qopen: open(9e)
+ * dld control node open procedure.
*/
/*ARGSUSED*/
static int
drv_open(queue_t *rq, dev_t *devp, int flag, int sflag, cred_t *credp)
{
- dld_str_t *dsp;
- dld_node_t *dnp;
- dld_ppa_t *dpp;
+ dld_ctl_str_t *ctls;
minor_t minor;
- int err;
+ queue_t *oq = OTHERQ(rq);
- ASSERT(sflag != MODOPEN);
+ if (sflag == MODOPEN)
+ return (ENOTSUP);
/*
* This is a cloning driver and therefore each queue should only
* ever get opened once.
*/
- ASSERT(rq->q_ptr == NULL);
if (rq->q_ptr != NULL)
return (EBUSY);
- /*
- * Grab the minor number of the dev_t that was opened. Because this
- * is a cloning driver this will be distinct from the actual minor
- * of the dev_t handed back.
- */
- minor = getminor(*devp);
+ minor = (minor_t)(uintptr_t)vmem_alloc(dld_ctl_vmem, 1, VM_NOSLEEP);
+ if (minor == 0)
+ return (ENOMEM);
- /*
- * Create a new dld_str_t for the stream. This will grab a new minor
- * number that will be handed back in the cloned dev_t.
- */
- dsp = dld_str_create(rq);
-
- if (minor != DLD_CONTROL_MINOR) {
- /*
- * This is not the control node, so look up the DLPI
- * provider node that is being opened.
- */
- if ((dnp = dld_node_find(minor)) == NULL) {
- err = ENODEV;
- goto failed;
- }
-
- dsp->ds_dnp = dnp;
- dsp->ds_type = DLD_DLPI;
-
- ASSERT(dsp->ds_dlstate == DL_UNATTACHED);
- if (dnp->dn_style == DL_STYLE1) {
- /*
- * This is a style 1 provider node so we have a
- * non-ambiguous PPA.
- */
- dpp = dld_node_ppa_find(dnp, -1);
-
- if ((err = dld_str_attach(dsp, dpp)) != 0)
- goto failed;
- dsp->ds_dlstate = DL_UNBOUND;
- }
- } else {
- /*
- * This is the control node. It is exclusive-access so
- * verify that it is not already open.
- */
- mutex_enter(&drv_lock);
- if (dld_open) {
- err = EBUSY;
- mutex_exit(&drv_lock);
- goto failed;
- }
+ ctls = kmem_zalloc(sizeof (dld_ctl_str_t), KM_NOSLEEP);
+ if (ctls == NULL) {
+ vmem_free(dld_ctl_vmem, (void *)(uintptr_t)minor, 1);
+ return (ENOMEM);
+ }
- dld_open = B_TRUE;
- mutex_exit(&drv_lock);
+ ctls->cs_minor = minor;
+ ctls->cs_wq = WR(rq);
- dsp->ds_type = DLD_CONTROL;
- }
+ rq->q_ptr = ctls;
+ oq->q_ptr = ctls;
/*
* Enable the queue srv(9e) routine.
@@ -399,102 +326,191 @@ drv_open(queue_t *rq, dev_t *devp, int flag, int sflag, cred_t *credp)
/*
* Construct a cloned dev_t to hand back.
*/
- *devp = makedevice(getmajor(*devp), dsp->ds_minor);
+ *devp = makedevice(getmajor(*devp), ctls->cs_minor);
return (0);
-
-failed:
- dld_str_destroy(dsp);
- return (err);
}
/*
- * qi_qclose: close(9e)
+ * dld control node close procedure.
*/
static int
drv_close(queue_t *rq)
{
- dld_str_t *dsp;
+ dld_ctl_str_t *ctls;
- dsp = rq->q_ptr;
- ASSERT(dsp != NULL);
+ ctls = rq->q_ptr;
+ ASSERT(ctls != NULL);
/*
* Disable the queue srv(9e) routine.
*/
qprocsoff(rq);
- if (dsp->ds_type != DLD_CONTROL) {
- /*
- * This stream was open to a provider node. Check to see
- * if it has been cleanly shut down.
- */
- if (dsp->ds_dlstate != DL_UNATTACHED) {
- /*
- * The stream is either open to a style 1 provider or
- * this is not clean shutdown. Detach from the PPA.
- * (This is still ok even in the style 1 case).
- */
- dld_str_detach(dsp);
- dsp->ds_dlstate = DL_UNATTACHED;
- }
- } else {
- /*
- * This stream was open to the control node. Clear the flag
- * to allow another stream access.
- */
- ASSERT(dld_open);
- dld_open = B_FALSE;
- }
+ vmem_free(dld_ctl_vmem, (void *)(uintptr_t)ctls->cs_minor, 1);
+
+ kmem_free(ctls, sizeof (dld_ctl_str_t));
- dld_str_destroy(dsp);
return (0);
}
/*
- * qi_qputp: put(9e)
+ * DLDIOCATTR
*/
static void
-drv_uw_put(queue_t *wq, mblk_t *mp)
+drv_ioc_attr(dld_ctl_str_t *ctls, mblk_t *mp)
{
- dld_str_t *dsp;
+ dld_ioc_attr_t *diap;
+ dls_vlan_t *dvp = NULL;
+ dls_link_t *dlp = NULL;
+ int err;
+ queue_t *q = ctls->cs_wq;
- dsp = wq->q_ptr;
- ASSERT(dsp != NULL);
+ if ((err = miocpullup(mp, sizeof (dld_ioc_attr_t))) != 0)
+ goto failed;
- /*
- * Call the put(9e) processor.
- */
- dld_str_put(dsp, mp);
+ diap = (dld_ioc_attr_t *)mp->b_cont->b_rptr;
+ diap->dia_name[IFNAMSIZ - 1] = '\0';
+
+ if (dls_vlan_hold(diap->dia_name, &dvp, B_FALSE) != 0) {
+ err = ENOENT;
+ goto failed;
+ }
+
+ dlp = dvp->dv_dlp;
+ (void) strlcpy(diap->dia_dev, dlp->dl_dev, MAXNAMELEN);
+ diap->dia_port = dlp->dl_port;
+ diap->dia_vid = dvp->dv_id;
+ diap->dia_max_sdu = dlp->dl_mip->mi_sdu_max;
+
+ dls_vlan_rele(dvp);
+ miocack(q, mp, sizeof (dld_ioc_attr_t), 0);
+ return;
+
+failed:
+ ASSERT(err != 0);
+ if (err == ENOENT) {
+ char devname[MAXNAMELEN];
+ uint_t instance;
+ major_t major;
+
+ /*
+ * Try to detect if the specified device is gldv3
+ * and return ENODEV if it is not.
+ */
+ if (ddi_parse(diap->dia_name, devname, &instance) == 0 &&
+ (major = ddi_name_to_major(devname)) != (major_t)-1 &&
+ !GLDV3_DRV(major))
+ err = ENODEV;
+ }
+ miocnak(q, mp, 0, err);
}
+
/*
- * qi_srvp: srv(9e)
+ * DLDIOCVLAN
*/
+typedef struct dld_ioc_vlan_state {
+ uint_t bytes_left;
+ uint_t count;
+ dld_vlan_info_t *vlanp;
+} dld_ioc_vlan_state_t;
+
+static int
+drv_ioc_vlan_info(dls_vlan_t *dvp, void *arg)
+{
+ dld_ioc_vlan_state_t *statep = arg;
+
+ if (statep->bytes_left < sizeof (dld_vlan_info_t))
+ return (ENOSPC);
+
+ (void) strlcpy(statep->vlanp->dvi_name, dvp->dv_name, IFNAMSIZ);
+ statep->vlanp->dvi_vid = dvp->dv_id;
+
+ statep->count++;
+ statep->bytes_left -= sizeof (dld_vlan_info_t);
+ statep->vlanp += 1;
+ return (0);
+}
+
static void
-drv_uw_srv(queue_t *wq)
+drv_ioc_vlan(dld_ctl_str_t *ctls, mblk_t *mp)
{
- mblk_t *mp = NULL;
- mblk_t *p;
- mblk_t **pp;
- dld_str_t *dsp;
+ dld_ioc_vlan_t *divp;
+ dld_ioc_vlan_state_t state;
+ int err = EINVAL;
+ queue_t *q = ctls->cs_wq;
- dsp = wq->q_ptr;
- ASSERT(dsp != NULL);
+ if ((err = miocpullup(mp, sizeof (dld_ioc_vlan_t))) != 0)
+ goto failed;
- /*
- * Loop round and pull a chain of messages from the queue.
- */
- for (pp = &mp; (p = getq(wq)) != NULL; pp = &(p->b_next))
- *pp = p;
+ divp = (dld_ioc_vlan_t *)mp->b_cont->b_rptr;
+ state.bytes_left = MBLKL(mp->b_cont) - sizeof (dld_ioc_vlan_t);
+ state.count = 0;
+ state.vlanp = (dld_vlan_info_t *)(divp + 1);
- /*
- * If there was nothing on the queue then there's nothing to do.
- */
- if (mp == NULL)
+ err = dls_vlan_walk(drv_ioc_vlan_info, &state);
+ if (err != 0)
+ goto failed;
+
+ divp->div_count = state.count;
+ miocack(q, mp, sizeof (dld_ioc_vlan_t) +
+ state.count * sizeof (dld_vlan_info_t), 0);
+ return;
+
+failed:
+ ASSERT(err != 0);
+ miocnak(q, mp, 0, err);
+}
+
+
+/*
+ * Process an IOCTL message received by the control node.
+ */
+static void
+drv_ioc(dld_ctl_str_t *ctls, mblk_t *mp)
+{
+ uint_t cmd;
+
+ cmd = ((struct iocblk *)mp->b_rptr)->ioc_cmd;
+ switch (cmd) {
+ case DLDIOCATTR:
+ drv_ioc_attr(ctls, mp);
+ return;
+ case DLDIOCVLAN:
+ drv_ioc_vlan(ctls, mp);
return;
+ default:
+ miocnak(ctls->cs_wq, mp, 0, ENOTSUP);
+ return;
+ }
+}
- /*
- * Call the srv(9e) processor.
- */
- dld_str_srv(dsp, mp);
+/*
+ * Write side put routine of the dld control node.
+ */
+static void
+drv_uw_put(queue_t *q, mblk_t *mp)
+{
+ dld_ctl_str_t *ctls = q->q_ptr;
+
+ switch (mp->b_datap->db_type) {
+ case M_IOCTL:
+ drv_ioc(ctls, mp);
+ break;
+ default:
+ freemsg(mp);
+ break;
+ }
+}
+
+/*
+ * Write-side service procedure.
+ */
+void
+drv_uw_srv(queue_t *q)
+{
+ mblk_t *mp;
+
+ while (mp = getq(q))
+ drv_uw_put(q, mp);
}
diff --git a/usr/src/uts/common/io/dld/dld_ioc.c b/usr/src/uts/common/io/dld/dld_ioc.c
deleted file mode 100644
index cbb3016df0..0000000000
--- a/usr/src/uts/common/io/dld/dld_ioc.c
+++ /dev/null
@@ -1,396 +0,0 @@
-/*
- * 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.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-/*
- * Data-Link Driver
- */
-
-#include <sys/types.h>
-#include <sys/stream.h>
-#include <sys/strsubr.h>
-#include <sys/ddi.h>
-#include <sys/sunddi.h>
-#include <sys/strsun.h>
-#include <sys/dlpi.h>
-#include <sys/mac.h>
-#include <sys/dls.h>
-#include <sys/dld.h>
-#include <sys/dld_impl.h>
-
-static void ioc_excl(queue_t *, mblk_t *);
-static void ioc_raw(dld_str_t *, mblk_t *);
-static void ioc_fast(dld_str_t *, mblk_t *);
-static void ioc_create(dld_str_t *, mblk_t *);
-static void ioc_destroy(dld_str_t *, mblk_t *);
-static void ioc_attr(dld_str_t *, mblk_t *);
-static void ioc(dld_str_t *, mblk_t *);
-
-typedef struct ioc_info {
- int i_cmd;
- const char *i_txt;
- uint_t i_type;
- void (*i_fn)(dld_str_t *, mblk_t *);
-} ioc_info_t;
-
-/*
- * DLIOC category jump table.
- */
-static ioc_info_t ioc_i[] = {
- { 0x00, "unknown", DLD_CONTROL | DLD_DLPI, ioc },
- { DLIOCRAW, "DLIOCRAW", DLD_DLPI, ioc_raw },
- { 0x02, "unknown", DLD_CONTROL | DLD_DLPI, ioc },
- { 0x03, "unknown", DLD_CONTROL | DLD_DLPI, ioc },
- { 0x04, "unknown", DLD_CONTROL | DLD_DLPI, ioc },
- { 0x05, "unknown", DLD_CONTROL | DLD_DLPI, ioc },
- { 0x06, "unknown", DLD_CONTROL | DLD_DLPI, ioc },
- { 0x07, "unknown", DLD_CONTROL | DLD_DLPI, ioc },
- { 0x08, "unknown", DLD_CONTROL | DLD_DLPI, ioc },
- { 0x09, "unknown", DLD_CONTROL | DLD_DLPI, ioc },
- { DLIOCHDRINFO, "DLIOCHDRINFO", DLD_DLPI, ioc_fast }
-};
-
-#define IOC_I_COUNT (sizeof (ioc_i) / sizeof (ioc_i[0]))
-
-/*
- * DLDIOC category jump table.
- */
-static ioc_info_t ioc_li[] = {
- { 0x00, "unknown", DLD_CONTROL | DLD_DLPI, ioc },
- { DLDIOCCREATE, "DLDIOC_CREATE", DLD_CONTROL, ioc_create },
- { DLDIOCDESTROY, "DLDIOC_DESTROY", DLD_CONTROL, ioc_destroy },
- { DLDIOCATTR, "DLDIOC_ATTR", DLD_CONTROL, ioc_attr }
-};
-
-#define IOC_LI_COUNT (sizeof (ioc_li) / sizeof (ioc_li[0]))
-
-/*
- * Process an M_IOCTL message.
- */
-void
-dld_ioc(dld_str_t *dsp, mblk_t *mp)
-{
- /*
- * We only have shared access and we need exclusive access.
- */
- ASSERT(!PERIM_EXCL(dsp->ds_wq));
-
- qwriter(dsp->ds_wq, mp, ioc_excl, PERIM_INNER);
-}
-
-/*
- * Called via qwriter(9f).
- */
-static void
-ioc_excl(queue_t *q, mblk_t *mp)
-{
- dld_str_t *dsp = q->q_ptr;
- struct iocblk *iocp;
- uint_t cmd;
- ioc_info_t *ip;
- uint_t cat;
-
- iocp = (struct iocblk *)mp->b_rptr;
- cmd = iocp->ioc_cmd;
-
- /*
- * We treat the least significate byte as the actual command and
- * the rest of it as a category.
- */
- cat = cmd & ~0xff;
- cmd &= 0xff;
-
- /*
- * Select the jump table according to the category.
- */
- switch (cat) {
- case DLIOC:
- if (cmd >= IOC_I_COUNT)
- goto unknown;
-
- ip = &ioc_i[cmd];
- break;
-
- case DLDIOC:
- if (cmd >= IOC_LI_COUNT)
- goto unknown;
-
- ip = &ioc_li[cmd];
- break;
-
- default:
- goto unknown;
- }
-
- ASSERT(ip->i_cmd == (cat | cmd));
-
- /*
- * Different ioctls are restricted to different types of stream. (I.e.
- * some ioctls are only for the control node, some are for provider
- * nodes).
- */
- if (!(dsp->ds_type & ip->i_type)) {
- miocnak(dsp->ds_wq, mp, 0, ENOTSUP);
- return;
- }
-
- ASSERT(ip->i_fn != NULL);
-
- ip->i_fn(dsp, mp);
- return;
-
-unknown:
- ioc(dsp, mp);
-}
-
-/*
- * DLIOCRAW
- */
-static void
-ioc_raw(dld_str_t *dsp, mblk_t *mp)
-{
- ASSERT(PERIM_EXCL(dsp->ds_wq));
- ASSERT(dsp->ds_type == DLD_DLPI);
-
- if (dsp->ds_polling) {
- miocnak(dsp->ds_wq, mp, 0, EPROTO);
- return;
- }
-
- if (dsp->ds_dlstate == DL_IDLE) {
- /*
- * Set the receive callback.
- */
- dls_rx_set(dsp->ds_dc, dld_str_rx_raw, dsp);
-
- /*
- * Set the M_DATA handler.
- */
- dld_str_tx_raw(dsp);
- }
-
- /*
- * Note that raw mode is enabled.
- */
- dsp->ds_mode = DLD_RAW;
-
- miocack(dsp->ds_wq, mp, 0, 0);
-}
-
-/*
- * DLIOCHDRINFO
- */
-static void
-ioc_fast(dld_str_t *dsp, mblk_t *mp)
-{
- dl_unitdata_req_t *dlp;
- off_t off;
- size_t len;
- const uint8_t *addr;
- uint16_t sap;
- mblk_t *nmp;
- mblk_t *hmp;
- const mac_info_t *mip;
- uint_t addr_length;
-
- ASSERT(PERIM_EXCL(dsp->ds_wq));
- ASSERT(dsp->ds_type == DLD_DLPI);
-
- if (dld_opt & DLD_OPT_NO_FASTPATH) {
- miocnak(dsp->ds_wq, mp, 0, ENOTSUP);
- return;
- }
-
- nmp = mp->b_cont;
-
- dlp = (dl_unitdata_req_t *)nmp->b_rptr;
- if (MBLKL(nmp) < sizeof (dl_unitdata_req_t) ||
- dlp->dl_primitive != DL_UNITDATA_REQ) {
- miocnak(dsp->ds_wq, mp, 0, EINVAL);
- return;
- }
-
- off = dlp->dl_dest_addr_offset;
- len = dlp->dl_dest_addr_length;
-
- if (!MBLKIN(nmp, off, len)) {
- miocnak(dsp->ds_wq, mp, 0, EINVAL);
- return;
- }
-
- if (dsp->ds_dlstate != DL_IDLE) {
- miocnak(dsp->ds_wq, mp, 0, ENOTSUP);
- return;
- }
-
- mip = dsp->ds_mip;
- addr_length = mip->mi_addr_length;
- if (len != addr_length + sizeof (uint16_t)) {
- miocnak(dsp->ds_wq, mp, 0, EINVAL);
- return;
- }
-
- addr = nmp->b_rptr + off;
- sap = *(uint16_t *)(nmp->b_rptr + off + addr_length);
-
- if ((hmp = dls_header(dsp->ds_dc, addr, sap, dsp->ds_pri)) == NULL) {
- miocnak(dsp->ds_wq, mp, 0, ENOMEM);
- return;
- }
-
- freemsg(nmp->b_cont);
- nmp->b_cont = hmp;
-
- /*
- * Set the receive callback (unless polling is enabled).
- */
- if (!dsp->ds_polling)
- dls_rx_set(dsp->ds_dc, dld_str_rx_fastpath, (void *)dsp);
-
- /*
- * Set the M_DATA handler.
- */
- dld_str_tx_fastpath(dsp);
-
- /*
- * Note that fast-path mode is enabled.
- */
- dsp->ds_mode = DLD_FASTPATH;
-
- miocack(dsp->ds_wq, mp, MBLKL(nmp) + MBLKL(hmp), 0);
-}
-
-/*
- * DLDIOCCREATE
- */
-static void
-ioc_create(dld_str_t *dsp, mblk_t *mp)
-{
- dld_ioc_create_t *dicp;
- mblk_t *nmp;
- int err;
-
- ASSERT(PERIM_EXCL(dsp->ds_wq));
- ASSERT(dsp->ds_type == DLD_CONTROL);
-
- if ((err = miocpullup(mp, sizeof (dld_ioc_create_t))) != 0) {
- miocnak(dsp->ds_wq, mp, 0, err);
- return;
- }
-
- nmp = mp->b_cont;
-
- dicp = (dld_ioc_create_t *)nmp->b_rptr;
- if ((err = dld_ppa_create(dicp->dic_name, dicp->dic_dev,
- dicp->dic_port, dicp->dic_vid)) != 0) {
- miocnak(dsp->ds_wq, mp, 0, err);
- return;
- }
-
- miocack(dsp->ds_wq, mp, 0, 0);
-}
-
-/*
- * DLDIOCDESTROY
- */
-static void
-ioc_destroy(dld_str_t *dsp, mblk_t *mp)
-{
- dld_ioc_destroy_t *didp;
- mblk_t *nmp;
- int err;
-
- ASSERT(PERIM_EXCL(dsp->ds_wq));
- ASSERT(dsp->ds_type == DLD_CONTROL);
-
- if ((err = miocpullup(mp, sizeof (dld_ioc_destroy_t))) != 0) {
- miocnak(dsp->ds_wq, mp, 0, err);
- return;
- }
-
- nmp = mp->b_cont;
-
- didp = (dld_ioc_destroy_t *)nmp->b_rptr;
- if ((err = dld_ppa_destroy(didp->did_name)) != 0) {
- miocnak(dsp->ds_wq, mp, 0, err);
- return;
- }
-
- miocack(dsp->ds_wq, mp, 0, 0);
-}
-
-/*
- * DLDIOCATTR
- */
-static void
-ioc_attr(dld_str_t *dsp, mblk_t *mp)
-{
- dld_ioc_attr_t *diap;
- mblk_t *nmp;
- int err;
-
- ASSERT(PERIM_EXCL(dsp->ds_wq));
- ASSERT(dsp->ds_type == DLD_CONTROL);
-
- if ((err = miocpullup(mp, sizeof (dld_ioc_attr_t))) != 0) {
- miocnak(dsp->ds_wq, mp, 0, err);
- return;
- }
-
- nmp = mp->b_cont;
-
- diap = (dld_ioc_attr_t *)nmp->b_rptr;
- if ((err = dld_ppa_attr(diap->dia_name, diap->dia_dev,
- &diap->dia_port, &diap->dia_vid)) != 0) {
- miocnak(dsp->ds_wq, mp, 0, err);
- return;
- }
-
- miocack(dsp->ds_wq, mp, sizeof (dld_ioc_attr_t), 0);
-}
-
-/*
- * Catch-all handler.
- */
-static void
-ioc(dld_str_t *dsp, mblk_t *mp)
-{
- ASSERT(PERIM_EXCL(dsp->ds_wq));
-
- if (dsp->ds_type == DLD_CONTROL) {
- miocnak(dsp->ds_wq, mp, 0, EINVAL);
- return;
- }
-
- if (dsp->ds_dlstate == DL_UNATTACHED) {
- miocnak(dsp->ds_wq, mp, 0, EINVAL);
- return;
- }
-
- ASSERT(dsp->ds_mh != NULL);
- mac_ioctl(dsp->ds_mh, dsp->ds_wq, mp);
-}
diff --git a/usr/src/uts/common/io/dld/dld_minor.c b/usr/src/uts/common/io/dld/dld_minor.c
deleted file mode 100644
index d729e54833..0000000000
--- a/usr/src/uts/common/io/dld/dld_minor.c
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * 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.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-/*
- * Data-Link Driver
- */
-
-#include <sys/types.h>
-#include <sys/mkdev.h>
-#include <sys/conf.h>
-#include <sys/stat.h>
-#include <sys/ddi.h>
-#include <sys/sunddi.h>
-#include <sys/vmem.h>
-#include <sys/atomic.h>
-
-#include <sys/dld.h>
-#include <sys/dld_impl.h>
-
-static vmem_t *minor_arenap;
-static uint32_t minor_count;
-
-#define MINOR_TO_PTR(minor) ((void *)(uintptr_t)(minor))
-#define PTR_TO_MINOR(ptr) ((minor_t)(uintptr_t)(ptr))
-
-/*
- * Initialize this module's data structures.
- */
-void
-dld_minor_init(void)
-{
- /*
- * Allocate a vmem arena to manage minor numbers. The range of the
- * arena will be from 1 to MAXMIN (maximum legal minor number).
- */
- minor_arenap = vmem_create("dld_minor_arena", MINOR_TO_PTR(1), MAXMIN,
- 1, NULL, NULL, NULL, 0, VM_SLEEP);
- ASSERT(minor_arenap != NULL);
-}
-
-/*
- * Tear down this module's data structures.
- */
-int
-dld_minor_fini(void)
-{
- /*
- * Check to see if there are any minor numbers still in use.
- */
- if (minor_count != 0)
- return (EBUSY);
-
- vmem_destroy(minor_arenap);
- return (0);
-}
-
-/*
- * Allocate a new minor number.
- */
-minor_t
-dld_minor_hold(boolean_t sleep)
-{
- minor_t minor;
-
- /*
- * Grab a value from the arena.
- */
- if ((minor = PTR_TO_MINOR(vmem_alloc(minor_arenap, 1,
- (sleep) ? VM_SLEEP : VM_NOSLEEP))) == 0)
- return (0);
-
- atomic_add_32(&minor_count, 1);
- return (minor);
-}
-
-/*
- * Release a previously allocated minor number.
- */
-void
-dld_minor_rele(minor_t minor)
-{
- /*
- * Return the value to the arena.
- */
- vmem_free(minor_arenap, MINOR_TO_PTR(minor), 1);
-
- atomic_add_32(&minor_count, -1);
-}
diff --git a/usr/src/uts/common/io/dld/dld_node.c b/usr/src/uts/common/io/dld/dld_node.c
deleted file mode 100644
index 57d28787ab..0000000000
--- a/usr/src/uts/common/io/dld/dld_node.c
+++ /dev/null
@@ -1,544 +0,0 @@
-/*
- * 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.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-/*
- * Data-Link Driver
- */
-
-#include <sys/types.h>
-#include <sys/conf.h>
-#include <sys/stat.h>
-#include <sys/ddi.h>
-#include <sys/sunddi.h>
-#include <sys/ght.h>
-#include <sys/atomic.h>
-#include <sys/fs/dv_node.h>
-#include <sys/dld.h>
-#include <sys/dld_impl.h>
-
-static int node_constructor(void *, void *, int);
-static void node_destructor(void *, void *);
-static dld_node_t *node_create(const char *, t_uscalar_t);
-static void node_destroy(dld_node_t *);
-static int node_insert(dld_node_t *);
-static void node_remove(dld_node_t *);
-static dld_node_t *node_find_byminor(minor_t);
-static dld_node_t *node_find_byname(const char *);
-
-static kmem_cache_t *node_cachep;
-static ght_t node_byminor_hash;
-static ght_t node_byname_hash;
-
-#define NODE_HASHSZ 67 /* prime value */
-
-/*
- * Initialize this module's data structures.
- */
-void
-dld_node_init(void)
-{
- int err;
-
- /*
- * Create a cache of dld_node_t structures.
- */
- node_cachep = kmem_cache_create("dld_node_cache", sizeof (dld_node_t),
- 0, node_constructor, node_destructor, NULL, NULL, NULL, 0);
- ASSERT(node_cachep != NULL);
-
- /*
- * Create a scalar hash to be keyed by minor number.
- */
- err = ght_scalar_create("dld_node_byminor_hash", NODE_HASHSZ,
- &node_byminor_hash);
- ASSERT(err == 0);
-
- /*
- * Create a string hash to be keyed by name.
- */
- err = ght_str_create("dld_node_byname_hash", NODE_HASHSZ,
- &node_byname_hash);
- ASSERT(err == 0);
-}
-
-/*
- * Tear down this module's data structures.
- */
-int
-dld_node_fini(void)
-{
- int err;
-
- /*
- * Check to make sure that the hash tables are empty.
- */
- ASSERT(ght_count(node_byname_hash) == ght_count(node_byminor_hash));
- if (ght_count(node_byname_hash) != 0)
- return (EBUSY);
-
- err = ght_destroy(node_byname_hash);
- ASSERT(err == 0);
-
- err = ght_destroy(node_byminor_hash);
- ASSERT(err == 0);
-
- kmem_cache_destroy(node_cachep);
- return (0);
-}
-
-/*
- * Find an existing node of the given style or create one if none is found.
- * Bump a reference count on the node to note that fact that a reference to
- * it is now held.
- */
-dld_node_t *
-dld_node_hold(const char *name, t_uscalar_t style)
-{
- dld_node_t *dnp;
- int err;
-
- ght_lock(node_byname_hash, GHT_WRITE);
- if ((dnp = node_find_byname(name)) == NULL) {
-
- if ((dnp = node_create(name, style)) == NULL) {
- ght_unlock(node_byname_hash);
- return (NULL);
- }
-
- ght_lock(node_byminor_hash, GHT_WRITE);
- err = node_insert(dnp);
- ght_unlock(node_byminor_hash);
-
- if (err != 0) {
- node_destroy(dnp);
- ght_unlock(node_byname_hash);
- return (NULL);
- }
- } else {
- /*
- * Make sure it's the right style.
- */
- if (dnp->dn_style != style) {
- ght_unlock(node_byname_hash);
- return (NULL);
- }
- }
-
- dnp->dn_ref++;
- ght_unlock(node_byname_hash);
- return (dnp);
-}
-
-/*
- * Look up a node by minor number. No reference count is bumped in this case
- * because of the transient nature of how the reference is used. (See
- * drv_open()).
- */
-dld_node_t *
-dld_node_find(minor_t minor)
-{
- dld_node_t *dnp;
-
- ght_lock(node_byminor_hash, GHT_READ);
- dnp = node_find_byminor(minor);
- ght_unlock(node_byminor_hash);
-
- return (dnp);
-}
-
-/*
- * Release a previously held reference to a dld_node_t.
- */
-void
-dld_node_rele(dld_node_t *dnp)
-{
- ght_lock(node_byname_hash, GHT_WRITE);
- if (--dnp->dn_ref == 0) {
- ght_lock(node_byminor_hash, GHT_WRITE);
- node_remove(dnp);
- ght_unlock(node_byminor_hash);
- node_destroy(dnp);
- }
- ght_unlock(node_byname_hash);
-}
-
-/*
- * kmem_cache constructor function: see kmem_cache_create(9f).
- */
-/*ARGSUSED*/
-static int
-node_constructor(void *buf, void *cdrarg, int kmflags)
-{
- dld_node_t *dnp = buf;
-
- bzero(buf, sizeof (dld_node_t));
-
- /*
- * Reserve a minor number for this node.
- */
- if ((dnp->dn_minor = dld_minor_hold(kmflags == KM_SLEEP)) == 0)
- return (-1);
-
- return (0);
-}
-
-/*
- * kmem_cache destructor function.
- */
-/*ARGSUSED*/
-static void
-node_destructor(void *buf, void *cdrarg)
-{
- dld_node_t *dnp = buf;
-
- /*
- * Release the minor number.
- */
- dld_minor_rele(dnp->dn_minor);
-}
-
-/*
- * Create a new dld_node_t object.
- */
-static dld_node_t *
-node_create(const char *name, t_uscalar_t style)
-{
- dld_node_t *dnp;
- char *buf;
- int err;
-#define SUFFIX "_ppa_hash"
-
- ASSERT(strlen(name) < IFNAMSIZ);
- ASSERT(style == DL_STYLE1 || style == DL_STYLE2);
-
- dnp = kmem_cache_alloc(node_cachep, KM_SLEEP);
-
- (void) strlcpy(dnp->dn_name, name, IFNAMSIZ);
-
- dnp->dn_style = style;
-
- if (style == DL_STYLE2) {
- /*
- * For style 2 nodes we need to create a private hash table
- * to manage the multiple PPAs.
- */
- size_t size = strlen(dnp->dn_name) + strlen(SUFFIX) + 1;
- buf = kmem_alloc(size, KM_SLEEP);
- (void) sprintf(buf, "%s" SUFFIX, name);
-
- err = ght_scalar_create(buf, NODE_HASHSZ, &(dnp->dn_hash));
- ASSERT(err == 0);
-
- kmem_free(buf, size);
- }
-
- /*
- * Create a dev_t in the file system with the given name.
- */
- if (ddi_create_minor_node(dld_dip, (char *)dnp->dn_name, S_IFCHR,
- dnp->dn_minor, DDI_NT_NET, 0) != DDI_SUCCESS)
- goto failed;
-
- return (dnp);
-
-failed:
- node_destroy(dnp);
- return (NULL);
-
-#undef SUFFIX
-}
-
-/*
- * Destroy a dld_node_t object.
- */
-static void
-node_destroy(dld_node_t *dnp)
-{
- int err;
-
- ASSERT(dnp->dn_ref == 0);
-
- if (dnp->dn_style == DL_STYLE2) {
- /*
- * This was a style 2 node so we must destroy the private
- * hash table.
- */
- err = ght_destroy(dnp->dn_hash);
- ASSERT(err == 0);
- }
-
- /*
- * Remove the dev_t from the file system.
- */
- ddi_remove_minor_node(dld_dip, dnp->dn_name);
-
- /*
- * Work around an apparent bug in devfs where /devices is not
- * kept up-to-date.
- */
- (void) devfs_clean(ddi_get_parent(dld_dip), NULL, 0);
-
- kmem_cache_free(node_cachep, dnp);
-}
-
-/*
- * Insert a node into both global hash tables.
- */
-static int
-node_insert(dld_node_t *dnp)
-{
- ghte_t byminor_hte;
- ghte_t byname_hte;
- int err;
-
- /*
- * Allocate a new entry for the 'by minor' hash table.
- */
- if ((byminor_hte = ght_alloc(node_byminor_hash, KM_NOSLEEP)) == NULL)
- return (ENOMEM);
-
- /*
- * Fill in the information.
- */
- GHT_KEY(byminor_hte) = GHT_SCALAR_TO_KEY(dnp->dn_minor);
- GHT_VAL(byminor_hte) = GHT_PTR_TO_VAL(dnp);
-
- /*
- * Insert the node into the table.
- */
- if ((err = ght_insert(byminor_hte)) != 0) {
- ght_free(byminor_hte);
- return (err);
- }
-
- ASSERT(dnp->dn_byminor_hte == NULL);
- dnp->dn_byminor_hte = byminor_hte;
-
- /*
- * Allocate a new node for the 'by name' hash table.
- */
- if ((byname_hte = ght_alloc(node_byname_hash, KM_NOSLEEP)) == NULL)
- goto failed;
-
- /*
- * Fill in the information.
- */
- GHT_KEY(byname_hte) = GHT_PTR_TO_KEY(dnp->dn_name);
- GHT_VAL(byname_hte) = GHT_PTR_TO_VAL(dnp);
-
- /*
- * Insert the node into the table.
- */
- if ((err = ght_insert(byname_hte)) != 0) {
- ght_free(byname_hte);
- goto failed;
- }
-
- ASSERT(dnp->dn_byname_hte == NULL);
- dnp->dn_byname_hte = byname_hte;
-
- return (0);
-
-failed:
- ght_remove(dnp->dn_byminor_hte);
- dnp->dn_byminor_hte = NULL;
-
- return (err);
-}
-
-/*
- * Remove a node from both the global hash tables.
- */
-static void
-node_remove(dld_node_t *dnp)
-{
- /*
- * Remove the node from the 'by name' hash table and free.
- */
- ASSERT(dnp->dn_byname_hte != NULL);
- ght_remove(dnp->dn_byname_hte);
- ght_free(dnp->dn_byname_hte);
- dnp->dn_byname_hte = NULL;
-
- /*
- * Remove the node from the 'by minor' hash table and free.
- */
- ASSERT(dnp->dn_byminor_hte != NULL);
- ght_remove(dnp->dn_byminor_hte);
- ght_free(dnp->dn_byminor_hte);
- dnp->dn_byminor_hte = NULL;
-}
-
-/*
- * Look up a node in the 'by minor' table.
- */
-static dld_node_t *
-node_find_byminor(minor_t minor)
-{
- ghte_t hte;
-
- if (ght_find(node_byminor_hash, GHT_SCALAR_TO_KEY(minor), &hte) != 0)
- return (NULL);
-
- return ((dld_node_t *)GHT_VAL(hte));
-}
-
-/*
- * Look up a node in the 'by name' table.
- */
-static dld_node_t *
-node_find_byname(const char *name)
-{
- ghte_t hte;
-
- if (ght_find(node_byname_hash, GHT_PTR_TO_KEY(name), &hte) != 0)
- return (NULL);
-
- return ((dld_node_t *)GHT_VAL(hte));
-}
-
-/*
- * Add a PPA to a node.
- */
-int
-dld_node_ppa_add(dld_node_t *dnp, t_scalar_t index, dld_ppa_t *dpp)
-{
- ghte_t hte;
- int err;
-
- if (dnp->dn_style == DL_STYLE1) {
- /*
- * Only a single PPA can be added to a style 1 node so we
- * insist that the index number argument is set to -1.
- */
- ASSERT(index == -1);
-
- /*
- * Check to see if there is an existing PPA.
- */
- if (dnp->dn_dpp != NULL)
- return (EEXIST);
-
- dnp->dn_dpp = dpp;
- return (0);
- }
- ASSERT(dnp->dn_style == DL_STYLE2);
-
- /*
- * Multiple PPAs can be added to a style 2 node and so we
- * insist that the index number argument is zero or greater.
- */
- ASSERT(index >= 0);
-
- /*
- * Allocate an entry for the private hash table.
- */
- hte = ght_alloc(dnp->dn_hash, KM_SLEEP);
-
- /*
- * Fill in the information.
- */
- GHT_KEY(hte) = GHT_SCALAR_TO_KEY(index);
- GHT_VAL(hte) = GHT_PTR_TO_VAL(dpp);
-
- /*
- * Lock the table.
- */
- ght_lock(dnp->dn_hash, GHT_WRITE);
-
- /*
- * Insert the node into the table.
- */
- if ((err = ght_insert(hte)) != 0)
- ght_free(hte);
-
- /*
- * Unlock the table.
- */
- ght_unlock(dnp->dn_hash);
- return (err);
-}
-
-/*
- * Remove a PPA from the node.
- */
-int
-dld_node_ppa_remove(dld_node_t *dnp, t_scalar_t index)
-{
- ghte_t hte;
- int err;
-
- if (dnp->dn_style == DL_STYLE1) {
- ASSERT(index == -1);
-
- if (dnp->dn_dpp == NULL)
- return (ENOENT);
-
- dnp->dn_dpp = NULL;
- return (0);
- }
- ASSERT(dnp->dn_style == DL_STYLE2);
-
- ASSERT(index >= 0);
-
- ght_lock(dnp->dn_hash, GHT_WRITE);
- if ((err = ght_find(dnp->dn_hash, GHT_SCALAR_TO_KEY(index),
- &hte)) == 0) {
- ght_remove(hte);
- ght_free(hte);
- }
- ght_unlock(dnp->dn_hash);
-
- return (err);
-}
-
-/*
- * Look up a dld_ppa_t from a dld_node_t.
- */
-dld_ppa_t *
-dld_node_ppa_find(dld_node_t *dnp, t_scalar_t index)
-{
- ghte_t hte;
-
- if (dnp->dn_style == DL_STYLE1) {
- ASSERT(index == -1);
- return (dnp->dn_dpp);
- }
- ASSERT(dnp->dn_style == DL_STYLE2);
-
- ASSERT(index >= 0);
-
- ght_lock(dnp->dn_hash, GHT_READ);
- if (ght_find(dnp->dn_hash, GHT_SCALAR_TO_KEY(index), &hte) != 0) {
- ght_unlock(dnp->dn_hash);
- return (NULL);
- }
- ght_unlock(dnp->dn_hash);
-
- return ((dld_ppa_t *)GHT_VAL(hte));
-}
diff --git a/usr/src/uts/common/io/dld/dld_ppa.c b/usr/src/uts/common/io/dld/dld_ppa.c
deleted file mode 100644
index 450bef44fc..0000000000
--- a/usr/src/uts/common/io/dld/dld_ppa.c
+++ /dev/null
@@ -1,373 +0,0 @@
-/*
- * 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.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-/*
- * Data-Link Driver
- */
-
-#include <sys/types.h>
-#include <sys/dlpi.h>
-#include <sys/atomic.h>
-#include <sys/ctype.h>
-#include <sys/ght.h>
-#include <net/if.h>
-
-#include <sys/dld.h>
-#include <sys/dld_impl.h>
-
-static int ppa_constructor(void *, void *, int);
-static void ppa_destructor(void *, void *);
-static int ppa_create(const char *, const char *, uint_t, uint16_t,
- dld_ppa_t **);
-static int ppa_destroy(dld_ppa_t *);
-static void ppa_attr(dld_ppa_t *, char *, uint_t *, uint16_t *);
-
-static kmem_cache_t *ppa_cachep;
-static ght_t ppa_hash;
-
-#define PPA_HASHSZ 23 /* prime value */
-
-/*
- * Initialize this module's data structures.
- */
-void
-dld_ppa_init(void)
-{
- int err;
-
- /*
- * Create a cache of dld_ppa_t objects.
- */
- ppa_cachep = kmem_cache_create("dld_ppa_cache", sizeof (dld_ppa_t), 0,
- ppa_constructor, ppa_destructor, NULL, NULL, NULL, 0);
- ASSERT(ppa_cachep != NULL);
-
- /*
- * Create a string hash table to be keyed by name.
- */
- err = ght_str_create("dld_ppa_hash", PPA_HASHSZ, &ppa_hash);
- ASSERT(err == 0);
-}
-
-/*
- * Tear down this module's data structures.
- */
-int
-dld_ppa_fini(void)
-{
- int err;
-
- /*
- * If the hash table cannot be destroyed then it is not empty.
- */
- if ((err = ght_destroy(ppa_hash)) != 0)
- return (err);
-
- kmem_cache_destroy(ppa_cachep);
- return (0);
-}
-
-/*
- * Create a new dld_ppa_t object.
- */
-int
-dld_ppa_create(const char *name, const char *dev, uint_t port, uint16_t vid)
-{
- dld_ppa_t *dpp;
- ghte_t hte;
- int err;
-
- ASSERT(strlen(name) < IFNAMSIZ);
- ASSERT(strlen(dev) < MAXNAMELEN);
-
- /*
- * Create the object.
- */
- if ((err = ppa_create(name, dev, port, vid, &dpp)) != 0)
- return (err);
-
- /*
- * Allocate an entry for the hash table.
- */
- hte = ght_alloc(ppa_hash, KM_SLEEP);
-
- /*
- * Fill in the information.
- */
- GHT_KEY(hte) = GHT_PTR_TO_KEY(dpp->dp_name);
- GHT_VAL(hte) = GHT_PTR_TO_VAL(dpp);
-
- /*
- * Lock the table.
- */
- ght_lock(ppa_hash, GHT_WRITE);
-
- /*
- * Insert the entry.
- */
- if ((err = ght_insert(hte)) != 0) {
- ght_free(hte);
- (void) ppa_destroy(dpp);
- }
-
- /*
- * Unlock the table.
- */
- ght_unlock(ppa_hash);
- return (err);
-}
-
-/*
- * Destroy a dld_ppa_t object.
- */
-int
-dld_ppa_destroy(const char *name)
-{
- ghte_t hte;
- int err;
- dld_ppa_t *dpp;
-
- ASSERT(strlen(name) < IFNAMSIZ);
-
- ght_lock(ppa_hash, GHT_WRITE);
- if ((err = ght_find(ppa_hash, GHT_PTR_TO_KEY(name), &hte)) != 0)
- goto failed;
-
- dpp = (dld_ppa_t *)GHT_VAL(hte);
- if ((err = ppa_destroy(dpp)) != 0)
- goto failed;
-
- ght_remove(hte);
- ght_free(hte);
-
-failed:
- ght_unlock(ppa_hash);
- return (err);
-}
-
-/*
- * Get the attributes of a dld_ppa_t object.
- */
-int
-dld_ppa_attr(const char *name, char *dev, uint_t *portp, uint16_t *vidp)
-{
- ghte_t hte;
- int err;
- dld_ppa_t *dpp;
-
- ASSERT(strlen(name) < IFNAMSIZ);
-
- ght_lock(ppa_hash, GHT_READ);
- if ((err = ght_find(ppa_hash, (ght_key_t)name, &hte)) == 0) {
- dpp = (dld_ppa_t *)GHT_VAL(hte);
- ppa_attr(dpp, dev, portp, vidp);
- }
- ght_unlock(ppa_hash);
-
- return (err);
-}
-
-/*
- * kmem_cache constructor function: see kmem_cache_create(9f).
- */
-/*ARGSUSED*/
-static int
-ppa_constructor(void *buf, void *cdrarg, int kmflags)
-{
- dld_ppa_t *dpp = buf;
-
- bzero(buf, sizeof (dld_ppa_t));
- dpp->dp_index = -1;
-
- return (0);
-}
-
-/*
- * kmem_cache destructor function
- */
-/*ARGSUSED*/
-static void
-ppa_destructor(void *buf, void *cdrarg)
-{
- dld_ppa_t *dpp = buf;
-
- ASSERT(dpp->dp_index == -1);
- ASSERT(dpp->dp_style1 == NULL);
- ASSERT(dpp->dp_style2 == NULL);
-}
-
-/*
- * Create a new dld_ppa_t.
- */
-static int
-ppa_create(const char *name, const char *dev, uint_t port, uint16_t vid,
- dld_ppa_t **dppp)
-{
- dld_ppa_t *dpp;
- dld_node_t *dnp;
- char provider[IFNAMSIZ];
- uint_t index;
- int err;
-
- /*
- * All dld_ppa_t must be represented by both style 1 and style 2
- * providers. Therefore their name must always be of the form
- * <DLS provider>##<PPA index>.
- */
- if (ddi_parse(name, provider, &index) != DDI_SUCCESS)
- return (EINVAL);
-
- /*
- * Allocate a dld_ppa_t from the cache.
- */
- dpp = kmem_cache_alloc(ppa_cachep, KM_SLEEP);
- (void) strlcpy(dpp->dp_name, name, IFNAMSIZ);
- (void) strlcpy(dpp->dp_dev, dev, MAXNAMELEN);
- dpp->dp_port = port;
- dpp->dp_vid = vid;
-
- /*
- * Create a data-link.
- */
- if ((err = dls_create(dpp->dp_name, dev, port, vid)) != 0) {
- kmem_cache_free(ppa_cachep, dpp);
- return (err);
- }
-
- /*
- * Create a style 1 dld_node_t, unless their use has been disabled.
- */
- if (!(dld_opt & DLD_OPT_NO_STYLE1)) {
- if ((dnp = dld_node_hold(name, DL_STYLE1)) == NULL) {
- err = ENOENT;
- goto failed;
- }
-
- /*
- * Add the dld_ppa_t to the dld_node_t and keep a backwards
- * reference.
- */
- if ((err = dld_node_ppa_add(dnp, -1, dpp)) != 0) {
- dld_node_rele(dnp);
- goto failed;
- }
-
- dpp->dp_style1 = dnp;
- }
-
- /*
- * Create, or grab a reference to an existing style 2 dld_node_t.
- */
- if ((dnp = dld_node_hold(provider, DL_STYLE2)) == NULL) {
- err = ENOENT;
- goto failed;
- }
-
- /*
- * Add the dld_ppa_t to the dld_node_t.
- */
- dpp->dp_index = index;
- if ((err = dld_node_ppa_add(dnp, dpp->dp_index, dpp)) != 0) {
- dld_node_rele(dnp);
- goto failed;
- }
-
- /*
- * Keep a backwards reference.
- */
- dpp->dp_style2 = dnp;
-
-done:
- *dppp = dpp;
- return (0);
-
-failed:
- (void) ppa_destroy(dpp);
- return (err);
-}
-
-/*
- * Destroy a dld_ppa_t.
- */
-static int
-ppa_destroy(dld_ppa_t *dpp)
-{
- dld_node_t *dnp;
- int err;
-
- /*
- * Destroy the data-link.
- */
- if ((err = dls_destroy(dpp->dp_name)) != 0) {
- ASSERT(err == EBUSY);
- return (EBUSY);
- }
-
- /*
- * If the style 2 dld_node_t exists then release it.
- */
- if ((dnp = dpp->dp_style2) != NULL) {
- ASSERT(dpp->dp_index != -1);
-
- err = dld_node_ppa_remove(dnp, dpp->dp_index);
- ASSERT(err == 0);
- dpp->dp_index = -1;
-
- dld_node_rele(dnp);
- dpp->dp_style2 = NULL;
- }
- ASSERT(dpp->dp_index == -1);
-
- /*
- * If the style 1 dld_node_t exists then release it.
- */
- if ((dnp = dpp->dp_style1) != NULL) {
- err = dld_node_ppa_remove(dnp, -1);
- ASSERT(err == 0);
-
- dld_node_rele(dnp);
- dpp->dp_style1 = NULL;
- }
-
- /*
- * Free the object back to the cache.
- */
- kmem_cache_free(ppa_cachep, dpp);
- return (0);
-}
-
-/*
- * Get the attributes of a dld_ppa_t.
- */
-static void
-ppa_attr(dld_ppa_t *dpp, char *dev, uint_t *portp, uint16_t *vidp)
-{
- (void) strlcpy(dev, dpp->dp_dev, MAXNAMELEN);
- *portp = dpp->dp_port;
- *vidp = dpp->dp_vid;
-}
diff --git a/usr/src/uts/common/io/dld/dld_proto.c b/usr/src/uts/common/io/dld/dld_proto.c
index 55da18f487..4dce2ecc6d 100644
--- a/usr/src/uts/common/io/dld/dld_proto.c
+++ b/usr/src/uts/common/io/dld/dld_proto.c
@@ -55,139 +55,9 @@ static proto_reqfunc_t proto_info_req, proto_attach_req, proto_detach_req,
proto_setphysaddr_req, proto_udqos_req, proto_req, proto_capability_req,
proto_notify_req, proto_unitdata_req, proto_passive_req;
-static void proto_excl(queue_t *, mblk_t *);
-static void proto_info_ack(dld_str_t *, mblk_t *);
-static void proto_attach_ack(dld_str_t *, mblk_t *, int);
-static void proto_detach_ack(dld_str_t *, mblk_t *);
-static void proto_bind_ack(dld_str_t *, mblk_t *, int);
-static void proto_unbind_ack(dld_str_t *, mblk_t *);
-static void proto_promiscon_ack(dld_str_t *, mblk_t *, int);
-static void proto_promiscoff_ack(dld_str_t *, mblk_t *, int);
-static void proto_enabmulti_ack(dld_str_t *, mblk_t *, int);
-static void proto_disabmulti_ack(dld_str_t *, mblk_t *, int);
-static void proto_setphysaddr_ack(dld_str_t *, mblk_t *, int);
-static void proto_physaddr_ack(dld_str_t *, mblk_t *, t_uscalar_t);
-static void proto_udqos_ack(dld_str_t *, mblk_t *);
-static void proto_poll_disable(dld_str_t *);
-static boolean_t proto_poll_enable(dld_str_t *, dl_capab_poll_t *);
-static void proto_capability_ack(dld_str_t *, mblk_t *);
-static void proto_capability_enable(dld_str_t *, mblk_t *);
-static void proto_notify_ack(dld_str_t *, mblk_t *, uint_t,
- uint_t);
-
-#define DL_SOLARIS 0x100
-
-/*
- * M_PROTO/M_PCPROTO request handlers
- */
-
-typedef struct proto_req_info {
- t_uscalar_t pri_prim;
- const char *pri_txt;
- boolean_t pri_needexcl;
- boolean_t pri_active;
- proto_reqfunc_t *pri_fn;
-} proto_req_info_t;
-
-static proto_req_info_t proto_ri[] = {
- { DL_INFO_REQ, "DL_INFO_REQ", B_FALSE, B_FALSE, proto_info_req },
- { DL_BIND_REQ, "DL_BIND_REQ", B_TRUE, B_TRUE, proto_bind_req },
- { DL_UNBIND_REQ, "DL_UNBIND_REQ", B_TRUE, B_FALSE, proto_unbind_req },
- { DL_INFO_ACK, "DL_INFO_ACK", B_FALSE, B_FALSE, proto_req },
- { DL_BIND_ACK, "DL_BIND_ACK", B_FALSE, B_FALSE, proto_req },
- { DL_ERROR_ACK, "DL_ERROR_ACK", B_FALSE, B_FALSE, proto_req },
- { DL_OK_ACK, "DL_OK_ACK", B_FALSE, B_FALSE, proto_req },
- { DL_UNITDATA_REQ, "DL_UNITDATA_REQ", B_FALSE, B_FALSE,
- proto_unitdata_req },
- { DL_UNITDATA_IND, "DL_UNITDATA_IND", B_FALSE, B_FALSE, proto_req },
- { DL_UDERROR_IND, "DL_UDERROR_IND", B_FALSE, B_FALSE, proto_req },
- { DL_UDQOS_REQ, "DL_UDQOS_REQ", B_TRUE, B_FALSE, proto_udqos_req },
- { DL_ATTACH_REQ, "DL_ATTACH_REQ", B_TRUE, B_FALSE, proto_attach_req },
- { DL_DETACH_REQ, "DL_DETACH_REQ", B_TRUE, B_FALSE, proto_detach_req },
- { DL_CONNECT_REQ, "DL_CONNECT_REQ", B_FALSE, B_FALSE, proto_req },
- { DL_CONNECT_IND, "DL_CONNECT_IND", B_FALSE, B_FALSE, proto_req },
- { DL_CONNECT_RES, "DL_CONNECT_RES", B_FALSE, B_FALSE, proto_req },
- { DL_CONNECT_CON, "DL_CONNECT_CON", B_FALSE, B_FALSE, proto_req },
- { DL_TOKEN_REQ, "DL_TOKEN_REQ", B_FALSE, B_FALSE, proto_req },
- { DL_TOKEN_ACK, "DL_TOKEN_ACK", B_FALSE, B_FALSE, proto_req },
- { DL_DISCONNECT_REQ, "DL_DISCONNECT_REQ", B_FALSE, B_FALSE, proto_req },
- { DL_DISCONNECT_IND, "DL_DISCONNECT_IND", B_FALSE, B_FALSE, proto_req },
- { DL_SUBS_UNBIND_REQ, "DL_SUBS_UNBIND_REQ", B_FALSE, B_FALSE,
- proto_req },
- { 0x16, "undefined", B_FALSE, B_FALSE, proto_req },
- { DL_RESET_REQ, "DL_RESET_REQ", B_FALSE, B_FALSE, proto_req },
- { DL_RESET_IND, "DL_RESET_IND", B_FALSE, B_FALSE, proto_req },
- { DL_RESET_RES, "DL_RESET_RES", B_FALSE, B_FALSE, proto_req },
- { DL_RESET_CON, "DL_RESET_CON", B_FALSE, B_FALSE, proto_req },
- { DL_SUBS_BIND_REQ, "DL_SUBS_BIND_REQ", B_FALSE, B_FALSE, proto_req },
- { DL_SUBS_BIND_ACK, "DL_SUBS_BIND_ACK", B_FALSE, B_FALSE, proto_req },
- { DL_ENABMULTI_REQ, "DL_ENABMULTI_REQ", B_TRUE, B_TRUE,
- proto_enabmulti_req },
- { DL_DISABMULTI_REQ, "DL_DISABMULTI_REQ", B_TRUE, B_FALSE,
- proto_disabmulti_req },
- { DL_PROMISCON_REQ, "DL_PROMISCON_REQ", B_TRUE, B_TRUE,
- proto_promiscon_req },
- { DL_PROMISCOFF_REQ, "DL_PROMISCOFF_REQ", B_TRUE, B_FALSE,
- proto_promiscoff_req },
- { DL_DATA_ACK_REQ, "DL_DATA_ACK_REQ", B_FALSE, B_FALSE, proto_req },
- { DL_DATA_ACK_IND, "DL_DATA_ACK_IND", B_FALSE, B_FALSE, proto_req },
- { DL_DATA_ACK_STATUS_IND, "DL_DATA_ACK_STATUS_IND", B_FALSE, B_FALSE,
- proto_req },
- { DL_REPLY_REQ, "DL_REPLY_REQ", B_FALSE, B_FALSE, proto_req },
- { DL_REPLY_IND, "DL_REPLY_IND", B_FALSE, B_FALSE, proto_req },
- { DL_REPLY_STATUS_IND, "DL_REPLY_STATUS_IND", B_FALSE, B_FALSE,
- proto_req },
- { DL_REPLY_UPDATE_REQ, "DL_REPLY_UPDATE_REQ", B_FALSE, B_FALSE,
- proto_req },
- { DL_REPLY_UPDATE_STATUS_IND, "DL_REPLY_UPDATE_STATUS_IND", B_FALSE,
- B_FALSE, proto_req },
- { DL_XID_REQ, "DL_XID_REQ", B_FALSE, B_FALSE, proto_req },
- { DL_XID_IND, "DL_XID_IND", B_FALSE, B_FALSE, proto_req },
- { DL_XID_RES, "DL_XID_RES", B_FALSE, B_FALSE, proto_req },
- { DL_XID_CON, "DL_XID_CON", B_FALSE, B_FALSE, proto_req },
- { DL_TEST_REQ, "DL_TEST_REQ", B_FALSE, B_FALSE, proto_req },
- { DL_TEST_IND, "DL_TEST_IND", B_FALSE, B_FALSE, proto_req },
- { DL_TEST_RES, "DL_TEST_RES", B_FALSE, B_FALSE, proto_req },
- { DL_TEST_CON, "DL_TEST_CON", B_FALSE, B_FALSE, proto_req },
- { DL_PHYS_ADDR_REQ, "DL_PHYS_ADDR_REQ", B_FALSE, B_FALSE,
- proto_physaddr_req },
- { DL_PHYS_ADDR_ACK, "DL_PHYS_ADDR_ACK", B_FALSE, B_FALSE, proto_req },
- { DL_SET_PHYS_ADDR_REQ, "DL_SET_PHYS_ADDR_REQ", B_TRUE, B_TRUE,
- proto_setphysaddr_req },
- { DL_GET_STATISTICS_REQ, "DL_GET_STATISTICS_REQ", B_FALSE, B_FALSE,
- proto_req },
- { DL_GET_STATISTICS_ACK, "DL_GET_STATISTICS_ACK", B_FALSE, B_FALSE,
- proto_req }
-};
-
-#define PROTO_RI_COUNT (sizeof (proto_ri) / sizeof (proto_ri[0]))
-
-static proto_req_info_t proto_sri[] = {
- { DL_NOTIFY_REQ, "DL_NOTIFY_REQ", B_FALSE, B_FALSE, proto_notify_req },
- { DL_NOTIFY_ACK, "DL_NOTIFY_ACK", B_FALSE, B_FALSE, proto_req },
- { DL_NOTIFY_IND, "DL_NOTIFY_IND", B_FALSE, B_FALSE, proto_req },
- { DL_AGGR_REQ, "DL_AGGR_REQ", B_FALSE, B_TRUE, proto_req },
- { DL_AGGR_IND, "DL_AGGR_IND", B_FALSE, B_FALSE, proto_req },
- { DL_UNAGGR_REQ, "DL_UNAGGR_REQ", B_FALSE, B_TRUE, proto_req },
- { 0x106, "undefined", B_FALSE, B_FALSE, proto_req },
- { 0x107, "undefined", B_FALSE, B_FALSE, proto_req },
- { 0x108, "undefined", B_FALSE, B_FALSE, proto_req },
- { 0x109, "undefined", B_FALSE, B_FALSE, proto_req },
- { 0x10a, "undefined", B_FALSE, B_FALSE, proto_req },
- { 0x10b, "undefined", B_FALSE, B_FALSE, proto_req },
- { 0x10c, "undefined", B_FALSE, B_FALSE, proto_req },
- { 0x10d, "undefined", B_FALSE, B_FALSE, proto_req },
- { 0x10e, "undefined", B_FALSE, B_FALSE, proto_req },
- { 0x10f, "undefined", B_FALSE, B_FALSE, proto_req },
- { DL_CAPABILITY_REQ, "DL_CAPABILITY_REQ", B_FALSE, B_FALSE,
- proto_capability_req },
- { DL_CAPABILITY_ACK, "DL_CAPABILITY_ACK", B_FALSE, B_FALSE, proto_req },
- { DL_CONTROL_REQ, "DL_CONTROL_REQ", B_FALSE, B_TRUE, proto_req },
- { DL_CONTROL_ACK, "DL_CONTROL_ACK", B_FALSE, B_FALSE, proto_req },
- { DL_PASSIVE_REQ, "DL_PASSIVE_REQ", B_TRUE, B_FALSE, proto_passive_req }
-};
-
-#define PROTO_SRI_COUNT (sizeof (proto_sri) / sizeof (proto_sri[0]))
+static void proto_poll_disable(dld_str_t *);
+static boolean_t proto_poll_enable(dld_str_t *, dl_capab_poll_t *);
+static boolean_t proto_capability_advertise(dld_str_t *, mblk_t *);
#define DL_ACK_PENDING(state) \
((state) == DL_ATTACH_PENDING || \
@@ -196,15 +66,18 @@ static proto_req_info_t proto_sri[] = {
(state) == DL_UNBIND_PENDING)
/*
- * Process a DLPI protocol message. (Only ever called from put(9e)).
+ * Process a DLPI protocol message.
+ * The primitives DL_BIND_REQ, DL_ENABMULTI_REQ, DL_PROMISCON_REQ,
+ * DL_SET_PHYS_ADDR_REQ put the data link below our dld_str_t into an
+ * 'active' state. The primitive DL_PASSIVE_REQ marks our dld_str_t
+ * as 'passive' and forbids it from being subsequently made 'active'
+ * by the above primitives.
*/
void
dld_proto(dld_str_t *dsp, mblk_t *mp)
{
union DL_primitives *udlp;
t_uscalar_t prim;
- proto_req_info_t *prip;
- boolean_t success;
if (MBLKL(mp) < sizeof (t_uscalar_t)) {
freemsg(mp);
@@ -214,159 +87,279 @@ dld_proto(dld_str_t *dsp, mblk_t *mp)
udlp = (union DL_primitives *)mp->b_rptr;
prim = udlp->dl_primitive;
+ switch (prim) {
+ case DL_INFO_REQ:
+ (void) proto_info_req(dsp, udlp, mp);
+ break;
+ case DL_BIND_REQ:
+ (void) proto_bind_req(dsp, udlp, mp);
+ break;
+ case DL_UNBIND_REQ:
+ (void) proto_unbind_req(dsp, udlp, mp);
+ break;
+ case DL_UNITDATA_REQ:
+ (void) proto_unitdata_req(dsp, udlp, mp);
+ break;
+ case DL_UDQOS_REQ:
+ (void) proto_udqos_req(dsp, udlp, mp);
+ break;
+ case DL_ATTACH_REQ:
+ (void) proto_attach_req(dsp, udlp, mp);
+ break;
+ case DL_DETACH_REQ:
+ (void) proto_detach_req(dsp, udlp, mp);
+ break;
+ case DL_ENABMULTI_REQ:
+ (void) proto_enabmulti_req(dsp, udlp, mp);
+ break;
+ case DL_DISABMULTI_REQ:
+ (void) proto_disabmulti_req(dsp, udlp, mp);
+ break;
+ case DL_PROMISCON_REQ:
+ (void) proto_promiscon_req(dsp, udlp, mp);
+ break;
+ case DL_PROMISCOFF_REQ:
+ (void) proto_promiscoff_req(dsp, udlp, mp);
+ break;
+ case DL_PHYS_ADDR_REQ:
+ (void) proto_physaddr_req(dsp, udlp, mp);
+ break;
+ case DL_SET_PHYS_ADDR_REQ:
+ (void) proto_setphysaddr_req(dsp, udlp, mp);
+ break;
+ case DL_NOTIFY_REQ:
+ (void) proto_notify_req(dsp, udlp, mp);
+ break;
+ case DL_CAPABILITY_REQ:
+ (void) proto_capability_req(dsp, udlp, mp);
+ break;
+ case DL_PASSIVE_REQ:
+ (void) proto_passive_req(dsp, udlp, mp);
+ break;
+ default:
+ (void) proto_req(dsp, udlp, mp);
+ break;
+ }
+}
+
+/*
+ * Finish any pending operations. At this moment we are single-threaded,
+ * hence there is no need to hold ds_lock as writer because we're already
+ * exclusive.
+ */
+void
+dld_finish_pending_ops(dld_str_t *dsp)
+{
+ ASSERT(MUTEX_HELD(&dsp->ds_thr_lock));
+ ASSERT(dsp->ds_thr == 0);
+
+ /* Pending DL_DETACH_REQ? */
+ if (dsp->ds_detach_req != NULL) {
+ mblk_t *mp;
+
+ ASSERT(dsp->ds_dlstate == DL_DETACH_PENDING);
+ dld_str_detach(dsp);
+
+ mp = dsp->ds_detach_req;
+ dsp->ds_detach_req = NULL;
+
+ mutex_exit(&dsp->ds_thr_lock);
+ dlokack(dsp->ds_wq, mp, DL_DETACH_REQ);
+ } else {
+ mutex_exit(&dsp->ds_thr_lock);
+ }
+}
+
+#define NEG(x) -(x)
+
+typedef struct dl_info_ack_wrapper {
+ dl_info_ack_t dl_info;
+ uint8_t dl_addr[MAXADDRLEN + sizeof (uint16_t)];
+ uint8_t dl_brdcst_addr[MAXADDRLEN];
+ dl_qos_cl_range1_t dl_qos_range1;
+ dl_qos_cl_sel1_t dl_qos_sel1;
+} dl_info_ack_wrapper_t;
+
+/*
+ * DL_INFO_REQ
+ */
+/*ARGSUSED*/
+static boolean_t
+proto_info_req(dld_str_t *dsp, union DL_primitives *udlp, mblk_t *mp)
+{
+ dl_info_ack_wrapper_t *dlwp;
+ dl_info_ack_t *dlp;
+ dl_qos_cl_sel1_t *selp;
+ dl_qos_cl_range1_t *rangep;
+ uint8_t *addr;
+ uint8_t *brdcst_addr;
+ uint_t addr_length;
+ uint_t sap_length;
+ mac_info_t minfo;
+ mac_info_t *minfop;
+ queue_t *q = dsp->ds_wq;
+
/*
- * Select the correct jump table.
+ * Swap the request message for one large enough to contain the
+ * wrapper structure defined above.
*/
- if (prim & DL_SOLARIS) {
- /*
- * Entries in the 'solaris extensions' jump table
- * have an extra bit in the primitive value. Clear it
- * to do the lookup.
- */
- prim &= ~DL_SOLARIS;
+ if ((mp = mexchange(q, mp, sizeof (dl_info_ack_wrapper_t),
+ M_PCPROTO, 0)) == NULL)
+ return (B_FALSE);
- /*
- * Check the primitive is in range.
- */
- if (prim >= PROTO_SRI_COUNT)
- goto unsupported;
+ rw_enter(&dsp->ds_lock, RW_READER);
- /*
- * Grab the jump table entry.
- */
- prip = &proto_sri[prim];
+ bzero(mp->b_rptr, sizeof (dl_info_ack_wrapper_t));
+ dlwp = (dl_info_ack_wrapper_t *)mp->b_rptr;
- /*
- * OR the cleared bit back in to make the primitive valid
- * again.
- */
- prim |= DL_SOLARIS;
- } else {
- /*
- * Check the primitive is in range.
- */
- if (prim >= PROTO_RI_COUNT)
- goto unsupported;
+ dlp = &(dlwp->dl_info);
+ ASSERT(dlp == (dl_info_ack_t *)mp->b_rptr);
- /*
- * Grab the jump table entry.
- */
- prip = &proto_ri[prim];
- }
+ dlp->dl_primitive = DL_INFO_ACK;
- ASSERT(prip->pri_prim == prim);
+ /*
+ * Set up the sub-structure pointers.
+ */
+ addr = dlwp->dl_addr;
+ brdcst_addr = dlwp->dl_brdcst_addr;
+ rangep = &(dlwp->dl_qos_range1);
+ selp = &(dlwp->dl_qos_sel1);
/*
- * If this primitive causes the data-link channel used by this
- * object to become active, then we need to notify dls. Note that
- * if we're already passive by having succesfully processed a
- * DL_PASSIVE_REQ, then active primitives do not cause us to become
- * active.
+ * This driver supports only version 2 connectionless DLPI provider
+ * nodes.
*/
- if (prip->pri_active && dsp->ds_passivestate == DLD_UNINITIALIZED) {
- if (!dls_active_set(dsp->ds_dc)) {
- dlerrorack(dsp->ds_wq, mp, prim, DL_SYSERR, EBUSY);
- return;
- }
- }
+ dlp->dl_service_mode = DL_CLDLS;
+ dlp->dl_version = DL_VERSION_2;
/*
- * Check whether we need, and whether we have, exclusive access to
- * the stream.
+ * Set the style of the provider
*/
- if (prip->pri_needexcl) {
- /*
- * We only have shared access and we need exclusive access.
- */
- ASSERT(!PERIM_EXCL(dsp->ds_wq));
+ dlp->dl_provider_style = dsp->ds_style;
+ ASSERT(dlp->dl_provider_style == DL_STYLE1 ||
+ dlp->dl_provider_style == DL_STYLE2);
- /*
- * Process via qwriter(9f).
- */
- qwriter(dsp->ds_wq, mp, proto_excl, PERIM_INNER);
- return;
- }
+ /*
+ * Set the current DLPI state.
+ */
+ dlp->dl_current_state = dsp->ds_dlstate;
- success = prip->pri_fn(dsp, udlp, mp);
- if (prip->pri_active && dsp->ds_passivestate == DLD_UNINITIALIZED) {
- if (success)
- dsp->ds_passivestate = DLD_ACTIVE;
- else
- dls_active_clear(dsp->ds_dc);
+ /*
+ * Gratuitously set the media type. This is to deal with modules
+ * that assume the media type is known prior to DL_ATTACH_REQ
+ * being completed.
+ */
+ dlp->dl_mac_type = DL_ETHER;
+
+ /*
+ * If the stream is not at least attached we try to retrieve the
+ * mac_info using mac_info_get()
+ */
+ if (dsp->ds_dlstate == DL_UNATTACHED ||
+ dsp->ds_dlstate == DL_ATTACH_PENDING ||
+ dsp->ds_dlstate == DL_DETACH_PENDING) {
+ if (!mac_info_get(ddi_major_to_name(dsp->ds_major), &minfo)) {
+ /*
+ * Cannot find mac_info. giving up.
+ */
+ goto done;
+ }
+ minfop = &minfo;
+ } else {
+ minfop = (mac_info_t *)dsp->ds_mip;
}
- return;
+ /*
+ * Set the media type (properly this time).
+ */
+ dlp->dl_mac_type = minfop->mi_media;
-unsupported:
- (void) proto_req(dsp, udlp, mp);
-}
+ /*
+ * Set the DLSAP length. We only support 16 bit values and they
+ * appear after the MAC address portion of DLSAP addresses.
+ */
+ sap_length = sizeof (uint16_t);
+ dlp->dl_sap_length = NEG(sap_length);
-/*
- * Called via qwriter(9f).
- */
-static void
-proto_excl(queue_t *q, mblk_t *mp)
-{
- dld_str_t *dsp = q->q_ptr;
- union DL_primitives *udlp;
- t_uscalar_t prim;
- proto_req_info_t *prip;
- boolean_t success;
+ /*
+ * Set the minimum and maximum payload sizes.
+ */
+ dlp->dl_min_sdu = minfop->mi_sdu_min;
+ dlp->dl_max_sdu = minfop->mi_sdu_max;
- ASSERT(MBLKL(mp) >= sizeof (t_uscalar_t));
+ addr_length = minfop->mi_addr_length;
+ ASSERT(addr_length != 0);
- udlp = (union DL_primitives *)mp->b_rptr;
- prim = udlp->dl_primitive;
+ /*
+ * Copy in the media broadcast address.
+ */
+ dlp->dl_brdcst_addr_offset = (uintptr_t)brdcst_addr - (uintptr_t)dlp;
+ bcopy(minfop->mi_brdcst_addr, brdcst_addr, addr_length);
+ dlp->dl_brdcst_addr_length = addr_length;
/*
- * Select the correct jump table.
+ * We only support QoS information for VLAN interfaces.
*/
- if (prim & DL_SOLARIS) {
- /*
- * Entries in the 'solaris extensions' jump table
- * have an extra bit in the primitive value. Clear it
- * to do the lookup.
- */
- prim &= ~DL_SOLARIS;
+ if (dsp->ds_vid != VLAN_ID_NONE) {
+ dlp->dl_qos_range_offset = (uintptr_t)rangep - (uintptr_t)dlp;
+ dlp->dl_qos_range_length = sizeof (dl_qos_cl_range1_t);
+
+ rangep->dl_qos_type = DL_QOS_CL_RANGE1;
+ rangep->dl_trans_delay.dl_target_value = DL_UNKNOWN;
+ rangep->dl_trans_delay.dl_accept_value = DL_UNKNOWN;
+ rangep->dl_protection.dl_min = DL_UNKNOWN;
+ rangep->dl_protection.dl_max = DL_UNKNOWN;
+ rangep->dl_residual_error = DL_UNKNOWN;
/*
- * Grab the jump table entry.
+ * Specify the supported range of priorities.
*/
- ASSERT(prim < PROTO_SRI_COUNT);
- prip = &proto_sri[prim];
+ rangep->dl_priority.dl_min = 0;
+ rangep->dl_priority.dl_max = (1 << VLAN_PRI_SIZE) - 1;
+
+ dlp->dl_qos_offset = (uintptr_t)selp - (uintptr_t)dlp;
+ dlp->dl_qos_length = sizeof (dl_qos_cl_sel1_t);
+
+ selp->dl_qos_type = DL_QOS_CL_SEL1;
+ selp->dl_trans_delay = DL_UNKNOWN;
+ selp->dl_protection = DL_UNKNOWN;
+ selp->dl_residual_error = DL_UNKNOWN;
/*
- * OR the cleared bit back in to make the primitive valid
- * again.
+ * Specify the current priority (which can be changed by
+ * the DL_UDQOS_REQ primitive).
*/
- prim |= DL_SOLARIS;
+ selp->dl_priority = dsp->ds_pri;
} else {
/*
- * Grab the jump table entry.
+ * Shorten the buffer to lose the unused QoS information
+ * structures.
*/
- ASSERT(prim < PROTO_RI_COUNT);
- prip = &proto_ri[prim];
+ mp->b_wptr = (uint8_t *)rangep;
}
- ASSERT(prip->pri_prim == prim);
-
- success = prip->pri_fn(dsp, udlp, mp);
- if (prip->pri_active && dsp->ds_passivestate == DLD_UNINITIALIZED) {
- if (success)
- dsp->ds_passivestate = DLD_ACTIVE;
- else
- dls_active_clear(dsp->ds_dc);
+ dlp->dl_addr_length = addr_length + sizeof (uint16_t);
+ if (dsp->ds_dlstate == DL_IDLE) {
+ /*
+ * The stream is bound. Therefore we can formulate a valid
+ * DLSAP address.
+ */
+ dlp->dl_addr_offset = (uintptr_t)addr - (uintptr_t)dlp;
+ bcopy(dsp->ds_curr_addr, addr, addr_length);
+ *(uint16_t *)(addr + addr_length) = dsp->ds_sap;
}
-}
-/*
- * DL_INFO_REQ
- */
-/*ARGSUSED*/
-static boolean_t
-proto_info_req(dld_str_t *dsp, union DL_primitives *udlp, mblk_t *mp)
-{
- proto_info_ack(dsp, mp);
+done:
+ ASSERT(IMPLY(dlp->dl_qos_offset != 0, dlp->dl_qos_length != 0));
+ ASSERT(IMPLY(dlp->dl_qos_range_offset != 0,
+ dlp->dl_qos_range_length != 0));
+ ASSERT(IMPLY(dlp->dl_addr_offset != 0, dlp->dl_addr_length != 0));
+ ASSERT(IMPLY(dlp->dl_brdcst_addr_offset != 0,
+ dlp->dl_brdcst_addr_length != 0));
+
+ rw_exit(&dsp->ds_lock);
+
+ qreply(q, mp);
return (B_TRUE);
}
@@ -376,39 +369,49 @@ proto_info_req(dld_str_t *dsp, union DL_primitives *udlp, mblk_t *mp)
static boolean_t
proto_attach_req(dld_str_t *dsp, union DL_primitives *udlp, mblk_t *mp)
{
- dl_attach_req_t *dlp = (dl_attach_req_t *)udlp;
- t_scalar_t index;
- dld_node_t *dnp;
- dld_ppa_t *dpp;
- int err;
+ dl_attach_req_t *dlp = (dl_attach_req_t *)udlp;
+ int err = 0;
+ t_uscalar_t dl_err;
+ queue_t *q = dsp->ds_wq;
- ASSERT(PERIM_EXCL(dsp->ds_wq));
+ rw_enter(&dsp->ds_lock, RW_WRITER);
- if (dsp->ds_dlstate != DL_UNATTACHED) {
- dlerrorack(dsp->ds_wq, mp, DL_ATTACH_REQ, DL_OUTSTATE, 0);
- return (B_FALSE);
+ if (MBLKL(mp) < sizeof (dl_attach_req_t) ||
+ dlp->dl_ppa < 0 || dsp->ds_style == DL_STYLE1) {
+ dl_err = DL_BADPRIM;
+ goto failed;
}
- if (MBLKL(mp) < sizeof (dl_attach_req_t)) {
- dlerrorack(dsp->ds_wq, mp, DL_ATTACH_REQ, DL_BADPRIM, 0);
- return (B_FALSE);
+ if (dsp->ds_dlstate != DL_UNATTACHED) {
+ dl_err = DL_OUTSTATE;
+ goto failed;
}
- index = dlp->dl_ppa;
-
- dnp = dsp->ds_dnp;
- ASSERT(dnp->dn_style == DL_STYLE2);
+ dsp->ds_dlstate = DL_ATTACH_PENDING;
- if ((dpp = dld_node_ppa_find(dnp, index)) == NULL) {
- dlerrorack(dsp->ds_wq, mp, DL_ATTACH_REQ, DL_BADPPA, 0);
- return (B_FALSE);
+ err = dld_str_attach(dsp, dlp->dl_ppa);
+ if (err != 0) {
+ switch (err) {
+ case ENOENT:
+ dl_err = DL_BADPPA;
+ err = 0;
+ break;
+ default:
+ dl_err = DL_SYSERR;
+ break;
+ }
+ dsp->ds_dlstate = DL_UNATTACHED;
+ goto failed;
}
+ ASSERT(dsp->ds_dlstate == DL_UNBOUND);
+ rw_exit(&dsp->ds_lock);
- dsp->ds_dlstate = DL_ATTACH_PENDING;
-
- err = dld_str_attach(dsp, dpp);
- proto_attach_ack(dsp, mp, err);
- return (err == 0);
+ dlokack(q, mp, DL_ATTACH_REQ);
+ return (B_TRUE);
+failed:
+ rw_exit(&dsp->ds_lock);
+ dlerrorack(q, mp, DL_ATTACH_REQ, dl_err, (t_uscalar_t)err);
+ return (B_FALSE);
}
/*
@@ -418,28 +421,42 @@ proto_attach_req(dld_str_t *dsp, union DL_primitives *udlp, mblk_t *mp)
static boolean_t
proto_detach_req(dld_str_t *dsp, union DL_primitives *udlp, mblk_t *mp)
{
- ASSERT(PERIM_EXCL(dsp->ds_wq));
+ queue_t *q = dsp->ds_wq;
+ t_uscalar_t dl_err;
- if (dsp->ds_dlstate != DL_UNBOUND) {
- dlerrorack(dsp->ds_wq, mp, DL_DETACH_REQ, DL_OUTSTATE, 0);
- return (B_FALSE);
- }
+ rw_enter(&dsp->ds_lock, RW_WRITER);
if (MBLKL(mp) < sizeof (dl_detach_req_t)) {
- dlerrorack(dsp->ds_wq, mp, DL_DETACH_REQ, DL_BADPRIM, 0);
- return (B_FALSE);
+ dl_err = DL_BADPRIM;
+ goto failed;
}
- if ((dsp->ds_dnp)->dn_style == DL_STYLE1) {
- dlerrorack(dsp->ds_wq, mp, DL_DETACH_REQ, DL_BADPRIM, 0);
- return (B_FALSE);
+ if (dsp->ds_dlstate != DL_UNBOUND) {
+ dl_err = DL_OUTSTATE;
+ goto failed;
+ }
+
+ if (dsp->ds_style == DL_STYLE1) {
+ dl_err = DL_BADPRIM;
+ goto failed;
}
dsp->ds_dlstate = DL_DETACH_PENDING;
- dld_str_detach(dsp);
- proto_detach_ack(dsp, mp);
+ /*
+ * Complete the detach when the driver is single-threaded.
+ */
+ mutex_enter(&dsp->ds_thr_lock);
+ ASSERT(dsp->ds_detach_req == NULL);
+ dsp->ds_detach_req = mp;
+ mutex_exit(&dsp->ds_thr_lock);
+ rw_exit(&dsp->ds_lock);
+
return (B_TRUE);
+failed:
+ rw_exit(&dsp->ds_lock);
+ dlerrorack(q, mp, DL_DETACH_REQ, dl_err, 0);
+ return (B_FALSE);
}
/*
@@ -448,33 +465,44 @@ proto_detach_req(dld_str_t *dsp, union DL_primitives *udlp, mblk_t *mp)
static boolean_t
proto_bind_req(dld_str_t *dsp, union DL_primitives *udlp, mblk_t *mp)
{
- dl_bind_req_t *dlp = (dl_bind_req_t *)udlp;
- int err;
-
- ASSERT(PERIM_EXCL(dsp->ds_wq));
-
- if (dsp->ds_dlstate != DL_UNBOUND) {
- dlerrorack(dsp->ds_wq, mp, DL_BIND_REQ, DL_OUTSTATE, 0);
- return (B_FALSE);
- }
+ dl_bind_req_t *dlp = (dl_bind_req_t *)udlp;
+ int err = 0;
+ uint8_t addr[MAXADDRLEN];
+ uint_t addr_length;
+ t_uscalar_t dl_err;
+ t_scalar_t sap;
+ queue_t *q = dsp->ds_wq;
if (MBLKL(mp) < sizeof (dl_bind_req_t)) {
- dlerrorack(dsp->ds_wq, mp, DL_BIND_REQ, DL_BADPRIM, 0);
- return (B_FALSE);
+ dl_err = DL_BADPRIM;
+ goto failed;
}
if (dlp->dl_xidtest_flg != 0) {
- dlerrorack(dsp->ds_wq, mp, DL_BIND_REQ, DL_NOAUTO, 0);
- return (B_FALSE);
+ dl_err = DL_NOAUTO;
+ goto failed;
}
if (dlp->dl_service_mode != DL_CLDLS) {
- dlerrorack(dsp->ds_wq, mp, DL_BIND_REQ, DL_UNSUPPORTED, 0);
- return (B_FALSE);
+ dl_err = DL_UNSUPPORTED;
+ goto failed;
}
- dsp->ds_dlstate = DL_BIND_PENDING;
+ rw_enter(&dsp->ds_lock, RW_WRITER);
+
+ if (dsp->ds_dlstate != DL_UNBOUND) {
+ dl_err = DL_OUTSTATE;
+ goto failed;
+ }
+
+ if (dsp->ds_passivestate == DLD_UNINITIALIZED &&
+ !dls_active_set(dsp->ds_dc)) {
+ dl_err = DL_SYSERR;
+ err = EBUSY;
+ goto failed;
+ }
+ dsp->ds_dlstate = DL_BIND_PENDING;
/*
* Set the receive callback.
*/
@@ -482,19 +510,51 @@ proto_bind_req(dld_str_t *dsp, union DL_primitives *udlp, mblk_t *mp)
dld_str_rx_raw : dld_str_rx_unitdata, dsp);
/*
- * Set the M_DATA handler.
+ * Bind the channel such that it can receive packets.
*/
- if (dsp->ds_mode == DLD_RAW)
- dld_str_tx_raw(dsp);
+ sap = dsp->ds_sap = dlp->dl_sap;
+ err = dls_bind(dsp->ds_dc, dlp->dl_sap);
+ if (err != 0) {
+ switch (err) {
+ case EINVAL:
+ dl_err = DL_BADADDR;
+ err = 0;
+ break;
+ default:
+ dl_err = DL_SYSERR;
+ break;
+ }
+ dsp->ds_dlstate = DL_UNBOUND;
+ if (dsp->ds_passivestate == DLD_UNINITIALIZED)
+ dls_active_clear(dsp->ds_dc);
+
+ goto failed;
+ }
/*
- * Bind the channel such that it can receive packets.
+ * Copy in MAC address.
*/
- dsp->ds_sap = dlp->dl_sap;
- err = dls_bind(dsp->ds_dc, dlp->dl_sap);
+ addr_length = dsp->ds_mip->mi_addr_length;
+ bcopy(dsp->ds_curr_addr, addr, addr_length);
+
+ /*
+ * Copy in the DLSAP.
+ */
+ *(uint16_t *)(addr + addr_length) = dsp->ds_sap;
+ addr_length += sizeof (uint16_t);
+
+ dsp->ds_dlstate = DL_IDLE;
+ if (dsp->ds_passivestate == DLD_UNINITIALIZED)
+ dsp->ds_passivestate = DLD_ACTIVE;
- proto_bind_ack(dsp, mp, err);
- return (err == 0);
+ rw_exit(&dsp->ds_lock);
+
+ dlbindack(q, mp, sap, (void *)addr, addr_length, 0, 0);
+ return (B_TRUE);
+failed:
+ rw_exit(&dsp->ds_lock);
+ dlerrorack(q, mp, DL_BIND_REQ, dl_err, (t_uscalar_t)err);
+ return (B_FALSE);
}
/*
@@ -504,16 +564,19 @@ proto_bind_req(dld_str_t *dsp, union DL_primitives *udlp, mblk_t *mp)
static boolean_t
proto_unbind_req(dld_str_t *dsp, union DL_primitives *udlp, mblk_t *mp)
{
- ASSERT(PERIM_EXCL(dsp->ds_wq));
+ queue_t *q = dsp->ds_wq;
+ t_uscalar_t dl_err;
- if (dsp->ds_dlstate != DL_IDLE) {
- dlerrorack(dsp->ds_wq, mp, DL_UNBIND_REQ, DL_OUTSTATE, 0);
- return (B_FALSE);
- }
+ rw_enter(&dsp->ds_lock, RW_WRITER);
if (MBLKL(mp) < sizeof (dl_unbind_req_t)) {
- dlerrorack(dsp->ds_wq, mp, DL_BIND_REQ, DL_BADPRIM, 0);
- return (B_FALSE);
+ dl_err = DL_BADPRIM;
+ goto failed;
+ }
+
+ if (dsp->ds_dlstate != DL_IDLE) {
+ dl_err = DL_OUTSTATE;
+ goto failed;
}
dsp->ds_dlstate = DL_UNBIND_PENDING;
@@ -521,12 +584,7 @@ proto_unbind_req(dld_str_t *dsp, union DL_primitives *udlp, mblk_t *mp)
/*
* Flush any remaining packets scheduled for transmission.
*/
- flushq(dsp->ds_wq, FLUSHALL);
-
- /*
- * Reset the M_DATA handler.
- */
- dld_str_tx_drop(dsp);
+ dld_tx_flush(dsp);
/*
* Unbind the channel to stop packets being received.
@@ -548,8 +606,15 @@ proto_unbind_req(dld_str_t *dsp, union DL_primitives *udlp, mblk_t *mp)
*/
dsp->ds_mode = DLD_UNITDATA;
- proto_unbind_ack(dsp, mp);
+ dsp->ds_dlstate = DL_UNBOUND;
+ rw_exit(&dsp->ds_lock);
+
+ dlokack(q, mp, DL_UNBIND_REQ);
return (B_TRUE);
+failed:
+ rw_exit(&dsp->ds_lock);
+ dlerrorack(q, mp, DL_UNBIND_REQ, dl_err, 0);
+ return (B_FALSE);
}
/*
@@ -558,22 +623,26 @@ proto_unbind_req(dld_str_t *dsp, union DL_primitives *udlp, mblk_t *mp)
static boolean_t
proto_promiscon_req(dld_str_t *dsp, union DL_primitives *udlp, mblk_t *mp)
{
- dl_promiscon_req_t *dlp = (dl_promiscon_req_t *)udlp;
- int err;
+ dl_promiscon_req_t *dlp = (dl_promiscon_req_t *)udlp;
+ int err = 0;
+ t_uscalar_t dl_err;
+ uint32_t promisc_saved;
+ queue_t *q = dsp->ds_wq;
- ASSERT(PERIM_EXCL(dsp->ds_wq));
+ if (MBLKL(mp) < sizeof (dl_promiscon_req_t)) {
+ dl_err = DL_BADPRIM;
+ goto failed;
+ }
+
+ rw_enter(&dsp->ds_lock, RW_WRITER);
if (dsp->ds_dlstate == DL_UNATTACHED ||
DL_ACK_PENDING(dsp->ds_dlstate)) {
- dlerrorack(dsp->ds_wq, mp, DL_PROMISCON_REQ, DL_OUTSTATE, 0);
- return (B_FALSE);
- }
-
- if (MBLKL(mp) < sizeof (dl_promiscon_req_t)) {
- dlerrorack(dsp->ds_wq, mp, DL_PROMISCON_REQ, DL_BADPRIM, 0);
- return (B_FALSE);
+ dl_err = DL_OUTSTATE;
+ goto failed;
}
+ promisc_saved = dsp->ds_promisc;
switch (dlp->dl_level) {
case DL_PROMISC_SAP:
dsp->ds_promisc |= DLS_PROMISC_SAP;
@@ -588,17 +657,41 @@ proto_promiscon_req(dld_str_t *dsp, union DL_primitives *udlp, mblk_t *mp)
break;
default:
- dlerrorack(dsp->ds_wq, mp, DL_PROMISCON_REQ, DL_NOTSUPPORTED,
- 0);
- return (B_FALSE);
+ dl_err = DL_NOTSUPPORTED;
+ goto failed;
+ }
+
+ if (dsp->ds_passivestate == DLD_UNINITIALIZED &&
+ !dls_active_set(dsp->ds_dc)) {
+ dsp->ds_promisc = promisc_saved;
+ dl_err = DL_SYSERR;
+ err = EBUSY;
+ goto failed;
}
/*
* Adjust channel promiscuity.
*/
err = dls_promisc(dsp->ds_dc, dsp->ds_promisc);
- proto_promiscon_ack(dsp, mp, err);
- return (err == 0);
+ if (err != 0) {
+ dl_err = DL_SYSERR;
+ dsp->ds_promisc = promisc_saved;
+ if (dsp->ds_passivestate == DLD_UNINITIALIZED)
+ dls_active_clear(dsp->ds_dc);
+
+ goto failed;
+ }
+
+ if (dsp->ds_passivestate == DLD_UNINITIALIZED)
+ dsp->ds_passivestate = DLD_ACTIVE;
+
+ rw_exit(&dsp->ds_lock);
+ dlokack(q, mp, DL_PROMISCON_REQ);
+ return (B_TRUE);
+failed:
+ rw_exit(&dsp->ds_lock);
+ dlerrorack(q, mp, DL_PROMISCON_REQ, dl_err, (t_uscalar_t)err);
+ return (B_FALSE);
}
/*
@@ -607,60 +700,73 @@ proto_promiscon_req(dld_str_t *dsp, union DL_primitives *udlp, mblk_t *mp)
static boolean_t
proto_promiscoff_req(dld_str_t *dsp, union DL_primitives *udlp, mblk_t *mp)
{
- dl_promiscoff_req_t *dlp = (dl_promiscoff_req_t *)udlp;
- int err;
+ dl_promiscoff_req_t *dlp = (dl_promiscoff_req_t *)udlp;
+ int err = 0;
+ t_uscalar_t dl_err;
+ uint32_t promisc_saved;
+ queue_t *q = dsp->ds_wq;
- ASSERT(PERIM_EXCL(dsp->ds_wq));
- if (dsp->ds_dlstate == DL_UNATTACHED ||
- DL_ACK_PENDING(dsp->ds_dlstate)) {
- dlerrorack(dsp->ds_wq, mp, DL_PROMISCOFF_REQ, DL_OUTSTATE, 0);
- return (B_FALSE);
+ if (MBLKL(mp) < sizeof (dl_promiscoff_req_t)) {
+ dl_err = DL_BADPRIM;
+ goto failed;
}
- if (MBLKL(mp) < sizeof (dl_promiscoff_req_t)) {
- dlerrorack(dsp->ds_wq, mp, DL_PROMISCOFF_REQ, DL_BADPRIM, 0);
- return (B_FALSE);
+ rw_enter(&dsp->ds_lock, RW_WRITER);
+
+ if (dsp->ds_dlstate == DL_UNATTACHED ||
+ DL_ACK_PENDING(dsp->ds_dlstate)) {
+ dl_err = DL_OUTSTATE;
+ goto failed;
}
+ promisc_saved = dsp->ds_promisc;
switch (dlp->dl_level) {
case DL_PROMISC_SAP:
- if (!(dsp->ds_promisc & DLS_PROMISC_SAP))
- goto notenab;
-
+ if (!(dsp->ds_promisc & DLS_PROMISC_SAP)) {
+ dl_err = DL_NOTENAB;
+ goto failed;
+ }
dsp->ds_promisc &= ~DLS_PROMISC_SAP;
break;
case DL_PROMISC_MULTI:
- if (!(dsp->ds_promisc & DLS_PROMISC_MULTI))
- goto notenab;
-
+ if (!(dsp->ds_promisc & DLS_PROMISC_MULTI)) {
+ dl_err = DL_NOTENAB;
+ goto failed;
+ }
dsp->ds_promisc &= ~DLS_PROMISC_MULTI;
break;
case DL_PROMISC_PHYS:
- if (!(dsp->ds_promisc & DLS_PROMISC_PHYS))
- goto notenab;
-
+ if (!(dsp->ds_promisc & DLS_PROMISC_PHYS)) {
+ dl_err = DL_NOTENAB;
+ goto failed;
+ }
dsp->ds_promisc &= ~DLS_PROMISC_PHYS;
break;
default:
- dlerrorack(dsp->ds_wq, mp, DL_PROMISCOFF_REQ, DL_NOTSUPPORTED,
- 0);
- return (B_FALSE);
+ dl_err = DL_NOTSUPPORTED;
+ goto failed;
}
/*
* Adjust channel promiscuity.
*/
err = dls_promisc(dsp->ds_dc, dsp->ds_promisc);
+ if (err != 0) {
+ dsp->ds_promisc = promisc_saved;
+ dl_err = DL_SYSERR;
+ goto failed;
+ }
- proto_promiscoff_ack(dsp, mp, err);
- return (err == 0);
-
-notenab:
- dlerrorack(dsp->ds_wq, mp, DL_PROMISCOFF_REQ, DL_NOTENAB, 0);
+ rw_exit(&dsp->ds_lock);
+ dlokack(q, mp, DL_PROMISCOFF_REQ);
+ return (B_TRUE);
+failed:
+ rw_exit(&dsp->ds_lock);
+ dlerrorack(q, mp, DL_PROMISCOFF_REQ, dl_err, (t_uscalar_t)err);
return (B_FALSE);
}
@@ -670,27 +776,64 @@ notenab:
static boolean_t
proto_enabmulti_req(dld_str_t *dsp, union DL_primitives *udlp, mblk_t *mp)
{
- dl_enabmulti_req_t *dlp = (dl_enabmulti_req_t *)udlp;
- int err;
+ dl_enabmulti_req_t *dlp = (dl_enabmulti_req_t *)udlp;
+ int err = 0;
+ t_uscalar_t dl_err;
+ queue_t *q = dsp->ds_wq;
- ASSERT(PERIM_EXCL(dsp->ds_wq));
+ rw_enter(&dsp->ds_lock, RW_WRITER);
if (dsp->ds_dlstate == DL_UNATTACHED ||
DL_ACK_PENDING(dsp->ds_dlstate)) {
- dlerrorack(dsp->ds_wq, mp, DL_ENABMULTI_REQ, DL_OUTSTATE, 0);
- return (B_FALSE);
+ dl_err = DL_OUTSTATE;
+ goto failed;
}
if (MBLKL(mp) < sizeof (dl_enabmulti_req_t) ||
!MBLKIN(mp, dlp->dl_addr_offset, dlp->dl_addr_length) ||
dlp->dl_addr_length != dsp->ds_mip->mi_addr_length) {
- dlerrorack(dsp->ds_wq, mp, DL_ENABMULTI_REQ, DL_BADPRIM, 0);
- return (B_FALSE);
+ dl_err = DL_BADPRIM;
+ goto failed;
+ }
+
+ if (dsp->ds_passivestate == DLD_UNINITIALIZED &&
+ !dls_active_set(dsp->ds_dc)) {
+ dl_err = DL_SYSERR;
+ err = EBUSY;
+ goto failed;
}
err = dls_multicst_add(dsp->ds_dc, mp->b_rptr + dlp->dl_addr_offset);
- proto_enabmulti_ack(dsp, mp, err);
- return (err == 0);
+ if (err != 0) {
+ switch (err) {
+ case EINVAL:
+ dl_err = DL_BADADDR;
+ err = 0;
+ break;
+ case ENOSPC:
+ dl_err = DL_TOOMANY;
+ err = 0;
+ break;
+ default:
+ dl_err = DL_SYSERR;
+ break;
+ }
+ if (dsp->ds_passivestate == DLD_UNINITIALIZED)
+ dls_active_clear(dsp->ds_dc);
+
+ goto failed;
+ }
+
+ if (dsp->ds_passivestate == DLD_UNINITIALIZED)
+ dsp->ds_passivestate = DLD_ACTIVE;
+
+ rw_exit(&dsp->ds_lock);
+ dlokack(q, mp, DL_ENABMULTI_REQ);
+ return (B_TRUE);
+failed:
+ rw_exit(&dsp->ds_lock);
+ dlerrorack(q, mp, DL_ENABMULTI_REQ, dl_err, (t_uscalar_t)err);
+ return (B_FALSE);
}
/*
@@ -699,27 +842,53 @@ proto_enabmulti_req(dld_str_t *dsp, union DL_primitives *udlp, mblk_t *mp)
static boolean_t
proto_disabmulti_req(dld_str_t *dsp, union DL_primitives *udlp, mblk_t *mp)
{
- dl_disabmulti_req_t *dlp = (dl_disabmulti_req_t *)udlp;
- int err;
+ dl_disabmulti_req_t *dlp = (dl_disabmulti_req_t *)udlp;
+ int err = 0;
+ t_uscalar_t dl_err;
+ queue_t *q = dsp->ds_wq;
- ASSERT(PERIM_EXCL(dsp->ds_wq));
+ rw_enter(&dsp->ds_lock, RW_READER);
if (dsp->ds_dlstate == DL_UNATTACHED ||
DL_ACK_PENDING(dsp->ds_dlstate)) {
- dlerrorack(dsp->ds_wq, mp, DL_DISABMULTI_REQ, DL_OUTSTATE, 0);
- return (B_FALSE);
+ dl_err = DL_OUTSTATE;
+ goto failed;
}
if (MBLKL(mp) < sizeof (dl_disabmulti_req_t) ||
!MBLKIN(mp, dlp->dl_addr_offset, dlp->dl_addr_length) ||
dlp->dl_addr_length != dsp->ds_mip->mi_addr_length) {
- dlerrorack(dsp->ds_wq, mp, DL_DISABMULTI_REQ, DL_BADPRIM, 0);
- return (B_FALSE);
+ dl_err = DL_BADPRIM;
+ goto failed;
}
err = dls_multicst_remove(dsp->ds_dc, mp->b_rptr + dlp->dl_addr_offset);
- proto_disabmulti_ack(dsp, mp, err);
- return (err == 0);
+ if (err != 0) {
+ switch (err) {
+ case EINVAL:
+ dl_err = DL_BADADDR;
+ err = 0;
+ break;
+
+ case ENOENT:
+ dl_err = DL_NOTENAB;
+ err = 0;
+ break;
+
+ default:
+ dl_err = DL_SYSERR;
+ break;
+ }
+ goto failed;
+ }
+
+ rw_exit(&dsp->ds_lock);
+ dlokack(q, mp, DL_DISABMULTI_REQ);
+ return (B_TRUE);
+failed:
+ rw_exit(&dsp->ds_lock);
+ dlerrorack(q, mp, DL_DISABMULTI_REQ, dl_err, (t_uscalar_t)err);
+ return (B_FALSE);
}
/*
@@ -728,27 +897,54 @@ proto_disabmulti_req(dld_str_t *dsp, union DL_primitives *udlp, mblk_t *mp)
static boolean_t
proto_physaddr_req(dld_str_t *dsp, union DL_primitives *udlp, mblk_t *mp)
{
- dl_phys_addr_req_t *dlp = (dl_phys_addr_req_t *)udlp;
+ dl_phys_addr_req_t *dlp = (dl_phys_addr_req_t *)udlp;
+ queue_t *q = dsp->ds_wq;
+ t_uscalar_t dl_err;
+ char *addr;
+ uint_t addr_length;
- if (dsp->ds_dlstate == DL_UNATTACHED ||
- DL_ACK_PENDING(dsp->ds_dlstate)) {
- dlerrorack(dsp->ds_wq, mp, DL_PHYS_ADDR_REQ, DL_OUTSTATE, 0);
- return (B_FALSE);
- }
+ rw_enter(&dsp->ds_lock, RW_READER);
if (MBLKL(mp) < sizeof (dl_phys_addr_req_t)) {
- dlerrorack(dsp->ds_wq, mp, DL_PHYS_ADDR_REQ, DL_BADPRIM, 0);
- return (B_FALSE);
+ dl_err = DL_BADPRIM;
+ goto failed;
+ }
+
+ if (dsp->ds_dlstate == DL_UNATTACHED ||
+ DL_ACK_PENDING(dsp->ds_dlstate)) {
+ dl_err = DL_OUTSTATE;
+ goto failed;
}
if (dlp->dl_addr_type != DL_CURR_PHYS_ADDR &&
dlp->dl_addr_type != DL_FACT_PHYS_ADDR) {
- dlerrorack(dsp->ds_wq, mp, DL_PHYS_ADDR_REQ, DL_UNSUPPORTED, 0);
+ dl_err = DL_UNSUPPORTED;
+ goto failed;
+ }
+
+ addr_length = dsp->ds_mip->mi_addr_length;
+ addr = kmem_alloc(addr_length, KM_NOSLEEP);
+ if (addr == NULL) {
+ rw_exit(&dsp->ds_lock);
+ merror(q, mp, ENOSR);
return (B_FALSE);
}
- proto_physaddr_ack(dsp, mp, dlp->dl_addr_type);
+ /*
+ * Copy out the address before we drop the lock; we don't
+ * want to call dlphysaddrack() while holding ds_lock.
+ */
+ bcopy((dlp->dl_addr_type == DL_CURR_PHYS_ADDR) ?
+ dsp->ds_curr_addr : dsp->ds_fact_addr, addr, addr_length);
+
+ rw_exit(&dsp->ds_lock);
+ dlphysaddrack(q, mp, addr, (t_uscalar_t)addr_length);
+ kmem_free(addr, addr_length);
return (B_TRUE);
+failed:
+ rw_exit(&dsp->ds_lock);
+ dlerrorack(q, mp, DL_PHYS_ADDR_REQ, dl_err, 0);
+ return (B_FALSE);
}
/*
@@ -757,29 +953,60 @@ proto_physaddr_req(dld_str_t *dsp, union DL_primitives *udlp, mblk_t *mp)
static boolean_t
proto_setphysaddr_req(dld_str_t *dsp, union DL_primitives *udlp, mblk_t *mp)
{
- dl_set_phys_addr_req_t *dlp = (dl_set_phys_addr_req_t *)udlp;
- int err;
+ dl_set_phys_addr_req_t *dlp = (dl_set_phys_addr_req_t *)udlp;
+ int err = 0;
+ t_uscalar_t dl_err;
+ queue_t *q = dsp->ds_wq;
- ASSERT(PERIM_EXCL(dsp->ds_wq));
+ rw_enter(&dsp->ds_lock, RW_WRITER);
if (dsp->ds_dlstate == DL_UNATTACHED ||
DL_ACK_PENDING(dsp->ds_dlstate)) {
- dlerrorack(dsp->ds_wq, mp, DL_SET_PHYS_ADDR_REQ, DL_OUTSTATE,
- 0);
- return (B_FALSE);
+ dl_err = DL_OUTSTATE;
+ goto failed;
}
if (MBLKL(mp) < sizeof (dl_set_phys_addr_req_t) ||
!MBLKIN(mp, dlp->dl_addr_offset, dlp->dl_addr_length) ||
dlp->dl_addr_length != dsp->ds_mip->mi_addr_length) {
- dlerrorack(dsp->ds_wq, mp, DL_SET_PHYS_ADDR_REQ, DL_BADPRIM,
- 0);
- return (B_FALSE);
+ dl_err = DL_BADPRIM;
+ goto failed;
+ }
+
+ if (dsp->ds_passivestate == DLD_UNINITIALIZED &&
+ !dls_active_set(dsp->ds_dc)) {
+ dl_err = DL_SYSERR;
+ err = EBUSY;
+ goto failed;
}
err = mac_unicst_set(dsp->ds_mh, mp->b_rptr + dlp->dl_addr_offset);
- proto_setphysaddr_ack(dsp, mp, err);
- return (err == 0);
+ if (err != 0) {
+ switch (err) {
+ case EINVAL:
+ dl_err = DL_BADADDR;
+ err = 0;
+ break;
+
+ default:
+ dl_err = DL_SYSERR;
+ break;
+ }
+ if (dsp->ds_passivestate == DLD_UNINITIALIZED)
+ dls_active_clear(dsp->ds_dc);
+
+ goto failed;
+ }
+ if (dsp->ds_passivestate == DLD_UNINITIALIZED)
+ dsp->ds_passivestate = DLD_ACTIVE;
+
+ rw_exit(&dsp->ds_lock);
+ dlokack(q, mp, DL_SET_PHYS_ADDR_REQ);
+ return (B_TRUE);
+failed:
+ rw_exit(&dsp->ds_lock);
+ dlerrorack(q, mp, DL_SET_PHYS_ADDR_REQ, dl_err, (t_uscalar_t)err);
+ return (B_FALSE);
}
/*
@@ -788,36 +1015,44 @@ proto_setphysaddr_req(dld_str_t *dsp, union DL_primitives *udlp, mblk_t *mp)
static boolean_t
proto_udqos_req(dld_str_t *dsp, union DL_primitives *udlp, mblk_t *mp)
{
- dl_udqos_req_t *dlp = (dl_udqos_req_t *)udlp;
- dl_qos_cl_sel1_t *selp;
- int off, len;
-
- ASSERT(PERIM_EXCL(dsp->ds_wq));
+ dl_udqos_req_t *dlp = (dl_udqos_req_t *)udlp;
+ dl_qos_cl_sel1_t *selp;
+ int off, len;
+ t_uscalar_t dl_err;
+ queue_t *q = dsp->ds_wq;
off = dlp->dl_qos_offset;
len = dlp->dl_qos_length;
if (MBLKL(mp) < sizeof (dl_udqos_req_t) || !MBLKIN(mp, off, len)) {
- dlerrorack(dsp->ds_wq, mp, DL_UDQOS_REQ, DL_BADPRIM, 0);
- return (B_FALSE);
+ dl_err = DL_BADPRIM;
+ goto failed;
}
selp = (dl_qos_cl_sel1_t *)(mp->b_rptr + off);
if (selp->dl_qos_type != DL_QOS_CL_SEL1) {
- dlerrorack(dsp->ds_wq, mp, DL_UDQOS_REQ, DL_BADQOSTYPE, 0);
- return (B_FALSE);
+ dl_err = DL_BADQOSTYPE;
+ goto failed;
}
+ rw_enter(&dsp->ds_lock, RW_WRITER);
+
if (dsp->ds_vid == VLAN_ID_NONE ||
selp->dl_priority > (1 << VLAN_PRI_SIZE) - 1 ||
selp->dl_priority < 0) {
- dlerrorack(dsp->ds_wq, mp, DL_UDQOS_REQ, DL_BADQOSPARAM, 0);
- return (B_FALSE);
+ dl_err = DL_BADQOSPARAM;
+ goto failed;
}
dsp->ds_pri = selp->dl_priority;
- proto_udqos_ack(dsp, mp);
+
+ rw_exit(&dsp->ds_lock);
+ dlokack(q, mp, DL_UDQOS_REQ);
return (B_TRUE);
+failed:
+ rw_exit(&dsp->ds_lock);
+ dlerrorack(q, mp, DL_UDQOS_REQ, dl_err, 0);
+ return (B_FALSE);
}
/*
@@ -827,18 +1062,25 @@ proto_udqos_req(dld_str_t *dsp, union DL_primitives *udlp, mblk_t *mp)
static boolean_t
proto_capability_req(dld_str_t *dsp, union DL_primitives *udlp, mblk_t *mp)
{
- dl_capability_req_t *dlp = (dl_capability_req_t *)udlp;
+ dl_capability_req_t *dlp = (dl_capability_req_t *)udlp;
+ dl_capability_sub_t *sp;
+ size_t size, len;
+ offset_t off, end;
+ t_uscalar_t dl_err;
+ queue_t *q = dsp->ds_wq;
+ boolean_t upgraded;
- if (dsp->ds_dlstate == DL_UNATTACHED ||
- DL_ACK_PENDING(dsp->ds_dlstate)) {
- dlerrorack(dsp->ds_wq, mp, DL_CAPABILITY_REQ, DL_OUTSTATE,
- 0);
- return (B_FALSE);
- }
+ rw_enter(&dsp->ds_lock, RW_READER);
if (MBLKL(mp) < sizeof (dl_capability_req_t)) {
- dlerrorack(dsp->ds_wq, mp, DL_CAPABILITY_REQ, DL_BADPRIM, 0);
- return (B_FALSE);
+ dl_err = DL_BADPRIM;
+ goto failed;
+ }
+
+ if (dsp->ds_dlstate == DL_UNATTACHED ||
+ DL_ACK_PENDING(dsp->ds_dlstate)) {
+ dl_err = DL_OUTSTATE;
+ goto failed;
}
/*
@@ -847,17 +1089,128 @@ proto_capability_req(dld_str_t *dsp, union DL_primitives *udlp, mblk_t *mp)
* support. Otherwise we enable the set of capabilities requested.
*/
if (dlp->dl_sub_length == 0) {
- proto_capability_ack(dsp, mp);
- return (B_TRUE);
+ /* callee drops lock */
+ return (proto_capability_advertise(dsp, mp));
}
if (!MBLKIN(mp, dlp->dl_sub_offset, dlp->dl_sub_length)) {
- dlerrorack(dsp->ds_wq, mp, DL_CAPABILITY_REQ, DL_BADPRIM, 0);
- return (B_FALSE);
+ dl_err = DL_BADPRIM;
+ goto failed;
}
- proto_capability_enable(dsp, mp);
+ dlp->dl_primitive = DL_CAPABILITY_ACK;
+
+ off = dlp->dl_sub_offset;
+ len = dlp->dl_sub_length;
+
+ /*
+ * Walk the list of capabilities to be enabled.
+ */
+ upgraded = B_FALSE;
+ for (end = off + len; off < end; ) {
+ sp = (dl_capability_sub_t *)(mp->b_rptr + off);
+ size = sizeof (dl_capability_sub_t) + sp->dl_length;
+
+ if (off + size > end ||
+ !IS_P2ALIGNED(off, sizeof (uint32_t))) {
+ dl_err = DL_BADPRIM;
+ goto failed;
+ }
+
+ switch (sp->dl_cap) {
+ /*
+ * TCP/IP checksum offload to hardware.
+ */
+ case DL_CAPAB_HCKSUM: {
+ dl_capab_hcksum_t *hcksump;
+ dl_capab_hcksum_t hcksum;
+
+ ASSERT(dsp->ds_mip->mi_cksum != 0);
+
+ hcksump = (dl_capab_hcksum_t *)&sp[1];
+ /*
+ * Copy for alignment.
+ */
+ bcopy(hcksump, &hcksum, sizeof (dl_capab_hcksum_t));
+ dlcapabsetqid(&(hcksum.hcksum_mid), dsp->ds_rq);
+ bcopy(&hcksum, hcksump, sizeof (dl_capab_hcksum_t));
+ break;
+ }
+
+ /*
+ * IP polling interface.
+ */
+ case DL_CAPAB_POLL: {
+ dl_capab_poll_t *pollp;
+ dl_capab_poll_t poll;
+
+ pollp = (dl_capab_poll_t *)&sp[1];
+ /*
+ * Copy for alignment.
+ */
+ bcopy(pollp, &poll, sizeof (dl_capab_poll_t));
+
+ /*
+ * We need to become writer before enabling and/or
+ * disabling the polling interface. If we couldn'
+ * upgrade, check state again after re-acquiring the
+ * lock to make sure we can proceed.
+ */
+ if (!upgraded && !rw_tryupgrade(&dsp->ds_lock)) {
+ rw_exit(&dsp->ds_lock);
+ rw_enter(&dsp->ds_lock, RW_WRITER);
+
+ if (dsp->ds_dlstate == DL_UNATTACHED ||
+ DL_ACK_PENDING(dsp->ds_dlstate)) {
+ dl_err = DL_OUTSTATE;
+ goto failed;
+ }
+ }
+ upgraded = B_TRUE;
+
+ switch (poll.poll_flags) {
+ default:
+ /*FALLTHRU*/
+ case POLL_DISABLE:
+ proto_poll_disable(dsp);
+ break;
+
+ case POLL_ENABLE:
+ ASSERT(!(dld_opt & DLD_OPT_NO_POLL));
+
+ /*
+ * Make sure polling is disabled.
+ */
+ proto_poll_disable(dsp);
+
+ /*
+ * Now attempt enable it.
+ */
+ if (!proto_poll_enable(dsp, &poll))
+ break;
+
+ bzero(&poll, sizeof (dl_capab_poll_t));
+ poll.poll_flags = POLL_ENABLE;
+ break;
+ }
+
+ dlcapabsetqid(&(poll.poll_mid), dsp->ds_rq);
+ bcopy(&poll, pollp, sizeof (dl_capab_poll_t));
+ break;
+ }
+ default:
+ break;
+ }
+
+ off += size;
+ }
+ rw_exit(&dsp->ds_lock);
+ qreply(q, mp);
return (B_TRUE);
+failed:
+ rw_exit(&dsp->ds_lock);
+ dlerrorack(q, mp, DL_CAPABILITY_REQ, dl_err, 0);
+ return (B_FALSE);
}
/*
@@ -866,8 +1219,10 @@ proto_capability_req(dld_str_t *dsp, union DL_primitives *udlp, mblk_t *mp)
static boolean_t
proto_notify_req(dld_str_t *dsp, union DL_primitives *udlp, mblk_t *mp)
{
- dl_notify_req_t *dlp = (dl_notify_req_t *)udlp;
- uint_t notifications =
+ dl_notify_req_t *dlp = (dl_notify_req_t *)udlp;
+ t_uscalar_t dl_err;
+ queue_t *q = dsp->ds_wq;
+ uint_t note =
DL_NOTE_PROMISC_ON_PHYS |
DL_NOTE_PROMISC_OFF_PHYS |
DL_NOTE_PHYS_ADDR |
@@ -875,24 +1230,47 @@ proto_notify_req(dld_str_t *dsp, union DL_primitives *udlp, mblk_t *mp)
DL_NOTE_LINK_DOWN |
DL_NOTE_CAPAB_RENEG;
- if (dsp->ds_dlstate == DL_UNATTACHED ||
- DL_ACK_PENDING(dsp->ds_dlstate)) {
- dlerrorack(dsp->ds_wq, mp, DL_NOTIFY_REQ, DL_OUTSTATE,
- 0);
- return (B_FALSE);
+ if (MBLKL(mp) < sizeof (dl_notify_req_t)) {
+ dl_err = DL_BADPRIM;
+ goto failed;
}
- if (MBLKL(mp) < sizeof (dl_notify_req_t)) {
- dlerrorack(dsp->ds_wq, mp, DL_NOTIFY_REQ, DL_BADPRIM, 0);
- return (B_FALSE);
+ rw_enter(&dsp->ds_lock, RW_WRITER);
+ if (dsp->ds_dlstate == DL_UNATTACHED ||
+ DL_ACK_PENDING(dsp->ds_dlstate)) {
+ dl_err = DL_OUTSTATE;
+ goto failed;
}
if (dsp->ds_mip->mi_stat[MAC_STAT_IFSPEED])
- notifications |= DL_NOTE_SPEED;
+ note |= DL_NOTE_SPEED;
- proto_notify_ack(dsp, mp, dlp->dl_notifications & notifications,
- notifications);
+ /*
+ * Cache the notifications that are being enabled.
+ */
+ dsp->ds_notifications = dlp->dl_notifications & note;
+ rw_exit(&dsp->ds_lock);
+ /*
+ * The ACK carries all notifications regardless of which set is
+ * being enabled.
+ */
+ dlnotifyack(q, mp, note);
+
+ /*
+ * Solicit DL_NOTIFY_IND messages for each enabled notification.
+ */
+ rw_enter(&dsp->ds_lock, RW_READER);
+ if (dsp->ds_notifications != 0) {
+ rw_exit(&dsp->ds_lock);
+ dld_str_notify_ind(dsp);
+ } else {
+ rw_exit(&dsp->ds_lock);
+ }
return (B_TRUE);
+failed:
+ rw_exit(&dsp->ds_lock);
+ dlerrorack(q, mp, DL_NOTIFY_REQ, dl_err, 0);
+ return (B_FALSE);
}
/*
@@ -904,40 +1282,39 @@ proto_unitdata_req(dld_str_t *dsp, union DL_primitives *udlp, mblk_t *mp)
queue_t *q = dsp->ds_wq;
dl_unitdata_req_t *dlp = (dl_unitdata_req_t *)udlp;
off_t off;
- size_t len;
- size_t size;
+ size_t len, size;
const uint8_t *addr;
uint16_t sap;
uint_t addr_length;
- mblk_t *bp;
- mblk_t *cont;
- uint32_t start;
- uint32_t stuff;
- uint32_t end;
- uint32_t value;
- uint32_t flags;
+ mblk_t *bp, *cont;
+ uint32_t start, stuff, end, value, flags;
+ t_uscalar_t dl_err;
- if (dsp->ds_dlstate != DL_IDLE) {
- dlerrorack(q, mp, DL_UNITDATA_REQ, DL_OUTSTATE, 0);
- return (B_FALSE);
- }
+ rw_enter(&dsp->ds_lock, RW_READER);
if (MBLKL(mp) < sizeof (dl_unitdata_req_t) || mp->b_cont == NULL) {
- dlerrorack(q, mp, DL_UNITDATA_REQ, DL_BADPRIM, 0);
- return (B_FALSE);
+ dl_err = DL_BADPRIM;
+ goto failed;
+ }
+
+ if (dsp->ds_dlstate != DL_IDLE) {
+ dl_err = DL_OUTSTATE;
+ goto failed;
}
+ addr_length = dsp->ds_mip->mi_addr_length;
off = dlp->dl_dest_addr_offset;
len = dlp->dl_dest_addr_length;
if (!MBLKIN(mp, off, len) || !IS_P2ALIGNED(off, sizeof (uint16_t))) {
- dlerrorack(q, mp, DL_UNITDATA_REQ, DL_BADPRIM, 0);
- return (B_FALSE);
+ dl_err = DL_BADPRIM;
+ goto failed;
}
- addr_length = dsp->ds_mip->mi_addr_length;
- if (len != addr_length + sizeof (uint16_t))
- goto badaddr;
+ if (len != addr_length + sizeof (uint16_t)) {
+ dl_err = DL_BADADDR;
+ goto failed;
+ }
addr = mp->b_rptr + off;
sap = *(uint16_t *)(mp->b_rptr + off + addr_length);
@@ -960,8 +1337,10 @@ proto_unitdata_req(dld_str_t *dsp, union DL_primitives *udlp, mblk_t *mp)
/*
* Build a packet header.
*/
- if ((bp = dls_header(dsp->ds_dc, addr, sap, dsp->ds_pri)) == NULL)
- goto badaddr;
+ if ((bp = dls_header(dsp->ds_dc, addr, sap, dsp->ds_pri)) == NULL) {
+ dl_err = DL_BADADDR;
+ goto failed;
+ }
/*
* We no longer need the M_PROTO header, so free it.
@@ -982,33 +1361,16 @@ proto_unitdata_req(dld_str_t *dsp, union DL_primitives *udlp, mblk_t *mp)
ASSERT(bp->b_cont == NULL);
bp->b_cont = cont;
- /*
- * If something is already queued then we must queue to avoid
- * re-ordering.
- */
- if (q->q_first != NULL) {
- (void) putq(q, bp);
- return (B_TRUE);
- }
-
- /*
- * Attempt to transmit the packet.
- */
- if ((mp = dls_tx(dsp->ds_dc, bp)) != NULL) {
- noenable(q);
- while ((bp = mp) != NULL) {
- mp = mp->b_next;
- bp->b_next = NULL;
- (void) putq(q, bp);
- }
- }
+ str_mdata_fastpath_put(dsp, bp);
+ rw_exit(&dsp->ds_lock);
return (B_TRUE);
-
-badaddr:
- dlerrorack(q, mp, DL_UNITDATA_REQ, DL_BADADDR, 0);
+failed:
+ rw_exit(&dsp->ds_lock);
+ dlerrorack(q, mp, DL_UNITDATA_REQ, dl_err, 0);
return (B_FALSE);
baddata:
+ rw_exit(&dsp->ds_lock);
dluderrorind(q, mp, (void *)addr, len, DL_BADDATA, 0);
return (B_FALSE);
}
@@ -1020,27 +1382,34 @@ baddata:
static boolean_t
proto_passive_req(dld_str_t *dsp, union DL_primitives *udlp, mblk_t *mp)
{
- ASSERT(PERIM_EXCL(dsp->ds_wq));
+ t_uscalar_t dl_err;
+ rw_enter(&dsp->ds_lock, RW_WRITER);
/*
* If we've already become active by issuing an active primitive,
* then it's too late to try to become passive.
*/
if (dsp->ds_passivestate == DLD_ACTIVE) {
- dlerrorack(dsp->ds_wq, mp, DL_PASSIVE_REQ, DL_OUTSTATE, 0);
- return (B_FALSE);
+ dl_err = DL_OUTSTATE;
+ goto failed;
}
if (MBLKL(mp) < sizeof (dl_passive_req_t)) {
- dlerrorack(dsp->ds_wq, mp, DL_PASSIVE_REQ, DL_BADPRIM, 0);
- return (B_FALSE);
+ dl_err = DL_BADPRIM;
+ goto failed;
}
dsp->ds_passivestate = DLD_PASSIVE;
+ rw_exit(&dsp->ds_lock);
dlokack(dsp->ds_wq, mp, DL_PASSIVE_REQ);
return (B_TRUE);
+failed:
+ rw_exit(&dsp->ds_lock);
+ dlerrorack(dsp->ds_wq, mp, DL_PASSIVE_REQ, dl_err, 0);
+ return (B_FALSE);
}
+
/*
* Catch-all handler.
*/
@@ -1051,440 +1420,13 @@ proto_req(dld_str_t *dsp, union DL_primitives *dlp, mblk_t *mp)
return (B_FALSE);
}
-typedef struct dl_info_ack_wrapper {
- dl_info_ack_t dl_info;
- uint8_t dl_addr[MAXADDRLEN + sizeof (uint16_t)];
- uint8_t dl_brdcst_addr[MAXADDRLEN];
- dl_qos_cl_range1_t dl_qos_range1;
- dl_qos_cl_sel1_t dl_qos_sel1;
-} dl_info_ack_wrapper_t;
-
-#define NEG(x) -(x)
-
-/*
- * DL_INFO_ACK
- */
-static void
-proto_info_ack(dld_str_t *dsp, mblk_t *mp)
-{
- dl_info_ack_wrapper_t *dlwp;
- dl_info_ack_t *dlp;
- dl_qos_cl_sel1_t *selp;
- dl_qos_cl_range1_t *rangep;
- uint8_t *addr;
- uint8_t *brdcst_addr;
- dld_node_t *dnp;
- uint_t addr_length;
- uint_t sap_length;
-
- /*
- * Swap the request message for one large enough to contain the
- * wrapper structure defined above.
- */
- if ((mp = mexchange(dsp->ds_wq, mp, sizeof (dl_info_ack_wrapper_t),
- M_PCPROTO, 0)) == NULL)
- return;
-
- bzero(mp->b_rptr, sizeof (dl_info_ack_wrapper_t));
- dlwp = (dl_info_ack_wrapper_t *)mp->b_rptr;
-
- dlp = &(dlwp->dl_info);
- ASSERT(dlp == (dl_info_ack_t *)mp->b_rptr);
-
- dlp->dl_primitive = DL_INFO_ACK;
-
- /*
- * Set up the sub-structure pointers.
- */
- addr = dlwp->dl_addr;
- brdcst_addr = dlwp->dl_brdcst_addr;
- rangep = &(dlwp->dl_qos_range1);
- selp = &(dlwp->dl_qos_sel1);
-
- /*
- * This driver supports only version 2 connectionless DLPI provider
- * nodes.
- */
- dlp->dl_service_mode = DL_CLDLS;
- dlp->dl_version = DL_VERSION_2;
-
- /*
- * Set the style of the provider from the dld_node_t structure
- * representing the dev_t that was opened.
- */
- dnp = dsp->ds_dnp;
- dlp->dl_provider_style = dnp->dn_style;
- ASSERT(dlp->dl_provider_style == DL_STYLE1 ||
- dlp->dl_provider_style == DL_STYLE2);
-
- /*
- * Set the current DLPI state.
- */
- dlp->dl_current_state = dsp->ds_dlstate;
-
- /*
- * Gratuitously set the media type. This is because the Cisco VPN 3000
- * module assumes that the media type is known prior to DL_ATTACH_REQ
- * being completed.
- */
- dlp->dl_mac_type = DL_ETHER;
-
- /*
- * If the stream is not at least attached then we're done.
- */
- if (dsp->ds_dlstate == DL_UNATTACHED ||
- dsp->ds_dlstate == DL_ATTACH_PENDING ||
- dsp->ds_dlstate == DL_DETACH_PENDING)
- goto done;
-
- /*
- * Set the media type (properly this time).
- */
- dlp->dl_mac_type = dsp->ds_mip->mi_media;
-
- /*
- * Set the DLSAP length. We only support 16 bit values and they
- * appear after the MAC address portion of DLSAP addresses.
- */
- sap_length = sizeof (uint16_t);
- dlp->dl_sap_length = NEG(sap_length);
-
- /*
- * Set the minimum and maximum payload sizes.
- */
- dlp->dl_min_sdu = dsp->ds_mip->mi_sdu_min;
- dlp->dl_max_sdu = dsp->ds_mip->mi_sdu_max;
-
- addr_length = dsp->ds_mip->mi_addr_length;
- ASSERT(addr_length != 0);
-
- /*
- * Copy in the media broadcast address.
- */
- dlp->dl_brdcst_addr_offset = (uintptr_t)brdcst_addr - (uintptr_t)dlp;
- bcopy(dsp->ds_mip->mi_brdcst_addr, brdcst_addr, addr_length);
- dlp->dl_brdcst_addr_length = addr_length;
-
- /*
- * We only support QoS information for VLAN interfaces.
- */
- if (dsp->ds_vid != VLAN_ID_NONE) {
- dlp->dl_qos_range_offset = (uintptr_t)rangep - (uintptr_t)dlp;
- dlp->dl_qos_range_length = sizeof (dl_qos_cl_range1_t);
-
- rangep->dl_qos_type = DL_QOS_CL_RANGE1;
- rangep->dl_trans_delay.dl_target_value = DL_UNKNOWN;
- rangep->dl_trans_delay.dl_accept_value = DL_UNKNOWN;
- rangep->dl_protection.dl_min = DL_UNKNOWN;
- rangep->dl_protection.dl_max = DL_UNKNOWN;
- rangep->dl_residual_error = DL_UNKNOWN;
-
- /*
- * Specify the supported range of priorities.
- */
- rangep->dl_priority.dl_min = 0;
- rangep->dl_priority.dl_max = (1 << VLAN_PRI_SIZE) - 1;
-
- dlp->dl_qos_offset = (uintptr_t)selp - (uintptr_t)dlp;
- dlp->dl_qos_length = sizeof (dl_qos_cl_sel1_t);
-
- selp->dl_qos_type = DL_QOS_CL_SEL1;
- selp->dl_trans_delay = DL_UNKNOWN;
- selp->dl_protection = DL_UNKNOWN;
- selp->dl_residual_error = DL_UNKNOWN;
-
- /*
- * Specify the current priority (which can be changed by
- * the DL_UDQOS_REQ primitive).
- */
- selp->dl_priority = dsp->ds_pri;
- } else {
- /*
- * Shorten the buffer to lose the unused QoS information
- * structures. This is to work around a bug in the Cisco VPN
- * 3000 module.
- */
- mp->b_wptr = (uint8_t *)rangep;
- }
-
- dlp->dl_addr_length = addr_length + sizeof (uint16_t);
- if (dsp->ds_dlstate == DL_IDLE) {
- /*
- * The stream is bound. Therefore we can formulate a valid
- * DLSAP address.
- */
- dlp->dl_addr_offset = (uintptr_t)addr - (uintptr_t)dlp;
- bcopy(dsp->ds_curr_addr, addr, addr_length);
- *(uint16_t *)(addr + addr_length) = dsp->ds_sap;
- }
-
-done:
- ASSERT(IMPLY(dlp->dl_qos_offset != 0, dlp->dl_qos_length != 0));
- ASSERT(IMPLY(dlp->dl_qos_range_offset != 0,
- dlp->dl_qos_range_length != 0));
- ASSERT(IMPLY(dlp->dl_addr_offset != 0, dlp->dl_addr_length != 0));
- ASSERT(IMPLY(dlp->dl_brdcst_addr_offset != 0,
- dlp->dl_brdcst_addr_length != 0));
-
- qreply(dsp->ds_wq, mp);
-}
-
-/*
- * DL_OK_ACK/DL_ERROR_ACK
- */
-static void
-proto_attach_ack(dld_str_t *dsp, mblk_t *mp, int err)
-{
- int dl_err;
-
- if (err != 0)
- goto failed;
-
- dsp->ds_dlstate = DL_UNBOUND;
- dlokack(dsp->ds_wq, mp, DL_ATTACH_REQ);
- return;
-
-failed:
- switch (err) {
- case ENOENT:
- dl_err = DL_BADPPA;
- err = 0;
- break;
-
- default:
- dl_err = DL_SYSERR;
- break;
- }
-
- dsp->ds_dlstate = DL_UNATTACHED;
- dlerrorack(dsp->ds_wq, mp, DL_ATTACH_REQ, dl_err, err);
-}
-
-/*
- * DL_OK_ACK
- */
-static void
-proto_detach_ack(dld_str_t *dsp, mblk_t *mp)
-{
- dsp->ds_dlstate = DL_UNATTACHED;
- dlokack(dsp->ds_wq, mp, DL_DETACH_REQ);
-}
-
-/*
- * DL_BIND_ACK/DL_ERROR_ACK
- */
-static void
-proto_bind_ack(dld_str_t *dsp, mblk_t *mp, int err)
-{
- uint8_t addr[MAXADDRLEN];
- uint_t addr_length;
- int dl_err;
-
- if (err != 0)
- goto failed;
-
- /*
- * Copy in MAC address.
- */
- addr_length = dsp->ds_mip->mi_addr_length;
- bcopy(dsp->ds_curr_addr, addr, addr_length);
-
- /*
- * Copy in the DLSAP.
- */
- *(uint16_t *)(addr + addr_length) = dsp->ds_sap;
- addr_length += sizeof (uint16_t);
-
- dsp->ds_dlstate = DL_IDLE;
- dlbindack(dsp->ds_wq, mp, dsp->ds_sap, (void *)addr, addr_length, 0,
- 0);
- return;
-
-failed:
- switch (err) {
- case EINVAL:
- dl_err = DL_BADADDR;
- err = 0;
- break;
-
- default:
- dl_err = DL_SYSERR;
- break;
- }
-
- dsp->ds_dlstate = DL_UNBOUND;
- dlerrorack(dsp->ds_wq, mp, DL_BIND_REQ, dl_err, err);
-}
-
-/*
- * DL_OK_ACK
- */
-static void
-proto_unbind_ack(dld_str_t *dsp, mblk_t *mp)
-{
- dsp->ds_dlstate = DL_UNBOUND;
- dlokack(dsp->ds_wq, mp, DL_UNBIND_REQ);
-}
-
-/*
- * DL_OK_ACK/DL_ERROR_ACK
- */
-static void
-proto_promiscon_ack(dld_str_t *dsp, mblk_t *mp, int err)
-{
- if (err != 0)
- goto failed;
-
- dlokack(dsp->ds_wq, mp, DL_PROMISCON_REQ);
- return;
-
-failed:
- dlerrorack(dsp->ds_wq, mp, DL_PROMISCON_REQ, DL_SYSERR, err);
-}
-
-/*
- * DL_OK_ACK/DL_ERROR_ACK
- */
-static void
-proto_promiscoff_ack(dld_str_t *dsp, mblk_t *mp, int err)
-{
- if (err != 0)
- goto failed;
-
- dlokack(dsp->ds_wq, mp, DL_PROMISCOFF_REQ);
- return;
-
-failed:
- dlerrorack(dsp->ds_wq, mp, DL_PROMISCOFF_REQ, DL_SYSERR, err);
-}
-
-/*
- * DL_OK_ACK/DL_ERROR_ACK
- */
-static void
-proto_enabmulti_ack(dld_str_t *dsp, mblk_t *mp, int err)
-{
- int dl_err;
-
- if (err != 0)
- goto failed;
-
- dlokack(dsp->ds_wq, mp, DL_ENABMULTI_REQ);
- return;
-
-failed:
- switch (err) {
- case EINVAL:
- dl_err = DL_BADADDR;
- err = 0;
- break;
-
- case ENOSPC:
- dl_err = DL_TOOMANY;
- err = 0;
- break;
-
- default:
- dl_err = DL_SYSERR;
- break;
- }
-
- dlerrorack(dsp->ds_wq, mp, DL_ENABMULTI_REQ, dl_err, err);
-}
-
-/*
- * DL_OK_ACK/DL_ERROR_ACK
- */
-static void
-proto_disabmulti_ack(dld_str_t *dsp, mblk_t *mp, int err)
-{
- int dl_err;
-
- if (err != 0)
- goto failed;
-
- dlokack(dsp->ds_wq, mp, DL_DISABMULTI_REQ);
- return;
-
-failed:
- switch (err) {
- case EINVAL:
- dl_err = DL_BADADDR;
- err = 0;
- break;
-
- case ENOENT:
- dl_err = DL_NOTENAB;
- err = 0;
- break;
-
- default:
- dl_err = DL_SYSERR;
- break;
- }
-
- dlerrorack(dsp->ds_wq, mp, DL_DISABMULTI_REQ, dl_err, err);
-}
-
-/*
- * DL_PHYS_ADDR_ACK
- */
-static void
-proto_physaddr_ack(dld_str_t *dsp, mblk_t *mp, t_uscalar_t type)
-{
- uint_t addr_length;
-
- /*
- * Copy in the address.
- */
- addr_length = dsp->ds_mip->mi_addr_length;
- dlphysaddrack(dsp->ds_wq, mp, (type == DL_CURR_PHYS_ADDR) ?
- dsp->ds_curr_addr : dsp->ds_fact_addr, addr_length);
-}
-
-/*
- * DL_OK_ACK/DL_ERROR_ACK
- */
-static void
-proto_setphysaddr_ack(dld_str_t *dsp, mblk_t *mp, int err)
-{
- int dl_err;
-
- if (err != 0)
- goto failed;
-
- dlokack(dsp->ds_wq, mp, DL_SET_PHYS_ADDR_REQ);
- return;
-
-failed:
- switch (err) {
- case EINVAL:
- dl_err = DL_BADADDR;
- err = 0;
- break;
-
- default:
- dl_err = DL_SYSERR;
- break;
- }
-
- dlerrorack(dsp->ds_wq, mp, DL_SET_PHYS_ADDR_REQ, dl_err, err);
-}
-
-/*
- * DL_OK_ACK
- */
-static void
-proto_udqos_ack(dld_str_t *dsp, mblk_t *mp)
-{
- dlokack(dsp->ds_wq, mp, DL_UDQOS_REQ);
-}
-
static void
proto_poll_disable(dld_str_t *dsp)
{
mac_handle_t mh;
+ ASSERT(RW_WRITE_HELD(&dsp->ds_lock));
+
if (!dsp->ds_polling)
return;
@@ -1516,6 +1458,7 @@ proto_poll_enable(dld_str_t *dsp, dl_capab_poll_t *pollp)
{
mac_handle_t mh;
+ ASSERT(RW_WRITE_HELD(&dsp->ds_lock));
ASSERT(!dsp->ds_polling);
/*
@@ -1551,8 +1494,8 @@ proto_poll_enable(dld_str_t *dsp, dl_capab_poll_t *pollp)
/*
* DL_CAPABILITY_ACK/DL_ERROR_ACK
*/
-static void
-proto_capability_ack(dld_str_t *dsp, mblk_t *mp)
+static boolean_t
+proto_capability_advertise(dld_str_t *dsp, mblk_t *mp)
{
dl_capability_ack_t *dlap;
dl_capability_sub_t *dlsp;
@@ -1563,6 +1506,10 @@ proto_capability_ack(dld_str_t *dsp, mblk_t *mp)
uint8_t *ptr;
uint32_t cksum;
boolean_t poll_cap;
+ queue_t *q = dsp->ds_wq;
+ mblk_t *mp1;
+
+ ASSERT(RW_READ_HELD(&dsp->ds_lock));
/*
* Initially assume no capabilities.
@@ -1600,19 +1547,20 @@ proto_capability_ack(dld_str_t *dsp, mblk_t *mp)
}
/*
- * If there are no capabilities to advertise, send a DL_ERROR_ACK.
+ * If there are no capabilities to advertise or if we
+ * can't allocate a response, send a DL_ERROR_ACK.
*/
- if (subsize == 0) {
- dlerrorack(dsp->ds_wq, mp, DL_CAPABILITY_REQ, DL_NOTSUPPORTED,
- 0);
- return;
+ if (subsize == 0 || (mp1 = reallocb(mp,
+ sizeof (dl_capability_ack_t) + subsize, 0)) == NULL) {
+ rw_exit(&dsp->ds_lock);
+ dlerrorack(q, mp, DL_CAPABILITY_REQ, DL_NOTSUPPORTED, 0);
+ return (B_FALSE);
}
- if ((mp = mexchange(dsp->ds_wq, mp,
- sizeof (dl_capability_ack_t) + subsize, M_PROTO, 0)) == NULL)
- return;
-
- bzero(mp->b_rptr, sizeof (dl_capability_ack_t));
+ mp = mp1;
+ DB_TYPE(mp) = M_PROTO;
+ mp->b_wptr = mp->b_rptr + sizeof (dl_capability_ack_t) + subsize;
+ bzero(mp->b_rptr, MBLKL(mp));
dlap = (dl_capability_ack_t *)mp->b_rptr;
dlap->dl_primitive = DL_CAPABILITY_ACK;
dlap->dl_sub_offset = sizeof (dl_capability_ack_t);
@@ -1624,27 +1572,58 @@ proto_capability_ack(dld_str_t *dsp, mblk_t *mp)
*/
if (poll_cap) {
/*
- * Attempt to disable just in case this is a re-negotiation.
+ * Attempt to disable just in case this is a re-negotiation;
+ * we need to become writer before doing so.
*/
- proto_poll_disable(dsp);
+ if (!rw_tryupgrade(&dsp->ds_lock)) {
+ rw_exit(&dsp->ds_lock);
+ rw_enter(&dsp->ds_lock, RW_WRITER);
+ }
- dlsp = (dl_capability_sub_t *)ptr;
+ /*
+ * Check if polling state has changed after we re-acquired
+ * the lock above, so that we don't mis-advertise it.
+ */
+ poll_cap = ((dsp->ds_mip->mi_poll & DL_CAPAB_POLL) &&
+ !(dld_opt & DLD_OPT_NO_POLL) &&
+ (dsp->ds_vid == VLAN_ID_NONE));
- dlsp->dl_cap = DL_CAPAB_POLL;
- dlsp->dl_length = sizeof (dl_capab_poll_t);
- ptr += sizeof (dl_capability_sub_t);
+ if (!poll_cap) {
+ int poll_capab_size;
+
+ rw_downgrade(&dsp->ds_lock);
+
+ poll_capab_size = sizeof (dl_capability_sub_t) +
+ sizeof (dl_capab_poll_t);
+
+ mp->b_wptr -= poll_capab_size;
+ subsize -= poll_capab_size;
+ dlap->dl_sub_length = subsize;
+ } else {
+ proto_poll_disable(dsp);
+
+ rw_downgrade(&dsp->ds_lock);
- bzero(&poll, sizeof (dl_capab_poll_t));
- poll.poll_version = POLL_VERSION_1;
- poll.poll_flags = POLL_CAPABLE;
- poll.poll_tx_handle = (uintptr_t)dsp->ds_dc;
- poll.poll_tx = (uintptr_t)dls_tx;
+ dlsp = (dl_capability_sub_t *)ptr;
- dlcapabsetqid(&(poll.poll_mid), dsp->ds_rq);
- bcopy(&poll, ptr, sizeof (dl_capab_poll_t));
- ptr += sizeof (dl_capab_poll_t);
+ dlsp->dl_cap = DL_CAPAB_POLL;
+ dlsp->dl_length = sizeof (dl_capab_poll_t);
+ ptr += sizeof (dl_capability_sub_t);
+
+ bzero(&poll, sizeof (dl_capab_poll_t));
+ poll.poll_version = POLL_VERSION_1;
+ poll.poll_flags = POLL_CAPABLE;
+ poll.poll_tx_handle = (uintptr_t)dsp;
+ poll.poll_tx = (uintptr_t)str_mdata_fastpath_put;
+
+ dlcapabsetqid(&(poll.poll_mid), dsp->ds_rq);
+ bcopy(&poll, ptr, sizeof (dl_capab_poll_t));
+ ptr += sizeof (dl_capab_poll_t);
+ }
}
+ ASSERT(RW_READ_HELD(&dsp->ds_lock));
+
/*
* TCP/IP checksum offload.
*/
@@ -1684,137 +1663,8 @@ proto_capability_ack(dld_str_t *dsp, mblk_t *mp)
}
ASSERT(ptr == mp->b_rptr + sizeof (dl_capability_ack_t) + subsize);
- qreply(dsp->ds_wq, mp);
-}
-
-/*
- * DL_CAPABILITY_ACK/DL_ERROR_ACK
- */
-static void
-proto_capability_enable(dld_str_t *dsp, mblk_t *mp)
-{
- dl_capability_req_t *dlp = (dl_capability_req_t *)mp->b_rptr;
- dl_capability_sub_t *sp;
- size_t size;
- offset_t off;
- size_t len;
- offset_t end;
-
- dlp->dl_primitive = DL_CAPABILITY_ACK;
-
- off = dlp->dl_sub_offset;
- len = dlp->dl_sub_length;
-
- /*
- * Walk the list of capabilities to be enabled.
- */
- for (end = off + len; off < end; ) {
- sp = (dl_capability_sub_t *)(mp->b_rptr + off);
- size = sizeof (dl_capability_sub_t) + sp->dl_length;
-
- if (off + size > end ||
- !IS_P2ALIGNED(off, sizeof (uint32_t))) {
- dlerrorack(dsp->ds_wq, mp, DL_CAPABILITY_REQ,
- DL_BADPRIM, 0);
- return;
- }
-
- switch (sp->dl_cap) {
-
- /*
- * TCP/IP checksum offload to hardware.
- */
- case DL_CAPAB_HCKSUM: {
- dl_capab_hcksum_t *hcksump;
- dl_capab_hcksum_t hcksum;
-
- ASSERT(dsp->ds_mip->mi_cksum != 0);
-
- hcksump = (dl_capab_hcksum_t *)&sp[1];
-
- /*
- * Copy for alignment.
- */
- bcopy(hcksump, &hcksum, sizeof (dl_capab_hcksum_t));
- dlcapabsetqid(&(hcksum.hcksum_mid), dsp->ds_rq);
- bcopy(&hcksum, hcksump, sizeof (dl_capab_hcksum_t));
- break;
- }
-
- /*
- * IP polling interface.
- */
- case DL_CAPAB_POLL: {
- dl_capab_poll_t *pollp;
- dl_capab_poll_t poll;
-
- pollp = (dl_capab_poll_t *)&sp[1];
-
- /*
- * Copy for alignment.
- */
- bcopy(pollp, &poll, sizeof (dl_capab_poll_t));
-
- switch (poll.poll_flags) {
- default:
- /*FALLTHRU*/
- case POLL_DISABLE:
- proto_poll_disable(dsp);
- break;
- case POLL_ENABLE:
- ASSERT(!(dld_opt & DLD_OPT_NO_POLL));
-
- /*
- * Make sure polling is disabled.
- */
- proto_poll_disable(dsp);
-
- /*
- * Now attempt enable it.
- */
- if (!proto_poll_enable(dsp, &poll))
- break;
-
- bzero(&poll, sizeof (dl_capab_poll_t));
- poll.poll_flags = POLL_ENABLE;
- break;
- }
-
- dlcapabsetqid(&(poll.poll_mid), dsp->ds_rq);
- bcopy(&poll, pollp, sizeof (dl_capab_poll_t));
- break;
- }
- default:
- break;
- }
-
- off += size;
- }
-
- qreply(dsp->ds_wq, mp);
-}
-
-/*
- * DL_NOTIFY_ACK
- */
-static void
-proto_notify_ack(dld_str_t *dsp, mblk_t *mp, uint_t enable_set, uint_t ack_set)
-{
- /*
- * Cache the notifications that are being enabled.
- */
- dsp->ds_notifications = enable_set;
-
- /*
- * The ACK carries all notifications regardless of which set is
- * being enabled.
- */
- dlnotifyack(dsp->ds_wq, mp, ack_set);
-
- /*
- * Solicit DL_NOTIFY_IND messages for each enabled notification.
- */
- if (dsp->ds_notifications != 0)
- dld_str_notify_ind(dsp);
+ rw_exit(&dsp->ds_lock);
+ qreply(q, mp);
+ return (B_TRUE);
}
diff --git a/usr/src/uts/common/io/dld/dld_str.c b/usr/src/uts/common/io/dld/dld_str.c
index 96f68cc139..0e697c39f1 100644
--- a/usr/src/uts/common/io/dld/dld_str.c
+++ b/usr/src/uts/common/io/dld/dld_str.c
@@ -30,31 +30,19 @@
* Data-Link Driver
*/
-#include <sys/types.h>
-#include <sys/stream.h>
#include <sys/stropts.h>
#include <sys/strsun.h>
#include <sys/strsubr.h>
#include <sys/atomic.h>
-#include <sys/sdt.h>
-#include <sys/mac.h>
-#include <sys/dls.h>
+#include <sys/mkdev.h>
+#include <sys/vlan.h>
#include <sys/dld.h>
#include <sys/dld_impl.h>
-#include <sys/taskq.h>
-#include <sys/vlan.h>
+#include <sys/dls_impl.h>
+#include <inet/common.h>
static int str_constructor(void *, void *, int);
static void str_destructor(void *, void *);
-static void str_m_put(dld_str_t *, mblk_t *);
-static void str_m_srv(dld_str_t *, mblk_t *);
-static void str_mdata_fastpath_put(dld_str_t *, mblk_t *);
-static void str_mdata_raw_put(dld_str_t *, mblk_t *);
-static void str_mdata_srv(dld_str_t *, mblk_t *);
-static void str_mproto_put(dld_str_t *, mblk_t *);
-static void str_mpcproto_put(dld_str_t *, mblk_t *);
-static void str_mioctl_put(dld_str_t *, mblk_t *);
-static void str_mflush_put(dld_str_t *, mblk_t *);
static mblk_t *str_unitdata_ind(dld_str_t *, mblk_t *);
static void str_notify_promisc_on_phys(dld_str_t *);
static void str_notify_promisc_off_phys(dld_str_t *);
@@ -64,69 +52,420 @@ static void str_notify_link_down(dld_str_t *);
static void str_notify_capab_reneg(dld_str_t *);
static void str_notify_speed(dld_str_t *, uint32_t);
static void str_notify(void *, mac_notify_type_t);
-static void str_putbq(queue_t *q, mblk_t *mp);
+
+static void ioc_raw(dld_str_t *, mblk_t *);
+static void ioc_fast(dld_str_t *, mblk_t *);
+static void ioc(dld_str_t *, mblk_t *);
+static void dld_ioc(dld_str_t *, mblk_t *);
+static minor_t dld_minor_hold(boolean_t);
+static void dld_minor_rele(minor_t);
static uint32_t str_count;
static kmem_cache_t *str_cachep;
+static vmem_t *minor_arenap;
+static uint32_t minor_count;
+
+#define MINOR_TO_PTR(minor) ((void *)(uintptr_t)(minor))
+#define PTR_TO_MINOR(ptr) ((minor_t)(uintptr_t)(ptr))
+
+/*
+ * Some notes on entry points, flow-control, queueing and locking:
+ *
+ * This driver exports the traditional STREAMS put entry point as well as
+ * the non-STREAMS fast-path transmit routine which is provided to IP via
+ * the DL_CAPAB_POLL negotiation. The put procedure handles all control
+ * and data operations, while the fast-path routine deals only with M_DATA
+ * fast-path packets. Regardless of the entry point, all outbound packets
+ * will end up in str_mdata_fastpath_put(), where they will be delivered to
+ * the MAC driver.
+ *
+ * The transmit logic operates in two modes: a "not busy" mode where the
+ * packets will be delivered to the MAC for a send attempt, or "busy" mode
+ * where they will be enqueued in the internal queue because of flow-control.
+ * Flow-control happens when the MAC driver indicates the packets couldn't
+ * be transmitted due to lack of resources (e.g. running out of descriptors).
+ * In such case, the driver will place a dummy message on its write-side
+ * STREAMS queue so that the queue is marked as "full". Any subsequent
+ * packets arriving at the driver will be enqueued in the internal queue,
+ * which is drained in the context of the service thread that gets scheduled
+ * whenever the driver is in the "busy" mode. When all packets have been
+ * successfully delivered by MAC and the internal queue is empty, it will
+ * transition to the "not busy" mode by removing the dummy message from the
+ * write-side STREAMS queue; in effect this will trigger backenabling.
+ * The sizes of q_hiwat and q_lowat are set to 1 and 0, respectively, due
+ * to the above reasons.
+ *
+ * The driver implements an internal transmit queue independent of STREAMS.
+ * This allows for flexibility and provides a fast enqueue/dequeue mechanism
+ * compared to the putq() and get() STREAMS interfaces. The only putq() and
+ * getq() operations done by the driver are those related to placing and
+ * removing the dummy message to/from the write-side STREAMS queue for flow-
+ * control purposes.
+ *
+ * Locking is done independent of STREAMS due to the driver being fully MT.
+ * Threads entering the driver (either from put or service entry points)
+ * will most likely be readers, with the exception of a few writer cases
+ * such those handling DLPI attach/detach/bind/unbind/etc. or any of the
+ * DLD-related ioctl requests. The DLPI detach case is special, because
+ * it involves freeing resources and therefore must be single-threaded.
+ * Unfortunately the readers/writers lock can't be used to protect against
+ * it, because the lock is dropped prior to the driver calling places where
+ * putnext() may be invoked, and such places may depend on those resources
+ * to exist. Because of this, the driver always completes the DLPI detach
+ * process when there are no other threads running in the driver. This is
+ * done by keeping track of the number of threads, such that the the last
+ * thread leaving the driver will finish the pending DLPI detach operation.
+ */
+
+/*
+ * dld_max_q_count is the queue depth threshold used to limit the number of
+ * outstanding packets or bytes allowed in the queue; once this limit is
+ * reached the driver will free any incoming ones until the queue depth
+ * drops below the threshold.
+ *
+ * This buffering is provided to accomodate clients which do not employ
+ * their own buffering scheme, and to handle occasional packet bursts.
+ * Clients which handle their own buffering will receive positive feedback
+ * from this driver as soon as it transitions into the "busy" state, i.e.
+ * when the queue is initially filled up; they will get backenabled once
+ * the queue is empty.
+ *
+ * The value chosen here is rather arbitrary; in future some intelligent
+ * heuristics may be involved which could take into account the hardware's
+ * transmit ring size, etc.
+ */
+uint_t dld_max_q_count = (16 * 1024 *1024);
+
+static dev_info_t *
+dld_finddevinfo(dev_t dev)
+{
+ minor_t minor = getminor(dev);
+ char *drvname = ddi_major_to_name(getmajor(dev));
+ char name[MAXNAMELEN];
+ dls_vlan_t *dvp = NULL;
+ dev_info_t *dip = NULL;
+
+ if (drvname == NULL || minor == 0 || minor > DLD_MAX_PPA + 1)
+ return (NULL);
+
+ (void) snprintf(name, MAXNAMELEN, "%s%d", drvname, (int)minor - 1);
+ if (dls_vlan_hold(name, &dvp, B_FALSE) != 0)
+ return (NULL);
+
+ dip = mac_devinfo_get(dvp->dv_dlp->dl_mh);
+ dls_vlan_rele(dvp);
+ return (dip);
+}
+
+/*
+ * devo_getinfo: getinfo(9e)
+ */
+/*ARGSUSED*/
+int
+dld_getinfo(dev_info_t *dip, ddi_info_cmd_t cmd, void *arg, void **resp)
+{
+ dev_info_t *devinfo;
+ minor_t minor = getminor((dev_t)arg);
+ int rc = DDI_FAILURE;
+
+ switch (cmd) {
+ case DDI_INFO_DEVT2DEVINFO:
+ if ((devinfo = dld_finddevinfo((dev_t)arg)) != NULL) {
+ *(dev_info_t **)resp = devinfo;
+ rc = DDI_SUCCESS;
+ }
+ break;
+ case DDI_INFO_DEVT2INSTANCE:
+ if (minor > 0 && minor <= DLD_MAX_PPA + 1) {
+ *(int *)resp = (int)minor - 1;
+ rc = DDI_SUCCESS;
+ }
+ break;
+ }
+ return (rc);
+}
+
+/*
+ * qi_qopen: open(9e)
+ */
+/*ARGSUSED*/
+int
+dld_open(queue_t *rq, dev_t *devp, int flag, int sflag, cred_t *credp)
+{
+ dld_str_t *dsp;
+ major_t major;
+ minor_t minor;
+ int err;
+
+ if (sflag == MODOPEN)
+ return (ENOTSUP);
+
+ /*
+ * This is a cloning driver and therefore each queue should only
+ * ever get opened once.
+ */
+ if (rq->q_ptr != NULL)
+ return (EBUSY);
+
+ major = getmajor(*devp);
+ minor = getminor(*devp);
+ if (minor > DLD_MAX_MINOR)
+ return (ENODEV);
+
+ /*
+ * Create a new dld_str_t for the stream. This will grab a new minor
+ * number that will be handed back in the cloned dev_t. Creation may
+ * fail if we can't allocate the dummy mblk used for flow-control.
+ */
+ dsp = dld_str_create(rq, DLD_DLPI, major,
+ ((minor == 0) ? DL_STYLE2 : DL_STYLE1));
+ if (dsp == NULL)
+ return (ENOSR);
+
+ ASSERT(dsp->ds_dlstate == DL_UNATTACHED);
+ if (minor != 0) {
+ /*
+ * Style 1 open
+ */
-typedef struct str_msg_info {
- uint8_t smi_type;
- const char *smi_txt;
- void (*smi_put)(dld_str_t *, mblk_t *);
- void (*smi_srv)(dld_str_t *, mblk_t *);
-} str_msg_info_t;
+ if ((err = dld_str_attach(dsp, (t_uscalar_t)minor - 1)) != 0)
+ goto failed;
+ ASSERT(dsp->ds_dlstate == DL_UNBOUND);
+ }
+
+ /*
+ * Enable the queue srv(9e) routine.
+ */
+ qprocson(rq);
+
+ /*
+ * Construct a cloned dev_t to hand back.
+ */
+ *devp = makedevice(getmajor(*devp), dsp->ds_minor);
+ return (0);
+
+failed:
+ dld_str_destroy(dsp);
+ return (err);
+}
+
+/*
+ * qi_qclose: close(9e)
+ */
+int
+dld_close(queue_t *rq)
+{
+ dld_str_t *dsp = rq->q_ptr;
+
+ /*
+ * Disable the queue srv(9e) routine.
+ */
+ qprocsoff(rq);
+
+ /*
+ * At this point we can not be entered by any threads via STREAMS
+ * or the direct call interface, which is available only to IP.
+ * After the interface is unplumbed, IP wouldn't have any reference
+ * to this instance, and therefore we are now effectively single
+ * threaded and don't require any lock protection. Flush all
+ * pending packets which are sitting in the transmit queue.
+ */
+ ASSERT(dsp->ds_thr == 0);
+ dld_tx_flush(dsp);
+
+ /*
+ * This stream was open to a provider node. Check to see
+ * if it has been cleanly shut down.
+ */
+ if (dsp->ds_dlstate != DL_UNATTACHED) {
+ /*
+ * The stream is either open to a style 1 provider or
+ * this is not clean shutdown. Detach from the PPA.
+ * (This is still ok even in the style 1 case).
+ */
+ dld_str_detach(dsp);
+ }
+
+ dld_str_destroy(dsp);
+ return (0);
+}
/*
- * Normal priority message jump table.
+ * qi_qputp: put(9e)
*/
-str_msg_info_t str_mi[] = {
- { M_DATA, "M_DATA", str_m_put, str_m_srv },
- { M_PROTO, "M_PROTO", str_mproto_put, str_m_srv },
- { 0x02, "undefined", str_m_put, str_m_srv },
- { 0x03, "undefined", str_m_put, str_m_srv },
- { 0x04, "undefined", str_m_put, str_m_srv },
- { 0x05, "undefined", str_m_put, str_m_srv },
- { 0x06, "undefined", str_m_put, str_m_srv },
- { 0x07, "undefined", str_m_put, str_m_srv },
- { M_BREAK, "M_BREAK", str_m_put, str_m_srv },
- { M_PASSFP, "M_PASSFP", str_m_put, str_m_srv },
- { M_EVENT, "M_EVENT", str_m_put, str_m_srv },
- { M_SIG, "M_SIG", str_m_put, str_m_srv },
- { M_DELAY, "M_DELAY", str_m_put, str_m_srv },
- { M_CTL, "M_CTL", str_m_put, str_m_srv },
- { M_IOCTL, "M_IOCTL", str_mioctl_put, str_m_srv },
- { M_SETOPTS, "M_SETOPTS", str_m_put, str_m_srv },
- { M_RSE, "M_RSE", str_m_put, str_m_srv }
-};
-
-#define STR_MI_COUNT (sizeof (str_mi) / sizeof (str_mi[0]))
+void
+dld_wput(queue_t *wq, mblk_t *mp)
+{
+ dld_str_t *dsp = (dld_str_t *)wq->q_ptr;
+
+ DLD_ENTER(dsp);
+
+ switch (DB_TYPE(mp)) {
+ case M_DATA:
+ rw_enter(&dsp->ds_lock, RW_READER);
+ if (dsp->ds_dlstate != DL_IDLE ||
+ dsp->ds_mode == DLD_UNITDATA) {
+ freemsg(mp);
+ } else if (dsp->ds_mode == DLD_FASTPATH) {
+ str_mdata_fastpath_put(dsp, mp);
+ } else if (dsp->ds_mode == DLD_RAW) {
+ str_mdata_raw_put(dsp, mp);
+ }
+ rw_exit(&dsp->ds_lock);
+ break;
+ case M_PROTO:
+ case M_PCPROTO:
+ dld_proto(dsp, mp);
+ break;
+ case M_IOCTL:
+ dld_ioc(dsp, mp);
+ break;
+ case M_FLUSH:
+ if (*mp->b_rptr & FLUSHW) {
+ dld_tx_flush(dsp);
+ *mp->b_rptr &= ~FLUSHW;
+ }
+
+ if (*mp->b_rptr & FLUSHR) {
+ qreply(wq, mp);
+ } else {
+ freemsg(mp);
+ }
+ break;
+ default:
+ freemsg(mp);
+ break;
+ }
+
+ DLD_EXIT(dsp);
+}
/*
- * High priority message jump table.
+ * qi_srvp: srv(9e)
*/
-str_msg_info_t str_pmi[] = {
- { 0x80, "undefined", str_m_put, str_m_srv },
- { M_IOCACK, "M_IOCACK", str_m_put, str_m_srv },
- { M_IOCNAK, "M_IOCNAK", str_m_put, str_m_srv },
- { M_PCPROTO, "M_PCPROTO", str_mpcproto_put, str_m_srv },
- { M_PCSIG, "M_PCSIG", str_m_put, str_m_srv },
- { M_READ, "M_READ", str_m_put, str_m_srv },
- { M_FLUSH, "M_FLUSH", str_mflush_put, str_m_srv },
- { M_STOP, "M_STOP", str_m_put, str_m_srv },
- { M_START, "M_START", str_m_put, str_m_srv },
- { M_HANGUP, "M_HANGUP", str_m_put, str_m_srv },
- { M_ERROR, "M_ERROR", str_m_put, str_m_srv },
- { M_COPYIN, "M_COPYIN", str_m_put, str_m_srv },
- { M_COPYOUT, "M_COPYOUT", str_m_put, str_m_srv },
- { M_IOCDATA, "M_IOCDATA", str_m_put, str_m_srv },
- { M_PCRSE, "M_PCRSE", str_m_put, str_m_srv },
- { M_STOPI, "M_STOPI", str_m_put, str_m_srv },
- { M_STARTI, "M_STARTI", str_m_put, str_m_srv },
- { M_PCEVENT, "M_PCEVENT", str_m_put, str_m_srv },
- { M_UNHANGUP, "M_UNHANGUP", str_m_put, str_m_srv }
-};
-
-#define STR_PMI_COUNT (sizeof (str_pmi) / sizeof (str_pmi[0]))
+void
+dld_wsrv(queue_t *wq)
+{
+ mblk_t *mp;
+ dld_str_t *dsp = wq->q_ptr;
+
+ DLD_ENTER(dsp);
+ rw_enter(&dsp->ds_lock, RW_READER);
+ /*
+ * Grab all packets (chained via b_next) off our transmit queue
+ * and try to send them all to the MAC layer. Since the queue
+ * is independent of streams, we are able to dequeue all messages
+ * at once without looping through getq() and manually chaining
+ * them. Note that the queue size parameters (byte and message
+ * counts) are cleared as well, but we postpone the backenabling
+ * until after the MAC transmit since some packets may end up
+ * back at our transmit queue.
+ */
+ mutex_enter(&dsp->ds_tx_list_lock);
+ if ((mp = dsp->ds_tx_list_head) == NULL) {
+ ASSERT(!dsp->ds_tx_qbusy);
+ ASSERT(dsp->ds_tx_flow_mp != NULL);
+ ASSERT(dsp->ds_tx_list_head == NULL);
+ ASSERT(dsp->ds_tx_list_tail == NULL);
+ ASSERT(dsp->ds_tx_cnt == 0);
+ ASSERT(dsp->ds_tx_msgcnt == 0);
+ mutex_exit(&dsp->ds_tx_list_lock);
+ goto done;
+ }
+ dsp->ds_tx_list_head = dsp->ds_tx_list_tail = NULL;
+ dsp->ds_tx_cnt = dsp->ds_tx_msgcnt = 0;
+ mutex_exit(&dsp->ds_tx_list_lock);
+
+ /*
+ * Discard packets unless we are attached and bound; note that
+ * the driver mode (fastpath/raw/unitdata) is irrelevant here,
+ * because regardless of the mode all transmit will end up in
+ * str_mdata_fastpath_put() where the packets may be queued.
+ */
+ ASSERT(DB_TYPE(mp) == M_DATA);
+ if (dsp->ds_dlstate != DL_IDLE) {
+ freemsgchain(mp);
+ goto done;
+ }
+
+ /*
+ * Attempt to transmit one or more packets. If the MAC can't
+ * send them all, re-queue the packet(s) at the beginning of
+ * the transmit queue to avoid any re-ordering.
+ */
+ if ((mp = dls_tx(dsp->ds_dc, mp)) != NULL)
+ dld_tx_enqueue(dsp, mp, B_TRUE);
+
+ /*
+ * Grab the list lock again and check if the transmit queue is
+ * really empty; if so, lift up flow-control and backenable any
+ * writer queues. If the queue is not empty, schedule service
+ * thread to drain it.
+ */
+ mutex_enter(&dsp->ds_tx_list_lock);
+ if (dsp->ds_tx_list_head == NULL) {
+ dsp->ds_tx_flow_mp = getq(wq);
+ ASSERT(dsp->ds_tx_flow_mp != NULL);
+ dsp->ds_tx_qbusy = B_FALSE;
+ }
+ mutex_exit(&dsp->ds_tx_list_lock);
+done:
+ rw_exit(&dsp->ds_lock);
+ DLD_EXIT(dsp);
+}
+
+void
+dld_init_ops(struct dev_ops *ops, const char *name)
+{
+ struct streamtab *stream;
+ struct qinit *rq, *wq;
+ struct module_info *modinfo;
+
+ modinfo = kmem_zalloc(sizeof (struct module_info), KM_SLEEP);
+ modinfo->mi_idname = kmem_zalloc(FMNAMESZ, KM_SLEEP);
+ (void) snprintf(modinfo->mi_idname, FMNAMESZ, "%s", name);
+ modinfo->mi_minpsz = 0;
+ modinfo->mi_maxpsz = 64*1024;
+ modinfo->mi_hiwat = 1;
+ modinfo->mi_lowat = 0;
+
+ rq = kmem_zalloc(sizeof (struct qinit), KM_SLEEP);
+ rq->qi_qopen = dld_open;
+ rq->qi_qclose = dld_close;
+ rq->qi_minfo = modinfo;
+
+ wq = kmem_zalloc(sizeof (struct qinit), KM_SLEEP);
+ wq->qi_putp = (pfi_t)dld_wput;
+ wq->qi_srvp = (pfi_t)dld_wsrv;
+ wq->qi_minfo = modinfo;
+
+ stream = kmem_zalloc(sizeof (struct streamtab), KM_SLEEP);
+ stream->st_rdinit = rq;
+ stream->st_wrinit = wq;
+ ops->devo_cb_ops->cb_str = stream;
+
+ ops->devo_getinfo = &dld_getinfo;
+}
+
+void
+dld_fini_ops(struct dev_ops *ops)
+{
+ struct streamtab *stream;
+ struct qinit *rq, *wq;
+ struct module_info *modinfo;
+
+ stream = ops->devo_cb_ops->cb_str;
+ rq = stream->st_rdinit;
+ wq = stream->st_wrinit;
+ modinfo = rq->qi_minfo;
+ ASSERT(wq->qi_minfo == modinfo);
+
+ kmem_free(stream, sizeof (struct streamtab));
+ kmem_free(wq, sizeof (struct qinit));
+ kmem_free(rq, sizeof (struct qinit));
+ kmem_free(modinfo->mi_idname, FMNAMESZ);
+ kmem_free(modinfo, sizeof (struct module_info));
+}
/*
* Initialize this module's data structures.
@@ -140,6 +479,16 @@ dld_str_init(void)
str_cachep = kmem_cache_create("dld_str_cache", sizeof (dld_str_t),
0, str_constructor, str_destructor, NULL, NULL, NULL, 0);
ASSERT(str_cachep != NULL);
+
+ /*
+ * Allocate a vmem arena to manage minor numbers. The range of the
+ * arena will be from DLD_MAX_MINOR + 1 to MAXMIN (maximum legal
+ * minor number).
+ */
+ minor_arenap = vmem_create("dld_minor_arena",
+ MINOR_TO_PTR(DLD_MAX_MINOR + 1), MAXMIN, 1, NULL, NULL, NULL, 0,
+ VM_SLEEP | VMC_IDENTIFIER);
+ ASSERT(minor_arenap != NULL);
}
/*
@@ -155,10 +504,16 @@ dld_str_fini(void)
return (EBUSY);
/*
+ * Check to see if there are any minor numbers still in use.
+ */
+ if (minor_count != 0)
+ return (EBUSY);
+
+ /*
* Destroy object cache.
*/
kmem_cache_destroy(str_cachep);
-
+ vmem_destroy(minor_arenap);
return (0);
}
@@ -166,15 +521,28 @@ dld_str_fini(void)
* Create a new dld_str_t object.
*/
dld_str_t *
-dld_str_create(queue_t *rq)
+dld_str_create(queue_t *rq, uint_t type, major_t major, t_uscalar_t style)
{
dld_str_t *dsp;
/*
* Allocate an object from the cache.
*/
- dsp = kmem_cache_alloc(str_cachep, KM_SLEEP);
atomic_add_32(&str_count, 1);
+ dsp = kmem_cache_alloc(str_cachep, KM_SLEEP);
+
+ /*
+ * Allocate the dummy mblk for flow-control.
+ */
+ dsp->ds_tx_flow_mp = allocb(1, BPRI_HI);
+ if (dsp->ds_tx_flow_mp == NULL) {
+ kmem_cache_free(str_cachep, dsp);
+ atomic_add_32(&str_count, -1);
+ return (NULL);
+ }
+ dsp->ds_type = type;
+ dsp->ds_major = major;
+ dsp->ds_style = style;
/*
* Initialize the queue pointers.
@@ -184,6 +552,12 @@ dld_str_create(queue_t *rq)
dsp->ds_wq = WR(rq);
rq->q_ptr = WR(rq)->q_ptr = (void *)dsp;
+ /*
+ * We want explicit control over our write-side STREAMS queue
+ * where the dummy mblk gets added/removed for flow-control.
+ */
+ noenable(WR(rq));
+
return (dsp);
}
@@ -206,6 +580,18 @@ dld_str_destroy(dld_str_t *dsp)
rq->q_ptr = wq->q_ptr = NULL;
dsp->ds_rq = dsp->ds_wq = NULL;
+ ASSERT(!RW_LOCK_HELD(&dsp->ds_lock));
+ ASSERT(MUTEX_NOT_HELD(&dsp->ds_tx_list_lock));
+ ASSERT(dsp->ds_tx_list_head == NULL);
+ ASSERT(dsp->ds_tx_list_tail == NULL);
+ ASSERT(dsp->ds_tx_cnt == 0);
+ ASSERT(dsp->ds_tx_msgcnt == 0);
+ ASSERT(!dsp->ds_tx_qbusy);
+
+ ASSERT(MUTEX_NOT_HELD(&dsp->ds_thr_lock));
+ ASSERT(dsp->ds_thr == 0);
+ ASSERT(dsp->ds_detach_req == NULL);
+
/*
* Reinitialize all the flags.
*/
@@ -214,6 +600,13 @@ dld_str_destroy(dld_str_t *dsp)
dsp->ds_mode = DLD_UNITDATA;
/*
+ * Free the dummy mblk if exists.
+ */
+ if (dsp->ds_tx_flow_mp != NULL) {
+ freeb(dsp->ds_tx_flow_mp);
+ dsp->ds_tx_flow_mp = NULL;
+ }
+ /*
* Free the object back to the cache.
*/
kmem_cache_free(str_cachep, dsp);
@@ -232,39 +625,20 @@ str_constructor(void *buf, void *cdrarg, int kmflags)
bzero(buf, sizeof (dld_str_t));
/*
- * Take a copy of the global message handler jump tables.
- */
- ASSERT(dsp->ds_mi == NULL);
- if ((dsp->ds_mi = kmem_zalloc(sizeof (str_mi), kmflags)) == NULL)
- return (-1);
-
- bcopy(str_mi, dsp->ds_mi, sizeof (str_mi));
-
- ASSERT(dsp->ds_pmi == NULL);
- if ((dsp->ds_pmi = kmem_zalloc(sizeof (str_pmi), kmflags)) == NULL) {
- kmem_free(dsp->ds_mi, sizeof (str_mi));
- dsp->ds_mi = NULL;
- return (-1);
- }
-
- bcopy(str_pmi, dsp->ds_pmi, sizeof (str_pmi));
-
- /*
* Allocate a new minor number.
*/
- if ((dsp->ds_minor = dld_minor_hold(kmflags == KM_SLEEP)) == 0) {
- kmem_free(dsp->ds_mi, sizeof (str_mi));
- dsp->ds_mi = NULL;
- kmem_free(dsp->ds_pmi, sizeof (str_pmi));
- dsp->ds_pmi = NULL;
+ if ((dsp->ds_minor = dld_minor_hold(kmflags == KM_SLEEP)) == 0)
return (-1);
- }
/*
* Initialize the DLPI state machine.
*/
dsp->ds_dlstate = DL_UNATTACHED;
+ mutex_init(&dsp->ds_thr_lock, NULL, MUTEX_DRIVER, NULL);
+ rw_init(&dsp->ds_lock, NULL, RW_DRIVER, NULL);
+ mutex_init(&dsp->ds_tx_list_lock, NULL, MUTEX_DRIVER, NULL);
+
return (0);
}
@@ -299,170 +673,53 @@ str_destructor(void *buf, void *cdrarg)
ASSERT(!dsp->ds_polling);
/*
- * Make sure M_DATA message handling is disabled.
- */
- ASSERT(dsp->ds_mi[M_DATA].smi_put == str_m_put);
- ASSERT(dsp->ds_mi[M_DATA].smi_srv == str_m_srv);
-
- /*
* Release the minor number.
*/
dld_minor_rele(dsp->ds_minor);
- /*
- * Clear down the jump tables.
- */
- kmem_free(dsp->ds_mi, sizeof (str_mi));
- dsp->ds_mi = NULL;
-
- kmem_free(dsp->ds_pmi, sizeof (str_pmi));
- dsp->ds_pmi = NULL;
-}
-
-/*
- * Called from put(9e) to process a streams message.
- */
-void
-dld_str_put(dld_str_t *dsp, mblk_t *mp)
-{
- uint8_t type;
- str_msg_info_t *smip;
-
- /*
- * Look up the message handler from the appropriate jump table.
- */
- if ((type = DB_TYPE(mp)) & QPCTL) {
- /*
- * Clear the priority bit to index into the jump table.
- */
- type &= ~QPCTL;
-
- /*
- * Check the message is not out of range for the jump table.
- */
- if (type >= STR_PMI_COUNT)
- goto unknown;
-
- /*
- * Get the handler from the jump table.
- */
- smip = &(dsp->ds_pmi[type]);
-
- /*
- * OR the priorty bit back in to restore the original message
- * type.
- */
- type |= QPCTL;
- } else {
- /*
- * Check the message is not out of range for the jump table.
- */
- if (type >= STR_MI_COUNT)
- goto unknown;
-
- /*
- * Get the handler from the jump table.
- */
- smip = &(dsp->ds_mi[type]);
- }
+ ASSERT(!RW_LOCK_HELD(&dsp->ds_lock));
+ rw_destroy(&dsp->ds_lock);
- ASSERT(smip->smi_type == type);
- smip->smi_put(dsp, mp);
- return;
+ ASSERT(MUTEX_NOT_HELD(&dsp->ds_tx_list_lock));
+ mutex_destroy(&dsp->ds_tx_list_lock);
+ ASSERT(dsp->ds_tx_flow_mp == NULL);
-unknown:
- str_m_put(dsp, mp);
-}
-
-/*
- * Called from srv(9e) to process a streams message.
- */
-void
-dld_str_srv(dld_str_t *dsp, mblk_t *mp)
-{
- uint8_t type;
- str_msg_info_t *smip;
-
- /*
- * Look up the message handler from the appropriate jump table.
- */
- if ((type = DB_TYPE(mp)) & QPCTL) {
- /*
- * Clear the priority bit to index into the jump table.
- */
- type &= ~QPCTL;
-
- /*
- * Check the message is not out of range for the jump table.
- */
- if (type >= STR_PMI_COUNT)
- goto unknown;
-
- /*
- * Get the handler from the jump table.
- */
- smip = &(dsp->ds_pmi[type]);
-
- /*
- * OR the priorty bit back in to restore the original message
- * type.
- */
- type |= QPCTL;
- } else {
- /*
- * Check the message is not out of range for the jump table.
- */
- if (type >= STR_MI_COUNT)
- goto unknown;
-
- /*
- * Get the handler from the jump table.
- */
- ASSERT(type < STR_MI_COUNT);
- smip = &(dsp->ds_mi[type]);
- }
-
- ASSERT(smip->smi_type == type);
- smip->smi_srv(dsp, mp);
- return;
-
-unknown:
- str_m_srv(dsp, mp);
+ ASSERT(MUTEX_NOT_HELD(&dsp->ds_thr_lock));
+ mutex_destroy(&dsp->ds_thr_lock);
+ ASSERT(dsp->ds_detach_req == NULL);
}
/*
* M_DATA put (IP fast-path mode)
*/
-static void
+void
str_mdata_fastpath_put(dld_str_t *dsp, mblk_t *mp)
{
- queue_t *q = dsp->ds_wq;
-
/*
- * If something is already queued then we must queue to avoid
- * re-ordering.
+ * We get here either as a result of putnext() from above or
+ * because IP has called us directly. If we are in the busy
+ * mode enqueue the packet(s) and return. Otherwise hand them
+ * over to the MAC driver for transmission; any remaining one(s)
+ * which didn't get sent will be queued.
+ *
+ * Note here that we don't grab the list lock prior to checking
+ * the busy flag. This is okay, because a missed transition
+ * will not cause any packet reordering for any particular TCP
+ * connection (which is single-threaded). The enqueue routine
+ * will atomically set the busy flag and schedule the service
+ * thread to run; the flag is only cleared by the service thread
+ * when there is no more packet to be transmitted.
*/
- if (q->q_first != NULL) {
- (void) putq(q, mp);
- return;
- }
-
- /*
- * Attempt to transmit the packet.
- */
- if ((mp = dls_tx(dsp->ds_dc, mp)) != NULL) {
- (void) putbq(q, mp);
- qenable(q);
- }
+ if (dsp->ds_tx_qbusy || (mp = dls_tx(dsp->ds_dc, mp)) != NULL)
+ dld_tx_enqueue(dsp, mp, B_FALSE);
}
/*
* M_DATA put (raw mode)
*/
-static void
+void
str_mdata_raw_put(dld_str_t *dsp, mblk_t *mp)
{
- queue_t *q = dsp->ds_wq;
struct ether_header *ehp;
mblk_t *bp;
size_t size;
@@ -496,7 +753,7 @@ str_mdata_raw_put(dld_str_t *dsp, mblk_t *mp)
* know the first fragment was M_DATA otherwise we could not
* have got here).
*/
- for (bp = mp->b_next; bp != NULL; bp = bp->b_cont) {
+ for (bp = mp->b_cont; bp != NULL; bp = bp->b_cont) {
if (DB_TYPE(bp) != M_DATA)
goto discard;
size += MBLKL(bp);
@@ -505,22 +762,7 @@ str_mdata_raw_put(dld_str_t *dsp, mblk_t *mp)
if (size > dsp->ds_mip->mi_sdu_max + hdrlen)
goto discard;
- /*
- * If something is already queued then we must queue to avoid
- * re-ordering.
- */
- if (q->q_first != NULL) {
- (void) putq(q, bp);
- return;
- }
-
- /*
- * Attempt to transmit the packet.
- */
- if ((mp = dls_tx(dsp->ds_dc, mp)) != NULL) {
- (void) putbq(q, mp);
- qenable(q);
- }
+ str_mdata_fastpath_put(dsp, mp);
return;
discard:
@@ -528,107 +770,35 @@ discard:
}
/*
- * M_DATA srv
- */
-static void
-str_mdata_srv(dld_str_t *dsp, mblk_t *mp)
-{
- queue_t *q = dsp->ds_wq;
-
- /*
- * Attempt to transmit the packet.
- */
- if ((mp = dls_tx(dsp->ds_dc, mp)) == NULL)
- return;
-
- (void) str_putbq(q, mp);
- qenable(q);
-}
-
-/*
- * M_PROTO put
- */
-static void
-str_mproto_put(dld_str_t *dsp, mblk_t *mp)
-{
- dld_proto(dsp, mp);
-}
-
-/*
- * M_PCPROTO put
- */
-static void
-str_mpcproto_put(dld_str_t *dsp, mblk_t *mp)
-{
- dld_proto(dsp, mp);
-}
-
-/*
- * M_IOCTL put
- */
-static void
-str_mioctl_put(dld_str_t *dsp, mblk_t *mp)
-{
- dld_ioc(dsp, mp);
-}
-
-/*
- * M_FLUSH put
- */
-/*ARGSUSED*/
-static void
-str_mflush_put(dld_str_t *dsp, mblk_t *mp)
-{
- queue_t *q = dsp->ds_wq;
-
- if (*mp->b_rptr & FLUSHW) {
- flushq(q, FLUSHALL);
- *mp->b_rptr &= ~FLUSHW;
- }
-
- if (*mp->b_rptr & FLUSHR)
- qreply(q, mp);
- else
- freemsg(mp);
-}
-
-/*
- * M_* put.
- */
-/*ARGSUSED*/
-static void
-str_m_put(dld_str_t *dsp, mblk_t *mp)
-{
- freemsg(mp);
-}
-
-/*
- * M_* put.
- */
-/*ARGSUSED*/
-static void
-str_m_srv(dld_str_t *dsp, mblk_t *mp)
-{
- freemsgchain(mp);
-}
-
-/*
* Process DL_ATTACH_REQ (style 2) or open(2) (style 1).
*/
int
-dld_str_attach(dld_str_t *dsp, dld_ppa_t *dpp)
+dld_str_attach(dld_str_t *dsp, t_uscalar_t ppa)
{
int err;
+ const char *drvname;
+ char name[MAXNAMELEN];
dls_channel_t dc;
uint_t addr_length;
ASSERT(dsp->ds_dc == NULL);
+ if ((drvname = ddi_major_to_name(dsp->ds_major)) == NULL)
+ return (EINVAL);
+
+ (void) snprintf(name, MAXNAMELEN, "%s%u", drvname, ppa);
+
+ if (strcmp(drvname, "aggr") != 0 &&
+ qassociate(dsp->ds_wq, DLS_PPA2INST(ppa)) != 0)
+ return (EINVAL);
+
/*
* Open a channel.
*/
- if ((err = dls_open(dpp->dp_name, &dc)) != 0)
+ if ((err = dls_open(name, &dc)) != 0) {
+ (void) qassociate(dsp->ds_wq, -1);
return (err);
+ }
/*
* Cache the MAC interface handle, a pointer to the immutable MAC
@@ -659,6 +829,8 @@ dld_str_attach(dld_str_t *dsp, dld_ppa_t *dpp)
dsp->ds_mnh = mac_notify_add(dsp->ds_mh, str_notify, (void *)dsp);
dsp->ds_dc = dc;
+ dsp->ds_dlstate = DL_UNBOUND;
+
return (0);
}
@@ -669,15 +841,17 @@ dld_str_attach(dld_str_t *dsp, dld_ppa_t *dpp)
void
dld_str_detach(dld_str_t *dsp)
{
+ ASSERT(dsp->ds_thr == 0);
+
/*
* Remove the notify function.
*/
mac_notify_remove(dsp->ds_mh, dsp->ds_mnh);
/*
- * Make sure the M_DATA handler is reset.
+ * Re-initialize the DLPI state machine.
*/
- dld_str_tx_drop(dsp);
+ dsp->ds_dlstate = DL_UNATTACHED;
/*
* Clear the polling and promisc flags.
@@ -691,46 +865,8 @@ dld_str_detach(dld_str_t *dsp)
dls_close(dsp->ds_dc);
dsp->ds_dc = NULL;
dsp->ds_mh = NULL;
-}
-
-/*
- * Enable raw mode for this stream. This mode is mutually exclusive with
- * fast-path and/or polling.
- */
-void
-dld_str_tx_raw(dld_str_t *dsp)
-{
- /*
- * Enable M_DATA message handling.
- */
- dsp->ds_mi[M_DATA].smi_put = str_mdata_raw_put;
- dsp->ds_mi[M_DATA].smi_srv = str_mdata_srv;
-}
-/*
- * Enable fast-path for this stream.
- */
-void
-dld_str_tx_fastpath(dld_str_t *dsp)
-{
- /*
- * Enable M_DATA message handling.
- */
- dsp->ds_mi[M_DATA].smi_put = str_mdata_fastpath_put;
- dsp->ds_mi[M_DATA].smi_srv = str_mdata_srv;
-}
-
-/*
- * Disable fast-path or raw mode.
- */
-void
-dld_str_tx_drop(dld_str_t *dsp)
-{
- /*
- * Disable M_DATA message handling.
- */
- dsp->ds_mi[M_DATA].smi_put = str_m_put;
- dsp->ds_mi[M_DATA].smi_srv = str_m_srv;
+ (void) qassociate(dsp->ds_wq, -1);
}
/*
@@ -1150,7 +1286,6 @@ str_notify(void *arg, mac_notify_type_t type)
switch (type) {
case MAC_NOTE_TX:
- enableok(q);
qenable(q);
break;
@@ -1236,36 +1371,308 @@ str_notify(void *arg, mac_notify_type_t type)
}
/*
- * Put a chain of packets back on the queue.
+ * Enqueue one or more messages to the transmit queue.
+ * Caller specifies the insertion position (head/tail).
*/
-static void
-str_putbq(queue_t *q, mblk_t *mp)
+void
+dld_tx_enqueue(dld_str_t *dsp, mblk_t *mp, boolean_t head_insert)
{
- mblk_t *bp = NULL;
- mblk_t *nextp;
+ mblk_t *tail;
+ queue_t *q = dsp->ds_wq;
+ uint_t cnt, msgcnt;
+ uint_t tot_cnt, tot_msgcnt;
+
+ ASSERT(DB_TYPE(mp) == M_DATA);
+ /* Calculate total size and count of the packet(s) */
+ for (tail = mp, cnt = msgdsize(mp), msgcnt = 1;
+ tail->b_next != NULL; tail = tail->b_next) {
+ ASSERT(DB_TYPE(tail) == M_DATA);
+ cnt += msgdsize(tail);
+ msgcnt++;
+ }
+
+ mutex_enter(&dsp->ds_tx_list_lock);
+ /*
+ * If the queue depth would exceed the allowed threshold, drop
+ * new packet(s) and drain those already in the queue.
+ */
+ tot_cnt = dsp->ds_tx_cnt + cnt;
+ tot_msgcnt = dsp->ds_tx_msgcnt + msgcnt;
+
+ if (!head_insert &&
+ (tot_cnt >= dld_max_q_count || tot_msgcnt >= dld_max_q_count)) {
+ ASSERT(dsp->ds_tx_qbusy);
+ mutex_exit(&dsp->ds_tx_list_lock);
+ freemsgchain(mp);
+ goto done;
+ }
+
+ /* Update the queue size parameters */
+ dsp->ds_tx_cnt = tot_cnt;
+ dsp->ds_tx_msgcnt = tot_msgcnt;
/*
- * Reverse the order of the chain.
+ * If the transmit queue is currently empty and we are
+ * about to deposit the packet(s) there, switch mode to
+ * "busy" and raise flow-control condition.
*/
- while (mp != NULL) {
- nextp = mp->b_next;
+ if (!dsp->ds_tx_qbusy) {
+ dsp->ds_tx_qbusy = B_TRUE;
+ ASSERT(dsp->ds_tx_flow_mp != NULL);
+ (void) putq(q, dsp->ds_tx_flow_mp);
+ dsp->ds_tx_flow_mp = NULL;
+ }
+
+ if (!head_insert) {
+ /* Tail insertion */
+ if (dsp->ds_tx_list_head == NULL)
+ dsp->ds_tx_list_head = mp;
+ else
+ dsp->ds_tx_list_tail->b_next = mp;
+ dsp->ds_tx_list_tail = tail;
+ } else {
+ /* Head insertion */
+ tail->b_next = dsp->ds_tx_list_head;
+ if (dsp->ds_tx_list_head == NULL)
+ dsp->ds_tx_list_tail = tail;
+ dsp->ds_tx_list_head = mp;
+ }
+ mutex_exit(&dsp->ds_tx_list_lock);
+done:
+ /* Schedule service thread to drain the transmit queue */
+ qenable(q);
+}
+
+void
+dld_tx_flush(dld_str_t *dsp)
+{
+ mutex_enter(&dsp->ds_tx_list_lock);
+ if (dsp->ds_tx_list_head != NULL) {
+ freemsgchain(dsp->ds_tx_list_head);
+ dsp->ds_tx_list_head = dsp->ds_tx_list_tail = NULL;
+ dsp->ds_tx_cnt = dsp->ds_tx_msgcnt = 0;
+ if (dsp->ds_tx_qbusy) {
+ dsp->ds_tx_flow_mp = getq(dsp->ds_wq);
+ ASSERT(dsp->ds_tx_flow_mp != NULL);
+ dsp->ds_tx_qbusy = B_FALSE;
+ }
+ }
+ mutex_exit(&dsp->ds_tx_list_lock);
+}
+
+/*
+ * Process an M_IOCTL message.
+ */
+static void
+dld_ioc(dld_str_t *dsp, mblk_t *mp)
+{
+ uint_t cmd;
- mp->b_next = bp;
- bp = mp;
+ cmd = ((struct iocblk *)mp->b_rptr)->ioc_cmd;
+ ASSERT(dsp->ds_type == DLD_DLPI);
- mp = nextp;
+ switch (cmd) {
+ case DLIOCRAW:
+ ioc_raw(dsp, mp);
+ break;
+ case DLIOCHDRINFO:
+ ioc_fast(dsp, mp);
+ break;
+ default:
+ ioc(dsp, mp);
+ }
+}
+
+/*
+ * DLIOCRAW
+ */
+static void
+ioc_raw(dld_str_t *dsp, mblk_t *mp)
+{
+ queue_t *q = dsp->ds_wq;
+
+ rw_enter(&dsp->ds_lock, RW_WRITER);
+ if (dsp->ds_polling) {
+ rw_exit(&dsp->ds_lock);
+ miocnak(q, mp, 0, EPROTO);
+ return;
+ }
+
+ if (dsp->ds_mode != DLD_RAW && dsp->ds_dlstate == DL_IDLE) {
+ /*
+ * Set the receive callback.
+ */
+ dls_rx_set(dsp->ds_dc, dld_str_rx_raw, (void *)dsp);
+
+ /*
+ * Note that raw mode is enabled.
+ */
+ dsp->ds_mode = DLD_RAW;
+ }
+
+ rw_exit(&dsp->ds_lock);
+ miocack(q, mp, 0, 0);
+}
+
+/*
+ * DLIOCHDRINFO
+ */
+static void
+ioc_fast(dld_str_t *dsp, mblk_t *mp)
+{
+ dl_unitdata_req_t *dlp;
+ off_t off;
+ size_t len;
+ const uint8_t *addr;
+ uint16_t sap;
+ mblk_t *nmp;
+ mblk_t *hmp;
+ uint_t addr_length;
+ queue_t *q = dsp->ds_wq;
+ int err;
+ dls_channel_t dc;
+
+ if (dld_opt & DLD_OPT_NO_FASTPATH) {
+ err = ENOTSUP;
+ goto failed;
+ }
+
+ nmp = mp->b_cont;
+ if (nmp == NULL || MBLKL(nmp) < sizeof (dl_unitdata_req_t) ||
+ (dlp = (dl_unitdata_req_t *)nmp->b_rptr,
+ dlp->dl_primitive != DL_UNITDATA_REQ)) {
+ err = EINVAL;
+ goto failed;
+ }
+
+ off = dlp->dl_dest_addr_offset;
+ len = dlp->dl_dest_addr_length;
+
+ if (!MBLKIN(nmp, off, len)) {
+ err = EINVAL;
+ goto failed;
+ }
+
+ rw_enter(&dsp->ds_lock, RW_READER);
+ if (dsp->ds_dlstate != DL_IDLE) {
+ rw_exit(&dsp->ds_lock);
+ err = ENOTSUP;
+ goto failed;
+ }
+
+ addr_length = dsp->ds_mip->mi_addr_length;
+ if (len != addr_length + sizeof (uint16_t)) {
+ rw_exit(&dsp->ds_lock);
+ err = EINVAL;
+ goto failed;
+ }
+
+ addr = nmp->b_rptr + off;
+ sap = *(uint16_t *)(nmp->b_rptr + off + addr_length);
+ dc = dsp->ds_dc;
+
+ if ((hmp = dls_header(dc, addr, sap, dsp->ds_pri)) == NULL) {
+ rw_exit(&dsp->ds_lock);
+ err = ENOMEM;
+ goto failed;
}
/*
- * Walk the reversed chain and put each message back on the
- * queue.
+ * This is a performance optimization. We originally entered
+ * as reader and only become writer upon transitioning into
+ * the DLD_FASTPATH mode for the first time. Otherwise we
+ * stay as reader and return the fast-path header to IP.
*/
- while (bp != NULL) {
- nextp = bp->b_next;
- bp->b_next = NULL;
+ if (dsp->ds_mode != DLD_FASTPATH) {
+ if (!rw_tryupgrade(&dsp->ds_lock)) {
+ rw_exit(&dsp->ds_lock);
+ rw_enter(&dsp->ds_lock, RW_WRITER);
- (void) putbq(q, bp);
+ /*
+ * State may have changed before we re-acquired
+ * the writer lock in case the upgrade failed.
+ */
+ if (dsp->ds_dlstate != DL_IDLE) {
+ rw_exit(&dsp->ds_lock);
+ err = ENOTSUP;
+ goto failed;
+ }
+ }
+
+ /*
+ * Set the receive callback (unless polling is enabled).
+ */
+ if (!dsp->ds_polling)
+ dls_rx_set(dc, dld_str_rx_fastpath, (void *)dsp);
- bp = nextp;
+ /*
+ * Note that fast-path mode is enabled.
+ */
+ dsp->ds_mode = DLD_FASTPATH;
}
+ rw_exit(&dsp->ds_lock);
+
+ freemsg(nmp->b_cont);
+ nmp->b_cont = hmp;
+
+ miocack(q, mp, MBLKL(nmp) + MBLKL(hmp), 0);
+ return;
+failed:
+ miocnak(q, mp, 0, err);
+}
+
+/*
+ * Catch-all handler.
+ */
+static void
+ioc(dld_str_t *dsp, mblk_t *mp)
+{
+ queue_t *q = dsp->ds_wq;
+ mac_handle_t mh;
+
+ rw_enter(&dsp->ds_lock, RW_READER);
+ if (dsp->ds_dlstate == DL_UNATTACHED) {
+ rw_exit(&dsp->ds_lock);
+ miocnak(q, mp, 0, EINVAL);
+ return;
+ }
+ mh = dsp->ds_mh;
+ ASSERT(mh != NULL);
+ rw_exit(&dsp->ds_lock);
+ mac_ioctl(mh, q, mp);
+}
+
+/*
+ * Allocate a new minor number.
+ */
+static minor_t
+dld_minor_hold(boolean_t sleep)
+{
+ minor_t minor;
+
+ /*
+ * Grab a value from the arena.
+ */
+ atomic_add_32(&minor_count, 1);
+ if ((minor = PTR_TO_MINOR(vmem_alloc(minor_arenap, 1,
+ (sleep) ? VM_SLEEP : VM_NOSLEEP))) == 0) {
+ atomic_add_32(&minor_count, -1);
+ return (0);
+ }
+
+ return (minor);
+}
+
+/*
+ * Release a previously allocated minor number.
+ */
+static void
+dld_minor_rele(minor_t minor)
+{
+ /*
+ * Return the value to the arena.
+ */
+ vmem_free(minor_arenap, MINOR_TO_PTR(minor), 1);
+
+ atomic_add_32(&minor_count, -1);
}
diff --git a/usr/src/uts/common/io/dls/dls.c b/usr/src/uts/common/io/dls/dls.c
index f9484c648c..d7f9d876fb 100644
--- a/usr/src/uts/common/io/dls/dls.c
+++ b/usr/src/uts/common/io/dls/dls.c
@@ -35,7 +35,6 @@
#include <sys/strsun.h>
#include <sys/sysmacros.h>
#include <sys/atomic.h>
-#include <sys/ght.h>
#include <sys/dlpi.h>
#include <sys/vlan.h>
#include <sys/ethernet.h>
@@ -295,9 +294,9 @@ dls_fini(void)
*/
int
-dls_create(const char *name, const char *dev, uint_t port, uint16_t vid)
+dls_create(const char *name, const char *dev, uint_t port)
{
- return (dls_vlan_create(name, dev, port, vid));
+ return (dls_vlan_create(name, dev, port, 0));
}
int
@@ -316,8 +315,9 @@ dls_open(const char *name, dls_channel_t *dcp)
/*
* Get a reference to the named dls_vlan_t.
+ * Tagged vlans get created automatically.
*/
- if ((err = dls_vlan_hold(name, &dvp)) != 0)
+ if ((err = dls_vlan_hold(name, &dvp, B_TRUE)) != 0)
return (err);
/*
@@ -433,7 +433,8 @@ dls_close(dls_channel_t dc)
/*
* Release our reference to the dls_vlan_t allowing that to be
- * destroyed if there are no more dls_impl_t.
+ * destroyed if there are no more dls_impl_t. An unreferenced tagged
+ * vlan gets destroyed automatically.
*/
dls_vlan_rele(dvp);
}
diff --git a/usr/src/uts/common/io/dls/dls_link.c b/usr/src/uts/common/io/dls/dls_link.c
index f061a625cd..edb04a6b67 100644
--- a/usr/src/uts/common/io/dls/dls_link.c
+++ b/usr/src/uts/common/io/dls/dls_link.c
@@ -36,7 +36,7 @@
#include <sys/strsubr.h>
#include <sys/sysmacros.h>
#include <sys/atomic.h>
-#include <sys/ght.h>
+#include <sys/modhash.h>
#include <sys/dlpi.h>
#include <sys/ethernet.h>
#include <sys/byteorder.h>
@@ -49,7 +49,9 @@
#include <sys/dls_impl.h>
static kmem_cache_t *i_dls_link_cachep;
-static ght_t i_dls_link_hash;
+static mod_hash_t *i_dls_link_hash;
+static uint_t i_dls_link_count;
+static krwlock_t i_dls_link_lock;
#define LINK_HASHSZ 67 /* prime */
#define IMPL_HASHSZ 67 /* prime */
@@ -58,7 +60,8 @@ static ght_t i_dls_link_hash;
* Construct a hash key encompassing both DLSAP value and VLAN idenitifier.
*/
#define MAKE_KEY(_sap, _vid) \
- GHT_SCALAR_TO_KEY(((_sap) << VLAN_ID_SIZE) | (_vid) & VLAN_ID_MASK)
+ ((mod_hash_key_t)(uintptr_t) \
+ (((_sap) << VLAN_ID_SIZE) | (_vid) & VLAN_ID_MASK))
/*
* Extract the DLSAP value from the hash key.
@@ -76,16 +79,16 @@ i_dls_link_constructor(void *buf, void *arg, int kmflag)
{
dls_link_t *dlp = buf;
char name[MAXNAMELEN];
- int err;
bzero(buf, sizeof (dls_link_t));
- (void) sprintf(name, "dls_link_t_%p_impl_hash", buf);
- err = ght_scalar_create(name, IMPL_HASHSZ, &(dlp->dl_impl_hash));
- ASSERT(err == 0);
+ (void) sprintf(name, "dls_link_t_%p_hash", buf);
+ dlp->dl_impl_hash = mod_hash_create_idhash(name, IMPL_HASHSZ,
+ mod_hash_null_valdtor);
mutex_init(&dlp->dl_lock, NULL, MUTEX_DEFAULT, NULL);
mutex_init(&dlp->dl_promisc_lock, NULL, MUTEX_DEFAULT, NULL);
+ rw_init(&dlp->dl_impl_lock, NULL, RW_DEFAULT, NULL);
return (0);
}
@@ -94,18 +97,17 @@ static void
i_dls_link_destructor(void *buf, void *arg)
{
dls_link_t *dlp = buf;
- int err;
ASSERT(dlp->dl_ref == 0);
- ASSERT(dlp->dl_hte == NULL);
ASSERT(dlp->dl_mh == NULL);
ASSERT(dlp->dl_unknowns == 0);
- err = ght_destroy(dlp->dl_impl_hash);
- ASSERT(err == 0);
+ mod_hash_destroy_idhash(dlp->dl_impl_hash);
+ dlp->dl_impl_hash = NULL;
mutex_destroy(&dlp->dl_lock);
mutex_destroy(&dlp->dl_promisc_lock);
+ rw_destroy(&dlp->dl_impl_lock);
}
#define ETHER_MATCH(_pkt_a, _pkt_b) \
@@ -219,21 +221,50 @@ done:
}
static void
+i_dls_head_hold(dls_head_t *dhp)
+{
+ atomic_inc_32(&dhp->dh_ref);
+}
+
+static void
+i_dls_head_rele(dls_head_t *dhp)
+{
+ atomic_dec_32(&dhp->dh_ref);
+}
+
+static dls_head_t *
+i_dls_head_alloc(mod_hash_key_t key)
+{
+ dls_head_t *dhp;
+
+ dhp = kmem_zalloc(sizeof (dls_head_t), KM_SLEEP);
+ dhp->dh_key = key;
+ return (dhp);
+}
+
+static void
+i_dls_head_free(dls_head_t *dhp)
+{
+ ASSERT(dhp->dh_ref == 0);
+ kmem_free(dhp, sizeof (dls_head_t));
+}
+
+static void
i_dls_link_ether_rx(void *arg, mac_resource_handle_t mrh, mblk_t *mp)
{
dls_link_t *dlp = arg;
- ght_t hash = dlp->dl_impl_hash;
+ mod_hash_t *hash = dlp->dl_impl_hash;
mblk_t *nextp;
uint_t header_length;
uint8_t *daddr;
uint16_t type_length;
uint16_t vid;
uint16_t sap;
- ghte_t hte;
+ dls_head_t *dhp;
dls_impl_t *dip;
dls_impl_t *ndip;
mblk_t *nmp;
- ght_key_t key;
+ mod_hash_key_t key;
uint_t npacket;
boolean_t accepted;
@@ -270,25 +301,19 @@ i_dls_link_ether_rx(void *arg, mac_resource_handle_t mrh, mblk_t *mp)
* Search the has table for dls_impl_t eligible to receive
* a packet chain for this DLSAP/VLAN combination.
*/
- ght_lock(hash, GHT_READ);
- if (ght_find(hash, key, &hte) != 0) {
- ght_unlock(hash);
+ rw_enter(&dlp->dl_impl_lock, RW_READER);
+ if (mod_hash_find(hash, key, (mod_hash_val_t *)&dhp) != 0) {
+ rw_exit(&dlp->dl_impl_lock);
freemsgchain(mp);
goto loop;
}
-
- /*
- * Place a hold the chain of dls_impl_t to make sure none are
- * removed from under our feet.
- */
- ght_hold(hte);
- ght_unlock(hash);
+ i_dls_head_hold(dhp);
+ rw_exit(&dlp->dl_impl_lock);
/*
* Find the first dls_impl_t that will accept the sub-chain.
*/
- for (dip = (dls_impl_t *)GHT_VAL(hte); dip != NULL;
- dip = dip->di_nextp)
+ for (dip = dhp->dh_list; dip != NULL; dip = dip->di_nextp)
if (dls_accept(dip, daddr))
break;
@@ -297,7 +322,7 @@ i_dls_link_ether_rx(void *arg, mac_resource_handle_t mrh, mblk_t *mp)
* sub-chain then throw it away.
*/
if (dip == NULL) {
- ght_rele(hte);
+ i_dls_head_rele(dhp);
freemsgchain(mp);
goto loop;
}
@@ -346,7 +371,7 @@ i_dls_link_ether_rx(void *arg, mac_resource_handle_t mrh, mblk_t *mp)
* Release the hold on the dls_impl_t chain now that we have
* finished walking it.
*/
- ght_rele(hte);
+ i_dls_head_rele(dhp);
loop:
/*
@@ -368,18 +393,18 @@ i_dls_link_ether_rx_promisc(void *arg, mac_resource_handle_t mrh,
mblk_t *mp)
{
dls_link_t *dlp = arg;
- ght_t hash = dlp->dl_impl_hash;
+ mod_hash_t *hash = dlp->dl_impl_hash;
mblk_t *nextp;
uint_t header_length;
uint8_t *daddr;
uint16_t type_length;
uint16_t vid;
uint16_t sap;
- ghte_t hte;
+ dls_head_t *dhp;
dls_impl_t *dip;
dls_impl_t *ndip;
mblk_t *nmp;
- ght_key_t key;
+ mod_hash_key_t key;
uint_t npacket;
boolean_t accepted;
@@ -409,24 +434,18 @@ i_dls_link_ether_rx_promisc(void *arg, mac_resource_handle_t mrh,
* Search the has table for dls_impl_t eligible to receive
* a packet chain for this DLSAP/VLAN combination.
*/
- ght_lock(hash, GHT_READ);
- if (ght_find(hash, key, &hte) != 0) {
- ght_unlock(hash);
+ rw_enter(&dlp->dl_impl_lock, RW_READER);
+ if (mod_hash_find(hash, key, (mod_hash_val_t *)&dhp) != 0) {
+ rw_exit(&dlp->dl_impl_lock);
goto non_promisc;
}
-
- /*
- * Place a hold the chain of dls_impl_t to make sure none are
- * removed from under our feet.
- */
- ght_hold(hte);
- ght_unlock(hash);
+ i_dls_head_hold(dhp);
+ rw_exit(&dlp->dl_impl_lock);
/*
* Find dls_impl_t that will accept the sub-chain.
*/
- for (dip = (dls_impl_t *)GHT_VAL(hte); dip != NULL;
- dip = dip->di_nextp) {
+ for (dip = dhp->dh_list; dip != NULL; dip = dip->di_nextp) {
if (!dls_accept(dip, daddr))
continue;
@@ -449,7 +468,7 @@ i_dls_link_ether_rx_promisc(void *arg, mac_resource_handle_t mrh,
* Release the hold on the dls_impl_t chain now that we have
* finished walking it.
*/
- ght_rele(hte);
+ i_dls_head_rele(dhp);
non_promisc:
/*
@@ -469,25 +488,19 @@ non_promisc:
* Search the has table for dls_impl_t eligible to receive
* a packet chain for this DLSAP/VLAN combination.
*/
- ght_lock(hash, GHT_READ);
- if (ght_find(hash, key, &hte) != 0) {
- ght_unlock(hash);
+ rw_enter(&dlp->dl_impl_lock, RW_READER);
+ if (mod_hash_find(hash, key, (mod_hash_val_t *)&dhp) != 0) {
+ rw_exit(&dlp->dl_impl_lock);
freemsgchain(mp);
goto loop;
}
-
- /*
- * Place a hold the chain of dls_impl_t to make sure none are
- * removed from under our feet.
- */
- ght_hold(hte);
- ght_unlock(hash);
+ i_dls_head_hold(dhp);
+ rw_exit(&dlp->dl_impl_lock);
/*
* Find the first dls_impl_t that will accept the sub-chain.
*/
- for (dip = (dls_impl_t *)GHT_VAL(hte); dip != NULL;
- dip = dip->di_nextp)
+ for (dip = dhp->dh_list; dip != NULL; dip = dip->di_nextp)
if (dls_accept(dip, daddr))
break;
@@ -496,7 +509,7 @@ non_promisc:
* sub-chain then throw it away.
*/
if (dip == NULL) {
- ght_rele(hte);
+ i_dls_head_rele(dhp);
freemsgchain(mp);
goto loop;
}
@@ -545,7 +558,7 @@ non_promisc:
* Release the hold on the dls_impl_t chain now that we have
* finished walking it.
*/
- ght_rele(hte);
+ i_dls_head_rele(dhp);
loop:
/*
@@ -566,18 +579,18 @@ static void
i_dls_link_ether_loopback(void *arg, mblk_t *mp)
{
dls_link_t *dlp = arg;
- ght_t hash = dlp->dl_impl_hash;
+ mod_hash_t *hash = dlp->dl_impl_hash;
mblk_t *nextp;
uint_t header_length;
uint8_t *daddr;
uint16_t type_length;
uint16_t vid;
uint16_t sap;
- ghte_t hte;
+ dls_head_t *dhp;
dls_impl_t *dip;
dls_impl_t *ndip;
mblk_t *nmp;
- ght_key_t key;
+ mod_hash_key_t key;
uint_t npacket;
/*
@@ -608,24 +621,18 @@ i_dls_link_ether_loopback(void *arg, mblk_t *mp)
* Search the has table for dls_impl_t eligible to receive
* a packet chain for this DLSAP/VLAN combination.
*/
- ght_lock(hash, GHT_READ);
- if (ght_find(hash, key, &hte) != 0) {
- ght_unlock(hash);
+ rw_enter(&dlp->dl_impl_lock, RW_READER);
+ if (mod_hash_find(hash, key, (mod_hash_val_t *)&dhp) != 0) {
+ rw_exit(&dlp->dl_impl_lock);
goto promisc;
}
-
- /*
- * Place a hold the chain of dls_impl_t to make sure none are
- * removed from under our feet.
- */
- ght_hold(hte);
- ght_unlock(hash);
+ i_dls_head_hold(dhp);
+ rw_exit(&dlp->dl_impl_lock);
/*
* Find dls_impl_t that will accept the sub-chain.
*/
- for (dip = (dls_impl_t *)GHT_VAL(hte); dip != NULL;
- dip = dip->di_nextp) {
+ for (dip = dhp->dh_list; dip != NULL; dip = dip->di_nextp) {
if (!dls_accept_loopback(dip, daddr))
continue;
@@ -643,7 +650,7 @@ i_dls_link_ether_loopback(void *arg, mblk_t *mp)
* Release the hold on the dls_impl_t chain now that we have
* finished walking it.
*/
- ght_rele(hte);
+ i_dls_head_rele(dhp);
promisc:
/*
@@ -656,25 +663,19 @@ promisc:
* Search the has table for dls_impl_t eligible to receive
* a packet chain for this DLSAP/VLAN combination.
*/
- ght_lock(hash, GHT_READ);
- if (ght_find(hash, key, &hte) != 0) {
- ght_unlock(hash);
+ rw_enter(&dlp->dl_impl_lock, RW_READER);
+ if (mod_hash_find(hash, key, (mod_hash_val_t *)&dhp) != 0) {
+ rw_exit(&dlp->dl_impl_lock);
freemsgchain(mp);
goto loop;
}
-
- /*
- * Place a hold the chain of dls_impl_t to make sure none are
- * removed from under our feet.
- */
- ght_hold(hte);
- ght_unlock(hash);
+ i_dls_head_hold(dhp);
+ rw_exit(&dlp->dl_impl_lock);
/*
* Find the first dls_impl_t that will accept the sub-chain.
*/
- for (dip = (dls_impl_t *)GHT_VAL(hte); dip != NULL;
- dip = dip->di_nextp)
+ for (dip = dhp->dh_list; dip != NULL; dip = dip->di_nextp)
if (dls_accept_loopback(dip, daddr))
break;
@@ -683,7 +684,7 @@ promisc:
* sub-chain then throw it away.
*/
if (dip == NULL) {
- ght_rele(hte);
+ i_dls_head_rele(dhp);
freemsgchain(mp);
goto loop;
}
@@ -728,7 +729,7 @@ promisc:
* Release the hold on the dls_impl_t chain now that we have
* finished walking it.
*/
- ght_rele(hte);
+ i_dls_head_rele(dhp);
loop:
/*
@@ -738,37 +739,25 @@ loop:
}
}
-static boolean_t
-i_dls_link_walk(void *arg, ghte_t hte)
+/*ARGSUSED*/
+static uint_t
+i_dls_link_walk(mod_hash_key_t key, mod_hash_val_t *val, void *arg)
{
boolean_t *promiscp = arg;
- ght_key_t key = GHT_KEY(hte);
uint32_t sap = KEY_SAP(key);
if (sap == DLS_SAP_PROMISC) {
*promiscp = B_TRUE;
- return (B_FALSE); /* terminate walk */
+ return (MH_WALK_TERMINATE);
}
- return (B_TRUE);
+ return (MH_WALK_CONTINUE);
}
static int
i_dls_link_create(const char *dev, uint_t port, dls_link_t **dlpp)
{
dls_link_t *dlp;
- int err;
- mac_handle_t mh;
-
- /*
- * Check that the MAC exists, and (for now) that it's
- * of type DL_ETHER.
- */
- if ((err = mac_open(dev, port, &mh)) != 0)
- return (err);
-
- ASSERT(mac_info(mh)->mi_media == DL_ETHER);
- mac_close(mh);
/*
* Allocate a new dls_link_t structure.
@@ -783,11 +772,6 @@ i_dls_link_create(const char *dev, uint_t port, dls_link_t **dlpp)
dlp->dl_port = port;
/*
- * Set the initial packet receive function.
- */
- ASSERT(ght_count(dlp->dl_impl_hash) == 0);
-
- /*
* Set the packet loopback function for use when the MAC is in
* promiscuous mode, and initialize promiscuous bookeeping fields.
*/
@@ -808,14 +792,14 @@ i_dls_link_destroy(dls_link_t *dlp)
ASSERT(dlp->dl_macref == 0);
ASSERT(dlp->dl_mh == NULL);
ASSERT(dlp->dl_mip == NULL);
+ ASSERT(dlp->dl_impl_count == 0);
+ ASSERT(dlp->dl_mrh == NULL);
/*
* Free the structure back to the cache.
*/
- dlp->dl_mrh = NULL;
dlp->dl_unknowns = 0;
kmem_cache_free(i_dls_link_cachep, dlp);
-
}
/*
@@ -825,8 +809,6 @@ i_dls_link_destroy(dls_link_t *dlp)
void
dls_link_init(void)
{
- int err;
-
/*
* Create a kmem_cache of dls_link_t structures.
*/
@@ -836,28 +818,31 @@ dls_link_init(void)
ASSERT(i_dls_link_cachep != NULL);
/*
- * Create a global hash tables to be keyed by a name.
+ * Create a dls_link_t hash table and associated lock.
*/
- err = ght_str_create("dls_link_hash", LINK_HASHSZ, &i_dls_link_hash);
- ASSERT(err == 0);
+ i_dls_link_hash = mod_hash_create_extended("dls_link_hash",
+ IMPL_HASHSZ, mod_hash_null_keydtor, mod_hash_null_valdtor,
+ mod_hash_bystr, NULL, mod_hash_strkey_cmp, KM_SLEEP);
+ rw_init(&i_dls_link_lock, NULL, RW_DEFAULT, NULL);
+ i_dls_link_count = 0;
}
int
dls_link_fini(void)
{
- int err;
+ if (i_dls_link_count > 0)
+ return (EBUSY);
/*
- * Destroy the hash table. This will return EBUSY if there are
- * still entries present.
+ * Destroy the kmem_cache.
*/
- if ((err = ght_destroy(i_dls_link_hash)) != 0)
- return (err);
+ kmem_cache_destroy(i_dls_link_cachep);
/*
- * Destroy the kmem_cache.
+ * Destroy the hash table and associated lock.
*/
- kmem_cache_destroy(i_dls_link_cachep);
+ mod_hash_destroy_hash(i_dls_link_hash);
+ rw_destroy(&i_dls_link_lock);
return (0);
}
@@ -871,13 +856,6 @@ dls_link_hold(const char *dev, uint_t port, dls_link_t **dlpp)
char name[MAXNAMELEN];
dls_link_t *dlp;
int err;
- ghte_t hte;
- ghte_t nhte;
-
- /*
- * Allocate a new hash table entry.
- */
- nhte = ght_alloc(i_dls_link_hash, KM_SLEEP);
/*
* Construct a copy of the name used to identify any existing
@@ -887,51 +865,51 @@ dls_link_hold(const char *dev, uint_t port, dls_link_t **dlpp)
/*
* Look up a dls_link_t corresponding to the given mac_handle_t
- * in the global hash table.
+ * in the global hash table. We need to hold i_dls_link_lock in
+ * order to atomically find and insert a dls_link_t into the
+ * hash table.
*/
- ght_lock(i_dls_link_hash, GHT_WRITE);
- if ((err = ght_find(i_dls_link_hash, GHT_PTR_TO_KEY(name),
- &hte)) == 0) {
- dlp = (dls_link_t *)GHT_VAL(hte);
- ght_free(nhte);
+ rw_enter(&i_dls_link_lock, RW_WRITER);
+ if ((err = mod_hash_find(i_dls_link_hash, (mod_hash_key_t)name,
+ (mod_hash_val_t *)&dlp)) == 0)
goto done;
- }
- ASSERT(err == ENOENT);
+
+ ASSERT(err == MH_ERR_NOTFOUND);
/*
* We didn't find anything so we need to create one.
*/
if ((err = i_dls_link_create(dev, port, &dlp)) != 0) {
- ght_free(nhte);
- ght_unlock(i_dls_link_hash);
+ rw_exit(&i_dls_link_lock);
return (err);
}
- GHT_KEY(nhte) = GHT_PTR_TO_KEY(dlp->dl_name);
- GHT_VAL(nhte) = GHT_PTR_TO_VAL(dlp);
- dlp->dl_hte = nhte;
/*
- * Insert the entry.
+ * Insert the dls_link_t.
*/
- err = ght_insert(nhte);
+ err = mod_hash_insert(i_dls_link_hash, (mod_hash_key_t)dlp->dl_name,
+ (mod_hash_val_t)dlp);
ASSERT(err == 0);
+ i_dls_link_count++;
+ ASSERT(i_dls_link_count != 0);
+
done:
/*
* Bump the reference count and hand back the reference.
*/
dlp->dl_ref++;
*dlpp = dlp;
- ght_unlock(i_dls_link_hash);
- return (err);
+ rw_exit(&i_dls_link_lock);
+ return (0);
}
void
dls_link_rele(dls_link_t *dlp)
{
- ghte_t hte;
+ mod_hash_val_t val;
- ght_lock(i_dls_link_hash, GHT_WRITE);
+ rw_enter(&i_dls_link_lock, RW_WRITER);
/*
* Check if there are any more references.
@@ -943,22 +921,18 @@ dls_link_rele(dls_link_t *dlp)
goto done;
}
- hte = dlp->dl_hte;
- dlp->dl_hte = NULL;
-
- /*
- * Remove the hash table entry.
- */
- ght_remove(hte);
- ght_free(hte);
+ (void) mod_hash_remove(i_dls_link_hash,
+ (mod_hash_key_t)dlp->dl_name, &val);
+ ASSERT(dlp == (dls_link_t *)val);
/*
* Destroy the dls_link_t.
*/
i_dls_link_destroy(dlp);
-
+ ASSERT(i_dls_link_count > 0);
+ i_dls_link_count--;
done:
- ght_unlock(i_dls_link_hash);
+ rw_exit(&i_dls_link_lock);
}
int
@@ -1006,17 +980,13 @@ void
dls_link_add(dls_link_t *dlp, uint32_t sap, dls_impl_t *dip)
{
dls_vlan_t *dvp = dip->di_dvp;
- ght_t hash = dlp->dl_impl_hash;
- ghte_t hte;
- ghte_t nhte;
- ght_key_t key;
- dls_impl_t **pp;
+ mod_hash_t *hash = dlp->dl_impl_hash;
+ mod_hash_key_t key;
+ dls_head_t *dhp;
dls_impl_t *p;
mac_rx_t rx;
int err;
- uint_t impl_count;
-
- ASSERT(dip->di_nextp == NULL);
+ boolean_t promisc = B_FALSE;
/*
* For ethernet media, sap values less than or equal to
@@ -1035,128 +1005,84 @@ dls_link_add(dls_link_t *dlp, uint32_t sap, dls_impl_t *dip)
* We need dl_lock here because we want to be able to walk
* the hash table *and* set the mac rx func atomically. if
* these two operations are separate, someone else could
- * insert/remove dls_impl_t from the ght after we drop the
- * ght lock and this could cause our chosen rx func to be
- * incorrect. note that we cannot call mac_rx_set when
- * holding the ght lock because this can cause deadlock.
+ * insert/remove dls_impl_t from the hash table after we
+ * drop the hash lock and this could cause our chosen rx
+ * func to be incorrect. note that we cannot call mac_rx_add
+ * when holding the hash lock because this can cause deadlock.
*/
mutex_enter(&dlp->dl_lock);
- /*
- * Allocate a new entry.
- */
- nhte = ght_alloc(hash, KM_SLEEP);
/*
- * Search the table for any existing entry with this key.
+ * Search the table for a list head with this key.
*/
- ght_lock(hash, GHT_WRITE);
- if ((err = ght_find(hash, key, &hte)) != 0) {
- ASSERT(err == ENOENT);
+ rw_enter(&dlp->dl_impl_lock, RW_WRITER);
- GHT_KEY(nhte) = key;
- GHT_VAL(nhte) = GHT_PTR_TO_VAL(dip);
+ if ((err = mod_hash_find(hash, key, (mod_hash_val_t *)&dhp)) != 0) {
+ ASSERT(err == MH_ERR_NOTFOUND);
- /*
- * Insert it in the table to be the head of a new list.
- */
- err = ght_insert(nhte);
+ dhp = i_dls_head_alloc(key);
+ err = mod_hash_insert(hash, key, (mod_hash_val_t)dhp);
ASSERT(err == 0);
-
- /*
- * Cache a reference to the hash table entry.
- */
- ASSERT(dip->di_hte == NULL);
- dip->di_hte = nhte;
-
- goto done;
}
/*
- * Free the unused hash table entry.
+ * Add the dls_impl_t to the head of the list.
*/
- ght_free(nhte);
+ ASSERT(dip->di_nextp == NULL);
+ p = dhp->dh_list;
+ dip->di_nextp = p;
+ dhp->dh_list = dip;
/*
- * Add the dls_impl_t to the end of the list. We can't add to the head
- * because the hash table internals already have a reference to the
- * head of the list.
+ * Save a pointer to the list head.
*/
- for (pp = (dls_impl_t **)&(GHT_VAL(hte)); (p = *pp) != NULL;
- pp = &(p->di_nextp))
- ASSERT(p != dip);
-
- *pp = dip;
+ dip->di_headp = dhp;
+ dlp->dl_impl_count++;
/*
- * Cache a reference to the hash table entry.
+ * Walk the bound dls_impl_t to see if there are any
+ * in promiscuous 'all sap' mode.
*/
- ASSERT(dip->di_hte == NULL);
- dip->di_hte = hte;
+ mod_hash_walk(hash, i_dls_link_walk, (void *)&promisc);
+ rw_exit(&dlp->dl_impl_lock);
-done:
/*
- * If there are no dls_impl_t then we can just drop all received
- * packets on the floor.
+ * If there are then we need to use a receive routine
+ * which will route packets to those dls_impl_t as well
+ * as ones bound to the DLSAP of the packet.
*/
- impl_count = ght_count(hash);
- if (impl_count == 0) {
- ght_unlock(hash);
- } else {
- boolean_t promisc = B_FALSE;
+ if (promisc)
+ rx = i_dls_link_ether_rx_promisc;
+ else
+ rx = i_dls_link_ether_rx;
- /*
- * Walk the bound dls_impl_t to see if there are any
- * in promiscuous 'all sap' mode.
- */
- ght_walk(hash, i_dls_link_walk, (void *)&promisc);
-
- /*
- * If there are then we need to use a receive routine
- * which will route packets to those dls_impl_t as well
- * as ones bound to the DLSAP of the packet.
- */
- if (promisc)
- rx = i_dls_link_ether_rx_promisc;
- else
- rx = i_dls_link_ether_rx;
-
- ght_unlock(hash);
-
- /* Replace the existing receive function if there is one. */
- if (dlp->dl_mrh != NULL)
- mac_rx_remove(dlp->dl_mh, dlp->dl_mrh);
- dlp->dl_mrh = mac_rx_add(dlp->dl_mh, rx, (void *)dlp);
- }
+ /* Replace the existing receive function if there is one. */
+ if (dlp->dl_mrh != NULL)
+ mac_rx_remove(dlp->dl_mh, dlp->dl_mrh);
+ dlp->dl_mrh = mac_rx_add(dlp->dl_mh, rx, (void *)dlp);
mutex_exit(&dlp->dl_lock);
}
void
dls_link_remove(dls_link_t *dlp, dls_impl_t *dip)
{
- ght_t hash = dlp->dl_impl_hash;
- ghte_t hte;
+ mod_hash_t *hash = dlp->dl_impl_hash;
dls_impl_t **pp;
dls_impl_t *p;
+ dls_head_t *dhp;
mac_rx_t rx;
/*
* We need dl_lock here because we want to be able to walk
* the hash table *and* set the mac rx func atomically. if
* these two operations are separate, someone else could
- * insert/remove dls_impl_t from the ght after we drop the
- * ght lock and this could cause our chosen rx func to be
- * incorrect. note that we cannot call mac_rx_add when
- * holding the ght lock because this can cause deadlock.
+ * insert/remove dls_impl_t from the hash table after we
+ * drop the hash lock and this could cause our chosen rx
+ * func to be incorrect. note that we cannot call mac_rx_add
+ * when holding the hash lock because this can cause deadlock.
*/
mutex_enter(&dlp->dl_lock);
-
- ght_lock(hash, GHT_WRITE);
-
- /*
- * Get the cached hash table entry reference.
- */
- hte = dip->di_hte;
- ASSERT(hte != NULL);
+ rw_enter(&dlp->dl_impl_lock, RW_WRITER);
/*
* Poll the hash table entry until all references have been dropped.
@@ -1166,35 +1092,39 @@ dls_link_remove(dls_link_t *dlp, dls_impl_t *dip)
* This is only a hint to quicken the decrease of the refcnt so
* the assignment need not be protected by any lock.
*/
+ dhp = dip->di_headp;
dip->di_removing = B_TRUE;
- while (ght_ref(hte) != 0) {
- ght_unlock(hash);
+ while (dhp->dh_ref != 0) {
+ rw_exit(&dlp->dl_impl_lock);
mutex_exit(&dlp->dl_lock);
delay(drv_usectohz(1000)); /* 1ms delay */
mutex_enter(&dlp->dl_lock);
- ght_lock(hash, GHT_WRITE);
+ rw_enter(&dlp->dl_impl_lock, RW_WRITER);
}
/*
* Walk the list and remove the dls_impl_t.
*/
- for (pp = (dls_impl_t **)&(GHT_VAL(hte)); (p = *pp) != NULL;
- pp = &(p->di_nextp)) {
+ for (pp = &dhp->dh_list; (p = *pp) != NULL; pp = &(p->di_nextp)) {
if (p == dip)
break;
}
ASSERT(p != NULL);
-
*pp = p->di_nextp;
p->di_nextp = NULL;
- dip->di_hte = NULL;
- if (GHT_VAL(hte) == NULL) {
+ ASSERT(dlp->dl_impl_count > 0);
+ dlp->dl_impl_count--;
+
+ if (dhp->dh_list == NULL) {
+ mod_hash_val_t val = NULL;
+
/*
* The list is empty so remove the hash table entry.
*/
- ght_remove(hte);
- ght_free(hte);
+ (void) mod_hash_remove(hash, dhp->dh_key, &val);
+ ASSERT(dhp == (dls_head_t *)val);
+ i_dls_head_free(dhp);
}
dip->di_removing = B_FALSE;
@@ -1202,8 +1132,8 @@ dls_link_remove(dls_link_t *dlp, dls_impl_t *dip)
* If there are no dls_impl_t then there's no need to register a
* receive function with the mac.
*/
- if (ght_count(hash) == 0) {
- ght_unlock(hash);
+ if (dlp->dl_impl_count == 0) {
+ rw_exit(&dlp->dl_impl_lock);
mac_rx_remove(dlp->dl_mh, dlp->dl_mrh);
dlp->dl_mrh = NULL;
} else {
@@ -1213,7 +1143,8 @@ dls_link_remove(dls_link_t *dlp, dls_impl_t *dip)
* Walk the bound dls_impl_t to see if there are any
* in promiscuous 'all sap' mode.
*/
- ght_walk(hash, i_dls_link_walk, (void *)&promisc);
+ mod_hash_walk(hash, i_dls_link_walk, (void *)&promisc);
+ rw_exit(&dlp->dl_impl_lock);
/*
* If there are then we need to use a receive routine
@@ -1225,8 +1156,6 @@ dls_link_remove(dls_link_t *dlp, dls_impl_t *dip)
else
rx = i_dls_link_ether_rx;
- ght_unlock(hash);
-
mac_rx_remove(dlp->dl_mh, dlp->dl_mrh);
dlp->dl_mrh = mac_rx_add(dlp->dl_mh, rx, (void *)dlp);
}
diff --git a/usr/src/uts/common/io/dls/dls_mod.c b/usr/src/uts/common/io/dls/dls_mod.c
index a9d007211f..9567d785ba 100644
--- a/usr/src/uts/common/io/dls/dls_mod.c
+++ b/usr/src/uts/common/io/dls/dls_mod.c
@@ -32,7 +32,6 @@
#include <sys/types.h>
#include <sys/modctl.h>
-#include <sys/ght.h>
#include <sys/mac.h>
#include <sys/dls.h>
diff --git a/usr/src/uts/common/io/dls/dls_stat.c b/usr/src/uts/common/io/dls/dls_stat.c
index 987628b74a..d0025c7fb9 100644
--- a/usr/src/uts/common/io/dls/dls_stat.c
+++ b/usr/src/uts/common/io/dls/dls_stat.c
@@ -33,7 +33,6 @@
#include <sys/types.h>
#include <sys/sysmacros.h>
#include <sys/atomic.h>
-#include <sys/ght.h>
#include <sys/kstat.h>
#include <sys/vlan.h>
#include <sys/mac.h>
diff --git a/usr/src/uts/common/io/dls/dls_vlan.c b/usr/src/uts/common/io/dls/dls_vlan.c
index e37f9c9f32..872dc29522 100644
--- a/usr/src/uts/common/io/dls/dls_vlan.c
+++ b/usr/src/uts/common/io/dls/dls_vlan.c
@@ -33,7 +33,7 @@
#include <sys/types.h>
#include <sys/sysmacros.h>
#include <sys/atomic.h>
-#include <sys/ght.h>
+#include <sys/modhash.h>
#include <sys/kstat.h>
#include <sys/vlan.h>
#include <sys/mac.h>
@@ -42,7 +42,9 @@
#include <sys/dls_impl.h>
static kmem_cache_t *i_dls_vlan_cachep;
-static ght_t i_dls_vlan_hash;
+static mod_hash_t *i_dls_vlan_hash;
+static krwlock_t i_dls_vlan_lock;
+static uint_t i_dls_vlan_count;
#define VLAN_HASHSZ 67 /* prime */
@@ -75,8 +77,6 @@ i_dls_vlan_destructor(void *buf, void *arg)
void
dls_vlan_init(void)
{
- int err;
-
/*
* Create a kmem_cache of dls_vlan_t structures.
*/
@@ -88,20 +88,24 @@ dls_vlan_init(void)
/*
* Create a hash table, keyed by name, of dls_vlan_t.
*/
- err = ght_str_create("dls_vlan_hash", VLAN_HASHSZ, &i_dls_vlan_hash);
- ASSERT(err == 0);
+ i_dls_vlan_hash = mod_hash_create_extended("dls_vlan_hash",
+ VLAN_HASHSZ, mod_hash_null_keydtor, mod_hash_null_valdtor,
+ mod_hash_bystr, NULL, mod_hash_strkey_cmp, KM_SLEEP);
+ rw_init(&i_dls_vlan_lock, NULL, RW_DEFAULT, NULL);
+ i_dls_vlan_count = 0;
}
int
dls_vlan_fini(void)
{
- int err;
+ if (i_dls_vlan_count > 0)
+ return (EBUSY);
/*
- * If the hash table is not empty then this call will return EBUSY.
+ * Destroy the hash table
*/
- if ((err = ght_destroy(i_dls_vlan_hash)) != 0)
- return (err);
+ mod_hash_destroy_hash(i_dls_vlan_hash);
+ rw_destroy(&i_dls_vlan_lock);
/*
* Destroy the kmem_cache.
@@ -120,7 +124,6 @@ dls_vlan_create(const char *name, const char *dev, uint_t port, uint16_t vid)
dls_link_t *dlp;
dls_vlan_t *dvp;
int err;
- ghte_t hte;
uint_t len;
/*
@@ -143,17 +146,6 @@ dls_vlan_create(const char *name, const char *dev, uint_t port, uint16_t vid)
return (err);
/*
- * If we're creating a tagged VLAN, grab a reference to the MAC.
- * Strictly speaking, this is only needed for aggregations (so that
- * they can't be deleted when there are configured VLAN's), but it
- * doesn't hurt for other MAC's either.
- */
- if (vid != 0 && (err = dls_mac_hold(dlp)) != 0) {
- dls_link_rele(dlp);
- return (err);
- }
-
- /*
* Allocate a new dls_vlan_t.
*/
dvp = kmem_cache_alloc(i_dls_vlan_cachep, KM_SLEEP);
@@ -162,33 +154,21 @@ dls_vlan_create(const char *name, const char *dev, uint_t port, uint16_t vid)
dvp->dv_dlp = dlp;
/*
- * Allocate a new hash table entry.
- */
- hte = ght_alloc(i_dls_vlan_hash, KM_SLEEP);
-
- GHT_KEY(hte) = GHT_PTR_TO_KEY(dvp->dv_name);
- GHT_VAL(hte) = GHT_PTR_TO_VAL(dvp);
-
- /*
* Insert the entry into the table.
*/
- ght_lock(i_dls_vlan_hash, GHT_WRITE);
- if ((err = ght_insert(hte)) != 0) {
- ght_free(hte);
+ rw_enter(&i_dls_vlan_lock, RW_WRITER);
+
+ if ((err = mod_hash_insert(i_dls_vlan_hash,
+ (mod_hash_key_t)dvp->dv_name, (mod_hash_val_t)dvp)) != 0) {
kmem_cache_free(i_dls_vlan_cachep, dvp);
- if (vid != 0)
- dls_mac_rele(dlp);
dls_link_rele(dlp);
+ err = EEXIST;
goto done;
}
-
- /*
- * Create kstats.
- */
- dls_stat_create(dvp);
+ i_dls_vlan_count++;
done:
- ght_unlock(i_dls_vlan_hash);
+ rw_exit(&i_dls_vlan_lock);
return (err);
}
@@ -196,50 +176,46 @@ int
dls_vlan_destroy(const char *name)
{
int err;
- ghte_t hte;
dls_vlan_t *dvp;
dls_link_t *dlp;
+ mod_hash_val_t val;
/*
* Find the dls_vlan_t in the global hash table.
*/
- ght_lock(i_dls_vlan_hash, GHT_WRITE);
- if ((err = ght_find(i_dls_vlan_hash, GHT_PTR_TO_KEY(name), &hte)) != 0)
+ rw_enter(&i_dls_vlan_lock, RW_WRITER);
+
+ err = mod_hash_find(i_dls_vlan_hash, (mod_hash_key_t)name,
+ (mod_hash_val_t *)&dvp);
+ if (err != 0) {
+ err = ENOENT;
goto done;
+ }
/*
- * Check to see if it is referenced by any dls_t.
+ * Check to see if it is referenced by any dls_impl_t.
*/
- dvp = (dls_vlan_t *)GHT_VAL(hte);
if (dvp->dv_ref != 0) {
err = EBUSY;
goto done;
}
/*
- * Destroy kstats before releasing dls_link_t and before destroying
- * the dls_vlan_t to ensure ks_update is safe.
- */
- dls_stat_destroy(dvp);
-
- /*
* Remove and destroy the hash table entry.
*/
- ght_remove(hte);
- ght_free(hte);
+ err = mod_hash_remove(i_dls_vlan_hash, (mod_hash_key_t)name,
+ (mod_hash_val_t *)&val);
+ ASSERT(err == 0);
+ ASSERT(dvp == (dls_vlan_t *)val);
- dlp = dvp->dv_dlp;
+ ASSERT(i_dls_vlan_count > 0);
+ i_dls_vlan_count--;
/*
- * If we're destroying a tagged VLAN, release the hold we acquired
- * in dls_vlan_create().
- */
- if (dvp->dv_id != 0)
- dls_mac_rele(dlp);
-
- /*
- * Free the dls_vlan_t back to the cache.
+ * Save a reference to dv_dlp before freeing the dls_vlan_t back
+ * to the cache.
*/
+ dlp = dvp->dv_dlp;
kmem_cache_free(i_dls_vlan_cachep, dvp);
/*
@@ -248,23 +224,76 @@ dls_vlan_destroy(const char *name)
*/
dls_link_rele(dlp);
done:
- ght_unlock(i_dls_vlan_hash);
+ rw_exit(&i_dls_vlan_lock);
return (err);
}
int
-dls_vlan_hold(const char *name, dls_vlan_t **dvpp)
+dls_vlan_hold(const char *name, dls_vlan_t **dvpp, boolean_t create_vlan)
{
int err;
- ghte_t hte;
dls_vlan_t *dvp;
dls_link_t *dlp;
+ boolean_t vlan_created = B_FALSE;
+
+again:
+ rw_enter(&i_dls_vlan_lock, RW_WRITER);
+
+ err = mod_hash_find(i_dls_vlan_hash, (mod_hash_key_t)name,
+ (mod_hash_val_t *)&dvp);
+ if (err != 0) {
+ char drv[MAXNAMELEN];
+ uint_t index, port, len;
+ uint16_t vid;
+
+ ASSERT(err == MH_ERR_NOTFOUND);
+
+ vlan_created = B_FALSE;
+ if (!create_vlan) {
+ err = ENOENT;
+ goto done;
+ }
+
+ /*
+ * Only create tagged vlans on demand.
+ * Note that if we get here, 'name' must be a sane
+ * value because it must have been derived from
+ * ddi_major_to_name().
+ */
+ if (ddi_parse(name, drv, &index) != DDI_SUCCESS ||
+ (vid = DLS_PPA2VID(index)) == VLAN_ID_NONE ||
+ vid > VLAN_ID_MAX) {
+ err = EINVAL;
+ goto done;
+ }
+
+ if (strcmp(drv, "aggr") == 0) {
+ port = (uint_t)DLS_PPA2INST(index);
+ (void) strlcpy(drv, "aggr0", MAXNAMELEN);
+ } else {
+ port = 0;
+ len = strlen(drv);
+ ASSERT(len < MAXNAMELEN);
+ (void) snprintf(drv + len, MAXNAMELEN - len, "%d",
+ DLS_PPA2INST(index));
+ }
+ rw_exit(&i_dls_vlan_lock);
+
+ if ((err = dls_vlan_create(name, drv, port, vid)) != 0) {
+ rw_enter(&i_dls_vlan_lock, RW_WRITER);
+ goto done;
+ }
+
+ /*
+ * At this point someone else could do a dls_vlan_hold and
+ * dls_vlan_rele on this new vlan and causes it to be
+ * destroyed. This will at worst cause us to spin a few
+ * times.
+ */
+ vlan_created = B_TRUE;
+ goto again;
+ }
- ght_lock(i_dls_vlan_hash, GHT_WRITE);
- if ((err = ght_find(i_dls_vlan_hash, GHT_PTR_TO_KEY(name), &hte)) != 0)
- goto done;
-
- dvp = (dls_vlan_t *)GHT_VAL(hte);
dlp = dvp->dv_dlp;
if ((err = dls_mac_hold(dlp)) != 0)
@@ -275,10 +304,20 @@ dls_vlan_hold(const char *name, dls_vlan_t **dvpp)
goto done;
}
- dvp->dv_ref++;
+ if (dvp->dv_ref++ == 0)
+ dls_stat_create(dvp);
+
*dvpp = dvp;
done:
- ght_unlock(i_dls_vlan_hash);
+ rw_exit(&i_dls_vlan_lock);
+
+ /*
+ * We could be destroying a vlan created by another thread. This
+ * is ok because this other thread will just loop back up and
+ * recreate the vlan.
+ */
+ if (err != 0 && vlan_created)
+ (void) dls_vlan_destroy(name);
return (err);
}
@@ -286,12 +325,62 @@ void
dls_vlan_rele(dls_vlan_t *dvp)
{
dls_link_t *dlp;
+ char name[IFNAMSIZ];
+ boolean_t destroy_vlan = B_FALSE;
- ght_lock(i_dls_vlan_hash, GHT_WRITE);
+ rw_enter(&i_dls_vlan_lock, RW_WRITER);
dlp = dvp->dv_dlp;
mac_stop(dlp->dl_mh);
dls_mac_rele(dlp);
- --dvp->dv_ref;
- ght_unlock(i_dls_vlan_hash);
+ if (--dvp->dv_ref == 0) {
+ dls_stat_destroy(dvp);
+ /*
+ * Tagged vlans get destroyed when dv_ref drops
+ * to 0. We need to copy dv_name here because
+ * dvp could disappear after we drop i_dls_vlan_lock.
+ */
+ if (dvp->dv_id != 0) {
+ (void) strlcpy(name, dvp->dv_name, IFNAMSIZ);
+ destroy_vlan = B_TRUE;
+ }
+ }
+ rw_exit(&i_dls_vlan_lock);
+ if (destroy_vlan)
+ (void) dls_vlan_destroy(name);
+}
+
+typedef struct dls_vlan_walk_state {
+ int (*fn)(dls_vlan_t *, void *);
+ void *arg;
+ int rc;
+} dls_vlan_walk_state_t;
+
+/*ARGSUSED*/
+static uint_t
+dls_vlan_walker(mod_hash_key_t key, mod_hash_val_t *val, void *arg)
+{
+ dls_vlan_walk_state_t *statep = arg;
+ dls_vlan_t *dvp;
+
+ dvp = (dls_vlan_t *)val;
+ statep->rc = statep->fn(dvp, statep->arg);
+
+ return ((statep->rc == 0) ? MH_WALK_CONTINUE : MH_WALK_TERMINATE);
+}
+
+int
+dls_vlan_walk(int (*fn)(dls_vlan_t *, void *), void *arg)
+{
+ dls_vlan_walk_state_t state;
+
+ rw_enter(&i_dls_vlan_lock, RW_READER);
+
+ state.fn = fn;
+ state.arg = arg;
+ state.rc = 0;
+ mod_hash_walk(i_dls_vlan_hash, dls_vlan_walker, (void *)&state);
+
+ rw_exit(&i_dls_vlan_lock);
+ return (state.rc);
}
diff --git a/usr/src/uts/common/io/mac/mac.c b/usr/src/uts/common/io/mac/mac.c
index ca69bb9be5..288bb79298 100644
--- a/usr/src/uts/common/io/mac/mac.c
+++ b/usr/src/uts/common/io/mac/mac.c
@@ -37,14 +37,18 @@
#include <sys/strsun.h>
#include <sys/strsubr.h>
#include <sys/dlpi.h>
+#include <sys/modhash.h>
#include <sys/mac.h>
#include <sys/mac_impl.h>
-#include <sys/dld_impl.h>
+#include <sys/dls.h>
+#include <sys/dld.h>
#define IMPL_HASHSZ 67 /* prime */
static kmem_cache_t *i_mac_impl_cachep;
-static ght_t i_mac_impl_hash;
+static mod_hash_t *i_mac_impl_hash;
+krwlock_t i_mac_impl_lock;
+uint_t i_mac_impl_count;
/*
* Private functions.
@@ -110,7 +114,6 @@ i_mac_destructor(void *buf, void *arg)
mac_impl_t *mip = buf;
ASSERT(mip->mi_mp == NULL);
- ASSERT(mip->mi_hte == NULL);
ASSERT(mip->mi_ref == 0);
ASSERT(mip->mi_active == 0);
ASSERT(mip->mi_link == LINK_STATE_UNKNOWN);
@@ -130,13 +133,12 @@ i_mac_destructor(void *buf, void *arg)
mutex_destroy(&mip->mi_activelink_lock);
}
-int
+static int
i_mac_create(mac_t *mp)
{
dev_info_t *dip;
mac_impl_t *mip;
- int err;
- ghte_t hte;
+ int err = 0;
dip = mp->m_dip;
ASSERT(dip != NULL);
@@ -163,24 +165,16 @@ i_mac_create(mac_t *mp)
mp->m_impl = (void *)mip;
/*
- * Allocate a hash table entry.
- */
- hte = ght_alloc(i_mac_impl_hash, KM_SLEEP);
-
- GHT_KEY(hte) = GHT_PTR_TO_KEY(mip->mi_name);
- GHT_VAL(hte) = GHT_PTR_TO_VAL(mip);
-
- /*
* Insert the hash table entry.
*/
- ght_lock(i_mac_impl_hash, GHT_WRITE);
- if ((err = ght_insert(hte)) != 0) {
- ght_free(hte);
+ rw_enter(&i_mac_impl_lock, RW_WRITER);
+ if (mod_hash_insert(i_mac_impl_hash,
+ (mod_hash_key_t)mip->mi_name, (mod_hash_val_t)mip) != 0) {
kmem_cache_free(i_mac_impl_cachep, mip);
+ err = EEXIST;
goto done;
}
-
- mip->mi_hte = hte;
+ i_mac_impl_count++;
/*
* Copy the fixed 'factory' MAC address from the immutable info.
@@ -210,7 +204,7 @@ i_mac_create(mac_t *mp)
mac_stat_create(mip);
done:
- ght_unlock(i_mac_impl_hash);
+ rw_exit(&i_mac_impl_lock);
return (err);
}
@@ -218,10 +212,10 @@ static void
i_mac_destroy(mac_t *mp)
{
mac_impl_t *mip = mp->m_impl;
- ghte_t hte;
mac_multicst_addr_t *p, *nextp;
+ mod_hash_val_t val;
- ght_lock(i_mac_impl_hash, GHT_WRITE);
+ rw_enter(&i_mac_impl_lock, RW_WRITER);
ASSERT(mip->mi_ref == 0);
ASSERT(!mip->mi_activelink);
@@ -234,10 +228,12 @@ i_mac_destroy(mac_t *mp)
/*
* Remove and destroy the hash table entry.
*/
- hte = mip->mi_hte;
- ght_remove(hte);
- ght_free(hte);
- mip->mi_hte = NULL;
+ (void) mod_hash_remove(i_mac_impl_hash,
+ (mod_hash_key_t)mip->mi_name, &val);
+ ASSERT(mip == (mac_impl_t *)val);
+
+ ASSERT(i_mac_impl_count > 0);
+ i_mac_impl_count--;
/*
* Free the list of multicast addresses.
@@ -261,7 +257,7 @@ i_mac_destroy(mac_t *mp)
*/
kmem_cache_free(i_mac_impl_cachep, mip);
- ght_unlock(i_mac_impl_hash);
+ rw_exit(&i_mac_impl_lock);
}
static void
@@ -292,24 +288,26 @@ i_mac_notify(mac_impl_t *mip, mac_notify_type_t type)
void
mac_init(void)
{
- int err;
-
i_mac_impl_cachep = kmem_cache_create("mac_impl_cache",
sizeof (mac_impl_t), 0, i_mac_constructor, i_mac_destructor, NULL,
NULL, NULL, 0);
ASSERT(i_mac_impl_cachep != NULL);
- err = ght_str_create("mac_impl_hash", IMPL_HASHSZ, &i_mac_impl_hash);
- ASSERT(err == 0);
+ i_mac_impl_hash = mod_hash_create_extended("mac_impl_hash",
+ IMPL_HASHSZ, mod_hash_null_keydtor, mod_hash_null_valdtor,
+ mod_hash_bystr, NULL, mod_hash_strkey_cmp, KM_SLEEP);
+ rw_init(&i_mac_impl_lock, NULL, RW_DEFAULT, NULL);
+ i_mac_impl_count = 0;
}
int
mac_fini(void)
{
- int err;
+ if (i_mac_impl_count > 0)
+ return (EBUSY);
- if ((err = ght_destroy(i_mac_impl_hash)) != 0)
- return (err);
+ mod_hash_destroy_hash(i_mac_impl_hash);
+ rw_destroy(&i_mac_impl_lock);
kmem_cache_destroy(i_mac_impl_cachep);
return (0);
@@ -328,7 +326,6 @@ mac_open(const char *dev, uint_t port, mac_handle_t *mhp)
major_t major;
dev_info_t *dip;
mac_impl_t *mip;
- ghte_t hte;
int err;
/*
@@ -352,7 +349,11 @@ mac_open(const char *dev, uint_t port, mac_handle_t *mhp)
/*
* Hold the given instance to prevent it from being detached.
- * (This will also attach it if it is not currently attached).
+ * This will also attach the instance if it is not currently attached.
+ * Currently we ensure that mac_register() (called by the driver's
+ * attach entry point) and all code paths under it cannot possibly
+ * call mac_open() because this would lead to a recursive attach
+ * panic.
*/
if ((dip = ddi_hold_devi_by_instance(major, instance, 0)) == NULL)
return (EINVAL);
@@ -366,26 +367,31 @@ mac_open(const char *dev, uint_t port, mac_handle_t *mhp)
* Look up its entry in the global hash table.
*/
again:
- ght_lock(i_mac_impl_hash, GHT_WRITE);
- if ((err = ght_find(i_mac_impl_hash, GHT_PTR_TO_KEY(name), &hte)) != 0)
+ rw_enter(&i_mac_impl_lock, RW_WRITER);
+ err = mod_hash_find(i_mac_impl_hash, (mod_hash_key_t)name,
+ (mod_hash_val_t *)&mip);
+ if (err != 0) {
+ err = ENOENT;
goto failed;
-
- mip = (mac_impl_t *)GHT_VAL(hte);
- ASSERT(mip->mi_mp->m_dip == dip);
+ }
if (mip->mi_destroying) {
- ght_unlock(i_mac_impl_hash);
+ rw_exit(&i_mac_impl_lock);
goto again;
}
+ /*
+ * We currently only support the DL_ETHER media type.
+ */
+ ASSERT(mip->mi_mp->m_info.mi_media == DL_ETHER);
mip->mi_ref++;
- ght_unlock(i_mac_impl_hash);
+ rw_exit(&i_mac_impl_lock);
*mhp = (mac_handle_t)mip;
return (0);
failed:
- ght_unlock(i_mac_impl_hash);
+ rw_exit(&i_mac_impl_lock);
ddi_release_devi(dip);
return (err);
}
@@ -396,14 +402,14 @@ mac_close(mac_handle_t mh)
mac_impl_t *mip = (mac_impl_t *)mh;
dev_info_t *dip = mip->mi_mp->m_dip;
- ght_lock(i_mac_impl_hash, GHT_WRITE);
+ rw_enter(&i_mac_impl_lock, RW_WRITER);
ASSERT(mip->mi_ref != 0);
if (--mip->mi_ref == 0) {
ASSERT(!mip->mi_activelink);
}
ddi_release_devi(dip);
- ght_unlock(i_mac_impl_hash);
+ rw_exit(&i_mac_impl_lock);
}
const mac_info_t *
@@ -418,6 +424,12 @@ mac_info(mac_handle_t mh)
return (&(mp->m_info));
}
+dev_info_t *
+mac_devinfo_get(mac_handle_t mh)
+{
+ return (((mac_impl_t *)mh)->mi_mp->m_dip);
+}
+
uint64_t
mac_stat_get(mac_handle_t mh, enum mac_stat stat)
{
@@ -1009,19 +1021,19 @@ mac_resource_set(mac_handle_t mh, mac_resource_add_t add, void *arg)
int
mac_register(mac_t *mp)
{
- int err;
- char name[MAXNAMELEN], aggr_name[MAXNAMELEN];
+ int err, instance;
+ char name[MAXNAMELEN], devname[MAXNAMELEN];
+ const char *drvname;
struct devnames *dnp;
+ minor_t minor;
-#ifdef DEBUG
- if (strcmp(mp->m_ident, MAC_IDENT) != 0)
- cmn_err(CE_WARN, "%s%d/%d: possible mac interface mismatch",
- ddi_driver_name(mp->m_dip),
- ddi_get_instance(mp->m_dip),
- mp->m_port);
-#endif /* DEBUG */
+ drvname = ddi_driver_name(mp->m_dip);
+ instance = ddi_get_instance(mp->m_dip);
- ASSERT(!(mp->m_info.mi_addr_length & 1));
+ if (strcmp(mp->m_ident, MAC_IDENT) != 0) {
+ cmn_err(CE_WARN, "%s%d/%d: possible mac interface mismatch",
+ drvname, instance, mp->m_port);
+ }
/*
* Create a new mac_impl_t to pair with the mac_t.
@@ -1029,71 +1041,80 @@ mac_register(mac_t *mp)
if ((err = i_mac_create(mp)) != 0)
return (err);
- /*
- * Create a DDI_NT_MAC minor node such that libdevinfo(3lib) can be
- * used to search for mac interfaces.
- */
- (void) sprintf(name, "%d", mp->m_port);
- if (ddi_create_minor_node(mp->m_dip, name, S_IFCHR, mp->m_port,
- DDI_NT_MAC, 0) != DDI_SUCCESS) {
- i_mac_destroy(mp);
- return (EEXIST);
- }
+ err = EEXIST;
+ if (ddi_create_minor_node(mp->m_dip, (char *)drvname, S_IFCHR, 0,
+ DDI_NT_NET, CLONE_DEV) != DDI_SUCCESS)
+ goto fail1;
- /*
- * Right now only the "aggr" driver creates nodes at mac_register
- * time, but it is expected that in the future with some
- * enhancement of devfs, all the drivers can create nodes here.
- */
- if (strcmp(ddi_driver_name(mp->m_dip), "aggr") == 0) {
- (void) snprintf(aggr_name, MAXNAMELEN, "aggr%u", mp->m_port);
- err = dld_ppa_create(aggr_name, AGGR_DEV, mp->m_port, 0);
- if (err != 0) {
- ASSERT(err != EEXIST);
- ddi_remove_minor_node(mp->m_dip, name);
- i_mac_destroy(mp);
- return (err);
- }
+ (void) snprintf(devname, MAXNAMELEN, "%s%d", drvname, instance);
+
+ if (strcmp(drvname, "aggr") == 0) {
+ (void) snprintf(name, MAXNAMELEN, "aggr%u", mp->m_port);
+ minor = (minor_t)mp->m_port + 1;
+ } else {
+ (void) strlcpy(name, devname, MAXNAMELEN);
+ minor = (minor_t)instance + 1;
}
+ if (ddi_create_minor_node(mp->m_dip, name, S_IFCHR, minor,
+ DDI_NT_NET, 0) != DDI_SUCCESS)
+ goto fail2;
+
+ if ((err = dls_create(name, devname, mp->m_port)) != 0)
+ goto fail3;
+
/* set the gldv3 flag in dn_flags */
dnp = &devnamesp[ddi_driver_major(mp->m_dip)];
LOCK_DEV_OPS(&dnp->dn_lock);
dnp->dn_flags |= DN_GLDV3_DRIVER;
UNLOCK_DEV_OPS(&dnp->dn_lock);
- cmn_err(CE_NOTE, "!%s%d/%d registered",
- ddi_driver_name(mp->m_dip),
- ddi_get_instance(mp->m_dip),
- mp->m_port);
-
+ cmn_err(CE_NOTE, "!%s%d/%d registered", drvname, instance, mp->m_port);
return (0);
+
+fail3:
+ ddi_remove_minor_node(mp->m_dip, name);
+fail2:
+ ddi_remove_minor_node(mp->m_dip, (char *)drvname);
+fail1:
+ i_mac_destroy(mp);
+ return (err);
}
int
mac_unregister(mac_t *mp)
{
- int err;
+ int err, instance;
char name[MAXNAMELEN];
+ const char *drvname;
mac_impl_t *mip = mp->m_impl;
+ drvname = ddi_driver_name(mp->m_dip);
+ instance = ddi_get_instance(mp->m_dip);
+
/*
* See if there are any other references to this mac_t (e.g., VLAN's).
* If not, set mi_destroying to prevent any new VLAN's from being
* created before we can perform the i_mac_destroy() below.
*/
- ght_lock(i_mac_impl_hash, GHT_WRITE);
+ rw_enter(&i_mac_impl_lock, RW_WRITER);
if (mip->mi_ref > 0) {
- ght_unlock(i_mac_impl_hash);
+ rw_exit(&i_mac_impl_lock);
return (EBUSY);
}
mip->mi_destroying = B_TRUE;
- ght_unlock(i_mac_impl_hash);
+ rw_exit(&i_mac_impl_lock);
- if (strcmp(ddi_driver_name(mp->m_dip), "aggr") == 0) {
+ if (strcmp(drvname, "aggr") == 0)
(void) snprintf(name, MAXNAMELEN, "aggr%u", mp->m_port);
- if ((err = dld_ppa_destroy(name)) != 0)
- return (err);
+ else
+ (void) snprintf(name, MAXNAMELEN, "%s%d", drvname, instance);
+
+ if ((err = dls_destroy(name)) != 0) {
+ rw_enter(&i_mac_impl_lock, RW_WRITER);
+ mip->mi_destroying = B_FALSE;
+ rw_exit(&i_mac_impl_lock);
+ return (err);
}
/*
@@ -1102,16 +1123,13 @@ mac_unregister(mac_t *mp)
i_mac_destroy(mp);
/*
- * Remove the minor node.
+ * Remove both style 1 and style 2 minor nodes
*/
- (void) sprintf(name, "%d", mp->m_port);
+ ddi_remove_minor_node(mp->m_dip, (char *)drvname);
ddi_remove_minor_node(mp->m_dip, name);
- cmn_err(CE_NOTE, "!%s%d/%d unregistered",
- ddi_driver_name(mp->m_dip),
- ddi_get_instance(mp->m_dip),
+ cmn_err(CE_NOTE, "!%s%d/%d unregistered", drvname, instance,
mp->m_port);
-
return (0);
}
@@ -1378,3 +1396,63 @@ mac_active_clear(mac_handle_t mh)
mip->mi_activelink = B_FALSE;
mutex_exit(&mip->mi_activelink_lock);
}
+
+/*
+ * mac_info_get() is used for retrieving the mac_info when a DL_INFO_REQ is
+ * issued before a DL_ATTACH_REQ. we walk the i_mac_impl_hash table and find
+ * the first mac_impl_t with a matching driver name; then we copy its mac_info_t
+ * to the caller. we do all this with i_mac_impl_lock held so the mac_impl_t
+ * cannot disappear while we are accessing it.
+ */
+typedef struct i_mac_info_state_s {
+ const char *mi_name;
+ mac_info_t *mi_infop;
+} i_mac_info_state_t;
+
+/*ARGSUSED*/
+static uint_t
+i_mac_info_walker(mod_hash_key_t key, mod_hash_val_t *val, void *arg)
+{
+ i_mac_info_state_t *statep = arg;
+ mac_impl_t *mip = (mac_impl_t *)val;
+
+ if (mip->mi_destroying)
+ return (MH_WALK_CONTINUE);
+
+ if (strcmp(statep->mi_name,
+ ddi_driver_name(mip->mi_mp->m_dip)) != 0)
+ return (MH_WALK_CONTINUE);
+
+ statep->mi_infop = &mip->mi_mp->m_info;
+ return (MH_WALK_TERMINATE);
+}
+
+boolean_t
+mac_info_get(const char *name, mac_info_t *minfop)
+{
+ i_mac_info_state_t state;
+
+ rw_enter(&i_mac_impl_lock, RW_READER);
+ state.mi_name = name;
+ state.mi_infop = NULL;
+ mod_hash_walk(i_mac_impl_hash, i_mac_info_walker, &state);
+ if (state.mi_infop == NULL) {
+ rw_exit(&i_mac_impl_lock);
+ return (B_FALSE);
+ }
+ *minfop = *state.mi_infop;
+ rw_exit(&i_mac_impl_lock);
+ return (B_TRUE);
+}
+
+void
+mac_init_ops(struct dev_ops *ops, const char *name)
+{
+ dld_init_ops(ops, name);
+}
+
+void
+mac_fini_ops(struct dev_ops *ops)
+{
+ dld_fini_ops(ops);
+}
diff --git a/usr/src/uts/common/io/strplumb.c b/usr/src/uts/common/io/strplumb.c
index 4e735f2dce..3bacfdc4be 100644
--- a/usr/src/uts/common/io/strplumb.c
+++ b/usr/src/uts/common/io/strplumb.c
@@ -360,50 +360,6 @@ done:
return (err);
}
-static int
-create_gldv3_linkobj(ldi_ident_t li, char *driver, int instance)
-{
- ldi_handle_t lh;
- int err;
- struct strioctl iocb;
- int rval;
- dld_ioc_create_t dic;
-
- /*
- * gld v3 driver. open the DLD control node.
- */
- if ((err = ldi_open_by_name(DLD_CONTROL_DEV, FREAD|FWRITE, CRED(), &lh,
- li)) != 0) {
- printf("strplumb: open CTLDEV failed: %d\n", err);
- return (ENXIO);
- }
-
- (void) snprintf(dic.dic_name, sizeof (dic.dic_name) - 1, "%s%d",
- driver, instance);
- (void) snprintf(dic.dic_dev, sizeof (dic.dic_dev) - 1, "%s%d",
- driver, instance);
- dic.dic_port = 0;
- dic.dic_vid = 0;
-
- iocb.ic_cmd = DLDIOCCREATE;
- iocb.ic_timout = 15;
- iocb.ic_len = sizeof (dic);
- iocb.ic_dp = (char *)&dic;
-
- /*
- * Try to create a data-link interface with the same name as the
- * device.
- */
- if ((err = ldi_ioctl(lh, I_STR, (intptr_t)&iocb, FKIOCTL, CRED(),
- &rval)) != 0) {
- cmn_err(CE_WARN, "strplumb: DLDIOCCREATE failed: %d\n", err);
- return (ENXIO);
- }
-
- (void) ldi_close(lh, FREAD|FWRITE, CRED());
- return (0);
-}
-
/*
* Can be set in /etc/system in the case of local booting. See comment below.
*/
@@ -420,13 +376,12 @@ int ndev_unit = 0;
* This can be overridden by setting "ndev_name" in /etc/system.
*/
static int
-resolve_boot_path(ldi_ident_t li)
+resolve_boot_path(void)
{
char *devpath = NULL;
dev_info_t *dip;
const char *driver;
int instance;
- int err;
if (strncmp(rootfs.bo_fstype, "nfs", 3) == 0)
devpath = rootfs.bo_name;
@@ -466,29 +421,12 @@ resolve_boot_path(ldi_ident_t li)
instance = ndev_unit;
}
- /* legcy driver, use clone to open */
- if (!GLDV3_DRV(ddi_name_to_major((char *)driver))) {
- (void) snprintf(rootfs.bo_devname, BO_MAXOBJNAME,
- "/devices/pseudo/clone@0:%s", driver);
- (void) snprintf(rootfs.bo_ifname, BO_MAXOBJNAME, "%s%d",
- driver, instance);
- rootfs.bo_ppa = instance;
- return (0);
- }
-
- /* GLDv3: create link object so open with succeed later */
- err = create_gldv3_linkobj(li, (char *)driver, instance);
- if (err != 0) {
- return (err);
- }
-
(void) snprintf(rootfs.bo_devname, BO_MAXOBJNAME,
- "/devices/pseudo/dld@0:%s", driver);
+ "/devices/pseudo/clone@0:%s", driver);
(void) snprintf(rootfs.bo_ifname, BO_MAXOBJNAME, "%s%d",
driver, instance);
rootfs.bo_ppa = instance;
-
- return (err);
+ return (0);
}
static int
@@ -697,7 +635,7 @@ strplumb(void)
if ((err = strplumb_tcpq(li)) != 0)
goto done;
- if ((err = resolve_boot_path(li)) != 0)
+ if ((err = resolve_boot_path()) != 0)
goto done;
DBG1("rootfs.bo_devname: %s\n", rootfs.bo_devname);
diff --git a/usr/src/uts/common/os/ght.c b/usr/src/uts/common/os/ght.c
deleted file mode 100644
index 7c33a8e125..0000000000
--- a/usr/src/uts/common/os/ght.c
+++ /dev/null
@@ -1,527 +0,0 @@
-/*
- * 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.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-/*
- * Generic Hash Table Module
- */
-
-#include <sys/types.h>
-#include <sys/sysmacros.h>
-#include <sys/kmem.h>
-#include <sys/sunddi.h>
-#include <sys/modctl.h>
-#include <sys/atomic.h>
-#include <sys/ght.h>
-
-/*
- * Revelations of the hash table and element structures.
- *
- * ght_t -> ght_impl_t *
- * ghte_t -> ghte_impl_t *
- */
-typedef struct ght_impl ght_impl_t;
-typedef struct ghte_impl ghte_impl_t;
-
-struct ghte_impl {
- ght_key_t ghtei_key;
- ght_val_t ghtei_val;
- ghte_impl_t **ghtei_prevp;
- ghte_impl_t *ghtei_next;
- ght_impl_t *ghtei_table;
- boolean_t ghtei_active;
- uint_t ghtei_ref;
-};
-
-struct ght_impl {
- char ghti_name[MAXNAMELEN];
- uint_t ghti_nbuckets;
- uint_t ghti_entries;
- ghte_impl_t **ghti_bucket;
- krwlock_t ghti_lock;
- kmem_cache_t *ghti_cache;
- uintptr_t (*ghti_hash)(ght_key_t);
- int (*ghti_keycmp)(ght_key_t, ght_key_t);
-};
-
-static uintptr_t i_ght_str_hash(ght_key_t);
-static int i_ght_str_keycmp(ght_key_t, ght_key_t);
-static uintptr_t i_ght_scalar_hash(ght_key_t);
-static int i_ght_scalar_keycmp(ght_key_t, ght_key_t);
-static int i_ght_ctor(void *, void *, int);
-static void i_ght_dtor(void *, void *);
-static int i_ght_create(char *, uint_t, uintptr_t (*)(ght_key_t),
- int (*)(ght_key_t, ght_key_t), ght_impl_t **);
-
-#define GHT_LINKINFO "Generic Hash Table v%I%"
-
-static struct modlmisc modlmisc = {
- &mod_miscops,
- GHT_LINKINFO
-};
-
-static struct modlinkage modlinkage = {
- MODREV_1,
- &modlmisc,
- NULL
-};
-
-int
-_init(void)
-{
- int err;
-
- if ((err = mod_install(&modlinkage)) != 0)
- return (err);
-
- return (0);
-}
-
-int
-_fini(void)
-{
- int err;
-
- if ((err = mod_remove(&modlinkage)) != 0)
- return (err);
-
- return (0);
-}
-
-int
-_info(struct modinfo *modinfop)
-{
- return (mod_info(&modlinkage, modinfop));
-}
-
-/*
- * Hash function for text string keys
- */
-static uintptr_t
-i_ght_str_hash(ght_key_t key)
-{
- char *k = (char *)key;
- uintptr_t hash;
-
- ASSERT(k != NULL);
- hash = *k++;
- while (*k != '\0') {
- uint_t g;
-
- hash = (hash << 4) + *k++;
- if ((g = (hash & 0xf0000000)) == 0)
- continue;
-
- hash ^= (g >> 24) ^ g;
- }
-
- return (hash);
-}
-
-/*
- * Comparitor for text string keys
- */
-static int
-i_ght_str_keycmp(ght_key_t key1, ght_key_t key2)
-{
- return (strcmp((char *)key1, (char *)key2));
-}
-
-/*
- * Hash function for scalar keys
- */
-static uintptr_t
-i_ght_scalar_hash(ght_key_t key)
-{
- return ((uintptr_t)key);
-}
-
-/*
- * Comparitor for scalar keys
- */
-static int
-i_ght_scalar_keycmp(ght_key_t key1, ght_key_t key2)
-{
- uintptr_t k1 = (uintptr_t)key1;
- uintptr_t k2 = (uintptr_t)key2;
-
- return ((k1 == k2) ? 0 : ((k1 > k2) ? 1 : -1));
-}
-
-/*
- * Cache constructor for hash table entries
- */
-/*ARGSUSED*/
-static int
-i_ght_ctor(void *buf, void *arg, int kmflags)
-{
- ghte_impl_t *ghteip = buf;
-
- bzero(buf, sizeof (ghte_impl_t));
-
- ghteip->ghtei_table = (ght_impl_t *)arg;
-
- return (0);
-}
-
-/*
- * Cache destructor for hash table entries
- */
-static void
-i_ght_dtor(void *buf, void *arg)
-{
- ghte_impl_t *ghteip = buf;
-
- ASSERT(!(ghteip->ghtei_active));
- ASSERT((void *)ghteip->ghtei_table == arg);
- ASSERT(ghteip->ghtei_next == NULL);
-}
-
-/*
- * Create a hash table
- */
-static int
-i_ght_create(char *name, uint_t nbuckets, uintptr_t (*hash)(ght_key_t),
- int (*keycmp)(ght_key_t, ght_key_t), ght_impl_t **ghtipp)
-{
- int len;
- size_t size;
- ght_impl_t *ghtip;
-
- ASSERT(name != NULL);
- ASSERT(hash != NULL);
- ASSERT(keycmp != NULL);
- ASSERT(ghtipp != NULL);
-
- if ((len = strlen(name)) >= MAXNAMELEN)
- return (EINVAL);
-
- size = sizeof (ght_impl_t) + (nbuckets * sizeof (ghte_impl_t));
- ghtip = kmem_zalloc(size, KM_SLEEP);
-
- (void) strlcpy(ghtip->ghti_name, name, MAXNAMELEN);
- ghtip->ghti_name[len] = '\0';
- ghtip->ghti_bucket = (ghte_impl_t **)&ghtip[1];
- ghtip->ghti_nbuckets = nbuckets;
- ghtip->ghti_entries = 0;
- ghtip->ghti_hash = hash;
- ghtip->ghti_keycmp = keycmp;
-
- rw_init(&ghtip->ghti_lock, NULL, RW_DRIVER, NULL);
- ghtip->ghti_cache = kmem_cache_create(name, sizeof (ghte_impl_t), 0,
- i_ght_ctor, i_ght_dtor, NULL, (void *)ghtip, NULL, 0);
-
- *ghtipp = ghtip;
- return (0);
-}
-
-/*
- * External functions.
- */
-
-/*
- * Lock a table.
- */
-void
-ght_lock(ght_t ght, int flag)
-{
- ght_impl_t *ghtip = (ght_impl_t *)ght;
-
- ASSERT(flag == GHT_READ || flag == GHT_WRITE);
- rw_enter(&(ghtip->ghti_lock), (flag == GHT_READ) ? RW_READER :
- RW_WRITER);
-}
-
-/*
- * Unlock a table.
- */
-void
-ght_unlock(ght_t ght)
-{
- ght_impl_t *ghtip = (ght_impl_t *)ght;
-
- rw_exit(&(ghtip->ghti_lock));
-}
-
-/*
- * Create a string keyed table.
- */
-int
-ght_str_create(char *name, uint_t nbuckets, ght_t *ghtp)
-{
- ght_impl_t *ghtip;
- int err;
-
- if ((err = i_ght_create(name, nbuckets, i_ght_str_hash,
- i_ght_str_keycmp, &ghtip)) != 0)
- return (err);
-
- *ghtp = (ght_t)ghtip;
- return (0);
-}
-
-/*
- * Create a scalar keyed table.
- */
-int
-ght_scalar_create(char *name, uint_t nbuckets, ght_t *ghtp)
-{
- ght_impl_t *ghtip;
- int err;
-
- if ((err = i_ght_create(name, nbuckets, i_ght_scalar_hash,
- i_ght_scalar_keycmp, &ghtip)) != 0)
- return (err);
-
- *ghtp = (ght_t)ghtip;
- return (0);
-}
-
-/*
- * Destroy a table.
- */
-int
-ght_destroy(ght_t ght)
-{
- ght_impl_t *ghtip = (ght_impl_t *)ght;
- size_t size;
-
- ASSERT(ghtip != NULL);
-
- if (ghtip->ghti_entries != 0)
- return (EBUSY);
-
- kmem_cache_destroy(ghtip->ghti_cache);
- rw_destroy(&ghtip->ghti_lock);
-
- size = sizeof (ght_impl_t) +
- (ghtip->ghti_nbuckets * sizeof (ghte_impl_t));
- kmem_free(ghtip, size);
-
- return (0);
-}
-
-/*
- * Return the number of entries in a table.
- */
-uint_t
-ght_count(ght_t ght)
-{
- ght_impl_t *ghtip = (ght_impl_t *)ght;
-
- return (ghtip->ghti_entries);
-}
-
-/*
- * Allocate a new entry for a table.
- */
-ghte_t
-ght_alloc(ght_t ght, int kmflags)
-{
- ght_impl_t *ghtip = (ght_impl_t *)ght;
- ghte_impl_t *ghteip;
-
- if ((ghteip = kmem_cache_alloc(ghtip->ghti_cache, kmflags)) == NULL)
- return (NULL);
-
- return ((ghte_t)ghteip);
-}
-
-/*
- * Free a table entry (after it has been removed).
- */
-void
-ght_free(ghte_t ghte)
-{
- ghte_impl_t *ghteip = (ghte_impl_t *)ghte;
- ght_impl_t *ghtip = ghteip->ghtei_table;
-
- ASSERT(!(ghteip->ghtei_active));
- ASSERT(ghteip->ghtei_ref == 0);
-
- kmem_cache_free(ghtip->ghti_cache, ghteip);
-}
-
-/*
- * Insert an entry into a table.
- */
-int
-ght_insert(ghte_t ghte)
-{
- ghte_impl_t *ghteip = (ghte_impl_t *)ghte;
- ght_impl_t *ghtip = ghteip->ghtei_table;
- ghte_impl_t **pp;
- ghte_impl_t *p;
- uint_t n;
-
- ASSERT(ghteip != NULL);
- ASSERT(!(ghteip->ghtei_active));
- ASSERT(rw_write_held(&(ghtip->ghti_lock)));
-
- n = ghtip->ghti_hash(ghteip->ghtei_key) % ghtip->ghti_nbuckets;
- for (pp = &(ghtip->ghti_bucket[n]); (p = *pp) != NULL;
- pp = &(p->ghtei_next)) {
- if (ghtip->ghti_keycmp(ghteip->ghtei_key, p->ghtei_key) == 0)
- return (EEXIST);
- }
-
- ghteip->ghtei_next = p;
- ghteip->ghtei_prevp = pp;
- *pp = ghteip;
-
- ghteip->ghtei_active = B_TRUE;
- ghtip->ghti_entries++;
- return (0);
-}
-
-/*
- * Look-up an enrty in a table.
- */
-int
-ght_find(ght_t ght, ght_key_t key, ghte_t *ghtep)
-{
- ght_impl_t *ghtip = (ght_impl_t *)ght;
- ghte_impl_t *p;
- uint_t n;
-
- ASSERT(ghtip != NULL);
- ASSERT(rw_read_held(&(ghtip->ghti_lock)) ||
- rw_write_held(&(ghtip->ghti_lock)));
-
- n = ghtip->ghti_hash(key) % ghtip->ghti_nbuckets;
- for (p = ghtip->ghti_bucket[n]; p != NULL; p = p->ghtei_next) {
- ASSERT(p->ghtei_active);
- if (ghtip->ghti_keycmp(key, p->ghtei_key) == 0)
- break;
- }
- if (p == NULL)
- return (ENOENT);
-
- *ghtep = (ghte_t)p;
- return (0);
-}
-
-/*
- * Increment the reference count on a hash table entry.
- */
-void
-ght_hold(ghte_t ghte)
-{
- ghte_impl_t *ghteip = (ghte_impl_t *)ghte;
- ght_impl_t *ghtip = ghteip->ghtei_table;
-
- ASSERT(ghteip->ghtei_active);
- ASSERT(rw_read_held(&(ghtip->ghti_lock)) ||
- rw_write_held(&(ghtip->ghti_lock)));
-
- atomic_add_32(&(ghteip->ghtei_ref), 1);
-}
-
-/*
- * Decrement the reference count on a hash table entry.
- */
-void
-ght_rele(ghte_t ghte)
-{
- ghte_impl_t *ghteip = (ghte_impl_t *)ghte;
-
- ASSERT(ghteip->ghtei_active);
- ASSERT(ghteip->ghtei_ref != 0);
-
- atomic_add_32(&(ghteip->ghtei_ref), -1);
-}
-
-/*
- * Return the reference count on a hash table entry.
- */
-uint_t
-ght_ref(ghte_t ghte)
-{
- ghte_impl_t *ghteip = (ghte_impl_t *)ghte;
- ght_impl_t *ghtip = ghteip->ghtei_table;
-
- ASSERT(ghteip->ghtei_active);
- ASSERT(rw_read_held(&(ghtip->ghti_lock)) ||
- rw_write_held(&(ghtip->ghti_lock)));
-
- return (ghteip->ghtei_ref);
-}
-
-/*
- * Remove an entry from its table.
- */
-void
-ght_remove(ghte_t ghte)
-{
- ghte_impl_t *ghteip = (ghte_impl_t *)ghte;
- ght_impl_t *ghtip = ghteip->ghtei_table;
- ghte_impl_t **pp;
- ghte_impl_t *p;
-
- ASSERT(ghteip != NULL);
- ASSERT(ghteip->ghtei_active);
- ASSERT(rw_write_held(&(ghtip->ghti_lock)));
-
- pp = ghteip->ghtei_prevp;
- p = ghteip->ghtei_next;
-
- *pp = p;
- if (p != NULL) {
- ASSERT(p->ghtei_prevp == &(ghteip->ghtei_next));
- p->ghtei_prevp = pp;
- }
-
- ghteip->ghtei_prevp = NULL;
- ghteip->ghtei_next = NULL;
-
- ghteip->ghtei_active = B_FALSE;
- --ghtip->ghti_entries;
-}
-
-/*
- * Walk table entries calling fn() for each one.
- */
-void
-ght_walk(ght_t ght, boolean_t (*fn)(void *, ghte_t), void *arg)
-{
- ght_impl_t *ghtip = (ght_impl_t *)ght;
- uint_t n;
- ghte_impl_t *p;
-
- ASSERT(ghtip != NULL);
- ASSERT(rw_read_held(&(ghtip->ghti_lock)) ||
- rw_write_held(&(ghtip->ghti_lock)));
- ASSERT(fn != NULL);
-
- for (n = 0; n < ghtip->ghti_nbuckets; n++) {
- for (p = ghtip->ghti_bucket[n]; p != NULL; p = p->ghtei_next) {
- ASSERT(p->ghtei_active);
- if (!(fn(arg, (ghte_t)p)))
- return;
- }
- }
-}
diff --git a/usr/src/uts/common/sys/Makefile b/usr/src/uts/common/sys/Makefile
index 25f7f90f15..259ceadd6d 100644
--- a/usr/src/uts/common/sys/Makefile
+++ b/usr/src/uts/common/sys/Makefile
@@ -236,7 +236,6 @@ CHKHDRS= \
fx.h \
fxpriocntl.h \
gfs.h \
- ght.h \
gld.h \
gldpriv.h \
hdio.h \
diff --git a/usr/src/uts/common/sys/aggr.h b/usr/src/uts/common/sys/aggr.h
index aaf6fe8231..d41899a3de 100644
--- a/usr/src/uts/common/sys/aggr.h
+++ b/usr/src/uts/common/sys/aggr.h
@@ -117,7 +117,6 @@ typedef struct laioc_port {
typedef struct laioc_create {
uint32_t lc_key;
uint32_t lc_nports;
- caddr_t lc_ports; /* ptr to lacio_port_t */
uint32_t lc_policy;
uchar_t lc_mac[ETHERADDRL];
boolean_t lc_mac_fixed;
@@ -130,7 +129,6 @@ typedef struct laioc_create {
typedef struct laioc_create32 {
uint32_t lc_key;
uint32_t lc_nports;
- caddr32_t lc_ports;
uint32_t lc_policy;
uchar_t lc_mac[ETHERADDRL];
boolean_t lc_mac_fixed;
@@ -187,7 +185,6 @@ typedef struct laioc_info_group {
} laioc_info_group_t;
typedef struct laioc_info {
- uint32_t li_bufsize;
uint32_t li_ngroups;
uint32_t li_group_key; /* 0 returns all */
} laioc_info_t;
@@ -198,15 +195,13 @@ typedef struct laioc_info {
typedef struct laioc_add_rem {
uint32_t la_key;
uint32_t la_nports;
- caddr_t la_ports;
-} laioc_add_t;
+} laioc_add_rem_t;
#ifdef _SYSCALL32
typedef struct laioc_add_rem32 {
uint32_t la_key;
uint32_t la_nports;
- caddr32_t la_ports;
} laioc_add_rem32_t;
#endif /* _SYSCALL32 */
diff --git a/usr/src/uts/common/sys/aggr_impl.h b/usr/src/uts/common/sys/aggr_impl.h
index 7fca234c8d..8c66b3dffe 100644
--- a/usr/src/uts/common/sys/aggr_impl.h
+++ b/usr/src/uts/common/sys/aggr_impl.h
@@ -31,7 +31,6 @@
#include <sys/types.h>
#include <sys/mac.h>
-#include <sys/ght.h>
#include <sys/aggr_lacp.h>
#ifdef __cplusplus
@@ -40,7 +39,7 @@ extern "C" {
#ifdef _KERNEL
-#define AGGR_MINOR_CTL 0 /* control interface minor */
+#define AGGR_MINOR_CTL 1 /* control interface minor */
/* flags for aggr_grp_modify() */
#define AGGR_MODIFY_POLICY 0x01
@@ -109,7 +108,6 @@ typedef struct aggr_grp_s {
uint32_t lg_refs; /* refcount */
uint16_t lg_nports; /* number of MAC ports */
uint8_t lg_addr[ETHERADDRL]; /* group MAC address */
- ghte_t lg_hte;
uint16_t
lg_addr_fixed : 1, /* fixed MAC address? */
lg_started : 1, /* group started? */
@@ -162,10 +160,7 @@ typedef struct aggr_grp_s {
}
extern dev_info_t *aggr_dip;
-
-extern int aggr_open(dev_t *, int, int, cred_t *);
-extern int aggr_close(dev_t, int, int, cred_t *);
-extern int aggr_ioctl(dev_t, int, intptr_t, int, cred_t *, int *);
+extern void aggr_ioctl(queue_t *, mblk_t *);
typedef int (*aggr_grp_info_new_grp_fn_t)(void *, uint32_t, uchar_t *,
boolean_t, uint32_t, uint32_t, aggr_lacp_mode_t, aggr_lacp_timer_t);
@@ -193,6 +188,7 @@ extern int aggr_grp_modify(uint32_t, aggr_grp_t *, uint8_t, uint32_t,
boolean_t, const uchar_t *, aggr_lacp_mode_t, aggr_lacp_timer_t);
extern void aggr_grp_multicst_port(aggr_port_t *, boolean_t);
extern void aggr_grp_walk(aggr_grp_walker_fn_t, void *);
+extern uint_t aggr_grp_count(void);
extern void aggr_port_init(void);
extern int aggr_port_fini(void);
diff --git a/usr/src/uts/common/sys/dld.h b/usr/src/uts/common/sys/dld.h
index 369bb54398..2fe60769e6 100644
--- a/usr/src/uts/common/sys/dld.h
+++ b/usr/src/uts/common/sys/dld.h
@@ -37,7 +37,6 @@
#include <sys/stream.h>
#include <sys/mac.h>
#include <sys/dls.h>
-#include <sys/ght.h>
#include <net/if.h>
#ifdef __cplusplus
@@ -49,18 +48,15 @@ extern "C" {
*/
#define DLD_INFO "Data-Link Driver v%I%"
+#define DLD_MAX_PPA 999
+#define DLD_MAX_MINOR (DLD_MAX_PPA + 1)
+
/*
* Options: To enable an option set the property name to a non-zero value
* in kernel/drv/dld.conf.
*/
/*
- * Prevent creation of DLPI style 1 provider nodes (thus forcing stacks such
- * as TCP/IP to use style 2 nodes).
- */
-#define DLD_PROP_NO_STYLE1 "no-style-1"
-
-/*
* Prevent use of the IP fast-path (direct M_DATA transmit).
*/
#define DLD_PROP_NO_FASTPATH "no-fastpath"
@@ -93,30 +89,37 @@ extern "C" {
*/
#define DLDIOC ('D' << 24 | 'L' << 16 | 'D' << 8)
-#define DLDIOCCREATE (DLDIOC | 0x01)
-
-typedef struct dld_ioc_create {
- char dic_name[IFNAMSIZ];
- char dic_dev[MAXNAMELEN];
- uint_t dic_port;
- uint16_t dic_vid;
-} dld_ioc_create_t;
-
-#define DLDIOCDESTROY (DLDIOC | 0x02)
-
-typedef struct dld_ioc_destroy {
- char did_name[IFNAMSIZ];
-} dld_ioc_destroy_t;
-
#define DLDIOCATTR (DLDIOC | 0x03)
typedef struct dld_ioc_attr {
char dia_name[IFNAMSIZ];
char dia_dev[MAXNAMELEN];
+ uint_t dia_max_sdu;
uint_t dia_port;
uint16_t dia_vid;
} dld_ioc_attr_t;
+#define DLDIOCVLAN (DLDIOC | 0x04)
+
+typedef struct dld_ioc_vlan {
+ uint_t div_count;
+} dld_ioc_vlan_t;
+
+typedef struct dld_vlan_info {
+ char dvi_name[IFNAMSIZ];
+ uint16_t dvi_vid;
+} dld_vlan_info_t;
+
+#ifdef _KERNEL
+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 *);
+void dld_wput(queue_t *, mblk_t *);
+void dld_wsrv(queue_t *);
+void dld_init_ops(struct dev_ops *, const char *);
+void dld_fini_ops(struct dev_ops *);
+#endif
+
#ifdef __cplusplus
}
#endif
diff --git a/usr/src/uts/common/sys/dld_impl.h b/usr/src/uts/common/sys/dld_impl.h
index eae8e262eb..cafc32433a 100644
--- a/usr/src/uts/common/sys/dld_impl.h
+++ b/usr/src/uts/common/sys/dld_impl.h
@@ -41,85 +41,6 @@
extern "C" {
#endif
-/*
- * dld_ppa_t object definition.
- */
-typedef struct dld_node dld_node_t;
-
-typedef struct dld_ppa {
- /*
- * Name of the data-link.
- */
- char dp_name[IFNAMSIZ];
-
- /*
- * The device and port of the MAC interface.
- */
- char dp_dev[MAXNAMELEN];
- uint_t dp_port;
-
- /*
- * The VLAN identifier of the data-link interface.
- */
- uint_t dp_vid;
-
- /*
- * Style 1 and style 2 provider nodes that reference the object.
- */
- dld_node_t *dp_style1;
- dld_node_t *dp_style2;
-
- /*
- * Style 2 PPA index number of the object.
- */
- t_scalar_t dp_index;
-} dld_ppa_t;
-
-/*
- * dld_node_t object definition.
- */
-struct dld_node {
- /*
- * Name of the node, this will be the name of the dev_t in the
- * file system.
- */
- char dn_name[IFNAMSIZ];
-
- /*
- * DL_STYLE1 or DL_STYLE2.
- */
- t_uscalar_t dn_style;
-
- /*
- * Minor number of the dev_t.
- */
- minor_t dn_minor;
-
- /*
- * Global hash table entries that reference the object.
- */
- ghte_t dn_byminor_hte;
- ghte_t dn_byname_hte;
-
- /*
- * Number of dld_ppa_t objects referencing the object.
- */
- uint32_t dn_ref;
-
- /*
- * For style 1 nodes there is only a single dld_ppa_t object reference.
- * This field is used for that purpose.
- */
- dld_ppa_t *dn_dpp;
-
- /*
- * For style 2 nodes there may be many dld_ppa_t references, keyed
- * by a PPA index number. The following hash table stores the
- * references and the subsequent methods are used to manage the table.
- */
- ght_t dn_hash;
-};
-
#define DLD_CONTROL 0x00000001
#define DLD_DLPI 0x00000002
@@ -142,6 +63,11 @@ typedef struct dld_str dld_str_t;
*/
struct dld_str {
/*
+ * Major number of the device
+ */
+ major_t ds_major;
+
+ /*
* Ephemeral minor number for the object.
*/
minor_t ds_minor;
@@ -153,6 +79,11 @@ struct dld_str {
queue_t *ds_wq;
/*
+ * Lock to protect this structure.
+ */
+ krwlock_t ds_lock;
+
+ /*
* Stream is open to DLD_CONTROL (control node) or
* DLD_DLPI (DLS provider) node.
*/
@@ -163,14 +94,14 @@ struct dld_str {
*/
/*
- * dld_node_t of the node that was opened.
+ * Current DLPI state.
*/
- dld_node_t *ds_dnp;
+ t_uscalar_t ds_dlstate;
/*
- * Current DLPI state.
+ * DLPI style
*/
- t_uscalar_t ds_dlstate;
+ t_uscalar_t ds_style;
/*
* Currently bound DLSAP.
@@ -241,10 +172,29 @@ struct dld_str {
dld_passivestate_t ds_passivestate;
/*
- * Message handler jump tables.
+ * Dummy mblk used for flow-control.
+ */
+ mblk_t *ds_tx_flow_mp;
+
+ /*
+ * Internal transmit queue and its parameters.
+ */
+ kmutex_t ds_tx_list_lock;
+ mblk_t *ds_tx_list_head;
+ mblk_t *ds_tx_list_tail;
+ uint_t ds_tx_cnt;
+ uint_t ds_tx_msgcnt;
+ boolean_t ds_tx_qbusy;
+
+ /*
+ * Number of threads currently in dld. If there is a pending
+ * DL_DETACH_REQ, the request is placed in the ds_detach_req
+ * and the operation will be finished when the driver goes
+ * single-threaded.
*/
- struct str_msg_info *ds_mi;
- struct str_msg_info *ds_pmi;
+ kmutex_t ds_thr_lock;
+ uint_t ds_thr;
+ mblk_t *ds_detach_req;
} dld_str;
/*
@@ -253,78 +203,37 @@ struct dld_str {
extern void dld_str_init(void);
extern int dld_str_fini(void);
-extern dld_str_t *dld_str_create(queue_t *);
+extern dld_str_t *dld_str_create(queue_t *, uint_t, major_t,
+ t_uscalar_t);
extern void dld_str_destroy(dld_str_t *);
-extern int dld_str_attach(dld_str_t *, dld_ppa_t *);
+extern int dld_str_attach(dld_str_t *, t_uscalar_t);
extern void dld_str_detach(dld_str_t *);
-extern void dld_str_tx_raw(dld_str_t *);
-extern void dld_str_tx_fastpath(dld_str_t *);
-extern void dld_str_tx_drop(dld_str_t *);
extern void dld_str_rx_raw(void *, mac_resource_handle_t,
mblk_t *, size_t);
extern void dld_str_rx_fastpath(void *, mac_resource_handle_t,
mblk_t *, size_t);
extern void dld_str_rx_unitdata(void *, mac_resource_handle_t,
mblk_t *, size_t);
-extern void dld_str_put(dld_str_t *, mblk_t *);
-extern void dld_str_srv(dld_str_t *, mblk_t *);
+extern void dld_tx_flush(dld_str_t *);
+extern void dld_tx_enqueue(dld_str_t *, mblk_t *, boolean_t);
extern void dld_str_notify_ind(dld_str_t *);
+extern void str_mdata_fastpath_put(dld_str_t *, mblk_t *);
+extern void str_mdata_raw_put(dld_str_t *, mblk_t *);
+
/*
* dld_proto.c
*/
extern void dld_proto(dld_str_t *, mblk_t *);
-
-/*
- * dld_ppa.c module.
- */
-extern void dld_ppa_init(void);
-extern int dld_ppa_fini(void);
-extern int dld_ppa_create(const char *, const char *, uint_t,
- uint16_t);
-extern int dld_ppa_destroy(const char *);
-extern int dld_ppa_attr(const char *, char *, uint_t *,
- uint16_t *);
-
-/*
- * dld_node.c module.
- */
-extern void dld_node_init(void);
-extern int dld_node_fini(void);
-extern dld_node_t *dld_node_hold(const char *, t_uscalar_t);
-extern void dld_node_rele(dld_node_t *);
-extern dld_node_t *dld_node_find(minor_t);
-extern int dld_node_ppa_add(dld_node_t *, t_scalar_t,
- dld_ppa_t *);
-extern int dld_node_ppa_remove(dld_node_t *, t_scalar_t);
-extern dld_ppa_t *dld_node_ppa_find(dld_node_t *, t_scalar_t);
-
-/*
- * dld_minor.c module.
- */
-extern void dld_minor_init(void);
-extern int dld_minor_fini(void);
-extern minor_t dld_minor_hold(boolean_t);
-extern void dld_minor_rele(minor_t);
-
-/*
- * dld_ioc.c module.
- */
-extern void dld_ioc(dld_str_t *, mblk_t *);
-
-/*
- * dld_drv.c module.
- */
-extern dev_info_t *dld_dip;
+extern void dld_finish_pending_ops(dld_str_t *);
/*
* Options: there should be a separate bit defined here for each
* DLD_PROP... defined in dld.h.
*/
-#define DLD_OPT_NO_STYLE1 0x00000001
-#define DLD_OPT_NO_FASTPATH 0x00000002
-#define DLD_OPT_NO_POLL 0x00000004
-#define DLD_OPT_NO_ZEROCOPY 0x00000008
+#define DLD_OPT_NO_FASTPATH 0x00000001
+#define DLD_OPT_NO_POLL 0x00000002
+#define DLD_OPT_NO_ZEROCOPY 0x00000004
extern uint32_t dld_opt;
@@ -335,6 +244,28 @@ extern uint32_t dld_opt;
#define IMPLY(p, c) (!(p) || (c))
#define AGGR_DEV "aggr0"
+#define DLD_ENTER(dsp) { \
+ mutex_enter(&dsp->ds_thr_lock); \
+ ++dsp->ds_thr; \
+ ASSERT(dsp->ds_thr != 0); \
+ mutex_exit(&dsp->ds_thr_lock); \
+}
+
+#define DLD_EXIT(dsp) { \
+ mutex_enter(&dsp->ds_thr_lock); \
+ ASSERT(dsp->ds_thr > 0); \
+ if (--dsp->ds_thr == 0 && dsp->ds_detach_req != NULL) \
+ dld_finish_pending_ops(dsp); \
+ else \
+ mutex_exit(&dsp->ds_thr_lock); \
+}
+
+#ifdef DEBUG
+#define DLD_DBG cmn_err
+#else
+#define DLD_DBG if (0) cmn_err
+#endif
+
#ifdef __cplusplus
}
#endif
diff --git a/usr/src/uts/common/sys/dls.h b/usr/src/uts/common/sys/dls.h
index 695b185a21..a9423be978 100644
--- a/usr/src/uts/common/sys/dls.h
+++ b/usr/src/uts/common/sys/dls.h
@@ -31,7 +31,6 @@
#include <sys/types.h>
#include <sys/stream.h>
-#include <sys/ght.h>
#include <sys/mac.h>
/*
@@ -66,9 +65,15 @@ extern "C" {
((sap) == 0) || \
((sap) <= ETHERMTU && (type) == DL_ETHER))
+/*
+ * Macros for converting ppas to instance #s and to Vlan IDs.
+ */
+#define DLS_PPA2INST(ppa) ((int)((ppa) % 1000))
+#define DLS_PPA2VID(ppa) ((uint16_t)((ppa) / 1000))
+
#ifdef _KERNEL
-extern int dls_create(const char *, const char *, uint_t, uint16_t);
+extern int dls_create(const char *, const char *, uint_t);
extern int dls_destroy(const char *);
typedef struct dls_t *dls_channel_t;
diff --git a/usr/src/uts/common/sys/dls_impl.h b/usr/src/uts/common/sys/dls_impl.h
index 117e113e83..70de658cc4 100644
--- a/usr/src/uts/common/sys/dls_impl.h
+++ b/usr/src/uts/common/sys/dls_impl.h
@@ -32,7 +32,7 @@
#include <sys/stream.h>
#include <sys/dls.h>
#include <sys/mac.h>
-#include <sys/ght.h>
+#include <sys/modhash.h>
#include <sys/kstat.h>
#include <net/if.h>
@@ -57,10 +57,11 @@ struct dls_link_s {
const mac_info_t *dl_mip;
mac_rx_handle_t dl_mrh;
mac_txloop_handle_t dl_mth;
- ghte_t dl_hte;
uint_t dl_ref;
uint_t dl_macref;
- ght_t dl_impl_hash;
+ mod_hash_t *dl_impl_hash;
+ krwlock_t dl_impl_lock;
+ uint_t dl_impl_count;
mac_txloop_t dl_loopback;
kmutex_t dl_promisc_lock;
uint_t dl_npromisc;
@@ -71,7 +72,6 @@ struct dls_link_s {
typedef struct dls_vlan_s {
char dv_name[IFNAMSIZ];
- ghte_t dv_hte;
uint_t dv_ref;
dls_link_t *dv_dlp;
uint16_t dv_id;
@@ -79,6 +79,7 @@ typedef struct dls_vlan_s {
} dls_vlan_t;
typedef struct dls_impl_s dls_impl_t;
+typedef struct dls_head_s dls_head_t;
typedef mblk_t *(*dls_priv_header_t)(dls_impl_t *,
const uint8_t *, uint16_t, uint_t);
@@ -87,13 +88,13 @@ typedef void (*dls_priv_header_info_t)(dls_impl_t *,
struct dls_impl_s {
dls_impl_t *di_nextp;
+ dls_head_t *di_headp;
dls_vlan_t *di_dvp;
mac_handle_t di_mh;
mac_notify_handle_t di_mnh;
const mac_info_t *di_mip;
krwlock_t di_lock;
uint16_t di_sap;
- ghte_t di_hte;
uint_t di_promisc;
dls_multicst_addr_t *di_dmap;
dls_rx_t di_rx;
@@ -107,6 +108,12 @@ struct dls_impl_s {
dls_priv_header_info_t di_header_info;
};
+struct dls_head_s {
+ dls_impl_t *dh_list;
+ uint_t dh_ref;
+ mod_hash_key_t dh_key;
+};
+
extern void dls_link_init(void);
extern int dls_link_fini(void);
extern int dls_link_hold(const char *, uint_t, dls_link_t **);
@@ -124,8 +131,9 @@ extern int dls_vlan_fini(void);
extern int dls_vlan_create(const char *, const char *, uint_t,
uint16_t);
extern int dls_vlan_destroy(const char *);
-extern int dls_vlan_hold(const char *, dls_vlan_t **);
+extern int dls_vlan_hold(const char *, dls_vlan_t **, boolean_t);
extern void dls_vlan_rele(dls_vlan_t *);
+extern int dls_vlan_walk(int (*)(dls_vlan_t *, void *), void *);
extern void dls_init(void);
extern int dls_fini(void);
diff --git a/usr/src/uts/common/sys/ght.h b/usr/src/uts/common/sys/ght.h
deleted file mode 100644
index 15d5754bf5..0000000000
--- a/usr/src/uts/common/sys/ght.h
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * 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.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-#ifndef _SYS_GHT_H
-#define _SYS_GHT_H
-
-#pragma ident "%Z%%M% %I% %E% SMI"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#ifdef _KERNEL
-
-#include <sys/types.h>
-
-typedef struct __ght_key *ght_key_t;
-typedef struct __ght_val *ght_val_t;
-
-#define GHT_SCALAR_TO_KEY(scalar) ((ght_key_t)(uintptr_t)(scalar))
-#define GHT_PTR_TO_KEY(ptr) ((ght_key_t)(ptr))
-
-#define GHT_SCALAR_TO_VAL(scalar) ((ght_val_t)(uintptr_t)(scalar))
-#define GHT_PTR_TO_VAL(ptr) ((ght_val_t)(ptr))
-
-typedef struct __ght *ght_t;
-typedef struct __ghte *ghte_t;
-
-struct ghte_reveal {
- ght_key_t key;
- ght_val_t val;
-};
-
-#define GHT_KEY(ghte) ((struct ghte_reveal *)ghte)->key
-#define GHT_VAL(ghte) ((struct ghte_reveal *)ghte)->val
-
-extern int ght_str_create(char *, uint_t, ght_t *);
-extern int ght_scalar_create(char *, uint_t, ght_t *);
-extern int ght_destroy(ght_t);
-extern uint_t ght_count(ght_t);
-
-extern ghte_t ght_alloc(ght_t, int);
-extern void ght_free(ghte_t);
-
-#define GHT_READ 0
-#define GHT_WRITE 1
-
-extern void ght_lock(ght_t, int);
-extern void ght_unlock(ght_t);
-
-extern int ght_insert(ghte_t);
-extern int ght_find(ght_t, ght_key_t, ghte_t *);
-extern void ght_remove(ghte_t);
-
-extern void ght_hold(ghte_t);
-extern void ght_rele(ghte_t);
-extern uint_t ght_ref(ghte_t);
-
-extern void ght_walk(ght_t, boolean_t (*)(void *, ghte_t), void *);
-
-#endif /* _KERNEL */
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _SYS_GHT_H */
diff --git a/usr/src/uts/common/sys/mac.h b/usr/src/uts/common/sys/mac.h
index 39c970b942..59e493f9bd 100644
--- a/usr/src/uts/common/sys/mac.h
+++ b/usr/src/uts/common/sys/mac.h
@@ -374,6 +374,7 @@ typedef mac_resource_handle_t (*mac_resource_add_t)(void *, mac_resource_t *);
extern int mac_open(const char *, uint_t, mac_handle_t *);
extern void mac_close(mac_handle_t);
extern const mac_info_t *mac_info(mac_handle_t);
+extern boolean_t mac_info_get(const char *, mac_info_t *);
extern uint64_t mac_stat_get(mac_handle_t, enum mac_stat);
extern int mac_start(mac_handle_t);
extern void mac_stop(mac_handle_t);
@@ -406,6 +407,7 @@ extern boolean_t mac_active_set(mac_handle_t);
extern void mac_active_clear(mac_handle_t);
extern void mac_resource_set(mac_handle_t,
mac_resource_add_t, void *);
+extern dev_info_t *mac_devinfo_get(mac_handle_t);
/*
* Driver interface functions.
@@ -425,6 +427,8 @@ extern void mac_unicst_refresh(mac_t *, mac_unicst_t,
void *);
extern void mac_promisc_refresh(mac_t *, mac_promisc_t,
void *);
+extern void mac_init_ops(struct dev_ops *, const char *);
+extern void mac_fini_ops(struct dev_ops *);
#endif /* _KERNEL */
diff --git a/usr/src/uts/common/sys/mac_impl.h b/usr/src/uts/common/sys/mac_impl.h
index a66d3693e4..0091402a28 100644
--- a/usr/src/uts/common/sys/mac_impl.h
+++ b/usr/src/uts/common/sys/mac_impl.h
@@ -30,7 +30,6 @@
#pragma ident "%Z%%M% %I% %E% SMI"
#include <sys/mac.h>
-#include <sys/ght.h>
#ifdef __cplusplus
extern "C" {
@@ -79,7 +78,6 @@ struct mac_impl_s {
uint_t mi_port;
char mi_name[MAXNAMELEN];
- ghte_t mi_hte;
uint32_t mi_ref;
boolean_t mi_destroying;
diff --git a/usr/src/uts/intel/Makefile.intel b/usr/src/uts/intel/Makefile.intel
index 96c2637ff0..c9125719cc 100644
--- a/usr/src/uts/intel/Makefile.intel
+++ b/usr/src/uts/intel/Makefile.intel
@@ -444,7 +444,6 @@ MISC_KMODS += diaudio
MISC_KMODS += dls
MISC_KMODS += fssnap_if
MISC_KMODS += gda
-MISC_KMODS += ght
MISC_KMODS += gld
MISC_KMODS += hidparser
MISC_KMODS += hpcsvc
diff --git a/usr/src/uts/intel/aggr/Makefile b/usr/src/uts/intel/aggr/Makefile
index 814c36da48..9852de4c84 100644
--- a/usr/src/uts/intel/aggr/Makefile
+++ b/usr/src/uts/intel/aggr/Makefile
@@ -56,7 +56,7 @@ INSTALL_TARGET = $(BINARY) $(ROOTMODULE) $(ROOT_CONFFILE)
# Overrides
#
CFLAGS += $(CCVERBOSE)
-LDFLAGS += -dy -Nmisc/ght -Nmisc/mac
+LDFLAGS += -dy -Ndrv/dld -Nmisc/mac
#
# Default build targets.
diff --git a/usr/src/uts/intel/bge/Makefile b/usr/src/uts/intel/bge/Makefile
index 94c2586c0b..da9c8fd16a 100644
--- a/usr/src/uts/intel/bge/Makefile
+++ b/usr/src/uts/intel/bge/Makefile
@@ -60,7 +60,7 @@ INSTALL_TARGET = $(BINARY) $(ROOTMODULE) $(ROOT_CONFFILE)
#
#
-# Driver depends on GLD & IP
+# Driver depends on MAC & IP
#
LDFLAGS += -dy -N misc/mac -N drv/ip
diff --git a/usr/src/uts/intel/dld/Makefile b/usr/src/uts/intel/dld/Makefile
index 6dd9842f4c..00cb2f7fc9 100644
--- a/usr/src/uts/intel/dld/Makefile
+++ b/usr/src/uts/intel/dld/Makefile
@@ -56,7 +56,7 @@ INSTALL_TARGET = $(BINARY) $(ROOTMODULE) $(ROOT_CONFFILE)
# Overrides
#
CFLAGS += $(CCVERBOSE)
-LDFLAGS += -dy -N misc/dls -N misc/mac -N misc/ght
+LDFLAGS += -dy -N misc/dls -N misc/mac
#
# Default build targets.
diff --git a/usr/src/uts/intel/dls/Makefile b/usr/src/uts/intel/dls/Makefile
index 741283f80f..c5acd953ce 100644
--- a/usr/src/uts/intel/dls/Makefile
+++ b/usr/src/uts/intel/dls/Makefile
@@ -54,7 +54,7 @@ INSTALL_TARGET = $(BINARY) $(ROOTMODULE)
# Overrides.
#
CFLAGS += $(CCVERBOSE)
-LDFLAGS += -dy -N misc/ght -N misc/mac
+LDFLAGS += -dy -N misc/mac
#
# Default build targets.
diff --git a/usr/src/uts/intel/ght/Makefile b/usr/src/uts/intel/ght/Makefile
deleted file mode 100644
index e0d462df78..0000000000
--- a/usr/src/uts/intel/ght/Makefile
+++ /dev/null
@@ -1,82 +0,0 @@
-#
-# 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.
-#
-# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
-# See the License for the specific language governing permissions
-# and limitations under the License.
-#
-# When distributing Covered Code, include this CDDL HEADER in each
-# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
-# If applicable, add the following below this CDDL HEADER, with the
-# fields enclosed by brackets "[]" replaced with your own identifying
-# information: Portions Copyright [yyyy] [name of copyright owner]
-#
-# CDDL HEADER END
-#
-#
-# Copyright 2005 Sun Microsystems, Inc. All rights reserved.
-# Use is subject to license terms.
-#
-#ident "%Z%%M% %I% %E% SMI"
-
-#
-# Path to the base of the uts directory tree (usually /usr/src/uts).
-#
-UTSBASE = ../..
-
-#
-# Define the module and object file sets.
-#
-MODULE = ght
-OBJECTS = $(GHT_OBJS:%=$(OBJS_DIR)/%)
-LINTS = $(GHT_OBJS:%.o=$(LINTS_DIR)/%.ln)
-ROOTMODULE = $(ROOT_MISC_DIR)/$(MODULE)
-
-#
-# Include common rules.
-#
-include $(UTSBASE)/intel/Makefile.intel
-
-#
-# Define targets
-#
-ALL_TARGET = $(BINARY)
-LINT_TARGET = $(MODULE).lint
-INSTALL_TARGET = $(BINARY) $(ROOTMODULE)
-
-#
-# Overrides.
-#
-CFLAGS += $(CCVERBOSE)
-
-#
-# Default build targets.
-#
-.KEEP_STATE:
-
-def: $(DEF_DEPS)
-
-all: $(ALL_DEPS)
-
-clean: $(CLEAN_DEPS)
-
-clobber: $(CLOBBER_DEPS)
-
-lint: $(LINT_DEPS)
-
-modlintlib: $(MODLINTLIB_DEPS)
-
-clean.lint: $(CLEAN_LINT_DEPS)
-
-install: $(INSTALL_DEPS)
-
-#
-# Include common targets.
-#
-include $(UTSBASE)/intel/Makefile.targ
diff --git a/usr/src/uts/intel/ia32/ml/modstubs.s b/usr/src/uts/intel/ia32/ml/modstubs.s
index 5d80c622fa..e0b0a92ee9 100644
--- a/usr/src/uts/intel/ia32/ml/modstubs.s
+++ b/usr/src/uts/intel/ia32/ml/modstubs.s
@@ -1129,10 +1129,22 @@ fcnname/**/_info: \
END_MODULE(sha1);
#endif
-#ifndef DLD_MODULE
+/*
+ * The following stubs are used by the mac module.
+ * Since dls and dld already depend on mac, these
+ * stubs are needed to avoid circular dependencies.
+ */
+#ifndef DLS_MODULE
+ MODULE(dls,misc);
+ STUB(dls, dls_create, nomod_einval);
+ STUB(dls, dls_destroy, nomod_einval);
+ END_MODULE(dls);
+#endif
+
+#ifndef DLD_MODULE
MODULE(dld,drv);
- STUB(dld, dld_ppa_create, nomod_einval);
- STUB(dld, dld_ppa_destroy, nomod_einval);
+ STUB(dld, dld_init_ops, nomod_void);
+ STUB(dld, dld_fini_ops, nomod_void);
END_MODULE(dld);
#endif
diff --git a/usr/src/uts/intel/mac/Makefile b/usr/src/uts/intel/mac/Makefile
index f751b380cd..8e34b910a9 100644
--- a/usr/src/uts/intel/mac/Makefile
+++ b/usr/src/uts/intel/mac/Makefile
@@ -59,7 +59,7 @@ INSTALL_TARGET = $(BINARY) $(ROOTMODULE)
# Overrides.
#
CFLAGS += $(CCVERBOSE)
-LDFLAGS += -dy -N misc/ght
+LDFLAGS += -dy
#
# Default build targets.
diff --git a/usr/src/uts/sparc/Makefile.sparc b/usr/src/uts/sparc/Makefile.sparc
index 2c43f6ac46..f2ddfb16ae 100644
--- a/usr/src/uts/sparc/Makefile.sparc
+++ b/usr/src/uts/sparc/Makefile.sparc
@@ -339,7 +339,7 @@ MISC_KMODS += ibmf
MISC_KMODS += ibtl
MISC_KMODS += ctf
MISC_KMODS += zmod
-MISC_KMODS += mac dls ght
+MISC_KMODS += mac dls
#
# Software Cryptographic Providers (/kernel/crypto):
diff --git a/usr/src/uts/sparc/aggr/Makefile b/usr/src/uts/sparc/aggr/Makefile
index f175b433cf..80e15198cc 100644
--- a/usr/src/uts/sparc/aggr/Makefile
+++ b/usr/src/uts/sparc/aggr/Makefile
@@ -56,7 +56,7 @@ INSTALL_TARGET = $(BINARY) $(ROOTMODULE) $(ROOT_CONFFILE)
# Overrides
#
CFLAGS += $(CCVERBOSE)
-LDFLAGS += -dy -N misc/ght -Nmisc/mac
+LDFLAGS += -dy -Ndrv/dld -Nmisc/mac
#
# Default build targets.
diff --git a/usr/src/uts/sparc/dld/Makefile b/usr/src/uts/sparc/dld/Makefile
index e8a29b5a5d..5e9c4a352f 100644
--- a/usr/src/uts/sparc/dld/Makefile
+++ b/usr/src/uts/sparc/dld/Makefile
@@ -58,7 +58,7 @@ INSTALL_TARGET = $(BINARY) $(ROOTMODULE) $(ROOT_CONFFILE)
CFLAGS += $(CCVERBOSE)
$(RELEASE_BUILD)CFLAGS += -xinline=auto -xcrossfile
$(RELEASE_BUILD)COPTIMIZE = -xO5
-LDFLAGS += -dy -N misc/dls -N misc/mac -N misc/ght
+LDFLAGS += -dy -N misc/dls -N misc/mac
#
# Default build targets.
diff --git a/usr/src/uts/sparc/dls/Makefile b/usr/src/uts/sparc/dls/Makefile
index 71d4ae3cab..7a11f43724 100644
--- a/usr/src/uts/sparc/dls/Makefile
+++ b/usr/src/uts/sparc/dls/Makefile
@@ -56,7 +56,7 @@ INSTALL_TARGET = $(BINARY) $(ROOTMODULE)
CFLAGS += $(CCVERBOSE)
$(RELEASE_BUILD)CFLAGS += -xinline=auto -xcrossfile
$(RELEASE_BUILD)COPTIMIZE = -xO5
-LDFLAGS += -dy -N misc/ght -N misc/mac
+LDFLAGS += -dy -N misc/mac
#
# Default build targets.
diff --git a/usr/src/uts/sparc/ght/Makefile b/usr/src/uts/sparc/ght/Makefile
deleted file mode 100644
index bd95b494f4..0000000000
--- a/usr/src/uts/sparc/ght/Makefile
+++ /dev/null
@@ -1,84 +0,0 @@
-#
-# 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.
-#
-# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
-# or http://www.opensolaris.org/os/licensing.
-# See the License for the specific language governing permissions
-# and limitations under the License.
-#
-# When distributing Covered Code, include this CDDL HEADER in each
-# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
-# If applicable, add the following below this CDDL HEADER, with the
-# fields enclosed by brackets "[]" replaced with your own identifying
-# information: Portions Copyright [yyyy] [name of copyright owner]
-#
-# CDDL HEADER END
-#
-#
-# Copyright 2005 Sun Microsystems, Inc. All rights reserved.
-# Use is subject to license terms.
-#
-#ident "%Z%%M% %I% %E% SMI"
-
-#
-# Path to the base of the uts directory tree (usually /usr/src/uts).
-#
-UTSBASE = ../..
-
-#
-# Define the module and object file sets.
-#
-MODULE = ght
-OBJECTS = $(GHT_OBJS:%=$(OBJS_DIR)/%)
-LINTS = $(GHT_OBJS:%.o=$(LINTS_DIR)/%.ln)
-ROOTMODULE = $(ROOT_MISC_DIR)/$(MODULE)
-
-#
-# Include common rules.
-#
-include $(UTSBASE)/sparc/Makefile.sparc
-
-#
-# Define targets
-#
-ALL_TARGET = $(BINARY)
-LINT_TARGET = $(MODULE).lint
-INSTALL_TARGET = $(BINARY) $(ROOTMODULE)
-
-#
-# Overrides.
-#
-CFLAGS += $(CCVERBOSE)
-$(RELEASE_BUILD)CFLAGS += -xinline=auto
-$(RELEASE_BUILD)COPTIMIZE = -xO5
-
-#
-# Default build targets.
-#
-.KEEP_STATE:
-
-def: $(DEF_DEPS)
-
-all: $(ALL_DEPS)
-
-clean: $(CLEAN_DEPS)
-
-clobber: $(CLOBBER_DEPS)
-
-lint: $(LINT_DEPS)
-
-modlintlib: $(MODLINTLIB_DEPS)
-
-clean.lint: $(CLEAN_LINT_DEPS)
-
-install: $(INSTALL_DEPS)
-
-#
-# Include common targets.
-#
-include $(UTSBASE)/sparc/Makefile.targ
diff --git a/usr/src/uts/sparc/mac/Makefile b/usr/src/uts/sparc/mac/Makefile
index a3c6814f0a..ecf5b2cfa2 100644
--- a/usr/src/uts/sparc/mac/Makefile
+++ b/usr/src/uts/sparc/mac/Makefile
@@ -62,7 +62,7 @@ INSTALL_TARGET = $(BINARY) $(ROOTMODULE)
CFLAGS += $(CCVERBOSE)
$(RELEASE_BUILD)CFLAGS += -xinline=auto -xcrossfile
$(RELEASE_BUILD)COPTIMIZE = -xO5
-LDFLAGS += -dy -N misc/ght
+LDFLAGS += -dy
#
# Default build targets.
diff --git a/usr/src/uts/sparc/ml/modstubs.s b/usr/src/uts/sparc/ml/modstubs.s
index 304a320d31..9594335f33 100644
--- a/usr/src/uts/sparc/ml/modstubs.s
+++ b/usr/src/uts/sparc/ml/modstubs.s
@@ -1082,10 +1082,22 @@ stubs_base:
END_MODULE(sha1);
#endif
-#ifndef DLD_MODULE
+/*
+ * The following stubs are used by the mac module.
+ * Since dls and dld already depend on mac, these
+ * stubs are needed to avoid circular dependencies.
+ */
+#ifndef DLS_MODULE
+ MODULE(dls,misc);
+ STUB(dls, dls_create, nomod_einval);
+ STUB(dls, dls_destroy, nomod_einval);
+ END_MODULE(dls);
+#endif
+
+#ifndef DLD_MODULE
MODULE(dld,drv);
- STUB(dld, dld_ppa_create, nomod_einval);
- STUB(dld, dld_ppa_destroy, nomod_einval);
+ STUB(dld, dld_init_ops, nomod_void);
+ STUB(dld, dld_fini_ops, nomod_void);
END_MODULE(dld);
#endif