summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorseb <none@none>2006-06-30 12:39:57 -0700
committerseb <none@none>2006-06-30 12:39:57 -0700
commitba2e4443695ee6a6f420a35cd4fc3d3346d22932 (patch)
treee3ebae9aaeecabfd5304f958583c09efb9b861c4
parent17e9c21c2c124e74a7e4a7cd9fcaa3f2d31b7069 (diff)
downloadillumos-gate-ba2e4443695ee6a6f420a35cd4fc3d3346d22932.tar.gz
PSARC/2006/248 Nemo MAC-Type Plugin Architecture
PSARC/2006/249 Nemo Changes for Binary Compatibility 6226635 MAC stats interface could cause problems with binary compatibility 6242059 nemo drivers must not know the size of the mac_t structure 6384371 GLDv3 only supports Ethernet 6401695 xge uses a receive ring even though it doesn't do blanking 6432471 panic in dls_close() if DL_BIND_REQ previously failed
-rw-r--r--usr/src/cmd/dladm/dladm.c213
-rw-r--r--usr/src/cmd/rcm_daemon/common/network_rcm.c11
-rw-r--r--usr/src/lib/libdladm/common/libdladm.c16
-rw-r--r--usr/src/lib/libdladm/common/libdladm.h8
-rw-r--r--usr/src/lib/liblaadm/common/liblaadm.c45
-rw-r--r--usr/src/lib/liblaadm/common/liblaadm.h9
-rw-r--r--usr/src/pkgdefs/SUNWckr/prototype_com1
-rw-r--r--usr/src/pkgdefs/SUNWckr/prototype_i3863
-rw-r--r--usr/src/pkgdefs/SUNWckr/prototype_sparc2
-rw-r--r--usr/src/tools/scripts/bfu.sh39
-rw-r--r--usr/src/uts/Makefile.targ3
-rw-r--r--usr/src/uts/Makefile.uts9
-rw-r--r--usr/src/uts/common/Makefile.files2
-rw-r--r--usr/src/uts/common/Makefile.rules7
-rw-r--r--usr/src/uts/common/io/aggr/aggr_ctl.c12
-rw-r--r--usr/src/uts/common/io/aggr/aggr_grp.c299
-rw-r--r--usr/src/uts/common/io/aggr/aggr_lacp.c203
-rw-r--r--usr/src/uts/common/io/aggr/aggr_port.c47
-rw-r--r--usr/src/uts/common/io/aggr/aggr_recv.c22
-rw-r--r--usr/src/uts/common/io/bge/bge_chip2.c4
-rw-r--r--usr/src/uts/common/io/bge/bge_kstats.c307
-rw-r--r--usr/src/uts/common/io/bge/bge_main2.c116
-rw-r--r--usr/src/uts/common/io/bge/bge_recv2.c2
-rw-r--r--usr/src/uts/common/io/bge/bge_send.c2
-rw-r--r--usr/src/uts/common/io/dld/dld_drv.c15
-rw-r--r--usr/src/uts/common/io/dld/dld_proto.c67
-rw-r--r--usr/src/uts/common/io/dld/dld_str.c184
-rw-r--r--usr/src/uts/common/io/dls/dls.c350
-rw-r--r--usr/src/uts/common/io/dls/dls_link.c329
-rw-r--r--usr/src/uts/common/io/dls/dls_stat.c76
-rw-r--r--usr/src/uts/common/io/dls/dls_vlan.c61
-rw-r--r--usr/src/uts/common/io/mac/mac.c1025
-rw-r--r--usr/src/uts/common/io/mac/mac_stat.c224
-rw-r--r--usr/src/uts/common/io/mac/plugins/mac_ether.c278
-rwxr-xr-xusr/src/uts/common/io/rge/rge.h12
-rwxr-xr-xusr/src/uts/common/io/rge/rge_chip.c9
-rwxr-xr-xusr/src/uts/common/io/rge/rge_kstats.c153
-rwxr-xr-xusr/src/uts/common/io/rge/rge_main.c147
-rwxr-xr-xusr/src/uts/common/io/rge/rge_rxtx.c11
-rw-r--r--usr/src/uts/common/io/xge/drv/xge.c2
-rw-r--r--usr/src/uts/common/io/xge/drv/xgell.c301
-rw-r--r--usr/src/uts/common/io/xge/drv/xgell.h11
-rw-r--r--usr/src/uts/common/sys/aggr.h9
-rw-r--r--usr/src/uts/common/sys/aggr_impl.h18
-rw-r--r--usr/src/uts/common/sys/bge_impl2.h5
-rw-r--r--usr/src/uts/common/sys/dld.h9
-rw-r--r--usr/src/uts/common/sys/dld_impl.h5
-rw-r--r--usr/src/uts/common/sys/dls.h33
-rw-r--r--usr/src/uts/common/sys/dls_impl.h30
-rw-r--r--usr/src/uts/common/sys/mac.h458
-rw-r--r--usr/src/uts/common/sys/mac_ether.h157
-rw-r--r--usr/src/uts/common/sys/mac_impl.h84
-rw-r--r--usr/src/uts/intel/Makefile.intel.shared5
-rw-r--r--usr/src/uts/intel/mac_ether/Makefile87
-rw-r--r--usr/src/uts/sparc/Makefile.sparc.shared5
-rw-r--r--usr/src/uts/sparc/mac_ether/Makefile87
-rw-r--r--usr/src/uts/sun4v/io/vnet.c210
-rw-r--r--usr/src/uts/sun4v/io/vnet_gen.c221
-rw-r--r--usr/src/uts/sun4v/io/vsw.c167
-rw-r--r--usr/src/uts/sun4v/sys/vnet.h4
-rw-r--r--usr/src/uts/sun4v/sys/vnet_gen.h4
-rw-r--r--usr/src/uts/sun4v/sys/vsw.h8
62 files changed, 3472 insertions, 2771 deletions
diff --git a/usr/src/cmd/dladm/dladm.c b/usr/src/cmd/dladm/dladm.c
index 540de6d23c..1167cb1603 100644
--- a/usr/src/cmd/dladm/dladm.c
+++ b/usr/src/cmd/dladm/dladm.c
@@ -44,7 +44,7 @@
#include <liblaadm.h>
#include <libmacadm.h>
-#define AGGR_DEV "aggr0"
+#define AGGR_DRV "aggr"
#define MAXPORT 256
#define DUMP_LACP_FORMAT " %-9s %-8s %-7s %-12s " \
"%-5s %-4s %-4s %-9s %-7s\n"
@@ -110,11 +110,11 @@ static void link_stats(const char *, uint32_t);
static void aggr_stats(uint16_t, uint32_t);
static void dev_stats(const char *dev, uint32_t);
-static void get_mac_stats(const char *, uint_t, pktsum_t *);
+static void get_mac_stats(const char *, pktsum_t *);
static void get_link_stats(const char *, pktsum_t *);
-static uint64_t mac_ifspeed(const char *, uint_t);
-static char *mac_link_state(const char *, uint_t);
-static char *mac_link_duplex(const char *, uint_t);
+static uint64_t mac_ifspeed(const char *);
+static char *mac_link_state(const char *);
+static char *mac_link_duplex(const char *);
static void stats_total(pktsum_t *, pktsum_t *, pktsum_t *);
static void stats_diff(pktsum_t *, pktsum_t *, pktsum_t *);
@@ -261,8 +261,6 @@ do_create_aggr(int argc, char *argv[])
exit(1);
}
- port[nport].lp_port = 0;
-
nport++;
break;
case 'P':
@@ -471,8 +469,6 @@ do_add_aggr(int argc, char *argv[])
progname);
exit(1);
}
- port[nport].lp_port = 0;
-
nport++;
break;
case 't':
@@ -561,8 +557,6 @@ do_remove_aggr(int argc, char *argv[])
progname);
exit(1);
}
- port[nport].lp_port = 0;
-
nport++;
break;
case 't':
@@ -834,15 +828,20 @@ print_link_parseable(const char *name, dladm_attr_t *dap, boolean_t legacy)
char type[TYPE_WIDTH];
if (!legacy) {
+ char drv[LIFNAMSIZ];
+ int instance;
+
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) {
+ if (dlpi_if_parse(dap->da_dev, drv, &instance) != 0)
+ return;
+ if (strncmp(drv, AGGR_DRV, sizeof (AGGR_DRV)) == 0) {
(void) printf("%s type=%s mtu=%d key=%u\n",
- name, type, dap->da_max_sdu, dap->da_port);
+ name, type, dap->da_max_sdu, instance);
} else {
(void) printf("%s type=%s mtu=%d device=%s\n",
name, type, dap->da_max_sdu, dap->da_dev);
@@ -859,16 +858,21 @@ print_link(const char *name, dladm_attr_t *dap, boolean_t legacy)
char type[TYPE_WIDTH];
if (!legacy) {
+ char drv[LIFNAMSIZ];
+ int instance;
+
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) {
+ if (dlpi_if_parse(dap->da_dev, drv, &instance) != 0)
+ return;
+ if (strncmp(drv, AGGR_DRV, sizeof (AGGR_DRV)) == 0) {
(void) printf(gettext("%-9s\ttype: %s\tmtu: %d"
"\taggregation: key %u\n"), name, type,
- dap->da_max_sdu, dap->da_port);
+ dap->da_max_sdu, instance);
} else {
(void) printf(gettext("%-9s\ttype: %s\tmtu: "
"%d\tdevice: %s\n"), name, type, dap->da_max_sdu,
@@ -1058,25 +1062,24 @@ static void
dump_port(laadm_port_attr_sys_t *port, boolean_t parseable)
{
char *dev = port->lp_devname;
- uint_t portnum = port->lp_port;
char buf[ETHERADDRL * 3];
if (!parseable) {
(void) printf(" %-9s\t%s", dev, laadm_mac_addr_to_str(
port->lp_mac, buf));
- (void) printf("\t %-5u Mbps", (int)(mac_ifspeed(dev, portnum) /
+ (void) printf("\t %-5u Mbps", (int)(mac_ifspeed(dev) /
1000000ull));
- (void) printf("\t%s", mac_link_duplex(dev, portnum));
- (void) printf("\t%s", mac_link_state(dev, portnum));
+ (void) printf("\t%s", mac_link_duplex(dev));
+ (void) printf("\t%s", mac_link_state(dev));
(void) printf("\t%s\n", port_state_to_str(port->lp_state));
} else {
(void) printf(" device=%s address=%s", dev,
laadm_mac_addr_to_str(port->lp_mac, buf));
- (void) printf(" speed=%u", (int)(mac_ifspeed(dev, portnum) /
+ (void) printf(" speed=%u", (int)(mac_ifspeed(dev) /
1000000ull));
- (void) printf(" duplex=%s", mac_link_duplex(dev, portnum));
- (void) printf(" link=%s", mac_link_state(dev, portnum));
+ (void) printf(" duplex=%s", mac_link_duplex(dev));
+ (void) printf(" link=%s", mac_link_state(dev));
(void) printf(" port=%s", port_state_to_str(port->lp_state));
}
}
@@ -1153,8 +1156,7 @@ show_key(void *arg, laadm_grp_attr_sys_t *grp)
/* sum the ports statistics */
bzero(&pktsumtot, sizeof (pktsumtot));
for (i = 0; i < grp->lg_nports; i++) {
- get_mac_stats(grp->lg_ports[i].lp_devname,
- grp->lg_ports[i].lp_port, &port_stat);
+ get_mac_stats(grp->lg_ports[i].lp_devname, &port_stat);
stats_total(&pktsumtot, &port_stat,
&state->gs_prevstats[i]);
}
@@ -1166,8 +1168,7 @@ show_key(void *arg, laadm_grp_attr_sys_t *grp)
(void) printf("%-12llu\n", pktsumtot.obytes);
for (i = 0; i < grp->lg_nports; i++) {
- get_mac_stats(grp->lg_ports[i].lp_devname,
- grp->lg_ports[i].lp_port, &port_stat);
+ get_mac_stats(grp->lg_ports[i].lp_devname, &port_stat);
(void) printf(" %s", grp->lg_ports[i].lp_devname);
dump_port_stat(i, state, &port_stat, &pktsumtot);
}
@@ -1228,16 +1229,16 @@ show_dev(void *arg, const char *dev)
if (!state->ms_parseable) {
(void) printf(gettext("\t\tlink: %s"),
- mac_link_state(dev, 0));
+ mac_link_state(dev));
(void) printf(gettext("\tspeed: %-5u Mbps"),
- (unsigned int)(mac_ifspeed(dev, 0) / 1000000ull));
+ (unsigned int)(mac_ifspeed(dev) / 1000000ull));
(void) printf(gettext("\tduplex: %s\n"),
- mac_link_duplex(dev, 0));
+ mac_link_duplex(dev));
} else {
- (void) printf(" link=%s", mac_link_state(dev, 0));
+ (void) printf(" link=%s", mac_link_state(dev));
(void) printf(" speed=%u",
- (unsigned int)(mac_ifspeed(dev, 0) / 1000000ull));
- (void) printf(" duplex=%s\n", mac_link_duplex(dev, 0));
+ (unsigned int)(mac_ifspeed(dev) / 1000000ull));
+ (void) printf(" duplex=%s\n", mac_link_duplex(dev));
}
}
@@ -1256,7 +1257,7 @@ show_dev_stats(void *arg, const char *dev)
bzero(&state->ms_prevstats, sizeof (state->ms_prevstats));
}
- get_mac_stats(dev, 0, &stats);
+ get_mac_stats(dev, &stats);
stats_diff(&diff_stats, &stats, &state->ms_prevstats);
(void) printf("%s", dev);
@@ -1737,14 +1738,12 @@ stats_diff(pktsum_t *s1, pktsum_t *s2, pktsum_t *s3)
}
/*
- * In the following routines, we do the first kstat_lookup()
- * assuming that the device is gldv3-based and that the kstat
- * name is of the format <driver_name><instance>/<port>. If the
- * lookup fails, we redo the kstat_lookup() using the kstat name
- * <driver_name><instance>. This second lookup is needed for
- * getting kstats from legacy devices. This can fail too if the
- * device is not attached or the device is legacy and doesn't
- * export the kstats we need.
+ * In the following routines, we do the first kstat_lookup() assuming that
+ * the device is gldv3-based and that the kstat name is the one passed in
+ * as the "name" argument. If the lookup fails, we redo the kstat_lookup()
+ * omitting the kstat name. This second lookup is needed for getting kstats
+ * from legacy devices. This can fail too if the device is not attached or
+ * the device is legacy and doesn't export the kstats we need.
*/
static void
get_stats(char *module, int instance, char *name, pktsum_t *stats)
@@ -1760,8 +1759,7 @@ get_stats(char *module, int instance, char *name, pktsum_t *stats)
}
if ((ksp = kstat_lookup(kcp, module, instance, name)) == NULL &&
- (module == NULL ||
- (ksp = kstat_lookup(kcp, NULL, -1, module)) == NULL)) {
+ (ksp = kstat_lookup(kcp, module, instance, NULL)) == NULL) {
/*
* The kstat query could fail if the underlying MAC
* driver was already detached.
@@ -1801,49 +1799,53 @@ get_stats(char *module, int instance, char *name, pktsum_t *stats)
return;
bail:
- (void) fprintf(stderr,
- gettext("%s: kstat operation failed\n"),
- progname);
(void) kstat_close(kcp);
}
static void
-get_mac_stats(const char *dev, uint_t port, pktsum_t *stats)
+get_mac_stats(const char *dev, pktsum_t *stats)
{
- char name[MAXNAMELEN];
+ char module[LIFNAMSIZ];
+ int instance;
+ if (dlpi_if_parse(dev, module, &instance) != 0)
+ return;
bzero(stats, sizeof (*stats));
-
- (void) snprintf(name, MAXNAMELEN - 1, "%s/%u", dev, port);
- get_stats((char *)dev, 0, name, stats);
+ get_stats(module, instance, "mac", stats);
}
static void
get_link_stats(const char *link, pktsum_t *stats)
{
+ char module[LIFNAMSIZ];
+ int instance;
+
+ if (dlpi_if_parse(link, module, &instance) != 0)
+ return;
bzero(stats, sizeof (*stats));
- get_stats(NULL, -1, (char *)link, stats);
+ get_stats(module, instance, (char *)link, stats);
}
-static uint64_t
-mac_ifspeed(const char *dev, uint_t port)
+static int
+get_single_mac_stat(const char *dev, const char *name, uint8_t type,
+ void *val)
{
- char name[MAXNAMELEN];
+ char module[LIFNAMSIZ];
+ int instance;
kstat_ctl_t *kcp;
kstat_t *ksp;
- uint64_t ifspeed = 0;
if ((kcp = kstat_open()) == NULL) {
(void) fprintf(stderr,
gettext("%s: kstat open operation failed\n"),
progname);
- return (0);
+ return (-1);
}
- (void) snprintf(name, MAXNAMELEN - 1, "%s/%u", dev, port);
- if ((ksp = kstat_lookup(kcp, (char *)dev, -1, name)) == NULL &&
- (ksp = kstat_lookup(kcp, NULL, -1, (char *)dev)) == NULL) {
-
+ if (dlpi_if_parse(dev, module, &instance) != 0)
+ return (-1);
+ if ((ksp = kstat_lookup(kcp, module, instance, "mac")) == NULL &&
+ (ksp = kstat_lookup(kcp, module, instance, NULL)) == NULL) {
/*
* The kstat query could fail if the underlying MAC
* driver was already detached.
@@ -1858,57 +1860,37 @@ mac_ifspeed(const char *dev, uint_t port)
goto bail;
}
- if (kstat_value(ksp, "ifspeed", KSTAT_DATA_UINT64, &ifspeed) < 0) {
- (void) fprintf(stderr,
- gettext("%s: kstat value failed\n"),
- progname);
+ if (kstat_value(ksp, name, type, val) < 0)
goto bail;
- }
+
+ (void) kstat_close(kcp);
+ return (0);
bail:
(void) kstat_close(kcp);
+ return (-1);
+}
+
+static uint64_t
+mac_ifspeed(const char *dev)
+{
+ uint64_t ifspeed = 0;
+
+ (void) get_single_mac_stat(dev, "ifspeed", KSTAT_DATA_UINT64, &ifspeed);
return (ifspeed);
}
static char *
-mac_link_state(const char *dev, uint_t port)
+mac_link_state(const char *dev)
{
- char name[MAXNAMELEN];
- kstat_ctl_t *kcp;
- kstat_t *ksp;
link_state_t link_state;
char *state_str = "unknown";
- if ((kcp = kstat_open()) == NULL) {
- (void) fprintf(stderr,
- gettext("%s: kstat open operation failed\n"),
- progname);
+ if (get_single_mac_stat(dev, "link_state", KSTAT_DATA_UINT32,
+ &link_state) != 0) {
return (state_str);
}
- (void) snprintf(name, MAXNAMELEN - 1, "%s/%u", dev, port);
-
- if ((ksp = kstat_lookup(kcp, (char *)dev, -1, name)) == NULL &&
- (ksp = kstat_lookup(kcp, NULL, -1, (char *)dev)) == NULL) {
- /*
- * The kstat query could fail if the underlying MAC
- * driver was already detached.
- */
- goto bail;
- }
-
- if (kstat_read(kcp, ksp, NULL) == -1) {
- (void) fprintf(stderr,
- gettext("%s: kstat read failed\n"),
- progname);
- goto bail;
- }
-
- if (kstat_value(ksp, "link_state", KSTAT_DATA_UINT32,
- &link_state) < 0) {
- goto bail;
- }
-
switch (link_state) {
case LINK_STATE_UP:
state_str = "up";
@@ -1920,50 +1902,21 @@ mac_link_state(const char *dev, uint_t port)
break;
}
-bail:
- (void) kstat_close(kcp);
return (state_str);
}
static char *
-mac_link_duplex(const char *dev, uint_t port)
+mac_link_duplex(const char *dev)
{
- char name[MAXNAMELEN];
- kstat_ctl_t *kcp;
- kstat_t *ksp;
link_duplex_t link_duplex;
char *duplex_str = "unknown";
- if ((kcp = kstat_open()) == NULL) {
- (void) fprintf(stderr,
- gettext("%s: kstat open operation failed\n"),
- progname);
+ if (get_single_mac_stat(dev, "link_duplex", KSTAT_DATA_UINT32,
+ &link_duplex) != 0) {
return (duplex_str);
}
- (void) snprintf(name, MAXNAMELEN - 1, "%s/%u", dev, port);
-
- if ((ksp = kstat_lookup(kcp, (char *)dev, -1, name)) == NULL &&
- (ksp = kstat_lookup(kcp, NULL, -1, (char *)dev)) == NULL) {
- /*
- * The kstat query could fail if the underlying MAC
- * driver was already detached.
- */
- goto bail;
- }
-
- if (kstat_read(kcp, ksp, NULL) == -1) {
- (void) fprintf(stderr,
- gettext("%s: kstat read failed\n"),
- progname);
- goto bail;
- }
-
- if (kstat_value(ksp, "link_duplex", KSTAT_DATA_UINT32,
- &link_duplex) < 0) {
- goto bail;
- }
switch (link_duplex) {
case LINK_DUPLEX_FULL:
duplex_str = "full";
@@ -1975,7 +1928,5 @@ mac_link_duplex(const char *dev, uint_t port)
break;
}
-bail:
- (void) kstat_close(kcp);
return (duplex_str);
}
diff --git a/usr/src/cmd/rcm_daemon/common/network_rcm.c b/usr/src/cmd/rcm_daemon/common/network_rcm.c
index 1c94cb5aca..f933a96ba8 100644
--- a/usr/src/cmd/rcm_daemon/common/network_rcm.c
+++ b/usr/src/cmd/rcm_daemon/common/network_rcm.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -761,8 +760,8 @@ aggr_walker(void *arg, laadm_grp_attr_sys_t *grp)
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);
+ rcm_log_message(RCM_TRACE1, "MAC: aggr (%d) port %s\n",
+ grp->lg_key, port->lp_devname);
if (strcmp(port->lp_devname, state->dev_name) != 0)
continue;
diff --git a/usr/src/lib/libdladm/common/libdladm.c b/usr/src/lib/libdladm/common/libdladm.c
index 16b95f3635..679368a9ae 100644
--- a/usr/src/lib/libdladm/common/libdladm.c
+++ b/usr/src/lib/libdladm/common/libdladm.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -86,7 +85,6 @@ i_dladm_info(int fd, const char *name, dladm_attr_t *dap)
(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;
return (0);
@@ -214,13 +212,7 @@ dladm_walk_vlan(void (*fn)(void *, const char *), void *arg, const char *name)
if ((iocp = (dld_ioc_vlan_t *)calloc(1, bufsize)) == NULL)
return (-1);
- if (strncmp(name, "aggr", 4) == 0) {
- (void) strlcpy((char *)iocp->div_name, "aggr0", IFNAMSIZ);
- iocp->div_port = atoi(strpbrk(name, "0123456789"));
- } else {
- (void) strlcpy((char *)iocp->div_name, name, IFNAMSIZ);
- iocp->div_port = 0;
- }
+ (void) strlcpy((char *)iocp->div_name, name, IFNAMSIZ);
if (i_dladm_ioctl(fd, DLDIOCVLAN, iocp, bufsize) == 0) {
dvip = (dld_vlan_info_t *)(iocp + 1);
for (i = 0; i < iocp->div_count; i++)
diff --git a/usr/src/lib/libdladm/common/libdladm.h b/usr/src/lib/libdladm/common/libdladm.h
index 5312aa9196..64315da820 100644
--- a/usr/src/lib/libdladm/common/libdladm.h
+++ b/usr/src/lib/libdladm/common/libdladm.h
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -42,7 +41,6 @@ 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;
};
diff --git a/usr/src/lib/liblaadm/common/liblaadm.c b/usr/src/lib/liblaadm/common/liblaadm.c
index 11004c78ea..0beeee27da 100644
--- a/usr/src/lib/liblaadm/common/liblaadm.c
+++ b/usr/src/lib/liblaadm/common/liblaadm.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -58,7 +57,7 @@
* <nports> ::= <number>
* <ports> ::= <port> <m-port>*
* <m-port> ::= ',' <port>
- * <port> ::= <devname> '/' <port-num>
+ * <port> ::= <devname>
* <devname> ::= <string>
* <port-num> ::= <number>
* <policy> ::= <pol-level> <m-pol>*
@@ -328,7 +327,6 @@ tryagain:
bcopy(port->lp_devname, attr.lg_ports[j].lp_devname,
MAXNAMELEN + 1);
- attr.lg_ports[j].lp_port = port->lp_port;
bcopy(port->lp_mac, attr.lg_ports[j].lp_mac,
ETHERADDRL);
attr.lg_ports[j].lp_state = port->lp_state;
@@ -401,26 +399,22 @@ i_laadm_parse_db(char *line, laadm_grp_attr_db_t *attr)
goto failed;
for (i = 0; i < attr->lt_nports; i++) {
- char *where, *ptoken;
+ char *where, *devname;
/* port */
if ((token = strtok_r(NULL, ", \t\n", &lasts)) == NULL)
goto failed;
- /* device name */
- if ((ptoken = strtok_r(token, "/", &where)) == NULL)
+ /*
+ * device name: In a previous version of this file, a port
+ * number could be specified using <devname>/<portnum>.
+ * This syntax is unecessary and obsolete.
+ */
+ if ((devname = strtok_r(token, "/", &where)) == NULL)
goto failed;
- if (strlcpy(attr->lt_ports[i].lp_devname, ptoken,
+ if (strlcpy(attr->lt_ports[i].lp_devname, devname,
MAXNAMELEN) >= MAXNAMELEN)
goto failed;
-
- /* port number */
- errno = 0;
- value = (int)strtol(token + strlen(ptoken) + 1, &endp, 10);
- if (errno != 0 || *endp != '\0')
- goto failed;
-
- attr->lt_ports[i].lp_port = value;
}
/* unicast MAC address */
@@ -530,7 +524,6 @@ i_laadm_add_rem_sys(laadm_grp_attr_db_t *attr, int cmd, laadm_diag_t *diag)
attr->lt_ports[i].lp_devname,
MAXNAMELEN) >= MAXNAMELEN)
goto failed;
- ports[i].lp_port = attr->lt_ports[i].lp_port;
}
if ((fd = open(LAADM_DEV, O_RDWR)) < 0) {
@@ -625,7 +618,6 @@ i_laadm_create_sys(int fd, laadm_grp_attr_db_t *attr, laadm_diag_t *diag)
free(iocp);
return (-1);
}
- ports[i].lp_port = attr->lt_ports[i].lp_port;
}
if (attr->lt_mac_fixed &&
@@ -1032,10 +1024,8 @@ i_laadm_add_db_fn(void *arg, laadm_grp_attr_db_t *grp)
/* are any of the ports to be added already members of the group? */
for (i = 0; i < grp->lt_nports; i++) {
for (j = 0; j < attr->lt_nports; j++) {
- if ((strcmp(grp->lt_ports[i].lp_devname,
- attr->lt_ports[j].lp_devname) == 0) &&
- (grp->lt_ports[i].lp_port ==
- attr->lt_ports[j].lp_port)) {
+ if (strcmp(grp->lt_ports[i].lp_devname,
+ attr->lt_ports[j].lp_devname) == 0) {
errno = EEXIST;
return (-1);
}
@@ -1112,9 +1102,7 @@ i_laadm_remove_db_fn(void *arg, laadm_grp_attr_db_t *grp)
match = B_FALSE;
for (j = 0; j < attr->lt_nports && !match; j++) {
match = (strcmp(grp->lt_ports[i].lp_devname,
- attr->lt_ports[j].lp_devname) == 0) &&
- (grp->lt_ports[i].lp_port ==
- attr->lt_ports[j].lp_port);
+ attr->lt_ports[j].lp_devname) == 0);
}
if (match)
nremoved++;
@@ -1370,8 +1358,7 @@ i_laadm_fput_grp(FILE *fp, laadm_grp_attr_db_t *attr)
for (i = 0; i < attr->lt_nports; i++) {
if (i > 0)
FPRINTF_ERR(fprintf(fp, ","));
- FPRINTF_ERR(fprintf(fp, "%s/%d", attr->lt_ports[i].lp_devname,
- attr->lt_ports[i].lp_port));
+ FPRINTF_ERR(fprintf(fp, "%s", attr->lt_ports[i].lp_devname));
}
FPRINTF_ERR(fprintf(fp, "\t"));
diff --git a/usr/src/lib/liblaadm/common/liblaadm.h b/usr/src/lib/liblaadm/common/liblaadm.h
index 0770892346..009c307c7f 100644
--- a/usr/src/lib/liblaadm/common/liblaadm.h
+++ b/usr/src/lib/liblaadm/common/liblaadm.h
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -48,12 +47,10 @@ extern "C" {
typedef struct laadm_port_attr_db {
char lp_devname[MAXNAMELEN + 1];
- uint32_t lp_port;
} laadm_port_attr_db_t;
typedef struct laadm_port_attr_sys {
char lp_devname[MAXNAMELEN + 1];
- uint32_t lp_port;
uchar_t lp_mac[ETHERADDRL];
aggr_port_state_t lp_state;
aggr_lacp_state_t lp_lacp_state;
diff --git a/usr/src/pkgdefs/SUNWckr/prototype_com b/usr/src/pkgdefs/SUNWckr/prototype_com
index d8606e2323..bb9644c646 100644
--- a/usr/src/pkgdefs/SUNWckr/prototype_com
+++ b/usr/src/pkgdefs/SUNWckr/prototype_com
@@ -119,6 +119,7 @@ f none kernel/drv/wc.conf 644 root sys
d none kernel/exec 755 root sys
d none kernel/fs 755 root sys
d none kernel/ipp 755 root sys
+d none kernel/mac 755 root sys
d none kernel/misc 755 root sys
d none kernel/sched 755 root sys
d none kernel/strmod 755 root sys
diff --git a/usr/src/pkgdefs/SUNWckr/prototype_i386 b/usr/src/pkgdefs/SUNWckr/prototype_i386
index 172f7d9c30..7602e51f64 100644
--- a/usr/src/pkgdefs/SUNWckr/prototype_i386
+++ b/usr/src/pkgdefs/SUNWckr/prototype_i386
@@ -147,6 +147,7 @@ f none kernel/genunix 755 root sys
f none kernel/ipp/ipgpc 755 root sys
d none boot/acpi 755 root sys
d none boot/acpi/tables 755 root sys
+f none kernel/mac/mac_ether 755 root sys
f none kernel/misc/acpica 755 root sys
f none kernel/misc/busra 755 root sys
f none kernel/misc/cardbus 755 root sys
@@ -316,6 +317,8 @@ f none kernel/fs/amd64/tmpfs 755 root sys
f none kernel/fs/amd64/ufs 755 root sys
d none kernel/ipp/amd64 755 root sys
f none kernel/ipp/amd64/ipgpc 755 root sys
+d none kernel/mac/amd64 755 root sys
+f none kernel/mac/amd64/mac_ether 755 root sys
d none kernel/misc/amd64 755 root sys
f none kernel/misc/amd64/acpica 755 root sys
f none kernel/misc/amd64/busra 755 root sys
diff --git a/usr/src/pkgdefs/SUNWckr/prototype_sparc b/usr/src/pkgdefs/SUNWckr/prototype_sparc
index 96db5abb16..722e4eb7d2 100644
--- a/usr/src/pkgdefs/SUNWckr/prototype_sparc
+++ b/usr/src/pkgdefs/SUNWckr/prototype_sparc
@@ -153,6 +153,8 @@ f none kernel/fs/sparcv9/tmpfs 755 root sys
f none kernel/fs/sparcv9/ufs 755 root sys
d none kernel/ipp/sparcv9 755 root sys
f none kernel/ipp/sparcv9/ipgpc 755 root sys
+d none kernel/mac/sparcv9 755 root sys
+f none kernel/mac/sparcv9/mac_ether 755 root sys
d none kernel/misc/sparcv9 755 root sys
f none kernel/misc/sparcv9/busra 755 root sys
f none kernel/misc/sparcv9/cardbus 755 root sys
diff --git a/usr/src/tools/scripts/bfu.sh b/usr/src/tools/scripts/bfu.sh
index e8d51720b8..c487a85fba 100644
--- a/usr/src/tools/scripts/bfu.sh
+++ b/usr/src/tools/scripts/bfu.sh
@@ -2507,6 +2507,23 @@ create_datalink_conf()
rm -f /tmp/ifnames.$$
}
+revert_aggregation_conf()
+{
+ aggrconf=$rootprefix/etc/aggregation.conf
+ nawk '
+ /^[ \t]*#/ || /^[ \t]*$/ {
+ print;
+ next;
+ }
+
+ {
+ OFS="\t";
+ gsub(/[^,]*/, "&/0", $4);
+ print;
+ }' $aggrconf > $aggrconf.bfutmp
+ mv -f $aggrconf.bfutmp $aggrconf
+}
+
remove_initd_links()
{
# If we're delivering a new version of an existing /etc/init.d script,
@@ -6019,6 +6036,19 @@ mondo_loop() {
rm -f $usr/lib/sparcv9/librac.so
rm -f $usr/lib/sparcv9/librac.so.1
+ #
+ # Remove /kernel/mac. This directory was introduced by
+ # PSARC/2006/248, and along with this came a syntax change to the
+ # /etc/aggregation.conf file. After archives have been extracted,
+ # we check for the existance of the /kernel/mac directory to see if
+ # we're doing a backward bfu and need to convert the syntax of the
+ # /etc/aggregation.conf file to its old format.
+ #
+ if [ -d $root/kernel/mac ]; then
+ from_new_aggrconf=1
+ rm -rf $root/kernel/mac;
+ fi
+
# End of pre-archive extraction hacks.
if [ $diskless = no -a $zone = global ]; then
@@ -6390,6 +6420,15 @@ mondo_loop() {
print "copying the corresponding file from the global zone.\n"
else
fixup_mpxio
+
+ #
+ # If we're bfuing backward across PSARC/2006/248, then
+ # revert the /etc/aggregation.conf to its old format.
+ #
+ if [ -f $rootprefix/etc/aggregation.conf -a \
+ ! -d $rootprefix/kernel/mac -a $from_new_aggrconf ]; then
+ revert_aggregation_conf
+ fi
fi
cd $root
diff --git a/usr/src/uts/Makefile.targ b/usr/src/uts/Makefile.targ
index 40526b3af2..f0282e370f 100644
--- a/usr/src/uts/Makefile.targ
+++ b/usr/src/uts/Makefile.targ
@@ -191,6 +191,9 @@ $(ROOT_MACH_DIR)/%: $(OBJS_DIR)/% $(ROOT_MACH_DIR) FRC
$(ROOT_FONT_DIR)/%: $(OBJS_DIR)/% $(ROOT_MOD_DIR) $(ROOT_FONT_DIR) FRC
$(INS.file)
+$(ROOT_MAC_DIR)/%: $(OBJS_DIR)/% $(ROOT_MOD_DIR) $(ROOT_MAC_DIR) FRC
+ $(INS.file)
+
$(USR_DRV_DIR)/%: $(OBJS_DIR)/% $(USR_DRV_DIR) FRC
$(INS.file)
diff --git a/usr/src/uts/Makefile.uts b/usr/src/uts/Makefile.uts
index bad396afa3..0fdb7cc69d 100644
--- a/usr/src/uts/Makefile.uts
+++ b/usr/src/uts/Makefile.uts
@@ -454,6 +454,7 @@ ROOT_TOD_DIR_32 = $(ROOT_MOD_DIR)/tod
ROOT_FONT_DIR_32 = $(ROOT_MOD_DIR)/fonts
ROOT_DACF_DIR_32 = $(ROOT_MOD_DIR)/dacf
ROOT_CRYPTO_DIR_32 = $(ROOT_MOD_DIR)/crypto
+ROOT_MAC_DIR_32 = $(ROOT_MOD_DIR)/mac
ROOT_KERN_DIR_64 = $(ROOT_MOD_DIR)/$(SUBDIR64)
ROOT_DRV_DIR_64 = $(ROOT_MOD_DIR)/drv/$(SUBDIR64)
@@ -473,6 +474,7 @@ ROOT_TOD_DIR_64 = $(ROOT_MOD_DIR)/tod/$(SUBDIR64)
ROOT_FONT_DIR_64 = $(ROOT_MOD_DIR)/fonts/$(SUBDIR64)
ROOT_DACF_DIR_64 = $(ROOT_MOD_DIR)/dacf/$(SUBDIR64)
ROOT_CRYPTO_DIR_64 = $(ROOT_MOD_DIR)/crypto/$(SUBDIR64)
+ROOT_MAC_DIR_64 = $(ROOT_MOD_DIR)/mac/$(SUBDIR64)
ROOT_KERN_DIR = $(ROOT_KERN_DIR_$(CLASS))
ROOT_DRV_DIR = $(ROOT_DRV_DIR_$(CLASS))
@@ -492,6 +494,7 @@ ROOT_TOD_DIR = $(ROOT_TOD_DIR_$(CLASS))
ROOT_FONT_DIR = $(ROOT_FONT_DIR_$(CLASS))
ROOT_DACF_DIR = $(ROOT_DACF_DIR_$(CLASS))
ROOT_CRYPTO_DIR = $(ROOT_CRYPTO_DIR_$(CLASS))
+ROOT_MAC_DIR = $(ROOT_MAC_DIR_$(CLASS))
ROOT_MOD_DIRS_32 = $(ROOT_DRV_DIR_32) $(ROOT_EXEC_DIR_32)
ROOT_MOD_DIRS_32 += $(ROOT_DTRACE_DIR_32)
@@ -502,7 +505,7 @@ ROOT_MOD_DIRS_32 += $(ROOT_MISC_DIR_32) $(ROOT_MACH_DIR_32)
ROOT_MOD_DIRS_32 += $(ROOT_KGSS_DIR_32)
ROOT_MOD_DIRS_32 += $(ROOT_CPU_DIR_32) $(ROOT_FONT_DIR_32)
ROOT_MOD_DIRS_32 += $(ROOT_TOD_DIR_32) $(ROOT_DACF_DIR_32)
-ROOT_MOD_DIRS_32 += $(ROOT_CRYPTO_DIR_32)
+ROOT_MOD_DIRS_32 += $(ROOT_CRYPTO_DIR_32) $(ROOT_MAC_DIR_32)
USR_MOD_DIR = $(ROOT)/usr/kernel
@@ -580,7 +583,7 @@ KMODS = $(DRV_KMODS) $(EXEC_KMODS) $(FS_KMODS) $(SCHED_KMODS) $(TOD_KMODS) \
$(MACH_KMODS) $(CPU_KMODS) $(GENUNIX_KMODS) \
$(GSS_KMODS) $(MMU_KMODS) $(DACF_KMODS) $(EXPORT_KMODS) \
$(IPP_KMODS) $(CRYPTO_KMODS) $(CRYPTO_EK_KMODS) $(PCBE_KMODS) \
- $(DRV_KMODS_$(CLASS)) $(MISC_KMODS_$(CLASS))
+ $(DRV_KMODS_$(CLASS)) $(MISC_KMODS_$(CLASS)) $(MAC_KMODS)
$(CLOSED_BUILD)CLOSED_KMODS = $(CLOSED_DRV_KMODS) $(CLOSED_TOD_KMODS) \
$(CLOSED_MISC_KMODS) \
@@ -590,7 +593,7 @@ LINT_KMODS = $(DRV_KMODS) $(EXEC_KMODS) $(FS_KMODS) $(SCHED_KMODS) \
$(TOD_KMODS) $(STRMOD_KMODS) $(SYS_KMODS) $(MISC_KMODS) \
$(MACH_KMODS) $(GSS_KMODS) $(DACF_KMODS) $(IPP_KMODS) \
$(CRYPTO_KMODS) $(PCBE_KMODS) \
- $(DRV_KMODS_$(CLASS)) $(MISC_KMODS_$(CLASS))
+ $(DRV_KMODS_$(CLASS)) $(MISC_KMODS_$(CLASS)) $(MAC_KMODS)
$(CLOSED_BUILD)CLOSED_LINT_KMODS = $(CLOSED_DRV_KMODS) $(CLOSED_TOD_KMODS) \
$(CLOSED_MISC_KMODS) $(CLOSED_DRV_KMODS_$(CLASS))
diff --git a/usr/src/uts/common/Makefile.files b/usr/src/uts/common/Makefile.files
index 6279f7c4ba..d029353751 100644
--- a/usr/src/uts/common/Makefile.files
+++ b/usr/src/uts/common/Makefile.files
@@ -513,6 +513,8 @@ GLD_OBJS += gld.o gldutil.o
MAC_OBJS += mac.o mac_mod.o mac_stat.o
+MAC_ETHER_OBJS += mac_ether.o
+
AGGR_OBJS += aggr_dev.o aggr_ctl.o aggr_grp.o aggr_port.o \
aggr_send.o aggr_recv.o aggr_lacp.o
diff --git a/usr/src/uts/common/Makefile.rules b/usr/src/uts/common/Makefile.rules
index b7f6e384ce..82fdea4c43 100644
--- a/usr/src/uts/common/Makefile.rules
+++ b/usr/src/uts/common/Makefile.rules
@@ -560,6 +560,10 @@ $(OBJS_DIR)/%.o: $(UTSBASE)/common/io/mac/%.c
$(COMPILE.c) -o $@ $<
$(CTFCONVERT_O)
+$(OBJS_DIR)/%.o: $(UTSBASE)/common/io/mac/plugins/%.c
+ $(COMPILE.c) -o $@ $<
+ $(CTFCONVERT_O)
+
$(OBJS_DIR)/%.o: $(UTSBASE)/common/io/pci-ide/%.c
$(COMPILE.c) -o $@ $<
$(CTFCONVERT_O)
@@ -1256,6 +1260,9 @@ $(LINTS_DIR)/%.ln: $(UTSBASE)/common/io/lvm/trans/%.c
$(LINTS_DIR)/%.ln: $(UTSBASE)/common/io/mac/%.c
@($(LHEAD) $(LINT.c) $< $(LTAIL))
+$(LINTS_DIR)/%.ln: $(UTSBASE)/common/io/mac/plugins/%.c
+ @($(LHEAD) $(LINT.c) $< $(LTAIL))
+
$(LINTS_DIR)/%.ln: $(UTSBASE)/common/io/pci-ide/%.c
@($(LHEAD) $(LINT.c) $< $(LTAIL))
diff --git a/usr/src/uts/common/io/aggr/aggr_ctl.c b/usr/src/uts/common/io/aggr/aggr_ctl.c
index 8606ecd1ee..f0990702cf 100644
--- a/usr/src/uts/common/io/aggr/aggr_ctl.c
+++ b/usr/src/uts/common/io/aggr/aggr_ctl.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -202,8 +201,8 @@ aggr_ioc_info_new_grp(void *arg, uint32_t key, uchar_t *mac,
}
static int
-aggr_ioc_info_new_port(void *arg, char *devname, uint32_t portnum,
- uchar_t *mac, aggr_port_state_t portstate, aggr_lacp_state_t *lacp_state)
+aggr_ioc_info_new_port(void *arg, char *devname, uchar_t *mac,
+ aggr_port_state_t portstate, aggr_lacp_state_t *lacp_state)
{
aggr_ioc_info_state_t *state = arg;
laioc_info_port_t port;
@@ -212,7 +211,6 @@ aggr_ioc_info_new_port(void *arg, char *devname, uint32_t portnum,
return (ENOSPC);
bcopy(devname, port.lp_devname, MAXNAMELEN + 1);
- port.lp_port = portnum;
bcopy(mac, port.lp_mac, ETHERADDRL);
port.lp_state = portstate;
port.lp_lacp_state = *lacp_state;
diff --git a/usr/src/uts/common/io/aggr/aggr_grp.c b/usr/src/uts/common/io/aggr/aggr_grp.c
index b178c84255..cb2f608377 100644
--- a/usr/src/uts/common/io/aggr/aggr_grp.c
+++ b/usr/src/uts/common/io/aggr/aggr_grp.c
@@ -58,20 +58,19 @@
#include <sys/aggr.h>
#include <sys/aggr_impl.h>
-static void aggr_m_info(void *, mac_info_t *);
static int aggr_m_start(void *);
static void aggr_m_stop(void *);
static int aggr_m_promisc(void *, boolean_t);
static int aggr_m_multicst(void *, boolean_t, const uint8_t *);
static int aggr_m_unicst(void *, const uint8_t *);
-static uint64_t aggr_m_stat(void *, enum mac_stat);
+static int aggr_m_stat(void *, uint_t, uint64_t *);
static void aggr_m_resources(void *);
static void aggr_m_ioctl(void *, queue_t *, mblk_t *);
+static boolean_t aggr_m_capab_get(void *, mac_capab_t, void *);
-static aggr_port_t *aggr_grp_port_lookup(aggr_grp_t *, const char *, uint32_t);
+static aggr_port_t *aggr_grp_port_lookup(aggr_grp_t *, const char *);
static int aggr_grp_rem_port(aggr_grp_t *, aggr_port_t *, boolean_t *,
boolean_t *);
-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 *);
@@ -84,7 +83,6 @@ static uint_t aggr_grp_cnt;
#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 };
/* used by grp_info_walker */
typedef struct aggr_grp_info_state {
@@ -96,6 +94,22 @@ typedef struct aggr_grp_info_state {
int ls_rc;
} aggr_grp_info_state_t;
+#define AGGR_M_CALLBACK_FLAGS (MC_RESOURCES | MC_IOCTL | MC_GETCAPAB)
+
+static mac_callbacks_t aggr_m_callbacks = {
+ AGGR_M_CALLBACK_FLAGS,
+ aggr_m_stat,
+ aggr_m_start,
+ aggr_m_stop,
+ aggr_m_promisc,
+ aggr_m_multicst,
+ aggr_m_unicst,
+ aggr_m_tx,
+ aggr_m_resources,
+ aggr_m_ioctl,
+ aggr_m_capab_get
+};
+
/*ARGSUSED*/
static int
aggr_grp_constructor(void *buf, void *arg, int kmflag)
@@ -393,8 +407,7 @@ aggr_grp_port_mac_changed(aggr_grp_t *grp, aggr_port_t *port,
* Add a port to a link aggregation group.
*/
static int
-aggr_grp_add_port(aggr_grp_t *grp, const char *name, uint_t portnum,
- aggr_port_t **pp)
+aggr_grp_add_port(aggr_grp_t *grp, const char *name, aggr_port_t **pp)
{
aggr_port_t *port, **cport;
int err;
@@ -403,7 +416,7 @@ aggr_grp_add_port(aggr_grp_t *grp, const char *name, uint_t portnum,
ASSERT(RW_WRITE_HELD(&grp->lg_lock));
/* create new port */
- err = aggr_port_create(name, portnum, &port);
+ err = aggr_port_create(name, &port);
if (err != 0)
return (err);
@@ -467,9 +480,10 @@ aggr_grp_add_ports(uint32_t key, uint_t nports, laioc_port_t *ports)
/* add the specified ports to group */
for (i = 0; i < nports; i++) {
/* add port to group */
- if ((rc = aggr_grp_add_port(grp, ports[i].lp_devname,
- ports[i].lp_port, &port)) != 0)
+ if ((rc = aggr_grp_add_port(grp, ports[i].lp_devname, &port)) !=
+ 0) {
goto bail;
+ }
ASSERT(port != NULL);
nadded++;
@@ -509,14 +523,13 @@ aggr_grp_add_ports(uint32_t key, uint_t nports, laioc_port_t *ports)
aggr_grp_update_ports_mac(grp);
if (link_state_changed)
- mac_link_update(&grp->lg_mac, grp->lg_link_state);
+ mac_link_update(grp->lg_mh, grp->lg_link_state);
bail:
if (rc != 0) {
/* stop and remove ports that have been added */
for (i = 0; i < nadded && !grp->lg_closing; i++) {
- port = aggr_grp_port_lookup(grp, ports[i].lp_devname,
- ports[i].lp_port);
+ port = aggr_grp_port_lookup(grp, ports[i].lp_devname);
ASSERT(port != NULL);
if (grp->lg_started) {
rw_enter(&port->lp_lock, RW_WRITER);
@@ -530,7 +543,7 @@ bail:
rw_exit(&grp->lg_lock);
AGGR_LACP_UNLOCK(grp);
if (rc == 0 && !grp->lg_closing)
- mac_resource_update(&grp->lg_mac);
+ mac_resource_update(grp->lg_mh);
AGGR_GRP_REFRELE(grp);
return (rc);
}
@@ -618,10 +631,10 @@ bail:
* will be sent there.
*/
if ((grp_arg == NULL) && mac_addr_changed)
- mac_unicst_update(&grp->lg_mac, grp->lg_addr);
+ mac_unicst_update(grp->lg_mh, grp->lg_addr);
if (link_state_changed)
- mac_link_update(&grp->lg_mac, grp->lg_link_state);
+ mac_link_update(grp->lg_mh, grp->lg_link_state);
}
@@ -650,8 +663,7 @@ aggr_grp_create(uint32_t key, uint_t nports, laioc_port_t *ports,
{
aggr_grp_t *grp = NULL;
aggr_port_t *port;
- mac_t *mac;
- mac_info_t *mip;
+ mac_register_t *mac;
boolean_t link_state_changed;
int err;
int i;
@@ -693,8 +705,7 @@ aggr_grp_create(uint32_t key, uint_t nports, laioc_port_t *ports,
grp->lg_ntx_ports = 0;
for (i = 0; i < nports; i++) {
- err = aggr_grp_add_port(grp, ports[i].lp_devname,
- ports[i].lp_port, NULL);
+ err = aggr_grp_add_port(grp, ports[i].lp_devname, NULL);
if (err != 0)
goto bail;
}
@@ -727,43 +738,22 @@ aggr_grp_create(uint32_t key, uint_t nports, laioc_port_t *ports,
/* update outbound load balancing policy */
aggr_send_update_policy(grp, policy);
- /* register with the MAC module */
- mac = &grp->lg_mac;
- bzero(mac, sizeof (*mac));
-
- mac->m_ident = MAC_IDENT;
-
- mac->m_driver = grp;
- mac->m_dip = aggr_dip;
- mac->m_port = key;
-
- mip = &(mac->m_info);
- mip->mi_media = DL_ETHER;
- mip->mi_sdu_min = 0;
- mip->mi_sdu_max = ETHERMTU;
-
- MAC_STAT_MIB(mip->mi_stat);
- MAC_STAT_ETHER(mip->mi_stat);
- mip->mi_stat[MAC_STAT_LINK_DUPLEX] = B_TRUE;
-
- mip->mi_addr_length = ETHERADDRL;
- bcopy(aggr_brdcst_mac, mip->mi_brdcst_addr, ETHERADDRL);
- bcopy(grp->lg_addr, mip->mi_unicst_addr, ETHERADDRL);
-
- mac->m_stat = aggr_m_stat;
- mac->m_start = aggr_m_start;
- mac->m_stop = aggr_m_stop;
- mac->m_promisc = aggr_m_promisc;
- mac->m_multicst = aggr_m_multicst;
- mac->m_unicst = aggr_m_unicst;
- mac->m_tx = aggr_m_tx;
- mac->m_resources = aggr_m_resources;
- mac->m_ioctl = aggr_m_ioctl;
-
/* set the initial group capabilities */
aggr_grp_capab_set(grp);
- if ((err = mac_register(mac)) != 0)
+ if ((mac = mac_alloc(MAC_VERSION)) == NULL)
+ goto bail;
+ mac->m_type_ident = MAC_PLUGIN_IDENT_ETHER;
+ mac->m_driver = grp;
+ mac->m_dip = aggr_dip;
+ mac->m_instance = key;
+ mac->m_src_addr = grp->lg_addr;
+ mac->m_callbacks = &aggr_m_callbacks;
+ mac->m_min_sdu = 0;
+ mac->m_max_sdu = ETHERMTU;
+ err = mac_register(mac, &grp->lg_mh);
+ mac_free(mac);
+ if (err != 0)
goto bail;
/* set LACP mode */
@@ -814,15 +804,14 @@ bail:
* and port number.
*/
static aggr_port_t *
-aggr_grp_port_lookup(aggr_grp_t *grp, const char *devname, uint32_t portnum)
+aggr_grp_port_lookup(aggr_grp_t *grp, const char *devname)
{
aggr_port_t *port;
ASSERT(RW_WRITE_HELD(&grp->lg_lock) || RW_READ_HELD(&grp->lg_lock));
for (port = grp->lg_ports; port != NULL; port = port->lp_next) {
- if ((strcmp(port->lp_devname, devname) == 0) &&
- (port->lp_port == portnum))
+ if (strcmp(port->lp_devname, devname) == 0)
break;
}
@@ -842,6 +831,7 @@ aggr_grp_rem_port(aggr_grp_t *grp, aggr_port_t *port,
boolean_t link_state_changed = B_FALSE;
uint64_t val;
uint_t i;
+ uint_t stat;
ASSERT(AGGR_LACP_LOCK_HELD(grp));
ASSERT(RW_WRITE_HELD(&grp->lg_lock));
@@ -880,21 +870,28 @@ aggr_grp_rem_port(aggr_grp_t *grp, aggr_port_t *port,
link_state_changed = aggr_grp_detach_port(grp, port);
/*
- * Add the statistics of the ports while it was aggregated
- * to the group's residual statistics.
+ * Add the counter statistics of the ports while it was aggregated
+ * to the group's residual statistics. This is done by obtaining
+ * the current counter from the underlying MAC then subtracting the
+ * value of the counter at the moment it was added to the
+ * aggregation.
*/
for (i = 0; i < MAC_NSTAT && !grp->lg_closing; i++) {
- /* avoid stats that are not counters */
- if (i == MAC_STAT_IFSPEED || i == MAC_STAT_LINK_DUPLEX)
+ stat = i + MAC_STAT_MIN;
+ if (!MAC_STAT_ISACOUNTER(stat))
continue;
-
- /* get current value */
- val = aggr_port_stat(port, i);
- /* subtract value at the point of aggregation */
+ val = aggr_port_stat(port, stat);
val -= port->lp_stat[i];
- /* add to the residual stat */
grp->lg_stat[i] += val;
}
+ for (i = 0; i < ETHER_NSTAT && !grp->lg_closing; i++) {
+ stat = i + MACTYPE_STAT_MIN;
+ if (!ETHER_STAT_ISACOUNTER(stat))
+ continue;
+ val = aggr_port_stat(port, stat);
+ val -= port->lp_ether_stat[i];
+ grp->lg_ether_stat[i] += val;
+ }
grp->lg_nports--;
@@ -953,8 +950,7 @@ aggr_grp_rem_ports(uint32_t key, uint_t nports, laioc_port_t *ports)
/* first verify that all the groups are valid */
for (i = 0; i < nports; i++) {
- if (aggr_grp_port_lookup(grp, ports[i].lp_devname,
- ports[i].lp_port) == NULL) {
+ if (aggr_grp_port_lookup(grp, ports[i].lp_devname) == NULL) {
/* port not found */
rc = ENOENT;
goto bail;
@@ -964,8 +960,7 @@ aggr_grp_rem_ports(uint32_t key, uint_t nports, laioc_port_t *ports)
/* remove the specified ports from group */
for (i = 0; i < nports && !grp->lg_closing; i++) {
/* lookup port */
- port = aggr_grp_port_lookup(grp, ports[i].lp_devname,
- ports[i].lp_port);
+ port = aggr_grp_port_lookup(grp, ports[i].lp_devname);
ASSERT(port != NULL);
/* stop port if group has already been started */
@@ -987,11 +982,11 @@ bail:
rw_exit(&grp->lg_lock);
AGGR_LACP_UNLOCK(grp);
if (mac_addr_update)
- mac_unicst_update(&grp->lg_mac, grp->lg_addr);
+ mac_unicst_update(grp->lg_mh, grp->lg_addr);
if (link_state_update)
- mac_link_update(&grp->lg_mac, grp->lg_link_state);
+ mac_link_update(grp->lg_mh, grp->lg_link_state);
if (rc == 0)
- mac_resource_update(&grp->lg_mac);
+ mac_resource_update(grp->lg_mh);
AGGR_GRP_REFRELE(grp);
return (rc);
@@ -1022,7 +1017,7 @@ aggr_grp_delete(uint32_t key)
* fail if a client hasn't closed the MAC port, we gracefully
* fail the operation.
*/
- if (mac_unregister(&grp->lg_mac)) {
+ if (mac_unregister(grp->lg_mh)) {
rw_exit(&grp->lg_lock);
AGGR_LACP_UNLOCK(grp);
rw_exit(&aggr_grp_lock);
@@ -1101,8 +1096,8 @@ aggr_grp_info_walker(mod_hash_key_t key, mod_hash_val_t *val, void *arg)
rw_enter(&port->lp_lock, RW_READER);
state->ls_rc = state->ls_new_port_fn(state->ls_fn_arg,
- port->lp_devname, port->lp_port, port->lp_addr,
- port->lp_state, &port->lp_lacp.ActorOperPortState);
+ port->lp_devname, port->lp_addr, port->lp_state,
+ &port->lp_lacp.ActorOperPortState);
rw_exit(&port->lp_lock);
@@ -1161,43 +1156,73 @@ aggr_m_ioctl(void *arg, queue_t *q, mblk_t *mp)
miocnak(q, mp, 0, ENOTSUP);
}
-static uint64_t
-aggr_m_stat(void *arg, enum mac_stat stat)
+static int
+aggr_grp_stat(aggr_grp_t *grp, uint_t stat, uint64_t *val)
{
- aggr_grp_t *grp = arg;
- aggr_port_t *port;
- uint64_t val;
+ aggr_port_t *port;
+ uint_t stat_index;
+
+ /* We only aggregate counter statistics. */
+ if (IS_MAC_STAT(stat) && !MAC_STAT_ISACOUNTER(stat) ||
+ IS_MACTYPE_STAT(stat) && !ETHER_STAT_ISACOUNTER(stat)) {
+ return (ENOTSUP);
+ }
+
+ /*
+ * Counter statistics for a group are computed by aggregating the
+ * counters of the members MACs while they were aggregated, plus
+ * the residual counter of the group itself, which is updated each
+ * time a MAC is removed from the group.
+ */
+ *val = 0;
+ for (port = grp->lg_ports; port != NULL; port = port->lp_next) {
+ /* actual port statistic */
+ *val += aggr_port_stat(port, stat);
+ /*
+ * minus the port stat when it was added, plus any residual
+ * ammount for the group.
+ */
+ if (IS_MAC_STAT(stat)) {
+ stat_index = stat - MAC_STAT_MIN;
+ *val -= port->lp_stat[stat_index];
+ *val += grp->lg_stat[stat_index];
+ } else if (IS_MACTYPE_STAT(stat)) {
+ stat_index = stat - MACTYPE_STAT_MIN;
+ *val -= port->lp_ether_stat[stat_index];
+ *val += grp->lg_ether_stat[stat_index];
+ }
+ }
+ return (0);
+}
+
+static int
+aggr_m_stat(void *arg, uint_t stat, uint64_t *val)
+{
+ aggr_grp_t *grp = arg;
+ int rval = 0;
rw_enter(&grp->lg_lock, RW_READER);
switch (stat) {
case MAC_STAT_IFSPEED:
- val = grp->lg_ifspeed;
+ *val = grp->lg_ifspeed;
break;
- case MAC_STAT_LINK_DUPLEX:
- val = grp->lg_link_duplex;
+
+ case ETHER_STAT_LINK_DUPLEX:
+ *val = grp->lg_link_duplex;
break;
+
default:
/*
- * The remaining statistics are counters. They are computed
- * by aggregating the counters of the members MACs while they
- * were aggregated, plus the residual counter of the group
- * itself, which is updated each time a MAC is removed from
- * the group.
+ * For all other statistics, we return the aggregated stat
+ * from the underlying ports. aggr_grp_stat() will set
+ * rval appropriately if the statistic isn't a counter.
*/
- val = 0;
- for (port = grp->lg_ports; port != NULL; port = port->lp_next) {
- /* actual port statistic */
- val += aggr_port_stat(port, stat);
- /* minus the port stat when it was added */
- val -= port->lp_stat[stat];
- /* plus any residual amount for the group */
- val += grp->lg_stat[stat];
- }
+ rval = aggr_grp_stat(grp, stat, val);
}
rw_exit(&grp->lg_lock);
- return (val);
+ return (rval);
}
static int
@@ -1296,7 +1321,7 @@ aggr_m_promisc(void *arg, boolean_t on)
grp->lg_promisc = on;
if (link_state_changed)
- mac_link_update(&grp->lg_mac, grp->lg_link_state);
+ mac_link_update(grp->lg_mh, grp->lg_link_state);
bail:
rw_exit(&grp->lg_lock);
@@ -1307,6 +1332,34 @@ bail:
}
/*
+ * Initialize the capabilities that are advertised for the group
+ * according to the capabilities of the constituent ports.
+ */
+static boolean_t
+aggr_m_capab_get(void *arg, mac_capab_t cap, void *cap_data)
+{
+ aggr_grp_t *grp = arg;
+
+ switch (cap) {
+ case MAC_CAPAB_HCKSUM: {
+ uint32_t *hcksum_txflags = cap_data;
+ *hcksum_txflags = grp->lg_hcksum_txflags;
+ break;
+ }
+ case MAC_CAPAB_POLL:
+ /*
+ * There's nothing for us to fill in, we simply return
+ * B_TRUE or B_FALSE to represent the group's support
+ * status for this capability.
+ */
+ return (grp->lg_gldv3_polling);
+ default:
+ return (B_FALSE);
+ }
+ return (B_TRUE);
+}
+
+/*
* Add or remove the multicast addresses that are defined for the group
* to or from the specified port.
* This function is called before stopping a port, before a port
@@ -1323,8 +1376,7 @@ aggr_grp_multicst_port(aggr_port_t *port, boolean_t add)
if (!port->lp_started)
return;
- mac_multicst_refresh(&grp->lg_mac, aggr_port_multicst, port,
- add);
+ mac_multicst_refresh(grp->lg_mh, aggr_port_multicst, port, add);
}
static int
@@ -1369,36 +1421,49 @@ aggr_m_unicst(void *arg, const uint8_t *macaddr)
static void
aggr_grp_capab_set(aggr_grp_t *grp)
{
- uint32_t cksum = (uint32_t)-1;
- uint32_t poll = DL_CAPAB_POLL;
aggr_port_t *port;
- const mac_info_t *port_mi;
ASSERT(RW_WRITE_HELD(&grp->lg_lock));
-
ASSERT(grp->lg_ports != NULL);
+
+ grp->lg_hcksum_txflags = (uint32_t)-1;
+ grp->lg_gldv3_polling = B_TRUE;
+
for (port = grp->lg_ports; port != NULL; port = port->lp_next) {
- port_mi = mac_info(port->lp_mh);
- cksum &= port_mi->mi_cksum;
- poll &= port_mi->mi_poll;
- }
+ if (!mac_capab_get(port->lp_mh, MAC_CAPAB_HCKSUM,
+ &grp->lg_hcksum_txflags)) {
+ grp->lg_hcksum_txflags = 0;
+ }
- grp->lg_mac.m_info.mi_cksum = cksum;
- grp->lg_mac.m_info.mi_poll = poll;
+ grp->lg_gldv3_polling &=
+ mac_capab_get(port->lp_mh, MAC_CAPAB_POLL, NULL);
+ }
}
+
/*
- * Checks whether the capabilities of the ports being added are compatible
+ * Checks whether the capabilities of the port being added are compatible
* with the current capabilities of the aggregation.
*/
static boolean_t
aggr_grp_capab_check(aggr_grp_t *grp, aggr_port_t *port)
{
- const mac_info_t *port_mi = mac_info(port->lp_mh);
- uint32_t grp_cksum = grp->lg_mac.m_info.mi_cksum;
+ uint32_t hcksum_txflags;
ASSERT(grp->lg_ports != NULL);
- return (((grp_cksum & port_mi->mi_cksum) == grp_cksum) &&
- (grp->lg_mac.m_info.mi_poll == port_mi->mi_poll));
+ if (!mac_capab_get(port->lp_mh, MAC_CAPAB_HCKSUM, &hcksum_txflags)) {
+ if (grp->lg_hcksum_txflags != 0)
+ return (B_FALSE);
+ } else if ((hcksum_txflags & grp->lg_hcksum_txflags) !=
+ grp->lg_hcksum_txflags) {
+ return (B_FALSE);
+ }
+
+ if (mac_capab_get(port->lp_mh, MAC_CAPAB_POLL, NULL) !=
+ grp->lg_gldv3_polling) {
+ return (B_FALSE);
+ }
+
+ return (B_TRUE);
}
diff --git a/usr/src/uts/common/io/aggr/aggr_lacp.c b/usr/src/uts/common/io/aggr/aggr_lacp.c
index 6eb017e2e0..5319d0d0a6 100644
--- a/usr/src/uts/common/io/aggr/aggr_lacp.c
+++ b/usr/src/uts/common/io/aggr/aggr_lacp.c
@@ -90,7 +90,6 @@ static uint16_t lacp_system_priority = 0x1000;
typedef struct lacp_sel_ports {
uint16_t sp_key;
char sp_devname[MAXNAMELEN + 1];
- uint_t sp_port;
struct ether_addr sp_partner_system;
uint32_t sp_partner_key;
struct lacp_sel_ports *sp_next;
@@ -213,10 +212,10 @@ aggr_lacp_init_port(aggr_port_t *portp)
offset = ((portp->lp_devname[0] + portp->lp_devname[1]) << 8);
instance = inst_num(portp->lp_devname);
/* actor port # */
- pl->ActorPortNumber = offset + instance + portp->lp_port;
- AGGR_LACP_DBG(("aggr_lacp_init_port(%s/%d): "
+ pl->ActorPortNumber = offset + instance;
+ AGGR_LACP_DBG(("aggr_lacp_init_port(%s): "
"ActorPortNumber = 0x%x\n", portp->lp_devname,
- portp->lp_port, pl->ActorPortNumber));
+ pl->ActorPortNumber));
pl->ActorPortPriority = (uint16_t)lacp_port_priority;
pl->ActorPortAggrId = 0; /* aggregator id - not used */
@@ -224,10 +223,9 @@ aggr_lacp_init_port(aggr_port_t *portp)
pl->ActorAdminPortKey = aggrp->lg_key;
pl->ActorOperPortKey = pl->ActorAdminPortKey;
- AGGR_LACP_DBG(("aggr_lacp_init_port(%s/%d) "
+ AGGR_LACP_DBG(("aggr_lacp_init_port(%s) "
"ActorAdminPortKey = 0x%x, ActorAdminPortKey = 0x%x\n",
- portp->lp_devname, portp->lp_port, pl->ActorAdminPortKey,
- pl->ActorOperPortKey));
+ portp->lp_devname, pl->ActorAdminPortKey, pl->ActorOperPortKey));
/* Actor admin. port state */
pl->ActorAdminPortState.bit.activity = B_FALSE;
@@ -454,8 +452,8 @@ lacp_periodic_sm(aggr_port_t *portp)
stop_periodic_timer(portp);
pl->sm.periodic_state = LACP_NO_PERIODIC;
pl->NTT = B_FALSE;
- AGGR_LACP_DBG(("lacp_periodic_sm(%s/%d):NO LACP "
- "%s--->%s\n", portp->lp_devname, portp->lp_port,
+ AGGR_LACP_DBG(("lacp_periodic_sm(%s):NO LACP "
+ "%s--->%s\n", portp->lp_devname,
lacp_periodic_str[oldstate],
lacp_periodic_str[pl->sm.periodic_state]));
return;
@@ -470,9 +468,8 @@ lacp_periodic_sm(aggr_port_t *portp)
stop_periodic_timer(portp);
pl->sm.periodic_state = LACP_NO_PERIODIC;
pl->NTT = B_FALSE;
- AGGR_LACP_DBG(("lacp_periodic_sm(%s/%d):STOP %s--->%s\n",
- portp->lp_devname, portp->lp_port,
- lacp_periodic_str[oldstate],
+ AGGR_LACP_DBG(("lacp_periodic_sm(%s):STOP %s--->%s\n",
+ portp->lp_devname, lacp_periodic_str[oldstate],
lacp_periodic_str[pl->sm.periodic_state]));
return;
}
@@ -672,9 +669,9 @@ lacp_mux_sm(aggr_port_t *portp)
if (pl->ActorOperPortState.bit.collecting ||
pl->ActorOperPortState.bit.distributing) {
- AGGR_LACP_DBG(("trunk link: (%s/%d): "
+ AGGR_LACP_DBG(("trunk link: (%s): "
"Collector_Distributor Disabled.\n",
- portp->lp_devname, portp->lp_port));
+ portp->lp_devname));
}
pl->ActorOperPortState.bit.collecting =
@@ -736,8 +733,8 @@ again:
return;
}
- AGGR_LACP_DBG(("lacp_mux_sm(%s/%d):%s--->%s\n",
- portp->lp_devname, portp->lp_port, lacp_mux_str[oldstate],
+ AGGR_LACP_DBG(("lacp_mux_sm(%s):%s--->%s\n",
+ portp->lp_devname, lacp_mux_str[oldstate],
lacp_mux_str[pl->sm.mux_state]));
/* perform actions on entering a new state */
@@ -745,9 +742,9 @@ again:
case LACP_DETACHED:
if (pl->ActorOperPortState.bit.collecting ||
pl->ActorOperPortState.bit.distributing) {
- AGGR_LACP_DBG(("trunk link: (%s/%d): "
+ AGGR_LACP_DBG(("trunk link: (%s): "
"Collector_Distributor Disabled.\n",
- portp->lp_devname, portp->lp_port));
+ portp->lp_devname));
}
pl->ActorOperPortState.bit.sync =
@@ -767,9 +764,9 @@ again:
case LACP_ATTACHED:
if (pl->ActorOperPortState.bit.collecting ||
pl->ActorOperPortState.bit.distributing) {
- AGGR_LACP_DBG(("trunk link: (%s%d): "
+ AGGR_LACP_DBG(("trunk link: (%s): "
"Collector_Distributor Disabled.\n",
- portp->lp_devname, portp->lp_port));
+ portp->lp_devname));
}
pl->ActorOperPortState.bit.sync = B_TRUE;
@@ -793,9 +790,9 @@ again:
case LACP_COLLECTING_DISTRIBUTING:
if (!pl->ActorOperPortState.bit.collecting &&
!pl->ActorOperPortState.bit.distributing) {
- AGGR_LACP_DBG(("trunk link: (%s/%d): "
+ AGGR_LACP_DBG(("trunk link: (%s): "
"Collector_Distributor Enabled.\n",
- portp->lp_devname, portp->lp_port));
+ portp->lp_devname));
}
pl->ActorOperPortState.bit.distributing = B_TRUE;
@@ -826,8 +823,8 @@ receive_marker_pdu(aggr_port_t *portp, mblk_t *mp)
AGGR_LACP_LOCK(portp->lp_grp);
- AGGR_LACP_DBG(("trunk link: (%s/%d): MARKER PDU received:\n",
- portp->lp_devname, portp->lp_port));
+ AGGR_LACP_DBG(("trunk link: (%s): MARKER PDU received:\n",
+ portp->lp_devname));
/* LACP_OFF state not in specification so check here. */
if (!portp->lp_lacp.sm.lacp_on)
@@ -837,50 +834,47 @@ receive_marker_pdu(aggr_port_t *portp, mblk_t *mp)
goto bail;
if (markerp->version != MARKER_VERSION) {
- AGGR_LACP_DBG(("trunk link (%s/%d): Malformed MARKER PDU: "
+ AGGR_LACP_DBG(("trunk link (%s): Malformed MARKER PDU: "
"version = %d does not match s/w version %d\n",
- portp->lp_devname, portp->lp_port,
- markerp->version, MARKER_VERSION));
+ portp->lp_devname, markerp->version, MARKER_VERSION));
goto bail;
}
if (markerp->tlv_marker == MARKER_RESPONSE_TLV) {
/* We do not yet send out MARKER info PDUs */
- AGGR_LACP_DBG(("trunk link (%s/%d): MARKER RESPONSE PDU: "
+ AGGR_LACP_DBG(("trunk link (%s): MARKER RESPONSE PDU: "
" MARKER TLV = %d - We don't send out info type!\n",
- portp->lp_devname, portp->lp_port,
- markerp->tlv_marker));
+ portp->lp_devname, markerp->tlv_marker));
goto bail;
}
if (markerp->tlv_marker != MARKER_INFO_TLV) {
- AGGR_LACP_DBG(("trunk link (%s/%d): Malformed MARKER PDU: "
- " MARKER TLV = %d \n", portp->lp_devname, portp->lp_port,
+ AGGR_LACP_DBG(("trunk link (%s): Malformed MARKER PDU: "
+ " MARKER TLV = %d \n", portp->lp_devname,
markerp->tlv_marker));
goto bail;
}
if (markerp->marker_len != MARKER_INFO_RESPONSE_LENGTH) {
- AGGR_LACP_DBG(("trunk link (%s/%d): Malformed MARKER PDU: "
- " MARKER length = %d \n", portp->lp_devname, portp->lp_port,
+ AGGR_LACP_DBG(("trunk link (%s): Malformed MARKER PDU: "
+ " MARKER length = %d \n", portp->lp_devname,
markerp->marker_len));
goto bail;
}
if (markerp->requestor_port != portp->lp_lacp.PartnerOperPortNum) {
- AGGR_LACP_DBG(("trunk link (%s/%d): MARKER PDU: "
+ AGGR_LACP_DBG(("trunk link (%s): MARKER PDU: "
" MARKER Port %d not equal to Partner port %d\n",
- portp->lp_devname, portp->lp_port,
- markerp->requestor_port,
+ portp->lp_devname, markerp->requestor_port,
portp->lp_lacp.PartnerOperPortNum));
goto bail;
}
if (ether_cmp(&markerp->system_id,
&portp->lp_lacp.PartnerOperSystem) != 0) {
- AGGR_LACP_DBG(("trunk link (%s/%d): MARKER PDU: "
+ AGGR_LACP_DBG(("trunk link (%s): MARKER PDU: "
" MARKER MAC not equal to Partner MAC\n",
- portp->lp_devname, portp->lp_port));
+ portp->lp_devname));
goto bail;
}
@@ -1066,12 +1060,12 @@ lacp_misconfig_check(aggr_port_t *portp)
mac->ether_addr_octet[4], mac->ether_addr_octet[5]);
portp->lp_lacp.sm.selected = AGGR_UNSELECTED;
- cmn_err(CE_NOTE, "aggr key %d port %s/%d: Port Partner "
+ cmn_err(CE_NOTE, "aggr key %d port %s: Port Partner "
"MAC %s and key %d in use on aggregation "
- "key %d port %s/%d\n", grp->lg_key,
- portp->lp_devname, portp->lp_port,
- mac_str, portp->lp_lacp.PartnerOperKey,
- cport->sp_key, cport->sp_devname, cport->sp_port);
+ "key %d port %s\n", grp->lg_key,
+ portp->lp_devname, mac_str,
+ portp->lp_lacp.PartnerOperKey, cport->sp_key,
+ cport->sp_devname);
break;
}
}
@@ -1094,8 +1088,7 @@ lacp_sel_ports_del(aggr_port_t *portp)
for (cport = sel_ports; cport != NULL; prev = &cport->sp_next,
cport = cport->sp_next) {
if (bcmp(portp->lp_devname, cport->sp_devname,
- MAXNAMELEN + 1) == 0 &&
- (portp->lp_port == cport->sp_port)) {
+ MAXNAMELEN + 1) == 0) {
break;
}
}
@@ -1129,8 +1122,7 @@ lacp_sel_ports_add(aggr_port_t *portp)
for (cport = sel_ports; cport != NULL;
last = &cport->sp_next, cport = cport->sp_next) {
if (bcmp(portp->lp_devname, cport->sp_devname,
- MAXNAMELEN + 1) == 0 && (portp->lp_port ==
- cport->sp_port)) {
+ MAXNAMELEN + 1) == 0) {
ASSERT(cport->sp_partner_key ==
portp->lp_lacp.PartnerOperKey);
ASSERT(ether_cmp(&cport->sp_partner_system,
@@ -1153,7 +1145,6 @@ lacp_sel_ports_add(aggr_port_t *portp)
&new_port->sp_partner_system, sizeof (new_port->sp_partner_system));
new_port->sp_partner_key = portp->lp_lacp.PartnerOperKey;
bcopy(portp->lp_devname, new_port->sp_devname, MAXNAMELEN + 1);
- new_port->sp_port = portp->lp_port;
*last = new_port;
@@ -1199,11 +1190,10 @@ lacp_selection_logic(aggr_port_t *portp)
if (pl->sm.begin || !pl->sm.lacp_enabled ||
(portp->lp_state != AGGR_PORT_STATE_ATTACHED)) {
- AGGR_LACP_DBG(("lacp_selection_logic:(%s/%d): "
+ AGGR_LACP_DBG(("lacp_selection_logic:(%s): "
"selected %d-->%d (begin=%d, lacp_enabled = %d, "
- "lp_state=%d)\n", portp->lp_devname, portp->lp_port,
- pl->sm.selected, AGGR_UNSELECTED,
- pl->sm.begin, pl->sm.lacp_enabled,
+ "lp_state=%d)\n", portp->lp_devname, pl->sm.selected,
+ AGGR_UNSELECTED, pl->sm.begin, pl->sm.lacp_enabled,
portp->lp_state));
lacp_port_unselect(portp);
@@ -1216,9 +1206,8 @@ lacp_selection_logic(aggr_port_t *portp)
* If LACP is not enabled then selected is never set.
*/
if (!pl->sm.lacp_enabled) {
- AGGR_LACP_DBG(("lacp_selection_logic:(%s/%d): "
- "selected %d-->%d\n", portp->lp_devname, portp->lp_port,
- pl->sm.selected, AGGR_UNSELECTED));
+ AGGR_LACP_DBG(("lacp_selection_logic:(%s): selected %d-->%d\n",
+ portp->lp_devname, pl->sm.selected, AGGR_UNSELECTED));
lacp_port_unselect(portp);
lacp_mux_sm(portp);
@@ -1286,8 +1275,8 @@ lacp_selection_logic(aggr_port_t *portp)
*/
if (ether_cmp(&pl->PartnerOperSystem,
(struct ether_addr *)&aggrp->lg_addr) == 0) {
- cmn_err(CE_NOTE, "trunk link: (%s/%d): Loopback condition.\n",
- portp->lp_devname, portp->lp_port);
+ cmn_err(CE_NOTE, "trunk link: (%s): Loopback condition.\n",
+ portp->lp_devname);
lacp_port_unselect(portp);
lacp_mux_sm(portp);
@@ -1342,11 +1331,11 @@ lacp_selection_logic(aggr_port_t *portp)
*/
lacp_port_unselect(portp);
- cmn_err(CE_NOTE, "trunk link: (%s/%d): Port Partner MAC or"
+ cmn_err(CE_NOTE, "trunk link: (%s): Port Partner MAC or"
" key (%d) incompatible with Aggregation Partner "
"MAC or key (%d)\n",
- portp->lp_devname, portp->lp_port,
- pl->PartnerOperKey, aggrp->aggr.PartnerOperAggrKey);
+ portp->lp_devname, pl->PartnerOperKey,
+ aggrp->aggr.PartnerOperAggrKey);
lacp_mux_sm(portp);
return;
@@ -1354,8 +1343,8 @@ lacp_selection_logic(aggr_port_t *portp)
/* If we get to here, automatically set selected */
if (pl->sm.selected != AGGR_SELECTED) {
- AGGR_LACP_DBG(("lacp_selection_logic:(%s/%d): "
- "selected %d-->%d\n", portp->lp_devname, portp->lp_port,
+ AGGR_LACP_DBG(("lacp_selection_logic:(%s): "
+ "selected %d-->%d\n", portp->lp_devname,
pl->sm.selected, AGGR_SELECTED));
if (!lacp_port_select(portp))
return;
@@ -1396,14 +1385,12 @@ lacp_selection_logic(aggr_port_t *portp)
}
if (aggrp->aggr.ready) {
- AGGR_LACP_DBG(("lacp_selection_logic:(%s/%d): "
- "aggr.ready already set\n", portp->lp_devname,
- portp->lp_port));
+ AGGR_LACP_DBG(("lacp_selection_logic:(%s): "
+ "aggr.ready already set\n", portp->lp_devname));
lacp_mux_sm(portp);
} else {
- AGGR_LACP_DBG(("lacp_selection_logic:(%s/%d): Ready %d-->%d\n",
- portp->lp_devname, portp->lp_port, aggrp->aggr.ready,
- B_TRUE));
+ AGGR_LACP_DBG(("lacp_selection_logic:(%s): Ready %d-->%d\n",
+ portp->lp_devname, aggrp->aggr.ready, B_TRUE));
aggrp->aggr.ready = B_TRUE;
for (tpp = aggrp->lg_ports; tpp; tpp = tpp->lp_next)
@@ -1426,8 +1413,8 @@ wait_while_timer_pop(void *data)
AGGR_LACP_LOCK(portp->lp_grp);
- AGGR_LACP_DBG(("trunk link:(%s/%d): wait_while_timer pop \n",
- portp->lp_devname, portp->lp_port));
+ AGGR_LACP_DBG(("trunk link:(%s): wait_while_timer pop \n",
+ portp->lp_devname));
portp->lp_lacp.wait_while_timer.id = 0;
portp->lp_lacp.sm.ready_n = B_TRUE;
@@ -1479,8 +1466,8 @@ aggr_lacp_port_attached(aggr_port_t *portp)
ASSERT(portp->lp_state == AGGR_PORT_STATE_ATTACHED);
ASSERT(RW_WRITE_HELD(&portp->lp_lock));
- AGGR_LACP_DBG(("aggr_lacp_port_attached: "
- "port %s/%d\n", portp->lp_devname, portp->lp_port));
+ AGGR_LACP_DBG(("aggr_lacp_port_attached: port %s\n",
+ portp->lp_devname));
portp->lp_lacp.sm.port_enabled = B_TRUE; /* link on */
@@ -1535,8 +1522,8 @@ aggr_lacp_port_detached(aggr_port_t *portp)
ASSERT(AGGR_LACP_LOCK_HELD(grp));
ASSERT(RW_WRITE_HELD(&portp->lp_lock));
- AGGR_LACP_DBG(("aggr_lacp_port_detached: port %s/%d\n",
- portp->lp_devname, portp->lp_port));
+ AGGR_LACP_DBG(("aggr_lacp_port_detached: port %s\n",
+ portp->lp_devname));
portp->lp_lacp.sm.port_enabled = B_FALSE;
@@ -1580,8 +1567,7 @@ lacp_on(aggr_port_t *portp)
lacp_reset_port(portp);
portp->lp_lacp.sm.lacp_on = B_TRUE;
- AGGR_LACP_DBG(("lacp_on:(%s/%d): \n", portp->lp_devname,
- portp->lp_port));
+ AGGR_LACP_DBG(("lacp_on:(%s): \n", portp->lp_devname));
lacp_receive_sm(portp, NULL);
lacp_mux_sm(portp);
@@ -1609,8 +1595,7 @@ lacp_off(aggr_port_t *portp)
portp->lp_lacp.sm.lacp_on = B_FALSE;
- AGGR_LACP_DBG(("lacp_off:(%s/%d): \n", portp->lp_devname,
- portp->lp_port));
+ AGGR_LACP_DBG(("lacp_off:(%s): \n", portp->lp_devname));
/*
* Disable Slow Protocol Timers. We must temporarely release
@@ -1659,9 +1644,9 @@ valid_lacp_pdu(aggr_port_t *portp, lacp_t *lacp)
(lacp->partner_info.information_len != sizeof (link_info_t)) ||
(lacp->collector_len != LACP_COLLECTOR_INFO_LEN) ||
(lacp->terminator_len != LACP_TERMINATOR_INFO_LEN)) {
- AGGR_LACP_DBG(("trunk link (%s/%d): Malformed LACPDU: "
+ AGGR_LACP_DBG(("trunk link (%s): Malformed LACPDU: "
" Terminator Length = %d \n", portp->lp_devname,
- portp->lp_port, lacp->terminator_len));
+ lacp->terminator_len));
return (B_FALSE);
}
@@ -1717,8 +1702,8 @@ current_while_timer_pop(void *data)
AGGR_LACP_LOCK(portp->lp_grp);
- AGGR_LACP_DBG(("trunk link:(%s/%d): current_while_timer "
- "pop id=%p\n", portp->lp_devname, portp->lp_port,
+ AGGR_LACP_DBG(("trunk link:(%s): current_while_timer "
+ "pop id=%p\n", portp->lp_devname,
portp->lp_lacp.current_while_timer.id));
portp->lp_lacp.current_while_timer.id = 0;
@@ -1805,9 +1790,9 @@ record_PDU(aggr_port_t *portp, lacp_t *lacp)
}
if (save_sync != pl->PartnerOperPortState.bit.sync) {
- AGGR_LACP_DBG(("record_PDU:(%s/%d): partner sync "
- "%d -->%d\n", portp->lp_devname, portp->lp_port,
- save_sync, pl->PartnerOperPortState.bit.sync));
+ AGGR_LACP_DBG(("record_PDU:(%s): partner sync "
+ "%d -->%d\n", portp->lp_devname, save_sync,
+ pl->PartnerOperPortState.bit.sync));
return (B_TRUE);
} else {
return (B_FALSE);
@@ -1837,9 +1822,9 @@ update_selected(aggr_port_t *portp, lacp_t *lacp)
(pl->PartnerOperKey != ntohs(lacp->actor_info.key)) ||
(pl->PartnerOperPortState.bit.aggregation !=
lacp->actor_info.state.bit.aggregation)) {
- AGGR_LACP_DBG(("update_selected:(%s/%d): "
- "selected %d-->%d\n", portp->lp_devname, portp->lp_port,
- pl->sm.selected, AGGR_UNSELECTED));
+ AGGR_LACP_DBG(("update_selected:(%s): "
+ "selected %d-->%d\n", portp->lp_devname, pl->sm.selected,
+ AGGR_UNSELECTED));
lacp_port_unselect(portp);
return (B_TRUE);
@@ -1869,8 +1854,8 @@ update_default_selected(aggr_port_t *portp)
(pl->PartnerOperPortState.bit.aggregation !=
pl->PartnerAdminPortState.bit.aggregation)) {
- AGGR_LACP_DBG(("update_default_selected:(%s/%d): "
- "selected %d-->%d\n", portp->lp_devname, portp->lp_port,
+ AGGR_LACP_DBG(("update_default_selected:(%s): "
+ "selected %d-->%d\n", portp->lp_devname,
pl->sm.selected, AGGR_UNSELECTED));
lacp_port_unselect(portp);
@@ -1908,9 +1893,8 @@ update_NTT(aggr_port_t *portp, lacp_t *lacp)
(pl->ActorOperPortState.bit.aggregation !=
lacp->partner_info.state.bit.aggregation)) {
- AGGR_LACP_DBG(("update_NTT:(%s/%d): NTT %d-->%d\n",
- portp->lp_devname, portp->lp_port, pl->NTT,
- B_TRUE));
+ AGGR_LACP_DBG(("update_NTT:(%s): NTT %d-->%d\n",
+ portp->lp_devname, pl->NTT, B_TRUE));
pl->NTT = B_TRUE;
}
@@ -1967,9 +1951,8 @@ lacp_receive_sm(aggr_port_t *portp, lacp_t *lacp)
if (!((lacp && (oldstate == LACP_CURRENT) &&
(pl->sm.receive_state == LACP_CURRENT)))) {
- AGGR_LACP_DBG(("lacp_receive_sm(%s/%d):%s--->%s\n",
- portp->lp_devname, portp->lp_port,
- lacp_receive_str[oldstate],
+ AGGR_LACP_DBG(("lacp_receive_sm(%s):%s--->%s\n",
+ portp->lp_devname, lacp_receive_str[oldstate],
lacp_receive_str[pl->sm.receive_state]));
}
@@ -2057,8 +2040,8 @@ lacp_receive_sm(aggr_port_t *portp, lacp_t *lacp)
if (!lacp) /* no LACPDU so current_while_timer popped */
break;
- AGGR_LACP_DBG(("lacp_receive_sm: (%s/%d): "
- "LACPDU received:\n", portp->lp_devname, portp->lp_port));
+ AGGR_LACP_DBG(("lacp_receive_sm: (%s): LACPDU received:\n",
+ portp->lp_devname));
/*
* Validate Actor_Information_Length,
@@ -2066,9 +2049,9 @@ lacp_receive_sm(aggr_port_t *portp, lacp_t *lacp)
* and Terminator_Length fields.
*/
if (!valid_lacp_pdu(portp, lacp)) {
- AGGR_LACP_DBG(("lacp_receive_sm (%s/%d): "
+ AGGR_LACP_DBG(("lacp_receive_sm (%s): "
"Invalid LACPDU received\n",
- portp->lp_devname, portp->lp_port));
+ portp->lp_devname));
break;
}
@@ -2125,9 +2108,8 @@ aggr_set_coll_dist_locked(aggr_port_t *portp, boolean_t enable)
{
ASSERT(RW_WRITE_HELD(&portp->lp_lock));
- AGGR_LACP_DBG(("AGGR_SET_COLL_DIST_TYPE: (%s/%d) %s\n",
- portp->lp_devname, portp->lp_port,
- enable ? "ENABLED" : "DISABLED"));
+ AGGR_LACP_DBG(("AGGR_SET_COLL_DIST_TYPE: (%s) %s\n",
+ portp->lp_devname, enable ? "ENABLED" : "DISABLED"));
if (!enable) {
/*
@@ -2169,8 +2151,8 @@ aggr_lacp_rx(aggr_port_t *portp, mblk_t *dmp)
switch (lacp->subtype) {
case LACP_SUBTYPE:
- AGGR_LACP_DBG(("aggr_lacp_rx:(%s/%d): "
- "LACPDU received.\n", portp->lp_devname, portp->lp_port));
+ AGGR_LACP_DBG(("aggr_lacp_rx:(%s): LACPDU received.\n",
+ portp->lp_devname));
AGGR_LACP_LOCK(portp->lp_grp);
if (!portp->lp_lacp.sm.lacp_on) {
@@ -2182,17 +2164,16 @@ aggr_lacp_rx(aggr_port_t *portp, mblk_t *dmp)
break;
case MARKER_SUBTYPE:
- AGGR_LACP_DBG(("aggr_lacp_rx:(%s%d): "
- "Marker Packet received.\n",
- portp->lp_devname, portp->lp_port));
+ AGGR_LACP_DBG(("aggr_lacp_rx:(%s): Marker Packet received.\n",
+ portp->lp_devname));
(void) receive_marker_pdu(portp, dmp);
break;
default:
- AGGR_LACP_DBG(("aggr_lacp_rx: (%s%d): "
+ AGGR_LACP_DBG(("aggr_lacp_rx: (%s): "
"Unknown Slow Protocol type %d\n",
- portp->lp_devname, portp->lp_port, lacp->subtype));
+ portp->lp_devname, lacp->subtype));
break;
}
diff --git a/usr/src/uts/common/io/aggr/aggr_port.c b/usr/src/uts/common/io/aggr/aggr_port.c
index 3c19ef44c0..4c188a0583 100644
--- a/usr/src/uts/common/io/aggr/aggr_port.c
+++ b/usr/src/uts/common/io/aggr/aggr_port.c
@@ -46,6 +46,7 @@
#include <sys/atomic.h>
#include <sys/stat.h>
#include <sys/sdt.h>
+#include <sys/dlpi.h>
#include <sys/aggr.h>
#include <sys/aggr_impl.h>
@@ -99,7 +100,7 @@ aggr_port_resource_add(void *arg, mac_resource_t *mrp)
aggr_port_t *port = (aggr_port_t *)arg;
aggr_grp_t *grp = port->lp_grp;
- return (mac_resource_add(&grp->lg_mac, mrp));
+ return (mac_resource_add(grp->lg_mh, mrp));
}
void
@@ -114,18 +115,30 @@ aggr_port_init_callbacks(aggr_port_t *port)
}
int
-aggr_port_create(const char *name, uint_t portnum, aggr_port_t **pp)
+aggr_port_create(const char *name, aggr_port_t **pp)
{
int err;
mac_handle_t mh;
aggr_port_t *port;
uint_t i;
+ const mac_info_t *mip;
+ char driver[MAXNAMELEN];
+ uint_t ddi_instance;
*pp = NULL;
- if ((err = mac_open(name, portnum, &mh)) != 0)
+ if (ddi_parse(name, driver, &ddi_instance) != DDI_SUCCESS)
+ return (EINVAL);
+
+ if ((err = mac_open(name, ddi_instance, &mh)) != 0)
return (err);
+ mip = mac_info(mh);
+ if (mip->mi_media != DL_ETHER) {
+ mac_close(mh);
+ return (EINVAL);
+ }
+
if (!mac_active_set(mh)) {
mac_close(mh);
return (EBUSY);
@@ -136,8 +149,7 @@ aggr_port_create(const char *name, uint_t portnum, aggr_port_t **pp)
port->lp_refs = 1;
port->lp_next = NULL;
port->lp_mh = mh;
- port->lp_mip = mac_info(mh);
- port->lp_port = portnum;
+ port->lp_mip = mip;
(void) strlcpy(port->lp_devname, name, sizeof (port->lp_devname));
port->lp_closing = 0;
@@ -162,10 +174,12 @@ aggr_port_create(const char *name, uint_t portnum, aggr_port_t **pp)
* the consistituent ports.
*/
for (i = 0; i < MAC_NSTAT; i++) {
- /* avoid non-counter stats */
- if (i == MAC_STAT_IFSPEED || i == MAC_STAT_LINK_DUPLEX)
- continue;
- port->lp_stat[i] = aggr_port_stat(port, i);
+ port->lp_stat[i] =
+ aggr_port_stat(port, i + MAC_STAT_MIN);
+ }
+ for (i = 0; i < ETHER_NSTAT; i++) {
+ port->lp_ether_stat[i] =
+ aggr_port_stat(port, i + MACTYPE_STAT_MIN);
}
/* LACP related state */
@@ -238,7 +252,7 @@ aggr_port_notify_link(aggr_grp_t *grp, aggr_port_t *port, boolean_t dolock)
port->lp_link_state = link_state;
/* link duplex change? */
- link_duplex = aggr_port_stat(port, MAC_STAT_LINK_DUPLEX);
+ link_duplex = aggr_port_stat(port, ETHER_STAT_LINK_DUPLEX);
if (port->lp_link_duplex != link_duplex) {
if (link_duplex == LINK_DUPLEX_FULL)
do_attach |= (port->lp_link_duplex != LINK_DUPLEX_FULL);
@@ -355,19 +369,19 @@ aggr_port_notify_cb(void *arg, mac_notify_type_t type)
switch (type) {
case MAC_NOTE_TX:
- mac_tx_update(&grp->lg_mac);
+ mac_tx_update(grp->lg_mh);
break;
case MAC_NOTE_LINK:
if (aggr_port_notify_link(grp, port, B_TRUE))
- mac_link_update(&grp->lg_mac, grp->lg_link_state);
+ mac_link_update(grp->lg_mh, grp->lg_link_state);
break;
case MAC_NOTE_UNICST:
aggr_port_notify_unicst(grp, port, &mac_addr_changed,
&link_state_changed);
if (mac_addr_changed)
- mac_unicst_update(&grp->lg_mac, grp->lg_addr);
+ mac_unicst_update(grp->lg_mh, grp->lg_addr);
if (link_state_changed)
- mac_link_update(&grp->lg_mac, grp->lg_link_state);
+ mac_link_update(grp->lg_mh, grp->lg_link_state);
break;
case MAC_NOTE_PROMISC:
port->lp_txinfo = mac_tx_get(port->lp_mh);
@@ -461,10 +475,7 @@ aggr_port_multicst(void *arg, boolean_t add, const uint8_t *addrp)
}
uint64_t
-aggr_port_stat(aggr_port_t *port, enum mac_stat stat)
+aggr_port_stat(aggr_port_t *port, uint_t stat)
{
- if (!port->lp_mip->mi_stat[stat])
- return (0);
-
return (mac_stat_get(port->lp_mh, stat));
}
diff --git a/usr/src/uts/common/io/aggr/aggr_recv.c b/usr/src/uts/common/io/aggr/aggr_recv.c
index 2ce605012d..6e409e4b89 100644
--- a/usr/src/uts/common/io/aggr/aggr_recv.c
+++ b/usr/src/uts/common/io/aggr/aggr_recv.c
@@ -51,7 +51,7 @@ aggr_recv_lacp(aggr_port_t *port, mblk_t *mp)
mblk_t *nmp = copymsg(mp);
if (nmp != NULL)
- mac_rx(&grp->lg_mac, NULL, nmp);
+ mac_rx(grp->lg_mh, NULL, nmp);
}
aggr_lacp_rx(port, mp);
@@ -68,7 +68,7 @@ aggr_recv_cb(void *arg, mac_resource_handle_t mrh, mblk_t *mp)
aggr_grp_t *grp = port->lp_grp;
if (grp->lg_lacp_mode == AGGR_LACP_OFF) {
- mac_rx(&grp->lg_mac, mrh, mp);
+ mac_rx(grp->lg_mh, mrh, mp);
} else {
mblk_t *cmp, *last, *head;
struct ether_header *ehp;
@@ -89,12 +89,10 @@ aggr_recv_cb(void *arg, mac_resource_handle_t mrh, mblk_t *mp)
} else {
/* send up accumulated packets */
last->b_next = NULL;
- if (port->lp_collector_enabled) {
- mac_rx(&grp->lg_mac, mrh,
- head);
- } else {
+ if (port->lp_collector_enabled)
+ mac_rx(grp->lg_mh, mrh, head);
+ else
freemsgchain(head);
- }
head = cmp->b_next;
cmp->b_next = NULL;
freemsg(cmp);
@@ -124,12 +122,10 @@ aggr_recv_cb(void *arg, mac_resource_handle_t mrh, mblk_t *mp)
ASSERT(last != NULL);
/* send up non-LACP packets */
last->b_next = NULL;
- if (port->lp_collector_enabled) {
- mac_rx(&grp->lg_mac, mrh,
- head);
- } else {
+ if (port->lp_collector_enabled)
+ mac_rx(grp->lg_mh, mrh, head);
+ else
freemsgchain(head);
- }
/* unlink and pass up LACP packets */
head = cmp->b_next;
cmp->b_next = NULL;
@@ -144,7 +140,7 @@ aggr_recv_cb(void *arg, mac_resource_handle_t mrh, mblk_t *mp)
}
if (head != NULL) {
if (port->lp_collector_enabled)
- mac_rx(&grp->lg_mac, mrh, head);
+ mac_rx(grp->lg_mh, mrh, head);
else
freemsgchain(head);
}
diff --git a/usr/src/uts/common/io/bge/bge_chip2.c b/usr/src/uts/common/io/bge/bge_chip2.c
index a79c192377..1fa6c28f50 100644
--- a/usr/src/uts/common/io/bge/bge_chip2.c
+++ b/usr/src/uts/common/io/bge/bge_chip2.c
@@ -3274,7 +3274,7 @@ bge_chip_start(bge_t *bgep, boolean_t reset_phys)
*/
if (bgep->chipid.flags & CHIP_FLAG_PARTIAL_CSUM)
bge_reg_set32(bgep, MODE_CONTROL_REG,
- MODE_SEND_NO_PSEUDO_HDR_CSUM);
+ MODE_SEND_NO_PSEUDO_HDR_CSUM);
/*
* Step 29: configure Timer Prescaler. The value is always the
@@ -4333,7 +4333,7 @@ bge_chip_factotum(caddr_t arg)
* Note: can't do this while still holding the mutex.
*/
if (linkchg)
- mac_link_update(bgep->macp, bgep->link_state);
+ mac_link_update(bgep->mh, bgep->link_state);
return (result);
}
diff --git a/usr/src/uts/common/io/bge/bge_kstats.c b/usr/src/uts/common/io/bge/bge_kstats.c
index 9775794b13..da910a9061 100644
--- a/usr/src/uts/common/io/bge/bge_kstats.c
+++ b/usr/src/uts/common/io/bge/bge_kstats.c
@@ -889,23 +889,30 @@ bge_fini_kstats(bge_t *bgep)
kstat_delete(bgep->bge_kstats[i]);
}
-uint64_t
-bge_m_stat(void *arg, enum mac_stat stat)
+int
+bge_m_stat(void *arg, uint_t stat, uint64_t *val)
{
bge_t *bgep = arg;
bge_statistics_t *bstp;
- uint64_t val;
mutex_enter(bgep->genlock);
if (bgep->bge_chip_state == BGE_CHIP_FAULT) {
mutex_exit(bgep->genlock);
- return (0);
+ return (EINVAL);
+ }
+
+ /*
+ * The MII/GMII physical layer 802.3 stats are not supported by the
+ * bge optical interface.
+ */
+ if ((bgep->chipid.flags & CHIP_FLAG_SERDES) && ETHER_STAT_ISMII(stat)) {
+ mutex_exit(bgep->genlock);
+ return (ENOTSUP);
}
if (bgep->chipid.statistic_type == BGE_STAT_BLK)
bstp = DMA_VPTR(bgep->statistics);
else {
-
bgep->stat_val.ifHCOutOctets +=
bge_reg_get32(bgep, STAT_IFHCOUT_OCTETS_REG);
bgep->stat_val.etherStatsCollisions +=
@@ -968,341 +975,337 @@ bge_m_stat(void *arg, enum mac_stat stat)
switch (stat) {
case MAC_STAT_IFSPEED:
- val = bgep->param_link_speed * 1000000ull;
+ *val = bgep->param_link_speed * 1000000ull;
break;
case MAC_STAT_MULTIRCV:
if (bgep->chipid.statistic_type == BGE_STAT_BLK)
- val = bstp->s.ifHCInMulticastPkts;
+ *val = bstp->s.ifHCInMulticastPkts;
else
- val = bgep->stat_val.ifHCInMulticastPkts;
+ *val = bgep->stat_val.ifHCInMulticastPkts;
break;
case MAC_STAT_BRDCSTRCV:
if (bgep->chipid.statistic_type == BGE_STAT_BLK)
- val = bstp->s.ifHCInBroadcastPkts;
+ *val = bstp->s.ifHCInBroadcastPkts;
else
- val = bgep->stat_val.ifHCInBroadcastPkts;
+ *val = bgep->stat_val.ifHCInBroadcastPkts;
break;
case MAC_STAT_MULTIXMT:
if (bgep->chipid.statistic_type == BGE_STAT_BLK)
- val = bstp->s.ifHCOutMulticastPkts;
+ *val = bstp->s.ifHCOutMulticastPkts;
else
- val = bgep->stat_val.ifHCOutMulticastPkts;
+ *val = bgep->stat_val.ifHCOutMulticastPkts;
break;
case MAC_STAT_BRDCSTXMT:
if (bgep->chipid.statistic_type == BGE_STAT_BLK)
- val = bstp->s.ifHCOutBroadcastPkts;
+ *val = bstp->s.ifHCOutBroadcastPkts;
else
- val = bgep->stat_val.ifHCOutBroadcastPkts;
+ *val = bgep->stat_val.ifHCOutBroadcastPkts;
break;
case MAC_STAT_NORCVBUF:
if (bgep->chipid.statistic_type == BGE_STAT_BLK)
- val = bstp->s.ifInDiscards;
+ *val = bstp->s.ifInDiscards;
else
- val = 0;
+ *val = 0;
break;
case MAC_STAT_IERRORS:
- if (bgep->chipid.statistic_type == BGE_STAT_BLK)
- val = bstp->s.dot3StatsFCSErrors +
+ if (bgep->chipid.statistic_type == BGE_STAT_BLK) {
+ *val = bstp->s.dot3StatsFCSErrors +
bstp->s.dot3StatsAlignmentErrors +
bstp->s.dot3StatsFrameTooLongs +
bstp->s.etherStatsUndersizePkts +
bstp->s.etherStatsJabbers;
- else
- val = bgep->stat_val.dot3StatsFCSErrors +
+ } else {
+ *val = bgep->stat_val.dot3StatsFCSErrors +
bgep->stat_val.dot3StatsAlignmentErrors +
bgep->stat_val.dot3StatsFrameTooLongs +
bgep->stat_val.etherStatsUndersizePkts +
bgep->stat_val.etherStatsJabbers;
+ }
break;
case MAC_STAT_NOXMTBUF:
if (bgep->chipid.statistic_type == BGE_STAT_BLK)
- val = bstp->s.ifOutDiscards;
+ *val = bstp->s.ifOutDiscards;
else
- val = 0;
+ *val = 0;
break;
case MAC_STAT_OERRORS:
if (bgep->chipid.statistic_type == BGE_STAT_BLK)
- val = bstp->s.ifOutDiscards;
+ *val = bstp->s.ifOutDiscards;
else
- val = 0;
+ *val = 0;
break;
case MAC_STAT_COLLISIONS:
if (bgep->chipid.statistic_type == BGE_STAT_BLK)
- val = bstp->s.etherStatsCollisions;
+ *val = bstp->s.etherStatsCollisions;
else
- val = bgep->stat_val.etherStatsCollisions;
+ *val = bgep->stat_val.etherStatsCollisions;
break;
case MAC_STAT_RBYTES:
if (bgep->chipid.statistic_type == BGE_STAT_BLK)
- val = bstp->s.ifHCInOctets;
+ *val = bstp->s.ifHCInOctets;
else
- val = bgep->stat_val.ifHCInOctets;
+ *val = bgep->stat_val.ifHCInOctets;
break;
case MAC_STAT_IPACKETS:
if (bgep->chipid.statistic_type == BGE_STAT_BLK)
- val = bstp->s.ifHCInUcastPkts +
- bstp->s.ifHCInMulticastPkts +
- bstp->s.ifHCInBroadcastPkts;
+ *val = bstp->s.ifHCInUcastPkts +
+ bstp->s.ifHCInMulticastPkts +
+ bstp->s.ifHCInBroadcastPkts;
else
- val = bgep->stat_val.ifHCInUcastPkts +
- bgep->stat_val.ifHCInMulticastPkts +
- bgep->stat_val.ifHCInBroadcastPkts;
+ *val = bgep->stat_val.ifHCInUcastPkts +
+ bgep->stat_val.ifHCInMulticastPkts +
+ bgep->stat_val.ifHCInBroadcastPkts;
break;
case MAC_STAT_OBYTES:
if (bgep->chipid.statistic_type == BGE_STAT_BLK)
- val = bstp->s.ifHCOutOctets;
+ *val = bstp->s.ifHCOutOctets;
else
- val = bgep->stat_val.ifHCOutOctets;
+ *val = bgep->stat_val.ifHCOutOctets;
break;
case MAC_STAT_OPACKETS:
if (bgep->chipid.statistic_type == BGE_STAT_BLK)
- val = bstp->s.ifHCOutUcastPkts +
- bstp->s.ifHCOutMulticastPkts +
- bstp->s.ifHCOutBroadcastPkts;
+ *val = bstp->s.ifHCOutUcastPkts +
+ bstp->s.ifHCOutMulticastPkts +
+ bstp->s.ifHCOutBroadcastPkts;
else
- val = bgep->stat_val.ifHCOutUcastPkts +
- bgep->stat_val.ifHCOutMulticastPkts +
- bgep->stat_val.ifHCOutBroadcastPkts;
+ *val = bgep->stat_val.ifHCOutUcastPkts +
+ bgep->stat_val.ifHCOutMulticastPkts +
+ bgep->stat_val.ifHCOutBroadcastPkts;
break;
- case MAC_STAT_ALIGN_ERRORS:
+ case ETHER_STAT_ALIGN_ERRORS:
if (bgep->chipid.statistic_type == BGE_STAT_BLK)
- val = bstp->s.dot3StatsAlignmentErrors;
+ *val = bstp->s.dot3StatsAlignmentErrors;
else
- val = bgep->stat_val.dot3StatsAlignmentErrors;
+ *val = bgep->stat_val.dot3StatsAlignmentErrors;
break;
- case MAC_STAT_FCS_ERRORS:
+ case ETHER_STAT_FCS_ERRORS:
if (bgep->chipid.statistic_type == BGE_STAT_BLK)
- val = bstp->s.dot3StatsFCSErrors;
+ *val = bstp->s.dot3StatsFCSErrors;
else
- val = bgep->stat_val.dot3StatsFCSErrors;
+ *val = bgep->stat_val.dot3StatsFCSErrors;
break;
- case MAC_STAT_FIRST_COLLISIONS:
+ case ETHER_STAT_FIRST_COLLISIONS:
if (bgep->chipid.statistic_type == BGE_STAT_BLK)
- val = bstp->s.dot3StatsSingleCollisionFrames;
+ *val = bstp->s.dot3StatsSingleCollisionFrames;
else
- val = bgep->stat_val.dot3StatsSingleCollisionFrames;
+ *val = bgep->stat_val.dot3StatsSingleCollisionFrames;
break;
- case MAC_STAT_MULTI_COLLISIONS:
+ case ETHER_STAT_MULTI_COLLISIONS:
if (bgep->chipid.statistic_type == BGE_STAT_BLK)
- val = bstp->s.dot3StatsMultipleCollisionFrames;
+ *val = bstp->s.dot3StatsMultipleCollisionFrames;
else
- val = bgep->stat_val.dot3StatsMultipleCollisionFrames;
+ *val = bgep->stat_val.dot3StatsMultipleCollisionFrames;
break;
- case MAC_STAT_DEFER_XMTS:
+ case ETHER_STAT_DEFER_XMTS:
if (bgep->chipid.statistic_type == BGE_STAT_BLK)
- val = bstp->s.dot3StatsDeferredTransmissions;
+ *val = bstp->s.dot3StatsDeferredTransmissions;
else
- val = bgep->stat_val.dot3StatsDeferredTransmissions;
+ *val = bgep->stat_val.dot3StatsDeferredTransmissions;
break;
- case MAC_STAT_TX_LATE_COLLISIONS:
+ case ETHER_STAT_TX_LATE_COLLISIONS:
if (bgep->chipid.statistic_type == BGE_STAT_BLK)
- val = bstp->s.dot3StatsLateCollisions;
+ *val = bstp->s.dot3StatsLateCollisions;
else
- val = bgep->stat_val.dot3StatsLateCollisions;
+ *val = bgep->stat_val.dot3StatsLateCollisions;
break;
- case MAC_STAT_EX_COLLISIONS:
+ case ETHER_STAT_EX_COLLISIONS:
if (bgep->chipid.statistic_type == BGE_STAT_BLK)
- val = bstp->s.dot3StatsExcessiveCollisions;
+ *val = bstp->s.dot3StatsExcessiveCollisions;
else
- val = bgep->stat_val.dot3StatsExcessiveCollisions;
+ *val = bgep->stat_val.dot3StatsExcessiveCollisions;
break;
- case MAC_STAT_MACXMT_ERRORS:
+ case ETHER_STAT_MACXMT_ERRORS:
if (bgep->chipid.statistic_type == BGE_STAT_BLK)
- val = bstp->s.dot3StatsInternalMacTransmitErrors;
+ *val = bstp->s.dot3StatsInternalMacTransmitErrors;
else
- val = bgep->stat_val.dot3StatsInternalMacTransmitErrors;
+ *val = bgep->
+ stat_val.dot3StatsInternalMacTransmitErrors;
break;
- case MAC_STAT_CARRIER_ERRORS:
+ case ETHER_STAT_CARRIER_ERRORS:
if (bgep->chipid.statistic_type == BGE_STAT_BLK)
- val = bstp->s.dot3StatsCarrierSenseErrors;
+ *val = bstp->s.dot3StatsCarrierSenseErrors;
else
- val = 0;
+ *val = 0;
break;
- case MAC_STAT_TOOLONG_ERRORS:
+ case ETHER_STAT_TOOLONG_ERRORS:
if (bgep->chipid.statistic_type == BGE_STAT_BLK)
- val = bstp->s.dot3StatsFrameTooLongs;
+ *val = bstp->s.dot3StatsFrameTooLongs;
else
- val = bgep->stat_val.dot3StatsFrameTooLongs;
+ *val = bgep->stat_val.dot3StatsFrameTooLongs;
break;
- case MAC_STAT_XCVR_ADDR:
- val = bgep->phy_mii_addr;
+ case ETHER_STAT_XCVR_ADDR:
+ *val = bgep->phy_mii_addr;
break;
- case MAC_STAT_XCVR_ID:
- val = bge_mii_get16(bgep, MII_PHYIDH);
- val <<= 16;
- val |= bge_mii_get16(bgep, MII_PHYIDL);
+ case ETHER_STAT_XCVR_ID:
+ *val = bge_mii_get16(bgep, MII_PHYIDH);
+ *val <<= 16;
+ *val |= bge_mii_get16(bgep, MII_PHYIDL);
if (bge_check_acc_handle(bgep, bgep->io_handle) != DDI_FM_OK) {
ddi_fm_service_impact(bgep->devinfo,
DDI_SERVICE_UNAFFECTED);
}
break;
- case MAC_STAT_XCVR_INUSE:
- val = XCVR_1000T;
+ case ETHER_STAT_XCVR_INUSE:
+ *val = XCVR_1000T;
break;
- case MAC_STAT_CAP_1000FDX:
- val = 1;
+ case ETHER_STAT_CAP_1000FDX:
+ *val = 1;
break;
- case MAC_STAT_CAP_1000HDX:
- val = 1;
+ case ETHER_STAT_CAP_1000HDX:
+ *val = 1;
break;
- case MAC_STAT_CAP_100FDX:
- val = 1;
+ case ETHER_STAT_CAP_100FDX:
+ *val = 1;
break;
- case MAC_STAT_CAP_100HDX:
- val = 1;
+ case ETHER_STAT_CAP_100HDX:
+ *val = 1;
break;
- case MAC_STAT_CAP_10FDX:
- val = 1;
+ case ETHER_STAT_CAP_10FDX:
+ *val = 1;
break;
- case MAC_STAT_CAP_10HDX:
- val = 1;
+ case ETHER_STAT_CAP_10HDX:
+ *val = 1;
break;
- case MAC_STAT_CAP_ASMPAUSE:
- val = 1;
+ case ETHER_STAT_CAP_ASMPAUSE:
+ *val = 1;
break;
- case MAC_STAT_CAP_PAUSE:
- val = 1;
+ case ETHER_STAT_CAP_PAUSE:
+ *val = 1;
break;
- case MAC_STAT_CAP_AUTONEG:
- val = 1;
+ case ETHER_STAT_CAP_AUTONEG:
+ *val = 1;
break;
- case MAC_STAT_ADV_CAP_1000FDX:
- val = bgep->param_adv_1000fdx;
+ case ETHER_STAT_ADV_CAP_1000FDX:
+ *val = bgep->param_adv_1000fdx;
break;
- case MAC_STAT_ADV_CAP_1000HDX:
- val = bgep->param_adv_1000hdx;
+ case ETHER_STAT_ADV_CAP_1000HDX:
+ *val = bgep->param_adv_1000hdx;
break;
- case MAC_STAT_ADV_CAP_100FDX:
- val = bgep->param_adv_100fdx;
+ case ETHER_STAT_ADV_CAP_100FDX:
+ *val = bgep->param_adv_100fdx;
break;
- case MAC_STAT_ADV_CAP_100HDX:
- val = bgep->param_adv_100hdx;
+ case ETHER_STAT_ADV_CAP_100HDX:
+ *val = bgep->param_adv_100hdx;
break;
- case MAC_STAT_ADV_CAP_10FDX:
- val = bgep->param_adv_10fdx;
+ case ETHER_STAT_ADV_CAP_10FDX:
+ *val = bgep->param_adv_10fdx;
break;
- case MAC_STAT_ADV_CAP_10HDX:
- val = bgep->param_adv_10hdx;
+ case ETHER_STAT_ADV_CAP_10HDX:
+ *val = bgep->param_adv_10hdx;
break;
- case MAC_STAT_ADV_CAP_ASMPAUSE:
- val = bgep->param_adv_asym_pause;
+ case ETHER_STAT_ADV_CAP_ASMPAUSE:
+ *val = bgep->param_adv_asym_pause;
break;
- case MAC_STAT_ADV_CAP_PAUSE:
- val = bgep->param_adv_pause;
+ case ETHER_STAT_ADV_CAP_PAUSE:
+ *val = bgep->param_adv_pause;
break;
- case MAC_STAT_ADV_CAP_AUTONEG:
- val = bgep->param_adv_autoneg;
+ case ETHER_STAT_ADV_CAP_AUTONEG:
+ *val = bgep->param_adv_autoneg;
break;
- case MAC_STAT_LP_CAP_1000FDX:
- val = bgep->param_lp_1000fdx;
+ case ETHER_STAT_LP_CAP_1000FDX:
+ *val = bgep->param_lp_1000fdx;
break;
- case MAC_STAT_LP_CAP_1000HDX:
- val = bgep->param_lp_1000hdx;
+ case ETHER_STAT_LP_CAP_1000HDX:
+ *val = bgep->param_lp_1000hdx;
break;
- case MAC_STAT_LP_CAP_100FDX:
- val = bgep->param_lp_100fdx;
+ case ETHER_STAT_LP_CAP_100FDX:
+ *val = bgep->param_lp_100fdx;
break;
- case MAC_STAT_LP_CAP_100HDX:
- val = bgep->param_lp_100hdx;
+ case ETHER_STAT_LP_CAP_100HDX:
+ *val = bgep->param_lp_100hdx;
break;
- case MAC_STAT_LP_CAP_10FDX:
- val = bgep->param_lp_10fdx;
+ case ETHER_STAT_LP_CAP_10FDX:
+ *val = bgep->param_lp_10fdx;
break;
- case MAC_STAT_LP_CAP_10HDX:
- val = bgep->param_lp_10hdx;
+ case ETHER_STAT_LP_CAP_10HDX:
+ *val = bgep->param_lp_10hdx;
break;
- case MAC_STAT_LP_CAP_ASMPAUSE:
- val = bgep->param_lp_asym_pause;
+ case ETHER_STAT_LP_CAP_ASMPAUSE:
+ *val = bgep->param_lp_asym_pause;
break;
- case MAC_STAT_LP_CAP_PAUSE:
- val = bgep->param_lp_pause;
+ case ETHER_STAT_LP_CAP_PAUSE:
+ *val = bgep->param_lp_pause;
break;
- case MAC_STAT_LP_CAP_AUTONEG:
- val = bgep->param_lp_autoneg;
+ case ETHER_STAT_LP_CAP_AUTONEG:
+ *val = bgep->param_lp_autoneg;
break;
- case MAC_STAT_LINK_ASMPAUSE:
- val = bgep->param_adv_asym_pause &&
+ case ETHER_STAT_LINK_ASMPAUSE:
+ *val = bgep->param_adv_asym_pause &&
bgep->param_lp_asym_pause &&
bgep->param_adv_pause != bgep->param_lp_pause;
- break;
+ break;
- case MAC_STAT_LINK_PAUSE:
- val = bgep->param_link_rx_pause;
+ case ETHER_STAT_LINK_PAUSE:
+ *val = bgep->param_link_rx_pause;
break;
- case MAC_STAT_LINK_AUTONEG:
- val = bgep->param_link_autoneg;
+ case ETHER_STAT_LINK_AUTONEG:
+ *val = bgep->param_link_autoneg;
break;
- case MAC_STAT_LINK_DUPLEX:
- val = bgep->param_link_duplex;
+ case ETHER_STAT_LINK_DUPLEX:
+ *val = bgep->param_link_duplex;
break;
-#ifdef DEBUG
default:
- /*
- * Shouldn't reach here...
- */
- cmn_err(CE_PANIC,
- "bge_m_stat: unrecognized parameter value = %d",
- stat);
-#endif
+ mutex_exit(bgep->genlock);
+ return (ENOTSUP);
}
mutex_exit(bgep->genlock);
- return (val);
+ return (0);
}
diff --git a/usr/src/uts/common/io/bge/bge_main2.c b/usr/src/uts/common/io/bge/bge_main2.c
index dd4f01216a..a864deb8d6 100644
--- a/usr/src/uts/common/io/bge/bge_main2.c
+++ b/usr/src/uts/common/io/bge/bge_main2.c
@@ -117,6 +117,31 @@ static ether_addr_t bge_broadcast_addr = {
*/
static uint32_t bge_net1_boot_support = 1;
+static int bge_m_start(void *);
+static void bge_m_stop(void *);
+static int bge_m_promisc(void *, boolean_t);
+static int bge_m_multicst(void *, boolean_t, const uint8_t *);
+static int bge_m_unicst(void *, const uint8_t *);
+static void bge_m_resources(void *);
+static void bge_m_ioctl(void *, queue_t *, mblk_t *);
+static boolean_t bge_m_getcapab(void *, mac_capab_t, void *);
+
+#define BGE_M_CALLBACK_FLAGS (MC_RESOURCES | MC_IOCTL | MC_GETCAPAB)
+
+static mac_callbacks_t bge_m_callbacks = {
+ BGE_M_CALLBACK_FLAGS,
+ bge_m_stat,
+ bge_m_start,
+ bge_m_stop,
+ bge_m_promisc,
+ bge_m_multicst,
+ bge_m_unicst,
+ bge_m_tx,
+ bge_m_resources,
+ bge_m_ioctl,
+ bge_m_getcapab
+};
+
/*
* ========== Transmit and receive ring reinitialisation ==========
*/
@@ -738,6 +763,29 @@ bge_m_promisc(void *arg, boolean_t on)
return (0);
}
+/*ARGSUSED*/
+static boolean_t
+bge_m_getcapab(void *arg, mac_capab_t cap, void *cap_data)
+{
+ switch (cap) {
+ case MAC_CAPAB_HCKSUM: {
+ uint32_t *txflags = cap_data;
+
+ *txflags = HCKSUM_INET_FULL_V4 | HCKSUM_IPHDRCKSUM;
+ break;
+ }
+ case MAC_CAPAB_POLL:
+ /*
+ * There's nothing for us to fill in, simply returning
+ * B_TRUE stating that we support polling is sufficient.
+ */
+ break;
+ default:
+ return (B_FALSE);
+ }
+ return (B_TRUE);
+}
+
/*
* Loopback ioctl code
*/
@@ -1058,7 +1106,7 @@ bge_m_resources(void *arg)
for (ring = 0; ring < bgep->chipid.rx_rings; ring++) {
rrp = &bgep->recv[ring];
- rrp->handle = mac_resource_add(bgep->macp,
+ rrp->handle = mac_resource_add(bgep->mh,
(mac_resource_t *)&mrf);
}
@@ -1891,8 +1939,6 @@ bge_unattach(bge_t *bgep, uint_t asf_mode)
bge_unattach(bge_t *bgep)
#endif
{
- mac_t *macp;
-
BGE_TRACE(("bge_unattach($%p)",
(void *)bgep));
@@ -1967,8 +2013,6 @@ bge_unattach(bge_t *bgep)
bge_fm_fini(bgep);
ddi_remove_minor_node(bgep->devinfo, NULL);
- macp = bgep->macp;
- kmem_free(macp, sizeof (*macp));
kmem_free(bgep, sizeof (*bgep));
}
@@ -2045,8 +2089,6 @@ bge_resume(dev_info_t *devinfo)
return (DDI_SUCCESS);
}
-static uint8_t ether_brdcst[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
-
/*
* attach(9E) -- Attach a device to the system
*
@@ -2056,14 +2098,13 @@ static int
bge_attach(dev_info_t *devinfo, ddi_attach_cmd_t cmd)
{
bge_t *bgep; /* Our private data */
- mac_t *macp;
+ mac_register_t *macp;
chip_id_t *cidp;
cyc_handler_t cychand;
cyc_time_t cyctime;
caddr_t regs;
int instance;
int err;
- mac_info_t *mip;
int intr_types;
#ifdef BGE_IPMI_ASF
uint32_t mhcrValue;
@@ -2086,18 +2127,10 @@ bge_attach(dev_info_t *devinfo, ddi_attach_cmd_t cmd)
break;
}
- /*
- * Allocate mac_t and BGE private structures, and
- * cross-link them so that given either one of these or
- * the devinfo the others can be derived.
- */
- macp = kmem_zalloc(sizeof (*macp), KM_SLEEP);
bgep = kmem_zalloc(sizeof (*bgep), KM_SLEEP);
ddi_set_driver_private(devinfo, bgep);
bgep->bge_guard = BGE_GUARD;
bgep->devinfo = devinfo;
- bgep->macp = macp;
- macp->m_driver = bgep;
/*
* Initialize more fields in BGE private data
@@ -2395,47 +2428,22 @@ bge_attach(dev_info_t *devinfo, ddi_attach_cmd_t cmd)
ethaddr_copy(cidp->vendor_addr.addr, bgep->curr_addr.addr);
bgep->curr_addr.set = 1;
- /*
- * Initialize pointers to device specific functions which
- * will be used by the generic layer.
- */
- mip = &(macp->m_info);
- mip->mi_media = DL_ETHER;
- mip->mi_sdu_min = 0;
- mip->mi_sdu_max = cidp->ethmax_size - sizeof (struct ether_header);
- mip->mi_cksum = HCKSUM_INET_FULL_V4 | HCKSUM_IPHDRCKSUM;
- mip->mi_poll = DL_CAPAB_POLL;
-
- mip->mi_addr_length = ETHERADDRL;
- bcopy(ether_brdcst, mip->mi_brdcst_addr, ETHERADDRL);
- bcopy(bgep->curr_addr.addr, mip->mi_unicst_addr, ETHERADDRL);
-
- MAC_STAT_MIB(mip->mi_stat);
- mip->mi_stat[MAC_STAT_UNKNOWNS] = B_FALSE;
- MAC_STAT_ETHER(mip->mi_stat);
- mip->mi_stat[MAC_STAT_SQE_ERRORS] = B_FALSE;
- mip->mi_stat[MAC_STAT_MACRCV_ERRORS] = B_FALSE;
- if (!(bgep->chipid.flags & CHIP_FLAG_SERDES))
- MAC_STAT_MII(mip->mi_stat);
-
- macp->m_stat = bge_m_stat;
- macp->m_stop = bge_m_stop;
- macp->m_start = bge_m_start;
- macp->m_unicst = bge_m_unicst;
- macp->m_multicst = bge_m_multicst;
- macp->m_promisc = bge_m_promisc;
- macp->m_tx = bge_m_tx;
- macp->m_resources = bge_m_resources;
- macp->m_ioctl = bge_m_ioctl;
-
+ if ((macp = mac_alloc(MAC_VERSION)) == NULL)
+ goto attach_fail;
+ macp->m_type_ident = MAC_PLUGIN_IDENT_ETHER;
+ macp->m_driver = bgep;
macp->m_dip = devinfo;
- macp->m_ident = MAC_IDENT;
-
+ macp->m_src_addr = bgep->curr_addr.addr;
+ macp->m_callbacks = &bge_m_callbacks;
+ macp->m_min_sdu = 0;
+ macp->m_max_sdu = cidp->ethmax_size - sizeof (struct ether_header);
/*
* Finally, we're ready to register ourselves with the MAC layer
* interface; if this succeeds, we're all ready to start()
*/
- if (mac_register(macp) != 0)
+ err = mac_register(macp, &bgep->mh);
+ mac_free(macp);
+ if (err != 0)
goto attach_fail;
cychand.cyh_func = bge_chip_cyclic;
@@ -2556,7 +2564,7 @@ bge_detach(dev_info_t *devinfo, ddi_detach_cmd_t cmd)
* in which case we just return failure without shutting
* down chip operations.
*/
- if (mac_unregister(bgep->macp) != 0)
+ if (mac_unregister(bgep->mh) != 0)
return (DDI_FAILURE);
/*
diff --git a/usr/src/uts/common/io/bge/bge_recv2.c b/usr/src/uts/common/io/bge/bge_recv2.c
index 33f402f5da..0aa7074c9f 100644
--- a/usr/src/uts/common/io/bge/bge_recv2.c
+++ b/usr/src/uts/common/io/bge/bge_recv2.c
@@ -385,7 +385,7 @@ restart:
mutex_exit(rrp->rx_lock);
if (mp != NULL) {
- mac_rx(bgep->macp, rrp->handle, mp);
+ mac_rx(bgep->mh, rrp->handle, mp);
/*
* Restart from ring 0, if the driver is compiled
diff --git a/usr/src/uts/common/io/bge/bge_send.c b/usr/src/uts/common/io/bge/bge_send.c
index 34a08f02e0..f44172956d 100644
--- a/usr/src/uts/common/io/bge/bge_send.c
+++ b/usr/src/uts/common/io/bge/bge_send.c
@@ -510,7 +510,7 @@ bge_reschedule(caddr_t arg)
BGE_TRACE(("bge_reschedule($%p)", (void *)bgep));
if (bgep->bge_mac_state == BGE_MAC_STARTED && bgep->resched_needed) {
- mac_tx_update(bgep->macp);
+ mac_tx_update(bgep->mh);
bgep->resched_needed = B_FALSE;
bgep->resched_running = B_FALSE;
}
diff --git a/usr/src/uts/common/io/dld/dld_drv.c b/usr/src/uts/common/io/dld/dld_drv.c
index 455f1b3290..c37ab7651a 100644
--- a/usr/src/uts/common/io/dld/dld_drv.c
+++ b/usr/src/uts/common/io/dld/dld_drv.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -359,7 +358,7 @@ drv_close(queue_t *rq)
static void
drv_ioc_attr(dld_ctl_str_t *ctls, mblk_t *mp)
{
- dld_ioc_attr_t *diap;
+ dld_ioc_attr_t *diap;
dls_vlan_t *dvp = NULL;
dls_link_t *dlp = NULL;
int err;
@@ -377,8 +376,7 @@ drv_ioc_attr(dld_ctl_str_t *ctls, mblk_t *mp)
}
dlp = dvp->dv_dlp;
- (void) strlcpy(diap->dia_dev, dlp->dl_dev, MAXNAMELEN);
- diap->dia_port = dlp->dl_port;
+ (void) strlcpy(diap->dia_dev, dlp->dl_name, sizeof (diap->dia_dev));
diap->dia_vid = dvp->dv_id;
diap->dia_max_sdu = dlp->dl_mip->mi_sdu_max;
@@ -424,8 +422,7 @@ drv_ioc_vlan_info(dls_vlan_t *dvp, void *arg)
* passed buffer space is limited to 65536 bytes. So
* copy only the vlans associated with the passed link.
*/
- if (strcmp(dvp->dv_dlp->dl_dev, statep->divp->div_name) == 0 &&
- dvp->dv_dlp->dl_port == statep->divp->div_port &&
+ if (strcmp(dvp->dv_dlp->dl_name, statep->divp->div_name) == 0 &&
dvp->dv_id != 0) {
if (statep->bytes_left < sizeof (dld_vlan_info_t))
return (ENOSPC);
diff --git a/usr/src/uts/common/io/dld/dld_proto.c b/usr/src/uts/common/io/dld/dld_proto.c
index c67dadb391..467d55c2d1 100644
--- a/usr/src/uts/common/io/dld/dld_proto.c
+++ b/usr/src/uts/common/io/dld/dld_proto.c
@@ -176,8 +176,8 @@ dld_finish_pending_ops(dld_str_t *dsp)
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];
+ uint8_t dl_addr[MAXMACADDRLEN + sizeof (uint16_t)];
+ uint8_t dl_brdcst_addr[MAXMACADDRLEN];
dl_qos_cl_range1_t dl_qos_range1;
dl_qos_cl_sel1_t dl_qos_sel1;
} dl_info_ack_wrapper_t;
@@ -290,14 +290,16 @@ proto_info_req(dld_str_t *dsp, union DL_primitives *udlp, mblk_t *mp)
dlp->dl_max_sdu = minfop->mi_sdu_max;
addr_length = minfop->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(minfop->mi_brdcst_addr, brdcst_addr, addr_length);
- dlp->dl_brdcst_addr_length = addr_length;
+ if (minfop->mi_brdcst_addr != NULL) {
+ 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;
+ }
/*
* We only support QoS information for VLAN interfaces.
@@ -347,7 +349,8 @@ proto_info_req(dld_str_t *dsp, union DL_primitives *udlp, mblk_t *mp)
* DLSAP address.
*/
dlp->dl_addr_offset = (uintptr_t)addr - (uintptr_t)dlp;
- bcopy(dsp->ds_curr_addr, addr, addr_length);
+ if (addr_length > 0)
+ bcopy(dsp->ds_curr_addr, addr, addr_length);
*(uint16_t *)(addr + addr_length) = dsp->ds_sap;
}
@@ -492,7 +495,7 @@ 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 = 0;
- uint8_t addr[MAXADDRLEN];
+ uint8_t addr[MAXMACADDRLEN];
uint_t addr_length;
t_uscalar_t dl_err;
t_scalar_t sap;
@@ -1199,8 +1202,6 @@ proto_capability_req(dld_str_t *dsp, union DL_primitives *udlp, mblk_t *mp)
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.
@@ -1367,7 +1368,8 @@ proto_notify_req(dld_str_t *dsp, union DL_primitives *udlp, mblk_t *mp)
DL_NOTE_PHYS_ADDR |
DL_NOTE_LINK_UP |
DL_NOTE_LINK_DOWN |
- DL_NOTE_CAPAB_RENEG;
+ DL_NOTE_CAPAB_RENEG |
+ DL_NOTE_SPEED;
rw_enter(&dsp->ds_lock, RW_WRITER);
@@ -1382,9 +1384,6 @@ proto_notify_req(dld_str_t *dsp, union DL_primitives *udlp, mblk_t *mp)
goto failed;
}
- if (dsp->ds_mip->mi_stat[MAC_STAT_IFSPEED])
- note |= DL_NOTE_SPEED;
-
/*
* Cache the notifications that are being enabled.
*/
@@ -1426,7 +1425,7 @@ proto_unitdata_req(dld_str_t *dsp, union DL_primitives *udlp, mblk_t *mp)
const uint8_t *addr;
uint16_t sap;
uint_t addr_length;
- mblk_t *bp, *cont;
+ mblk_t *bp, *payload;
uint32_t start, stuff, end, value, flags;
t_uscalar_t dl_err;
@@ -1463,8 +1462,8 @@ proto_unitdata_req(dld_str_t *dsp, union DL_primitives *udlp, mblk_t *mp)
* Check the length of the packet and the block types.
*/
size = 0;
- cont = mp->b_cont;
- for (bp = cont; bp != NULL; bp = bp->b_cont) {
+ payload = mp->b_cont;
+ for (bp = payload; bp != NULL; bp = bp->b_cont) {
if (DB_TYPE(bp) != M_DATA)
goto baddata;
@@ -1475,16 +1474,10 @@ proto_unitdata_req(dld_str_t *dsp, union DL_primitives *udlp, mblk_t *mp)
goto baddata;
/*
- * sap <= ETHERMTU indicates that LLC is being used
- * and ethertype needs to be set to the payload length.
- */
- if (sap <= ETHERMTU)
- sap = (uint16_t)size;
-
- /*
* Build a packet header.
*/
- if ((bp = dls_header(dsp->ds_dc, addr, sap, dsp->ds_pri)) == NULL) {
+ bp = dls_header(dsp->ds_dc, addr, sap, dsp->ds_pri, payload);
+ if (bp == NULL) {
dl_err = DL_BADADDR;
goto failed;
}
@@ -1497,16 +1490,15 @@ proto_unitdata_req(dld_str_t *dsp, union DL_primitives *udlp, mblk_t *mp)
/*
* Transfer the checksum offload information if it is present.
*/
- hcksum_retrieve(cont, NULL, NULL, &start, &stuff, &end, &value,
+ hcksum_retrieve(payload, NULL, NULL, &start, &stuff, &end, &value,
&flags);
- (void) hcksum_assoc(bp, NULL, NULL, start, stuff, end, value, flags,
- 0);
+ (void) hcksum_assoc(bp, NULL, NULL, start, stuff, end, value, flags, 0);
/*
* Link the payload onto the new header.
*/
ASSERT(bp->b_cont == NULL);
- bp->b_cont = cont;
+ bp->b_cont = payload;
str_mdata_fastpath_put(dsp, bp);
rw_exit(&dsp->ds_lock);
@@ -1706,7 +1698,7 @@ proto_capability_advertise(dld_str_t *dsp, mblk_t *mp)
dl_capab_hcksum_t hcksum;
dl_capab_zerocopy_t zcopy;
uint8_t *ptr;
- uint32_t cksum;
+ boolean_t cksum_cap;
boolean_t poll_cap;
queue_t *q = dsp->ds_wq;
mblk_t *mp1;
@@ -1731,7 +1723,7 @@ proto_capability_advertise(dld_str_t *dsp, mblk_t *mp)
* If advertising DL_CAPAB_POLL has not been explicitly disabled
* then reserve space for that capability.
*/
- poll_cap = ((dsp->ds_mip->mi_poll & DL_CAPAB_POLL) &&
+ poll_cap = (mac_capab_get(dsp->ds_mh, MAC_CAPAB_POLL, NULL) &&
!(dld_opt & DLD_OPT_NO_POLL) && (dsp->ds_vid == VLAN_ID_NONE));
if (poll_cap) {
subsize += sizeof (dl_capability_sub_t) +
@@ -1742,7 +1734,8 @@ proto_capability_advertise(dld_str_t *dsp, mblk_t *mp)
* If the MAC interface supports checksum offload then reserve
* space for the DL_CAPAB_HCKSUM capability.
*/
- if ((cksum = dsp->ds_mip->mi_cksum) != 0) {
+ if (cksum_cap = mac_capab_get(dsp->ds_mh, MAC_CAPAB_HCKSUM,
+ &hcksum.hcksum_txflags)) {
subsize += sizeof (dl_capability_sub_t) +
sizeof (dl_capab_hcksum_t);
}
@@ -1794,9 +1787,8 @@ proto_capability_advertise(dld_str_t *dsp, mblk_t *mp)
* 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));
+ poll_cap = !(dld_opt & DLD_OPT_NO_POLL) &&
+ (dsp->ds_vid == VLAN_ID_NONE);
if (!poll_cap) {
int poll_capab_size;
@@ -1859,17 +1851,14 @@ proto_capability_advertise(dld_str_t *dsp, mblk_t *mp)
/*
* TCP/IP checksum offload.
*/
- if (cksum != 0) {
+ if (cksum_cap) {
dlsp = (dl_capability_sub_t *)ptr;
dlsp->dl_cap = DL_CAPAB_HCKSUM;
dlsp->dl_length = sizeof (dl_capab_hcksum_t);
ptr += sizeof (dl_capability_sub_t);
- bzero(&hcksum, sizeof (dl_capab_hcksum_t));
hcksum.hcksum_version = HCKSUM_VERSION_1;
- hcksum.hcksum_txflags = cksum;
-
dlcapabsetqid(&(hcksum.hcksum_mid), dsp->ds_rq);
bcopy(&hcksum, ptr, sizeof (dl_capab_hcksum_t));
ptr += sizeof (dl_capab_hcksum_t);
diff --git a/usr/src/uts/common/io/dld/dld_str.c b/usr/src/uts/common/io/dld/dld_str.c
index 8dc0dab931..29ea09c260 100644
--- a/usr/src/uts/common/io/dld/dld_str.c
+++ b/usr/src/uts/common/io/dld/dld_str.c
@@ -816,32 +816,25 @@ str_mdata_fastpath_put(dld_str_t *dsp, mblk_t *mp)
void
str_mdata_raw_put(dld_str_t *dsp, mblk_t *mp)
{
- struct ether_header *ehp;
- mblk_t *bp;
+ mblk_t *bp, *newmp;
size_t size;
- size_t hdrlen;
+ mac_header_info_t mhi;
- size = MBLKL(mp);
- if (size < sizeof (struct ether_header))
+ /*
+ * Certain MAC type plugins provide an illusion for raw DLPI
+ * consumers. They pretend that the MAC layer is something that
+ * it's not for the benefit of observability tools. For example, a
+ * wifi plugin might pretend that it's Ethernet for such consumers.
+ * Here, we call into the MAC layer so that this illusion can be
+ * maintained. The plugin will optionally transform the MAC header
+ * here into something that can be passed down. The header goes
+ * from raw mode to "cooked" mode.
+ */
+ if ((newmp = mac_header_cook(dsp->ds_mh, mp)) == NULL)
goto discard;
+ mp = newmp;
- hdrlen = sizeof (struct ether_header);
-
- ehp = (struct ether_header *)mp->b_rptr;
- if (ntohs(ehp->ether_type) == VLAN_TPID) {
- struct ether_vlan_header *evhp;
-
- if (size < sizeof (struct ether_vlan_header))
- goto discard;
-
- /*
- * Replace vtag with our own
- */
- evhp = (struct ether_vlan_header *)ehp;
- evhp->ether_tci = htons(VLAN_TCI(dsp->ds_pri,
- ETHER_CFI, dsp->ds_vid));
- hdrlen = sizeof (struct ether_vlan_header);
- }
+ size = MBLKL(mp);
/*
* Check the packet is not too big and that any remaining
@@ -855,9 +848,25 @@ str_mdata_raw_put(dld_str_t *dsp, mblk_t *mp)
size += MBLKL(bp);
}
- if (size > dsp->ds_mip->mi_sdu_max + hdrlen)
+ if (dls_header_info(dsp->ds_dc, mp, &mhi) != 0)
+ goto discard;
+
+ if (size > dsp->ds_mip->mi_sdu_max + mhi.mhi_hdrsize)
goto discard;
+ if (dsp->ds_mip->mi_media == DL_ETHER && mhi.mhi_origsap == VLAN_TPID) {
+ struct ether_vlan_header *evhp;
+
+ if (size < sizeof (struct ether_vlan_header))
+ goto discard;
+ /*
+ * Replace vtag with our own
+ */
+ evhp = (struct ether_vlan_header *)mp->b_rptr;
+ evhp->ether_tci = htons(VLAN_TCI(dsp->ds_pri,
+ ETHER_CFI, dsp->ds_vid));
+ }
+
str_mdata_fastpath_put(dsp, mp);
return;
@@ -978,7 +987,7 @@ dld_str_rx_raw(void *arg, mac_resource_handle_t mrh, mblk_t *mp,
size_t header_length)
{
dld_str_t *dsp = (dld_str_t *)arg;
- mblk_t *next;
+ mblk_t *next, *newmp;
ASSERT(mp != NULL);
do {
@@ -994,16 +1003,39 @@ dld_str_rx_raw(void *arg, mac_resource_handle_t mrh, mblk_t *mp,
*/
ASSERT(mp->b_rptr >= DB_BASE(mp) + header_length);
mp->b_rptr -= header_length;
- if (header_length == sizeof (struct ether_vlan_header)) {
- /*
- * Strip off the vtag
- */
- ovbcopy(mp->b_rptr, mp->b_rptr + VLAN_TAGSZ,
- 2 * ETHERADDRL);
- mp->b_rptr += VLAN_TAGSZ;
- }
/*
+ * Certain MAC type plugins provide an illusion for raw
+ * DLPI consumers. They pretend that the MAC layer is
+ * something that it's not for the benefit of observability
+ * tools. For example, a wifi plugin might pretend that
+ * it's Ethernet for such consumers. Here, we call into
+ * the MAC layer so that this illusion can be maintained.
+ * The plugin will optionally transform the MAC header here
+ * into something that can be passed up to raw consumers.
+ * The header goes from "cooked" mode to raw mode.
+ */
+ if ((newmp = mac_header_uncook(dsp->ds_mh, mp)) == NULL) {
+ freemsg(mp);
+ mp = next;
+ continue;
+ }
+ mp = newmp;
+
+ if (dsp->ds_mip->mi_media == DL_ETHER) {
+ struct ether_header *ehp =
+ (struct ether_header *)mp->b_rptr;
+
+ if (ntohs(ehp->ether_type) == VLAN_TPID) {
+ /*
+ * Strip off the vtag
+ */
+ ovbcopy(mp->b_rptr, mp->b_rptr + VLAN_TAGSZ,
+ 2 * ETHERADDRL);
+ mp->b_rptr += VLAN_TAGSZ;
+ }
+ }
+ /*
* Pass the packet on.
*/
if (canputnext(dsp->ds_rq))
@@ -1127,8 +1159,8 @@ dld_str_notify_ind(dld_str_t *dsp)
typedef struct dl_unitdata_ind_wrapper {
dl_unitdata_ind_t dl_unitdata;
- uint8_t dl_dest_addr[MAXADDRLEN + sizeof (uint16_t)];
- uint8_t dl_src_addr[MAXADDRLEN + sizeof (uint16_t)];
+ uint8_t dl_dest_addr[MAXMACADDRLEN + sizeof (uint16_t)];
+ uint8_t dl_src_addr[MAXMACADDRLEN + sizeof (uint16_t)];
} dl_unitdata_ind_wrapper_t;
/*
@@ -1140,7 +1172,7 @@ str_unitdata_ind(dld_str_t *dsp, mblk_t *mp)
mblk_t *nmp;
dl_unitdata_ind_wrapper_t *dlwp;
dl_unitdata_ind_t *dlp;
- dls_header_info_t dhi;
+ mac_header_info_t mhi;
uint_t addr_length;
uint8_t *daddr;
uint8_t *saddr;
@@ -1148,7 +1180,8 @@ str_unitdata_ind(dld_str_t *dsp, mblk_t *mp)
/*
* Get the packet header information.
*/
- dls_header_info(dsp->ds_dc, mp, &dhi);
+ if (dls_header_info(dsp->ds_dc, mp, &mhi) != 0)
+ return (NULL);
/*
* Allocate a message large enough to contain the wrapper structure
@@ -1171,7 +1204,7 @@ str_unitdata_ind(dld_str_t *dsp, mblk_t *mp)
addr_length = dsp->ds_mip->mi_addr_length;
daddr = dlwp->dl_dest_addr;
dlp->dl_dest_addr_offset = (uintptr_t)daddr - (uintptr_t)dlp;
- bcopy(dhi.dhi_daddr, daddr, addr_length);
+ bcopy(mhi.mhi_daddr, daddr, addr_length);
/*
* Set the destination DLSAP to our bound DLSAP value.
@@ -1180,23 +1213,29 @@ str_unitdata_ind(dld_str_t *dsp, mblk_t *mp)
dlp->dl_dest_addr_length = addr_length + sizeof (uint16_t);
/*
- * If the destination address was a group address then
+ * If the destination address was multicast or broadcast then the
* dl_group_address field should be non-zero.
*/
- dlp->dl_group_address = dhi.dhi_isgroup;
+ dlp->dl_group_address = (mhi.mhi_dsttype == MAC_ADDRTYPE_MULTICAST) ||
+ (mhi.mhi_dsttype == MAC_ADDRTYPE_BROADCAST);
/*
- * Copy in the source address.
+ * Copy in the source address if one exists. Some MAC types (DL_IB
+ * for example) may not have access to source information.
*/
- saddr = dlwp->dl_src_addr;
- dlp->dl_src_addr_offset = (uintptr_t)saddr - (uintptr_t)dlp;
- bcopy(dhi.dhi_saddr, saddr, addr_length);
+ if (mhi.mhi_saddr == NULL) {
+ dlp->dl_src_addr_offset = dlp->dl_src_addr_length = 0;
+ } else {
+ saddr = dlwp->dl_src_addr;
+ dlp->dl_src_addr_offset = (uintptr_t)saddr - (uintptr_t)dlp;
+ bcopy(mhi.mhi_saddr, saddr, addr_length);
- /*
- * Set the source DLSAP to the packet ethertype.
- */
- *(uint16_t *)(saddr + addr_length) = dhi.dhi_ethertype;
- dlp->dl_src_addr_length = addr_length + sizeof (uint16_t);
+ /*
+ * Set the source DLSAP to the packet ethertype.
+ */
+ *(uint16_t *)(saddr + addr_length) = mhi.mhi_origsap;
+ dlp->dl_src_addr_length = addr_length + sizeof (uint16_t);
+ }
return (nmp);
}
@@ -1384,6 +1423,30 @@ str_notify_capab_reneg(dld_str_t *dsp)
}
/*
+ * DL_NOTIFY_IND: DL_NOTE_FASTPATH_FLUSH
+ */
+static void
+str_notify_fastpath_flush(dld_str_t *dsp)
+{
+ mblk_t *mp;
+ dl_notify_ind_t *dlip;
+
+ if (!(dsp->ds_notifications & DL_NOTE_FASTPATH_FLUSH))
+ return;
+
+ if ((mp = mexchange(dsp->ds_wq, NULL, sizeof (dl_notify_ind_t),
+ M_PROTO, 0)) == NULL)
+ return;
+
+ bzero(mp->b_rptr, sizeof (dl_notify_ind_t));
+ dlip = (dl_notify_ind_t *)mp->b_rptr;
+ dlip->dl_primitive = DL_NOTIFY_IND;
+ dlip->dl_notification = DL_NOTE_FASTPATH_FLUSH;
+
+ qreply(dsp->ds_wq, mp);
+}
+
+/*
* MAC notification callback.
*/
static void
@@ -1429,27 +1492,18 @@ str_notify(void *arg, mac_notify_type_t type)
* updates the link state.
*/
switch (mac_link_get(dsp->ds_mh)) {
- case LINK_STATE_UP:
+ case LINK_STATE_UP: {
+ uint64_t speed;
/*
* The link is up so send the appropriate
* DL_NOTIFY_IND.
*/
str_notify_link_up(dsp);
- /*
- * If we can find the link speed then send a
- * DL_NOTIFY_IND for that too.
- */
- if (dsp->ds_mip->mi_stat[MAC_STAT_IFSPEED]) {
- uint64_t val;
-
- val = mac_stat_get(dsp->ds_mh,
- MAC_STAT_IFSPEED);
- str_notify_speed(dsp,
- (uint32_t)(val / 1000ull));
- }
+ speed = mac_stat_get(dsp->ds_mh, MAC_STAT_IFSPEED);
+ str_notify_speed(dsp, (uint32_t)(speed / 1000ull));
break;
-
+ }
case LINK_STATE_DOWN:
/*
* The link is down so send the appropriate
@@ -1472,6 +1526,10 @@ str_notify(void *arg, mac_notify_type_t type)
str_notify_capab_reneg(dsp);
break;
+ case MAC_NOTE_FASTPATH_FLUSH:
+ str_notify_fastpath_flush(dsp);
+ break;
+
default:
ASSERT(B_FALSE);
break;
@@ -1679,7 +1737,7 @@ ioc_fast(dld_str_t *dsp, mblk_t *mp)
sap = *(uint16_t *)(nmp->b_rptr + off + addr_length);
dc = dsp->ds_dc;
- if ((hmp = dls_header(dc, addr, sap, dsp->ds_pri)) == NULL) {
+ if ((hmp = dls_header(dc, addr, sap, dsp->ds_pri, NULL)) == NULL) {
rw_exit(&dsp->ds_lock);
err = ENOMEM;
goto failed;
diff --git a/usr/src/uts/common/io/dls/dls.c b/usr/src/uts/common/io/dls/dls.c
index a432743f65..51456292d5 100644
--- a/usr/src/uts/common/io/dls/dls.c
+++ b/usr/src/uts/common/io/dls/dls.c
@@ -106,164 +106,6 @@ i_dls_notify(void *arg, mac_notify_type_t type)
}
}
-static mblk_t *
-i_dls_ether_header(dls_impl_t *dip, const uint8_t *daddr, uint16_t sap,
- uint_t pri)
-{
- struct ether_header *ehp;
- struct ether_vlan_header *evhp;
- const mac_info_t *mip;
- uint_t addr_length;
- uint16_t vid;
- mblk_t *mp;
-
- mip = dip->di_mip;
- addr_length = mip->mi_addr_length;
-
- /*
- * Check whether the DLSAP value is legal for ethernet.
- */
- if (!SAP_LEGAL(mip->mi_media, sap))
- return (NULL);
-
- /*
- * If the interface is a VLAN interface then we need VLAN packet
- * headers.
- */
- if ((vid = dip->di_dvp->dv_id) != VLAN_ID_NONE)
- goto vlan;
-
- /*
- * Allocate a normal ethernet packet header.
- */
- if ((mp = allocb(sizeof (struct ether_header), BPRI_HI)) == NULL)
- return (NULL);
-
- /*
- * Copy in the given address as the destination, our current unicast
- * address as the source and the given sap as the type/length.
- */
- ehp = (struct ether_header *)mp->b_rptr;
- bcopy(daddr, &(ehp->ether_dhost), addr_length);
- bcopy(dip->di_unicst_addr, &(ehp->ether_shost), addr_length);
- ehp->ether_type = htons(sap);
-
- mp->b_wptr += sizeof (struct ether_header);
- return (mp);
-
-vlan:
- /*
- * Allocate a VLAN ethernet packet header.
- */
- if ((mp = allocb(sizeof (struct ether_vlan_header), BPRI_HI)) == NULL)
- return (NULL);
-
- /*
- * Copy in the given address as the destination, our current unicast
- * address as the source, the VLAN tpid and tci and the given sap as
- * the type/length.
- */
- evhp = (struct ether_vlan_header *)mp->b_rptr;
- bcopy(daddr, &(evhp->ether_dhost), addr_length);
- bcopy(dip->di_unicst_addr, &(evhp->ether_shost), addr_length);
- evhp->ether_tpid = htons(VLAN_TPID);
- evhp->ether_tci = htons(VLAN_TCI(pri, ETHER_CFI, vid));
- evhp->ether_type = htons(sap);
-
- mp->b_wptr += sizeof (struct ether_vlan_header);
- return (mp);
-}
-
-/*ARGSUSED*/
-static void
-i_dls_ether_header_info(dls_impl_t *dip, mblk_t *mp, dls_header_info_t *dhip)
-{
- struct ether_header *ehp;
- struct ether_vlan_header *evhp;
- uint16_t type_length;
- uint16_t tci;
-
- ASSERT(MBLKL(mp) >= sizeof (struct ether_header));
- ehp = (struct ether_header *)mp->b_rptr;
-
- /*
- * Determine whether to parse a normal or VLAN ethernet header.
- */
- if ((type_length = ntohs(ehp->ether_type)) == VLAN_TPID)
- goto vlan;
-
- /*
- * Specify the length of the header.
- */
- dhip->dhi_length = sizeof (struct ether_header);
-
- /*
- * Get the destination address.
- */
- dhip->dhi_daddr = (const uint8_t *)&(ehp->ether_dhost);
-
- /*
- * If the destination address was a group address then
- * dl_group_address field should be non-zero.
- */
- dhip->dhi_isgroup = (dhip->dhi_daddr[0] & 0x01);
-
- /*
- * Get the source address.
- */
- dhip->dhi_saddr = (uint8_t *)&(ehp->ether_shost);
-
- /*
- * Get the ethertype
- */
- dhip->dhi_ethertype = type_length;
-
- /*
- * The VLAN identifier must be VLAN_ID_NONE.
- */
- dhip->dhi_vid = VLAN_ID_NONE;
-
- return;
-
-vlan:
- ASSERT(MBLKL(mp) >= sizeof (struct ether_vlan_header));
- evhp = (struct ether_vlan_header *)mp->b_rptr;
-
- /*
- * Specify the length of the header.
- */
- dhip->dhi_length = sizeof (struct ether_vlan_header);
-
- /*
- * Get the destination address.
- */
- dhip->dhi_daddr = (const uint8_t *)&(evhp->ether_dhost);
-
- /*
- * If the destination address was a group address then
- * dl_group_address field should be non-zero.
- */
- dhip->dhi_isgroup = (dhip->dhi_daddr[0] & 0x01);
-
- /*
- * Get the source address.
- */
- dhip->dhi_saddr = (uint8_t *)&(evhp->ether_shost);
-
- /*
- * Get the ethertype
- */
- type_length = ntohs(evhp->ether_type);
- dhip->dhi_ethertype = type_length;
- ASSERT(dhip->dhi_ethertype != VLAN_TPID);
-
- /*
- * Get the VLAN identifier.
- */
- tci = ntohs(evhp->ether_tci);
- dhip->dhi_vid = VLAN_ID(tci);
-}
-
static void
dls_stat_init()
{
@@ -325,9 +167,9 @@ dls_fini(void)
*/
int
-dls_create(const char *name, const char *dev, uint_t port)
+dls_create(const char *linkname, const char *macname, uint_t ddi_instance)
{
- return (dls_vlan_create(name, dev, port, 0));
+ return (dls_vlan_create(linkname, macname, ddi_instance, 0));
}
int
@@ -373,14 +215,6 @@ dls_open(const char *name, dls_channel_t *dcp)
dip->di_txinfo = mac_tx_get(dip->di_mh);
/*
- * Set up packet header constructor and parser functions. (We currently
- * only support ethernet).
- */
- ASSERT(dip->di_mip->mi_media == DL_ETHER);
- dip->di_header = i_dls_ether_header;
- dip->di_header_info = i_dls_ether_header_info;
-
- /*
* Add a notification function so that we get updates from the MAC.
*/
dip->di_mnh = mac_notify_add(dip->di_mh, i_dls_notify, (void *)dip);
@@ -427,11 +261,12 @@ dls_close(dls_channel_t dc)
rw_exit(&(dip->di_lock));
dls_link_remove(dlp, dip);
rw_enter(&(dip->di_lock), RW_WRITER);
- dip->di_rx = NULL;
- dip->di_rx_arg = NULL;
dip->di_bound = B_FALSE;
}
+ dip->di_rx = NULL;
+ dip->di_rx_arg = NULL;
+
/*
* Walk the list of multicast addresses, disabling each at the MAC.
*/
@@ -481,30 +316,29 @@ dls_close(dls_channel_t dc)
mac_handle_t
dls_mac(dls_channel_t dc)
{
- dls_impl_t *dip = (dls_impl_t *)dc;
-
- return (dip->di_mh);
+ return (((dls_impl_t *)dc)->di_mh);
}
uint16_t
dls_vid(dls_channel_t dc)
{
- dls_impl_t *dip = (dls_impl_t *)dc;
-
- return (dip->di_dvp->dv_id);
+ return (((dls_impl_t *)dc)->di_dvp->dv_id);
}
int
-dls_bind(dls_channel_t dc, uint16_t sap)
+dls_bind(dls_channel_t dc, uint32_t sap)
{
dls_impl_t *dip = (dls_impl_t *)dc;
dls_link_t *dlp;
+ uint32_t dls_sap;
/*
* Check to see the value is legal for the media type.
*/
- if (!SAP_LEGAL(dip->di_mip->mi_media, sap))
+ if (!mac_sap_verify(dip->di_mh, sap, &dls_sap))
return (EINVAL);
+ if (dip->di_promisc & DLS_PROMISC_SAP)
+ dls_sap = DLS_SAP_PROMISC;
/*
* Set up the dls_impl_t to mark it as able to receive packets.
@@ -523,9 +357,7 @@ dls_bind(dls_channel_t dc, uint16_t sap)
* otherwise deadlock may ensue.
*/
dlp = dip->di_dvp->dv_dlp;
- dls_link_add(dlp,
- (dip->di_promisc & DLS_PROMISC_SAP) ? DLS_SAP_PROMISC :
- (uint32_t)sap, dip);
+ dls_link_add(dlp, dls_sap, dip);
return (0);
}
@@ -586,13 +418,16 @@ dls_promisc(dls_channel_t dc, uint32_t flags)
*/
if (!(flags & DLS_PROMISC_SAP) &&
(dip->di_promisc & DLS_PROMISC_SAP)) {
+ uint32_t dls_sap;
+
dip->di_promisc &= ~DLS_PROMISC_SAP;
if (!dip->di_bound)
goto multi;
rw_exit(&(dip->di_lock));
dls_link_remove(dlp, dip);
- dls_link_add(dlp, dip->di_sap, dip);
+ (void) mac_sap_verify(dip->di_mh, dip->di_sap, &dls_sap);
+ dls_link_add(dlp, dls_sap, dip);
rw_enter(&(dip->di_lock), RW_WRITER);
}
@@ -608,7 +443,7 @@ multi:
if (dlp->dl_npromisc == 0 &&
(flags & (DLS_PROMISC_MULTI|DLS_PROMISC_PHYS))) {
ASSERT(dlp->dl_mth == NULL);
- dlp->dl_mth = mac_txloop_add(dlp->dl_mh, dlp->dl_loopback, dlp);
+ dlp->dl_mth = mac_txloop_add(dlp->dl_mh, dlp->dl_txloop, dlp);
}
/*
@@ -766,19 +601,51 @@ done:
}
mblk_t *
-dls_header(dls_channel_t dc, const uint8_t *addr, uint16_t sap, uint_t pri)
+dls_header(dls_channel_t dc, const uint8_t *addr, uint16_t sap, uint_t pri,
+ mblk_t *payload)
{
dls_impl_t *dip = (dls_impl_t *)dc;
+ uint16_t vid;
+ size_t extra_len;
+ uint16_t mac_sap;
+ mblk_t *mp;
+ struct ether_vlan_header *evhp;
+
+ vid = dip->di_dvp->dv_id;
+ if (vid != VLAN_ID_NONE) {
+ /*
+ * We know ahead of time that we'll need to fill in
+ * additional VLAN information in the link-layer header.
+ * We will tell the MAC layer to pre-allocate some space at
+ * the end of the Ethernet header for us.
+ */
+ ASSERT(dip->di_mip->mi_media == DL_ETHER);
+ extra_len = sizeof (struct ether_vlan_header) -
+ sizeof (struct ether_header);
+ mac_sap = VLAN_TPID;
+ } else {
+ extra_len = 0;
+ mac_sap = sap;
+ }
+
+ mp = mac_header(dip->di_mh, addr, mac_sap, payload, extra_len);
+ if (vid == VLAN_ID_NONE || mp == NULL)
+ return (mp);
- return (dip->di_header(dip, addr, sap, pri));
+ /* This is an Ethernet VLAN link. Fill in the VLAN information */
+ ASSERT(MBLKL(mp) == sizeof (struct ether_header));
+ mp->b_wptr += extra_len;
+ evhp = (struct ether_vlan_header *)mp->b_rptr;
+ evhp->ether_tci = htons(VLAN_TCI(pri, ETHER_CFI, vid));
+ evhp->ether_type = htons(sap);
+ return (mp);
}
-void
-dls_header_info(dls_channel_t dc, mblk_t *mp, dls_header_info_t *dhip)
+int
+dls_header_info(dls_channel_t dc, mblk_t *mp, mac_header_info_t *mhip)
{
- dls_impl_t *dip = (dls_impl_t *)dc;
-
- dip->di_header_info(dip, mp, dhip);
+ return (dls_link_header_info(((dls_impl_t *)dc)->di_dvp->dv_dlp,
+ mp, mhip, NULL));
}
void
@@ -800,39 +667,12 @@ dls_tx(dls_channel_t dc, mblk_t *mp)
return (mtp->mt_fn(mtp->mt_arg, mp));
}
-/*
- * Exported functions.
- */
-
-#define ADDR_MATCH(_addr_a, _addr_b, _length, _match) \
- { \
- uint_t i; \
- \
- /* \
- * Make sure the addresses are 16 bit aligned and that \
- * the length is an even number of octets. \
- */ \
- ASSERT(IS_P2ALIGNED((_addr_a), sizeof (uint16_t))); \
- ASSERT(IS_P2ALIGNED((_addr_b), sizeof (uint16_t))); \
- ASSERT((_length & 1) == 0); \
- \
- (_match) = B_TRUE; \
- for (i = 0; i < (_length) >> 1; i++) { \
- if (((uint16_t *)(_addr_a))[i] != \
- ((uint16_t *)(_addr_b))[i]) { \
- (_match) = B_FALSE; \
- break; \
- } \
- } \
- }
-
boolean_t
-dls_accept(dls_impl_t *dip, const uint8_t *daddr, dls_rx_t *di_rx,
+dls_accept(dls_impl_t *dip, mac_header_info_t *mhip, dls_rx_t *di_rx,
void **di_rx_arg)
{
- boolean_t match;
dls_multicst_addr_t *dmap;
- uint_t addr_length = dip->di_mip->mi_addr_length;
+ size_t addr_length = dip->di_mip->mi_addr_length;
/*
* We must not accept packets if the dls_impl_t is not marked as bound
@@ -848,43 +688,39 @@ dls_accept(dls_impl_t *dip, const uint8_t *daddr, dls_rx_t *di_rx,
if (dip->di_promisc & DLS_PROMISC_PHYS)
goto accept;
- /*
- * Check to see if the destination address matches the dls_impl_t
- * unicast address.
- */
- ADDR_MATCH(daddr, dip->di_unicst_addr, addr_length, match);
- if (match)
- goto accept;
-
- /*
- * Check for a 'group' address. If it is not then refuse it since we
- * already know it does not match the unicast address.
- */
- if (!(daddr[0] & 0x01))
- goto refuse;
-
- /*
- * If the address is broadcast then the dls_impl_t will always accept
- * it.
- */
- ADDR_MATCH(daddr, dip->di_mip->mi_brdcst_addr, addr_length,
- match);
- if (match)
- goto accept;
-
- /*
- * If a group address is not broadcast then it must be multicast so
- * check it against the list of addresses enabled for this dls_impl_t
- * or accept it unconditionally if the dls_impl_t is in 'all
- * multicast' mode.
- */
- if (dip->di_promisc & DLS_PROMISC_MULTI)
- goto accept;
-
- for (dmap = dip->di_dmap; dmap != NULL; dmap = dmap->dma_nextp) {
- ADDR_MATCH(daddr, dmap->dma_addr, addr_length, match);
- if (match)
+ switch (mhip->mhi_dsttype) {
+ case MAC_ADDRTYPE_UNICAST:
+ /*
+ * Check to see if the destination address matches the
+ * dls_impl_t unicast address.
+ */
+ if (memcmp(mhip->mhi_daddr, dip->di_unicst_addr, addr_length) ==
+ 0) {
+ goto accept;
+ }
+ break;
+ case MAC_ADDRTYPE_MULTICAST:
+ /*
+ * Check the address against the list of addresses enabled
+ * for this dls_impl_t or accept it unconditionally if the
+ * dls_impl_t is in 'all multicast' mode.
+ */
+ if (dip->di_promisc & DLS_PROMISC_MULTI)
goto accept;
+ for (dmap = dip->di_dmap; dmap != NULL;
+ dmap = dmap->dma_nextp) {
+ if (memcmp(mhip->mhi_daddr, dmap->dma_addr,
+ addr_length) == 0) {
+ goto accept;
+ }
+ }
+ break;
+ case MAC_ADDRTYPE_BROADCAST:
+ /*
+ * If the address is broadcast then the dls_impl_t will
+ * always accept it.
+ */
+ goto accept;
}
refuse:
@@ -902,10 +738,8 @@ accept:
return (B_TRUE);
}
-/*ARGSUSED*/
boolean_t
-dls_accept_loopback(dls_impl_t *dip, const uint8_t *daddr, dls_rx_t *di_rx,
- void **di_rx_arg)
+dls_accept_loopback(dls_impl_t *dip, dls_rx_t *di_rx, void **di_rx_arg)
{
/*
* We must not accept packets if the dls_impl_t is not marked as bound
diff --git a/usr/src/uts/common/io/dls/dls_link.c b/usr/src/uts/common/io/dls/dls_link.c
index 0499a12074..47b0d99169 100644
--- a/usr/src/uts/common/io/dls/dls_link.c
+++ b/usr/src/uts/common/io/dls/dls_link.c
@@ -68,6 +68,15 @@ static krwlock_t i_dls_link_lock;
#define KEY_SAP(_key) \
(((uint32_t)(uintptr_t)(_key)) >> VLAN_ID_SIZE)
+#define DLS_STRIP_PADDING(pktsize, p) { \
+ if (pktsize != 0) { \
+ ssize_t delta = pktsize - msgdsize(p); \
+ \
+ if (delta < 0) \
+ (void) adjmsg(p, delta); \
+ } \
+}
+
/*
* Private functions.
*/
@@ -109,63 +118,38 @@ i_dls_link_destructor(void *buf, void *arg)
rw_destroy(&dlp->dl_impl_lock);
}
-#define ETHER_MATCH(_pkt_a, _pkt_b) \
- ((((uint16_t *)(_pkt_a))[0] == ((uint16_t *)(_pkt_b))[0]) && \
- (((uint16_t *)(_pkt_a))[1] == ((uint16_t *)(_pkt_b))[1]) && \
- (((uint16_t *)(_pkt_a))[2] == ((uint16_t *)(_pkt_b))[2]) && \
- (((uint16_t *)(_pkt_a))[6] == ((uint16_t *)(_pkt_b))[6]))
-
-#define ETHER_VLAN_MATCH(_pkt_a, _pkt_b) \
- ((((uint16_t *)(_pkt_a))[0] == ((uint16_t *)(_pkt_b))[0]) && \
- (((uint16_t *)(_pkt_a))[1] == ((uint16_t *)(_pkt_b))[1]) && \
- (((uint16_t *)(_pkt_a))[2] == ((uint16_t *)(_pkt_b))[2]) && \
- (((uint16_t *)(_pkt_a))[6] == ((uint16_t *)(_pkt_b))[6]) && \
- (((uint16_t *)(_pkt_a))[7] == ((uint16_t *)(_pkt_b))[7]) && \
- (((uint16_t *)(_pkt_a))[8] == ((uint16_t *)(_pkt_b))[8]))
-
-#define ETHER_STRIP_PADDING(typelen, hdrlen, p) { \
- if (typelen <= ETHERMTU) { \
- ssize_t delta = typelen + hdrlen - msgdsize(p); \
- \
- if (delta < 0) \
- (void) adjmsg(p, delta); \
- } \
-}
-
+/*
+ * Truncate the chain starting at mp such that all packets in the chain
+ * have identical source and destination addresses, saps, and VLAN tags (if
+ * any). It returns a pointer to the mblk following the chain, NULL if
+ * there is no further packet following the processed chain. The countp
+ * argument is set to the number of valid packets in the chain. It is set
+ * to 0 if the function encountered a problem with the first packet.
+ */
static mblk_t *
-i_dls_link_ether_subchain(mblk_t *mp, uint_t *header_lengthp,
- uint8_t **daddrp, uint16_t *type_lengthp, uint16_t *vidp,
- uint_t *countp)
+i_dls_link_subchain(dls_link_t *dlp, mblk_t *mp, mac_header_info_t *mhip,
+ uint16_t *vidp, uint_t *countp)
{
- struct ether_header *ehp;
- struct ether_vlan_header *evhp;
- mblk_t **pp;
- mblk_t *p;
- uint_t npacket;
+ mblk_t **pp;
+ mblk_t *p;
+ uint_t npacket;
+ size_t addr_size = dlp->dl_mip->mi_addr_length;
/*
* Packets should always be at least 16 bit aligned.
*/
ASSERT(IS_P2ALIGNED(mp->b_rptr, sizeof (uint16_t)));
- /*
- * Determine whether this is a VLAN or non-VLAN packet.
- */
- ASSERT(MBLKL(mp) >= sizeof (struct ether_header));
- ehp = (struct ether_header *)mp->b_rptr;
- if ((*type_lengthp = ntohs(ehp->ether_type)) == VLAN_TPID)
- goto vlan;
-
- /*
- * It is a non-VLAN header.
- */
- *header_lengthp = sizeof (struct ether_header);
-
- /*
- * Parse the rest of the header information that we need.
- */
- *daddrp = (uint8_t *)&(ehp->ether_dhost);
- *vidp = VLAN_ID_NONE;
+ if (dls_link_header_info(dlp, mp, mhip, vidp) != 0) {
+ /*
+ * Something is wrong with the initial header. No chain is
+ * possible.
+ */
+ p = mp->b_next;
+ mp->b_next = NULL;
+ *countp = 0;
+ return (p);
+ }
/*
* Compare with subsequent headers until we find one that has
@@ -174,55 +158,36 @@ i_dls_link_ether_subchain(mblk_t *mp, uint_t *header_lengthp,
*/
npacket = 1;
for (pp = &(mp->b_next); (p = *pp) != NULL; pp = &(p->b_next)) {
- if (!ETHER_MATCH(p->b_rptr, mp->b_rptr) != 0)
- break;
- ETHER_STRIP_PADDING(*type_lengthp, *header_lengthp, p);
- p->b_rptr += sizeof (struct ether_header);
- npacket++;
- }
-
- /*
- * Strip padding and skip over the initial packet's header.
- */
- ETHER_STRIP_PADDING(*type_lengthp, *header_lengthp, mp);
- mp->b_rptr += sizeof (struct ether_header);
- goto done;
+ mac_header_info_t cmhi;
+ uint16_t cvid;
-vlan:
- /*
- * It is a VLAN header.
- */
- evhp = (struct ether_vlan_header *)mp->b_rptr;
- *header_lengthp = sizeof (struct ether_vlan_header);
+ if (dls_link_header_info(dlp, p, &cmhi, &cvid) != 0)
+ break;
- /*
- * Parse the header information.
- */
- *daddrp = (uint8_t *)&(evhp->ether_dhost);
- *vidp = VLAN_ID(ntohs(evhp->ether_tci));
- *type_lengthp = ntohs(evhp->ether_type);
+ /*
+ * The source, destination, sap, and vlan id must all match
+ * in a given subchain.
+ */
+ if (memcmp(mhip->mhi_daddr, cmhi.mhi_daddr, addr_size) != 0 ||
+ memcmp(mhip->mhi_saddr, cmhi.mhi_saddr, addr_size) != 0 ||
+ mhip->mhi_bindsap != cmhi.mhi_bindsap) {
+ break;
+ }
- /*
- * Compare with subsequent headers until we find one that has
- * differing header information. After checking each packet
- * strip padding and skip over the header.
- */
- npacket = 1;
- for (pp = &(mp->b_next); (p = *pp) != NULL; pp = &(p->b_next)) {
- if (!ETHER_VLAN_MATCH(p->b_rptr, mp->b_rptr) != 0)
+ if (cvid != *vidp)
break;
- ETHER_STRIP_PADDING(*type_lengthp, *header_lengthp, p);
- p->b_rptr += sizeof (struct ether_vlan_header);
+
+ DLS_STRIP_PADDING(cmhi.mhi_pktsize, p);
+ p->b_rptr += cmhi.mhi_hdrsize;
npacket++;
}
/*
* Strip padding and skip over the initial packet's header.
*/
- ETHER_STRIP_PADDING(*type_lengthp, *header_lengthp, mp);
- mp->b_rptr += sizeof (struct ether_vlan_header);
+ DLS_STRIP_PADDING(mhip->mhi_pktsize, mp);
+ mp->b_rptr += mhip->mhi_hdrsize;
-done:
/*
* Break the chain at this point and return a pointer to the next
* sub-chain.
@@ -262,16 +227,13 @@ i_dls_head_free(dls_head_t *dhp)
}
static void
-i_dls_link_ether_rx(void *arg, mac_resource_handle_t mrh, mblk_t *mp)
+i_dls_link_rx(void *arg, mac_resource_handle_t mrh, mblk_t *mp)
{
dls_link_t *dlp = arg;
mod_hash_t *hash = dlp->dl_impl_hash;
mblk_t *nextp;
- uint_t header_length;
- uint8_t *daddr;
- uint16_t type_length;
+ mac_header_info_t mhi;
uint16_t vid;
- uint16_t sap;
dls_head_t *dhp;
dls_impl_t *dip;
dls_impl_t *ndip;
@@ -295,21 +257,24 @@ i_dls_link_ether_rx(void *arg, mac_resource_handle_t mrh, mblk_t *mp)
* Grab the longest sub-chain we can process as a single
* unit.
*/
- nextp = i_dls_link_ether_subchain(mp, &header_length, &daddr,
- &type_length, &vid, &npacket);
+ nextp = i_dls_link_subchain(dlp, mp, &mhi, &vid, &npacket);
- /*
- * Calculate the DLSAP: LLC (0) if the type/length field is
- * interpreted as a length, otherwise it is the value of the
- * type/length field.
- */
- sap = (type_length <= ETHERMTU) ? DLS_SAP_LLC : type_length;
+ if (npacket == 0) {
+ /*
+ * The first packet had an unrecognized header.
+ * Modify npacket so that this stray can be
+ * accounted for.
+ */
+ npacket = 1;
+ freemsg(mp);
+ goto loop;
+ }
/*
* Construct a hash key from the VLAN identifier and the
* DLSAP.
*/
- key = MAKE_KEY(sap, vid);
+ key = MAKE_KEY(mhi.mhi_bindsap, vid);
/*
* Search the has table for dls_impl_t eligible to receive
@@ -328,7 +293,7 @@ i_dls_link_ether_rx(void *arg, mac_resource_handle_t mrh, mblk_t *mp)
* Find the first dls_impl_t that will accept the sub-chain.
*/
for (dip = dhp->dh_list; dip != NULL; dip = dip->di_nextp)
- if (dls_accept(dip, daddr, &di_rx, &di_rx_arg))
+ if (dls_accept(dip, &mhi, &di_rx, &di_rx_arg))
break;
/*
@@ -352,7 +317,7 @@ i_dls_link_ether_rx(void *arg, mac_resource_handle_t mrh, mblk_t *mp)
*/
for (ndip = dip->di_nextp; ndip != NULL;
ndip = ndip->di_nextp)
- if (dls_accept(ndip, daddr, &ndi_rx,
+ if (dls_accept(ndip, &mhi, &ndi_rx,
&ndi_rx_arg))
break;
@@ -362,7 +327,7 @@ i_dls_link_ether_rx(void *arg, mac_resource_handle_t mrh, mblk_t *mp)
* it before handing it to the current one.
*/
if (ndip == NULL) {
- di_rx(di_rx_arg, mrh, mp, header_length);
+ di_rx(di_rx_arg, mrh, mp, mhi.mhi_hdrsize);
/*
* Since there are no more dls_impl_t, we're
@@ -375,7 +340,7 @@ i_dls_link_ether_rx(void *arg, mac_resource_handle_t mrh, mblk_t *mp)
* There are more dls_impl_t so dup the sub-chain.
*/
if ((nmp = copymsgchain(mp)) != NULL)
- di_rx(di_rx_arg, mrh, nmp, header_length);
+ di_rx(di_rx_arg, mrh, nmp, mhi.mhi_hdrsize);
dip = ndip;
di_rx = ndi_rx;
@@ -404,17 +369,13 @@ loop:
}
static void
-i_dls_link_ether_rx_promisc(void *arg, mac_resource_handle_t mrh,
- mblk_t *mp)
+i_dls_link_rx_promisc(void *arg, mac_resource_handle_t mrh, mblk_t *mp)
{
dls_link_t *dlp = arg;
mod_hash_t *hash = dlp->dl_impl_hash;
mblk_t *nextp;
- uint_t header_length;
- uint8_t *daddr;
- uint16_t type_length;
+ mac_header_info_t mhi;
uint16_t vid;
- uint16_t sap;
dls_head_t *dhp;
dls_impl_t *dip;
dls_impl_t *ndip;
@@ -438,8 +399,18 @@ i_dls_link_ether_rx_promisc(void *arg, mac_resource_handle_t mrh,
* Grab the longest sub-chain we can process as a single
* unit.
*/
- nextp = i_dls_link_ether_subchain(mp, &header_length, &daddr,
- &type_length, &vid, &npacket);
+ nextp = i_dls_link_subchain(dlp, mp, &mhi, &vid, &npacket);
+
+ if (npacket == 0) {
+ /*
+ * The first packet had an unrecognized header.
+ * Modify npacket so that this stray can be
+ * accounted for.
+ */
+ npacket = 1;
+ freemsg(mp);
+ goto loop;
+ }
/*
* Construct a hash key from the VLAN identifier and the
@@ -463,7 +434,7 @@ i_dls_link_ether_rx_promisc(void *arg, mac_resource_handle_t mrh,
* Find dls_impl_t that will accept the sub-chain.
*/
for (dip = dhp->dh_list; dip != NULL; dip = dip->di_nextp) {
- if (!dls_accept(dip, daddr, &di_rx, &di_rx_arg))
+ if (!dls_accept(dip, &mhi, &di_rx, &di_rx_arg))
continue;
/*
@@ -477,7 +448,7 @@ i_dls_link_ether_rx_promisc(void *arg, mac_resource_handle_t mrh,
* dls_impl_t) so dup the sub-chain.
*/
if ((nmp = copymsgchain(mp)) != NULL)
- di_rx(di_rx_arg, mrh, nmp, header_length);
+ di_rx(di_rx_arg, mrh, nmp, mhi.mhi_hdrsize);
}
/*
@@ -488,17 +459,10 @@ i_dls_link_ether_rx_promisc(void *arg, mac_resource_handle_t mrh,
non_promisc:
/*
- * Calculate the DLSAP: LLC (0) if the type/length field is
- * interpreted as a length, otherwise it is the value of the
- * type/length field.
- */
- sap = (type_length <= ETHERMTU) ? DLS_SAP_LLC : type_length;
-
- /*
* Construct a hash key from the VLAN identifier and the
* DLSAP.
*/
- key = MAKE_KEY(sap, vid);
+ key = MAKE_KEY(mhi.mhi_bindsap, vid);
/*
* Search the has table for dls_impl_t eligible to receive
@@ -517,7 +481,7 @@ non_promisc:
* Find the first dls_impl_t that will accept the sub-chain.
*/
for (dip = dhp->dh_list; dip != NULL; dip = dip->di_nextp)
- if (dls_accept(dip, daddr, &di_rx, &di_rx_arg))
+ if (dls_accept(dip, &mhi, &di_rx, &di_rx_arg))
break;
/*
@@ -541,7 +505,7 @@ non_promisc:
*/
for (ndip = dip->di_nextp; ndip != NULL;
ndip = ndip->di_nextp)
- if (dls_accept(ndip, daddr, &ndi_rx,
+ if (dls_accept(ndip, &mhi, &ndi_rx,
&ndi_rx_arg))
break;
@@ -551,7 +515,7 @@ non_promisc:
* it before handing it to the current one.
*/
if (ndip == NULL) {
- di_rx(di_rx_arg, mrh, mp, header_length);
+ di_rx(di_rx_arg, mrh, mp, mhi.mhi_hdrsize);
/*
* Since there are no more dls_impl_t, we're
@@ -564,7 +528,7 @@ non_promisc:
* There are more dls_impl_t so dup the sub-chain.
*/
if ((nmp = copymsgchain(mp)) != NULL)
- di_rx(di_rx_arg, mrh, nmp, header_length);
+ di_rx(di_rx_arg, mrh, nmp, mhi.mhi_hdrsize);
dip = ndip;
di_rx = ndi_rx;
@@ -593,16 +557,13 @@ loop:
}
static void
-i_dls_link_ether_loopback(void *arg, mblk_t *mp)
+i_dls_link_txloop(void *arg, mblk_t *mp)
{
dls_link_t *dlp = arg;
mod_hash_t *hash = dlp->dl_impl_hash;
mblk_t *nextp;
- uint_t header_length;
- uint8_t *daddr;
- uint16_t type_length;
+ mac_header_info_t mhi;
uint16_t vid;
- uint16_t sap;
dls_head_t *dhp;
dls_impl_t *dip;
dls_impl_t *ndip;
@@ -620,21 +581,18 @@ i_dls_link_ether_loopback(void *arg, mblk_t *mp)
* Grab the longest sub-chain we can process as a single
* unit.
*/
- nextp = i_dls_link_ether_subchain(mp, &header_length, &daddr,
- &type_length, &vid, &npacket);
+ nextp = i_dls_link_subchain(dlp, mp, &mhi, &vid, &npacket);
- /*
- * Calculate the DLSAP: LLC (0) if the type/length field is
- * interpreted as a length, otherwise it is the value of the
- * type/length field.
- */
- sap = (type_length <= ETHERMTU) ? DLS_SAP_LLC : type_length;
+ if (npacket == 0) {
+ freemsg(mp);
+ goto loop;
+ }
/*
* Construct a hash key from the VLAN identifier and the
* DLSAP.
*/
- key = MAKE_KEY(sap, vid);
+ key = MAKE_KEY(mhi.mhi_bindsap, vid);
/*
* Search the has table for dls_impl_t eligible to receive
@@ -652,8 +610,7 @@ i_dls_link_ether_loopback(void *arg, mblk_t *mp)
* Find dls_impl_t that will accept the sub-chain.
*/
for (dip = dhp->dh_list; dip != NULL; dip = dip->di_nextp) {
- if (!dls_accept_loopback(dip, daddr, &di_rx,
- &di_rx_arg))
+ if (!dls_accept_loopback(dip, &di_rx, &di_rx_arg))
continue;
/*
@@ -662,7 +619,7 @@ i_dls_link_ether_loopback(void *arg, mblk_t *mp)
* mode) so dup the sub-chain.
*/
if ((nmp = copymsgchain(mp)) != NULL)
- di_rx(di_rx_arg, NULL, nmp, header_length);
+ di_rx(di_rx_arg, NULL, nmp, mhi.mhi_hdrsize);
}
/*
@@ -695,7 +652,7 @@ promisc:
* Find the first dls_impl_t that will accept the sub-chain.
*/
for (dip = dhp->dh_list; dip != NULL; dip = dip->di_nextp)
- if (dls_accept_loopback(dip, daddr, &di_rx, &di_rx_arg))
+ if (dls_accept_loopback(dip, &di_rx, &di_rx_arg))
break;
/*
@@ -715,9 +672,10 @@ promisc:
*/
for (ndip = dip->di_nextp; ndip != NULL;
ndip = ndip->di_nextp)
- if (dls_accept_loopback(ndip, daddr,
- &ndi_rx, &ndi_rx_arg))
+ if (dls_accept_loopback(ndip, &ndi_rx,
+ &ndi_rx_arg)) {
break;
+ }
/*
* If there are no more dls_impl_t that are willing
@@ -725,7 +683,7 @@ promisc:
* it before handing it to the current one.
*/
if (ndip == NULL) {
- di_rx(di_rx_arg, NULL, mp, header_length);
+ di_rx(di_rx_arg, NULL, mp, mhi.mhi_hdrsize);
/*
* Since there are no more dls_impl_t, we're
@@ -738,7 +696,7 @@ promisc:
* There are more dls_impl_t so dup the sub-chain.
*/
if ((nmp = copymsgchain(mp)) != NULL)
- di_rx(di_rx_arg, NULL, nmp, header_length);
+ di_rx(di_rx_arg, NULL, nmp, mhi.mhi_hdrsize);
dip = ndip;
di_rx = ndi_rx;
@@ -775,7 +733,7 @@ i_dls_link_walk(mod_hash_key_t key, mod_hash_val_t *val, void *arg)
}
static int
-i_dls_link_create(const char *dev, uint_t port, dls_link_t **dlpp)
+i_dls_link_create(const char *name, uint_t ddi_instance, dls_link_t **dlpp)
{
dls_link_t *dlp;
@@ -787,15 +745,14 @@ i_dls_link_create(const char *dev, uint_t port, dls_link_t **dlpp)
/*
* Name the dls_link_t after the MAC interface it represents.
*/
- MAC_NAME(dlp->dl_name, dev, port);
- (void) strlcpy(dlp->dl_dev, dev, MAXNAMELEN);
- dlp->dl_port = port;
+ (void) strlcpy(dlp->dl_name, name, sizeof (dlp->dl_name));
+ dlp->dl_ddi_instance = ddi_instance;
/*
* Set the packet loopback function for use when the MAC is in
* promiscuous mode, and initialize promiscuous bookeeping fields.
*/
- dlp->dl_loopback = i_dls_link_ether_loopback;
+ dlp->dl_txloop = i_dls_link_txloop;
dlp->dl_npromisc = 0;
dlp->dl_mth = NULL;
@@ -871,19 +828,12 @@ dls_link_fini(void)
*/
int
-dls_link_hold(const char *dev, uint_t port, dls_link_t **dlpp)
+dls_link_hold(const char *name, uint_t ddi_instance, dls_link_t **dlpp)
{
- char name[MAXNAMELEN];
dls_link_t *dlp;
int err;
/*
- * Construct a copy of the name used to identify any existing
- * dls_link_t.
- */
- MAC_NAME(name, dev, port);
-
- /*
* Look up a dls_link_t corresponding to the given mac_handle_t
* 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
@@ -899,7 +849,7 @@ dls_link_hold(const char *dev, uint_t port, dls_link_t **dlpp)
/*
* We didn't find anything so we need to create one.
*/
- if ((err = i_dls_link_create(dev, port, &dlp)) != 0) {
+ if ((err = i_dls_link_create(name, ddi_instance, &dlp)) != 0) {
rw_exit(&i_dls_link_lock);
return (err);
}
@@ -907,7 +857,7 @@ dls_link_hold(const char *dev, uint_t port, dls_link_t **dlpp)
/*
* Insert the dls_link_t.
*/
- err = mod_hash_insert(i_dls_link_hash, (mod_hash_key_t)dlp->dl_name,
+ err = mod_hash_insert(i_dls_link_hash, (mod_hash_key_t)name,
(mod_hash_val_t)dlp);
ASSERT(err == 0);
@@ -969,7 +919,7 @@ dls_mac_hold(dls_link_t *dlp)
/*
* First reference; hold open the MAC interface.
*/
- err = mac_open(dlp->dl_dev, dlp->dl_port, &dlp->dl_mh);
+ err = mac_open(dlp->dl_name, dlp->dl_ddi_instance, &dlp->dl_mh);
if (err != 0)
goto done;
@@ -1009,15 +959,7 @@ dls_link_add(dls_link_t *dlp, uint32_t sap, dls_impl_t *dip)
boolean_t promisc = B_FALSE;
/*
- * For ethernet media, sap values less than or equal to
- * ETHERMTU (1500) represent LLC channels. (See PSARC 2003/150).
- * We strictly use 0 to represent LLC channels.
- */
- sap = (sap <= ETHERMTU) ? 0 : sap;
-
- /*
- * Make the appropriate key value depending on whether the
- * dls_impl_t is in promiscuous mode or not.
+ * Generate a hash key based on the sap and the VLAN id.
*/
key = MAKE_KEY(sap, dvp->dv_id);
@@ -1072,9 +1014,9 @@ dls_link_add(dls_link_t *dlp, uint32_t sap, dls_impl_t *dip)
* as ones bound to the DLSAP of the packet.
*/
if (promisc)
- rx = i_dls_link_ether_rx_promisc;
+ rx = i_dls_link_rx_promisc;
else
- rx = i_dls_link_ether_rx;
+ rx = i_dls_link_rx;
/* Replace the existing receive function if there is one. */
if (dlp->dl_mrh != NULL)
@@ -1172,12 +1114,43 @@ dls_link_remove(dls_link_t *dlp, dls_impl_t *dip)
* as ones bound to the DLSAP of the packet.
*/
if (promisc)
- rx = i_dls_link_ether_rx_promisc;
+ rx = i_dls_link_rx_promisc;
else
- rx = i_dls_link_ether_rx;
+ rx = i_dls_link_rx;
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);
}
+
+int
+dls_link_header_info(dls_link_t *dlp, mblk_t *mp, mac_header_info_t *mhip,
+ uint16_t *vidp)
+{
+ boolean_t is_ethernet = (dlp->dl_mip->mi_media == DL_ETHER);
+ int err = 0;
+
+ if ((err = mac_header_info(dlp->dl_mh, mp, mhip)) != 0)
+ return (err);
+
+ /*
+ * If this is a VLAN-tagged Ethernet packet, then the SAP in the
+ * mac_header_info_t as returned by mac_header_info() is VLAN_TPID.
+ * We need to grab the ethertype from the VLAN header.
+ */
+ if (is_ethernet && (mhip->mhi_bindsap == VLAN_TPID)) {
+ struct ether_vlan_header *evhp;
+ uint16_t sap;
+
+ evhp = (struct ether_vlan_header *)mp->b_rptr;
+ sap = ntohs(evhp->ether_type);
+ (void) mac_sap_verify(dlp->dl_mh, sap, &mhip->mhi_bindsap);
+ mhip->mhi_hdrsize = sizeof (struct ether_vlan_header);
+ if (vidp != NULL)
+ *vidp = VLAN_ID(ntohs(evhp->ether_tci));
+ } else if (vidp != NULL) {
+ *vidp = VLAN_ID_NONE;
+ }
+ return (0);
+}
diff --git a/usr/src/uts/common/io/dls/dls_stat.c b/usr/src/uts/common/io/dls/dls_stat.c
index 3d58c49cbd..daee626df4 100644
--- a/usr/src/uts/common/io/dls/dls_stat.c
+++ b/usr/src/uts/common/io/dls/dls_stat.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -40,31 +39,25 @@
#include <sys/dls.h>
#include <sys/dls_impl.h>
-typedef struct i_dls_stat_info_s {
- enum mac_stat dsi_stat;
- char *dsi_name;
- uint_t dsi_type;
-} i_mac_stat_info_t;
-
-static i_mac_stat_info_t i_dls_si[] = {
- { MAC_STAT_IFSPEED, "ifspeed", KSTAT_DATA_UINT64 },
- { MAC_STAT_MULTIRCV, "multircv", KSTAT_DATA_UINT32 },
- { MAC_STAT_BRDCSTRCV, "brdcstrcv", KSTAT_DATA_UINT32 },
- { MAC_STAT_MULTIXMT, "multixmt", KSTAT_DATA_UINT32 },
- { MAC_STAT_BRDCSTXMT, "brdcstxmt", KSTAT_DATA_UINT32 },
- { MAC_STAT_NORCVBUF, "norcvbuf", KSTAT_DATA_UINT32 },
- { MAC_STAT_IERRORS, "ierrors", KSTAT_DATA_UINT32 },
- { MAC_STAT_NOXMTBUF, "noxmtbuf", KSTAT_DATA_UINT32 },
- { MAC_STAT_OERRORS, "oerrors", KSTAT_DATA_UINT32 },
- { MAC_STAT_COLLISIONS, "collisions", KSTAT_DATA_UINT32 },
- { MAC_STAT_RBYTES, "rbytes", KSTAT_DATA_UINT32 },
- { MAC_STAT_IPACKETS, "ipackets", KSTAT_DATA_UINT32 },
- { MAC_STAT_OBYTES, "obytes", KSTAT_DATA_UINT32 },
- { MAC_STAT_OPACKETS, "opackets", KSTAT_DATA_UINT32 },
- { MAC_STAT_RBYTES, "rbytes64", KSTAT_DATA_UINT64 },
- { MAC_STAT_IPACKETS, "ipackets64", KSTAT_DATA_UINT64 },
- { MAC_STAT_OBYTES, "obytes64", KSTAT_DATA_UINT64 },
- { MAC_STAT_OPACKETS, "opackets64", KSTAT_DATA_UINT64 }
+static mac_stat_info_t i_dls_si[] = {
+ { MAC_STAT_IFSPEED, "ifspeed", KSTAT_DATA_UINT64, 0 },
+ { MAC_STAT_MULTIRCV, "multircv", KSTAT_DATA_UINT32, 0 },
+ { MAC_STAT_BRDCSTRCV, "brdcstrcv", KSTAT_DATA_UINT32, 0 },
+ { MAC_STAT_MULTIXMT, "multixmt", KSTAT_DATA_UINT32, 0 },
+ { MAC_STAT_BRDCSTXMT, "brdcstxmt", KSTAT_DATA_UINT32, 0 },
+ { MAC_STAT_NORCVBUF, "norcvbuf", KSTAT_DATA_UINT32, 0 },
+ { MAC_STAT_IERRORS, "ierrors", KSTAT_DATA_UINT32, 0 },
+ { MAC_STAT_NOXMTBUF, "noxmtbuf", KSTAT_DATA_UINT32, 0 },
+ { MAC_STAT_OERRORS, "oerrors", KSTAT_DATA_UINT32, 0 },
+ { MAC_STAT_COLLISIONS, "collisions", KSTAT_DATA_UINT32, 0 },
+ { MAC_STAT_RBYTES, "rbytes", KSTAT_DATA_UINT32, 0 },
+ { MAC_STAT_IPACKETS, "ipackets", KSTAT_DATA_UINT32, 0 },
+ { MAC_STAT_OBYTES, "obytes", KSTAT_DATA_UINT32, 0 },
+ { MAC_STAT_OPACKETS, "opackets", KSTAT_DATA_UINT32, 0 },
+ { MAC_STAT_RBYTES, "rbytes64", KSTAT_DATA_UINT64, 0 },
+ { MAC_STAT_IPACKETS, "ipackets64", KSTAT_DATA_UINT64, 0 },
+ { MAC_STAT_OBYTES, "obytes64", KSTAT_DATA_UINT64, 0 },
+ { MAC_STAT_OPACKETS, "opackets64", KSTAT_DATA_UINT64, 0 }
};
#define STAT_INFO_COUNT (sizeof (i_dls_si) / sizeof (i_dls_si[0]))
@@ -91,12 +84,9 @@ i_dls_stat_update(kstat_t *ksp, int rw)
knp = (kstat_named_t *)ksp->ks_data;
for (i = 0; i < STAT_INFO_COUNT; i++) {
- if (!(dlp->dl_mip->mi_stat[i_dls_si[i].dsi_stat]))
- continue;
+ val = mac_stat_get(dlp->dl_mh, i_dls_si[i].msi_stat);
- val = mac_stat_get(dlp->dl_mh, i_dls_si[i].dsi_stat);
-
- switch (i_dls_si[i].dsi_type) {
+ switch (i_dls_si[i].msi_type) {
case KSTAT_DATA_UINT64:
knp->value.ui64 = val;
break;
@@ -129,23 +119,16 @@ dls_mac_stat_create(dls_vlan_t *dvp)
kstat_t *ksp;
kstat_named_t *knp;
uint_t i;
- uint_t count;
int err;
if (dls_mac_hold(dlp) != 0)
return;
- count = 0;
- for (i = 0; i < STAT_INFO_COUNT; i++) {
- if (dlp->dl_mip->mi_stat[i_dls_si[i].dsi_stat])
- count++;
- }
-
err = ddi_parse(dvp->dv_name, module, &instance);
ASSERT(err == DDI_SUCCESS);
if ((ksp = kstat_create(module, instance, NULL, "net",
- KSTAT_TYPE_NAMED, count + 1, 0)) == NULL)
+ KSTAT_TYPE_NAMED, STAT_INFO_COUNT + 1, 0)) == NULL)
goto done;
ksp->ks_update = i_dls_stat_update;
@@ -154,15 +137,10 @@ dls_mac_stat_create(dls_vlan_t *dvp)
knp = (kstat_named_t *)ksp->ks_data;
for (i = 0; i < STAT_INFO_COUNT; i++) {
- if (!(dlp->dl_mip->mi_stat[i_dls_si[i].dsi_stat]))
- continue;
-
- kstat_named_init(knp, i_dls_si[i].dsi_name,
- i_dls_si[i].dsi_type);
+ kstat_named_init(knp, i_dls_si[i].msi_name,
+ i_dls_si[i].msi_type);
knp++;
- --count;
}
- ASSERT(count == 0);
kstat_named_init(knp, "unknowns", KSTAT_DATA_UINT32);
diff --git a/usr/src/uts/common/io/dls/dls_vlan.c b/usr/src/uts/common/io/dls/dls_vlan.c
index 9e20730ea6..eb6bc4c3bb 100644
--- a/usr/src/uts/common/io/dls/dls_vlan.c
+++ b/usr/src/uts/common/io/dls/dls_vlan.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -119,7 +118,8 @@ dls_vlan_fini(void)
*/
int
-dls_vlan_create(const char *name, const char *dev, uint_t port, uint16_t vid)
+dls_vlan_create(const char *vlanname, const char *macname, uint_t ddi_instance,
+ uint16_t vid)
{
dls_link_t *dlp;
dls_vlan_t *dvp;
@@ -131,25 +131,25 @@ dls_vlan_create(const char *name, const char *dev, uint_t port, uint16_t vid)
* characters in length and must terminate with a digit (before the
* NUL, of course).
*/
- len = strlen(name);
+ len = strlen(vlanname);
if (len == 0 || len >= IFNAMSIZ)
return (EINVAL);
- if (!isdigit(name[len - 1]))
+ if (!isdigit(vlanname[len - 1]))
return (EINVAL);
/*
* Get a reference to a dls_link_t representing the MAC. This call
* will create one if necessary.
*/
- if ((err = dls_link_hold(dev, port, &dlp)) != 0)
+ if ((err = dls_link_hold(macname, ddi_instance, &dlp)) != 0)
return (err);
/*
* Allocate a new dls_vlan_t.
*/
dvp = kmem_cache_alloc(i_dls_vlan_cachep, KM_SLEEP);
- (void) strlcpy(dvp->dv_name, name, IFNAMSIZ);
+ (void) strlcpy(dvp->dv_name, vlanname, sizeof (dvp->dv_name));
dvp->dv_id = vid;
dvp->dv_dlp = dlp;
@@ -242,8 +242,8 @@ again:
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;
+ char mac[MAXNAMELEN];
+ uint_t index, ddi_inst, mac_ppa, len;
uint16_t vid;
ASSERT(err == MH_ERR_NOTFOUND);
@@ -260,26 +260,25 @@ again:
* value because it must have been derived from
* ddi_major_to_name().
*/
- if (ddi_parse(name, drv, &index) != DDI_SUCCESS ||
+ if (ddi_parse(name, mac, &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));
- }
+ mac_ppa = (uint_t)DLS_PPA2INST(index);
+ if (strcmp(mac, "aggr") == 0)
+ ddi_inst = 0;
+ else
+ ddi_inst = mac_ppa;
+
+ len = strlen(mac);
+ ASSERT(len < MAXNAMELEN);
+ (void) snprintf(mac + len, MAXNAMELEN - len, "%d", mac_ppa);
rw_exit(&i_dls_vlan_lock);
- if ((err = dls_vlan_create(name, drv, port, vid)) != 0) {
+ if ((err = dls_vlan_create(name, mac, ddi_inst, vid)) != 0) {
rw_enter(&i_dls_vlan_lock, RW_WRITER);
goto done;
}
@@ -299,6 +298,22 @@ again:
if ((err = dls_mac_hold(dlp)) != 0)
goto done;
+ /*
+ * Do not allow the creation of tagged VLAN interfaces on
+ * non-Ethernet links. Note that we cannot do this check in
+ * dls_vlan_create() nor in this function prior to the call to
+ * dls_mac_hold(). The reason is that before we do a
+ * dls_mac_hold(), we may not have opened the mac, and therefore do
+ * not know what kind of media the mac represents. In other words,
+ * dls_mac_hold() assigns the dl_mip of the dls_link_t we're
+ * interested in.
+ */
+ if (dvp->dv_id != VLAN_ID_NONE && dlp->dl_mip->mi_media != DL_ETHER) {
+ dls_mac_rele(dlp);
+ err = EINVAL;
+ goto done;
+ }
+
if ((err = mac_start(dlp->dl_mh)) != 0) {
dls_mac_rele(dlp);
goto done;
diff --git a/usr/src/uts/common/io/mac/mac.c b/usr/src/uts/common/io/mac/mac.c
index 669d8e5d43..bb5b4bbcb4 100644
--- a/usr/src/uts/common/io/mac/mac.c
+++ b/usr/src/uts/common/io/mac/mac.c
@@ -41,6 +41,7 @@
#include <sys/mac_impl.h>
#include <sys/dls.h>
#include <sys/dld.h>
+#include <sys/modctl.h>
#define IMPL_HASHSZ 67 /* prime */
@@ -49,6 +50,10 @@ static mod_hash_t *i_mac_impl_hash;
krwlock_t i_mac_impl_lock;
uint_t i_mac_impl_count;
+#define MACTYPE_KMODDIR "mac"
+#define MACTYPE_HASHSZ 67
+static mod_hash_t *i_mactype_hash;
+
static void i_mac_notify_task(void *);
/*
@@ -56,39 +61,6 @@ static void i_mac_notify_task(void *);
*/
/*ARGSUSED*/
-static boolean_t
-i_mac_ether_unicst_verify(mac_impl_t *mip, const uint8_t *addr)
-{
- /*
- * Check the address is not a group address.
- */
- if (addr[0] & 0x01)
- return (B_FALSE);
-
- return (B_TRUE);
-}
-
-static boolean_t
-i_mac_ether_multicst_verify(mac_impl_t *mip, const uint8_t *addr)
-{
- mac_t *mp = mip->mi_mp;
-
- /*
- * Check the address is a group address.
- */
- if (!(addr[0] & 0x01))
- return (B_FALSE);
-
- /*
- * Check the address is not the media broadcast address.
- */
- if (bcmp(addr, mp->m_info.mi_brdcst_addr, mip->mi_addr_length) == 0)
- return (B_FALSE);
-
- return (B_TRUE);
-}
-
-/*ARGSUSED*/
static int
i_mac_constructor(void *buf, void *arg, int kmflag)
{
@@ -96,7 +68,7 @@ i_mac_constructor(void *buf, void *arg, int kmflag)
bzero(buf, sizeof (mac_impl_t));
- mip->mi_link = LINK_STATE_UNKNOWN;
+ mip->mi_linkstate = LINK_STATE_UNKNOWN;
rw_init(&mip->mi_state_lock, NULL, RW_DRIVER, NULL);
rw_init(&mip->mi_data_lock, NULL, RW_DRIVER, NULL);
@@ -116,16 +88,16 @@ i_mac_destructor(void *buf, void *arg)
{
mac_impl_t *mip = buf;
- ASSERT(mip->mi_mp == NULL);
ASSERT(mip->mi_ref == 0);
ASSERT(mip->mi_active == 0);
- ASSERT(mip->mi_link == LINK_STATE_UNKNOWN);
+ ASSERT(mip->mi_linkstate == LINK_STATE_UNKNOWN);
ASSERT(mip->mi_devpromisc == 0);
ASSERT(mip->mi_promisc == 0);
ASSERT(mip->mi_mmap == NULL);
ASSERT(mip->mi_mnfp == NULL);
ASSERT(mip->mi_resource_add == NULL);
ASSERT(mip->mi_ksp == NULL);
+ ASSERT(mip->mi_kstat_count == 0);
rw_destroy(&mip->mi_state_lock);
rw_destroy(&mip->mi_data_lock);
@@ -138,138 +110,6 @@ i_mac_destructor(void *buf, void *arg)
cv_destroy(&mip->mi_notify_cv);
}
-static int
-i_mac_create(mac_t *mp)
-{
- dev_info_t *dip;
- mac_impl_t *mip;
- int err = 0;
-
- dip = mp->m_dip;
- ASSERT(dip != NULL);
- ASSERT(ddi_get_instance(dip) >= 0);
-
- /*
- * Allocate a new mac_impl_t.
- */
- mip = kmem_cache_alloc(i_mac_impl_cachep, KM_SLEEP);
-
- /*
- * Construct a name.
- */
- (void) snprintf(mip->mi_dev, MAXNAMELEN - 1, "%s%d",
- ddi_driver_name(dip), ddi_get_instance(dip));
- mip->mi_port = mp->m_port;
-
- MAC_NAME(mip->mi_name, mip->mi_dev, mip->mi_port);
-
- /*
- * Set the mac_t/mac_impl_t cross-references.
- */
- mip->mi_mp = mp;
- mp->m_impl = (void *)mip;
-
- /*
- * The mac is not ready for open yet.
- */
- mip->mi_disabled = B_TRUE;
-
- /*
- * Insert the hash table entry.
- */
- 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;
- }
- i_mac_impl_count++;
-
- /*
- * Copy the fixed 'factory' MAC address from the immutable info.
- * This is taken to be the MAC address currently in use.
- */
- mip->mi_addr_length = mp->m_info.mi_addr_length;
- bcopy(mp->m_info.mi_unicst_addr, mip->mi_addr, mip->mi_addr_length);
-
- /*
- * Set up the address verification functions.
- */
- ASSERT(mp->m_info.mi_media == DL_ETHER);
- mip->mi_unicst_verify = i_mac_ether_unicst_verify;
- mip->mi_multicst_verify = i_mac_ether_multicst_verify;
-
- /*
- * Set up the two possible transmit routines.
- */
- mip->mi_txinfo.mt_fn = mp->m_tx;
- mip->mi_txinfo.mt_arg = mp->m_driver;
- mip->mi_txloopinfo.mt_fn = mac_txloop;
- mip->mi_txloopinfo.mt_arg = mip;
-
- /*
- * Initialize the kstats for this device.
- */
- mac_stat_create(mip);
-
-done:
- rw_exit(&i_mac_impl_lock);
- return (err);
-}
-
-static void
-i_mac_destroy(mac_t *mp)
-{
- mac_impl_t *mip = mp->m_impl;
- mac_multicst_addr_t *p, *nextp;
- mod_hash_val_t val;
-
- rw_enter(&i_mac_impl_lock, RW_WRITER);
-
- ASSERT(mip->mi_ref == 0);
- ASSERT(!mip->mi_activelink);
-
- /*
- * Destroy the kstats.
- */
- mac_stat_destroy(mip);
-
- /*
- * Remove and destroy the hash table entry.
- */
- (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.
- */
- for (p = mip->mi_mmap; p != NULL; p = nextp) {
- nextp = p->mma_nextp;
- kmem_free(p, sizeof (mac_multicst_addr_t));
- }
- mip->mi_mmap = NULL;
-
- /*
- * Clean up the mac_impl_t ready to go back into the cache.
- */
- mp->m_impl = NULL;
- mip->mi_mp = NULL;
- mip->mi_link = LINK_STATE_UNKNOWN;
- mip->mi_disabled = B_FALSE;
-
- /*
- * Free the structure back to the cache.
- */
- kmem_cache_free(i_mac_impl_cachep, mip);
-
- rw_exit(&i_mac_impl_lock);
-}
-
static void
i_mac_notify(mac_impl_t *mip, mac_notify_type_t type)
{
@@ -338,13 +178,46 @@ i_mac_notify_task(void *notify_arg)
notify(arg, type);
}
rw_exit(&mip->mi_notify_lock);
-
mutex_enter(&mip->mi_notify_ref_lock);
if (--mip->mi_notify_ref == 0)
cv_signal(&mip->mi_notify_cv);
mutex_exit(&mip->mi_notify_ref_lock);
}
+static mactype_t *
+i_mactype_getplugin(const char *plugin_name)
+{
+ mactype_t *mtype = NULL;
+ boolean_t tried_modload = B_FALSE;
+
+find_registered_mactype:
+ if (mod_hash_find(i_mactype_hash, (mod_hash_key_t)plugin_name,
+ (mod_hash_val_t *)&mtype) == 0) {
+ /*
+ * Because the reference count is initialized at 1 (see
+ * mactype_register()), we don't need to bump up the
+ * reference count if we're the first reference.
+ */
+ if (!tried_modload)
+ mtype->mt_ref++;
+ return (mtype);
+ } else if (tried_modload) {
+ return (NULL);
+ }
+
+ /*
+ * If the plugin has not yet been loaded, then attempt to load it
+ * now. If modload succeeds, the plugin should have registered
+ * using mactype_register(), in which case we can go back and
+ * attempt to find it again.
+ */
+ if (modload(MACTYPE_KMODDIR, (char *)plugin_name) != -1) {
+ tried_modload = B_TRUE;
+ goto find_registered_mactype;
+ }
+ return (NULL);
+}
+
/*
* Module initialization functions.
*/
@@ -353,8 +226,8 @@ void
mac_init(void)
{
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);
+ sizeof (mac_impl_t), 0, i_mac_constructor, i_mac_destructor,
+ NULL, NULL, NULL, 0);
ASSERT(i_mac_impl_cachep != NULL);
i_mac_impl_hash = mod_hash_create_extended("mac_impl_hash",
@@ -362,6 +235,11 @@ mac_init(void)
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;
+
+ i_mactype_hash = mod_hash_create_extended("mactype_hash",
+ MACTYPE_HASHSZ,
+ mod_hash_null_keydtor, mod_hash_null_valdtor,
+ mod_hash_bystr, NULL, mod_hash_strkey_cmp, KM_SLEEP);
}
int
@@ -374,6 +252,8 @@ mac_fini(void)
rw_destroy(&i_mac_impl_lock);
kmem_cache_destroy(i_mac_impl_cachep);
+
+ mod_hash_destroy_hash(i_mactype_hash);
return (0);
}
@@ -382,9 +262,8 @@ mac_fini(void)
*/
int
-mac_open(const char *dev, uint_t port, mac_handle_t *mhp)
+mac_open(const char *macname, uint_t ddi_instance, mac_handle_t *mhp)
{
- char name[MAXNAMELEN];
char driver[MAXNAMELEN];
uint_t instance;
major_t major;
@@ -396,13 +275,13 @@ mac_open(const char *dev, uint_t port, mac_handle_t *mhp)
* Check the device name length to make sure it won't overflow our
* buffer.
*/
- if (strlen(dev) >= MAXNAMELEN)
+ if (strlen(macname) >= MAXNAMELEN)
return (EINVAL);
/*
* Split the device name into driver and instance components.
*/
- if (ddi_parse(dev, driver, &instance) != DDI_SUCCESS)
+ if (ddi_parse(macname, driver, &instance) != DDI_SUCCESS)
return (EINVAL);
/*
@@ -419,20 +298,15 @@ mac_open(const char *dev, uint_t port, mac_handle_t *mhp)
* call mac_open() because this would lead to a recursive attach
* panic.
*/
- if ((dip = ddi_hold_devi_by_instance(major, instance, 0)) == NULL)
+ if ((dip = ddi_hold_devi_by_instance(major, ddi_instance, 0)) == NULL)
return (EINVAL);
/*
- * Construct the name of the MAC interface.
- */
- MAC_NAME(name, dev, port);
-
- /*
* Look up its entry in the global hash table.
*/
again:
rw_enter(&i_mac_impl_lock, RW_WRITER);
- err = mod_hash_find(i_mac_impl_hash, (mod_hash_key_t)name,
+ err = mod_hash_find(i_mac_impl_hash, (mod_hash_key_t)macname,
(mod_hash_val_t *)&mip);
if (err != 0) {
err = ENOENT;
@@ -444,10 +318,6 @@ again:
goto again;
}
- /*
- * We currently only support the DL_ETHER media type.
- */
- ASSERT(mip->mi_mp->m_info.mi_media == DL_ETHER);
mip->mi_ref++;
rw_exit(&i_mac_impl_lock);
@@ -464,7 +334,7 @@ void
mac_close(mac_handle_t mh)
{
mac_impl_t *mip = (mac_impl_t *)mh;
- dev_info_t *dip = mip->mi_mp->m_dip;
+ dev_info_t *dip = mip->mi_dip;
rw_enter(&i_mac_impl_lock, RW_WRITER);
@@ -479,44 +349,63 @@ mac_close(mac_handle_t mh)
const mac_info_t *
mac_info(mac_handle_t mh)
{
- mac_impl_t *mip = (mac_impl_t *)mh;
- mac_t *mp = mip->mi_mp;
-
- /*
- * Return a pointer to the mac_info_t embedded in the mac_t.
- */
- return (&(mp->m_info));
+ return (&((mac_impl_t *)mh)->mi_info);
}
dev_info_t *
mac_devinfo_get(mac_handle_t mh)
{
- return (((mac_impl_t *)mh)->mi_mp->m_dip);
+ return (((mac_impl_t *)mh)->mi_dip);
}
uint64_t
-mac_stat_get(mac_handle_t mh, enum mac_stat stat)
+mac_stat_get(mac_handle_t mh, uint_t stat)
{
mac_impl_t *mip = (mac_impl_t *)mh;
- mac_t *mp = mip->mi_mp;
-
- ASSERT(mp->m_info.mi_stat[stat]);
- ASSERT(mp->m_stat != NULL);
+ uint64_t val;
+ int ret;
+
+ /*
+ * The range of stat determines where it is maintained. Stat
+ * values from 0 up to (but not including) MAC_STAT_MIN are
+ * mainteined by the mac module itself. Everything else is
+ * maintained by the driver.
+ */
+ if (stat < MAC_STAT_MIN) {
+ /* These stats are maintained by the mac module itself. */
+ switch (stat) {
+ case MAC_STAT_LINK_STATE:
+ return (mip->mi_linkstate);
+ case MAC_STAT_LINK_UP:
+ return (mip->mi_linkstate == LINK_STATE_UP);
+ case MAC_STAT_PROMISC:
+ return (mip->mi_devpromisc != 0);
+ default:
+ ASSERT(B_FALSE);
+ }
+ }
/*
* Call the driver to get the given statistic.
*/
- return (mp->m_stat(mp->m_driver, stat));
+ ret = mip->mi_getstat(mip->mi_driver, stat, &val);
+ if (ret != 0) {
+ /*
+ * The driver doesn't support this statistic. Get the
+ * statistic's default value.
+ */
+ val = mac_stat_default(mip, stat);
+ }
+ return (val);
}
int
mac_start(mac_handle_t mh)
{
mac_impl_t *mip = (mac_impl_t *)mh;
- mac_t *mp = mip->mi_mp;
int err;
- ASSERT(mp->m_start != NULL);
+ ASSERT(mip->mi_start != NULL);
rw_enter(&(mip->mi_state_lock), RW_WRITER);
@@ -534,7 +423,7 @@ mac_start(mac_handle_t mh)
/*
* Start the device.
*/
- if ((err = mp->m_start(mp->m_driver)) != 0)
+ if ((err = mip->mi_start(mip->mi_driver)) != 0)
--mip->mi_active;
done:
@@ -546,9 +435,8 @@ void
mac_stop(mac_handle_t mh)
{
mac_impl_t *mip = (mac_impl_t *)mh;
- mac_t *mp = mip->mi_mp;
- ASSERT(mp->m_stop != NULL);
+ ASSERT(mip->mi_stop != NULL);
rw_enter(&(mip->mi_state_lock), RW_WRITER);
@@ -566,7 +454,7 @@ mac_stop(mac_handle_t mh)
/*
* Stop the device.
*/
- mp->m_stop(mp->m_driver);
+ mip->mi_stop(mip->mi_driver);
done:
rw_exit(&(mip->mi_state_lock));
@@ -576,25 +464,27 @@ int
mac_multicst_add(mac_handle_t mh, const uint8_t *addr)
{
mac_impl_t *mip = (mac_impl_t *)mh;
- mac_t *mp = mip->mi_mp;
mac_multicst_addr_t **pp;
mac_multicst_addr_t *p;
int err;
- ASSERT(mp->m_multicst != NULL);
+ ASSERT(mip->mi_multicst != NULL);
/*
* Verify the address.
*/
- if (!(mip->mi_multicst_verify(mip, addr)))
- return (EINVAL);
+ if ((err = mip->mi_type->mt_ops.mtops_multicst_verify(addr,
+ mip->mi_pdata)) != 0) {
+ return (err);
+ }
/*
* Check whether the given address is already enabled.
*/
rw_enter(&(mip->mi_data_lock), RW_WRITER);
for (pp = &(mip->mi_mmap); (p = *pp) != NULL; pp = &(p->mma_nextp)) {
- if (bcmp(p->mma_addr, addr, mip->mi_addr_length) == 0) {
+ if (bcmp(p->mma_addr, addr, mip->mi_type->mt_addr_length) ==
+ 0) {
/*
* The address is already enabled so just bump the
* reference count.
@@ -617,7 +507,7 @@ mac_multicst_add(mac_handle_t mh, const uint8_t *addr)
/*
* Enable a new multicast address.
*/
- if ((err = mp->m_multicst(mp->m_driver, B_TRUE, addr)) != 0) {
+ if ((err = mip->mi_multicst(mip->mi_driver, B_TRUE, addr)) != 0) {
kmem_free(p, sizeof (mac_multicst_addr_t));
goto done;
}
@@ -625,7 +515,7 @@ mac_multicst_add(mac_handle_t mh, const uint8_t *addr)
/*
* Add the address to the list of enabled addresses.
*/
- bcopy(addr, p->mma_addr, mip->mi_addr_length);
+ bcopy(addr, p->mma_addr, mip->mi_type->mt_addr_length);
p->mma_ref++;
*pp = p;
@@ -638,19 +528,19 @@ int
mac_multicst_remove(mac_handle_t mh, const uint8_t *addr)
{
mac_impl_t *mip = (mac_impl_t *)mh;
- mac_t *mp = mip->mi_mp;
mac_multicst_addr_t **pp;
mac_multicst_addr_t *p;
int err;
- ASSERT(mp->m_multicst != NULL);
+ ASSERT(mip->mi_multicst != NULL);
/*
* Find the entry in the list for the given address.
*/
rw_enter(&(mip->mi_data_lock), RW_WRITER);
for (pp = &(mip->mi_mmap); (p = *pp) != NULL; pp = &(p->mma_nextp)) {
- if (bcmp(p->mma_addr, addr, mip->mi_addr_length) == 0) {
+ if (bcmp(p->mma_addr, addr, mip->mi_type->mt_addr_length) ==
+ 0) {
if (--p->mma_ref == 0)
break;
@@ -676,7 +566,7 @@ mac_multicst_remove(mac_handle_t mh, const uint8_t *addr)
/*
* Disable the multicast address.
*/
- if ((err = mp->m_multicst(mp->m_driver, B_FALSE, addr)) != 0) {
+ if ((err = mip->mi_multicst(mip->mi_driver, B_FALSE, addr)) != 0) {
p->mma_ref++;
goto done;
}
@@ -696,17 +586,18 @@ int
mac_unicst_set(mac_handle_t mh, const uint8_t *addr)
{
mac_impl_t *mip = (mac_impl_t *)mh;
- mac_t *mp = mip->mi_mp;
int err;
boolean_t notify = B_FALSE;
- ASSERT(mp->m_unicst != NULL);
+ ASSERT(mip->mi_unicst != NULL);
/*
* Verify the address.
*/
- if (!(mip->mi_unicst_verify(mip, addr)))
- return (EINVAL);
+ if ((err = mip->mi_type->mt_ops.mtops_unicst_verify(addr,
+ mip->mi_pdata)) != 0) {
+ return (err);
+ }
/*
* Program the new unicast address.
@@ -718,18 +609,18 @@ mac_unicst_set(mac_handle_t mh, const uint8_t *addr)
* This check is necessary otherwise it may call into mac_unicst_set
* recursively.
*/
- if (bcmp(addr, mip->mi_addr, mip->mi_addr_length) == 0) {
+ if (bcmp(addr, mip->mi_addr, mip->mi_type->mt_addr_length) == 0) {
err = 0;
goto done;
}
- if ((err = mp->m_unicst(mp->m_driver, addr)) != 0)
+ if ((err = mip->mi_unicst(mip->mi_driver, addr)) != 0)
goto done;
/*
* Save the address and flag that we need to send a notification.
*/
- bcopy(addr, mip->mi_addr, mip->mi_addr_length);
+ bcopy(addr, mip->mi_addr, mip->mi_type->mt_addr_length);
notify = B_TRUE;
done:
@@ -747,10 +638,23 @@ mac_unicst_get(mac_handle_t mh, uint8_t *addr)
mac_impl_t *mip = (mac_impl_t *)mh;
/*
- * Copy out the current unicast address.
+ * Copy out the current unicast source address.
+ */
+ rw_enter(&(mip->mi_data_lock), RW_READER);
+ bcopy(mip->mi_addr, addr, mip->mi_type->mt_addr_length);
+ rw_exit(&(mip->mi_data_lock));
+}
+
+void
+mac_dest_get(mac_handle_t mh, uint8_t *addr)
+{
+ mac_impl_t *mip = (mac_impl_t *)mh;
+
+ /*
+ * Copy out the current destination address.
*/
rw_enter(&(mip->mi_data_lock), RW_READER);
- bcopy(mip->mi_addr, addr, mip->mi_addr_length);
+ bcopy(mip->mi_dstaddr, addr, mip->mi_type->mt_addr_length);
rw_exit(&(mip->mi_data_lock));
}
@@ -758,10 +662,9 @@ int
mac_promisc_set(mac_handle_t mh, boolean_t on, mac_promisc_type_t ptype)
{
mac_impl_t *mip = (mac_impl_t *)mh;
- mac_t *mp = mip->mi_mp;
int err = 0;
- ASSERT(mp->m_promisc != NULL);
+ ASSERT(mip->mi_setpromisc != NULL);
ASSERT(ptype == MAC_DEVPROMISC || ptype == MAC_PROMISC);
/*
@@ -775,7 +678,8 @@ mac_promisc_set(mac_handle_t mh, boolean_t on, mac_promisc_type_t ptype)
* Enable promiscuous mode on the device if not yet enabled.
*/
if (mip->mi_devpromisc++ == 0) {
- if ((err = mp->m_promisc(mp->m_driver, B_TRUE)) != 0) {
+ err = mip->mi_setpromisc(mip->mi_driver, B_TRUE);
+ if (err != 0) {
mip->mi_devpromisc--;
goto done;
}
@@ -798,7 +702,8 @@ mac_promisc_set(mac_handle_t mh, boolean_t on, mac_promisc_type_t ptype)
* enabling.
*/
if (--mip->mi_devpromisc == 0) {
- if ((err = mp->m_promisc(mp->m_driver, B_FALSE)) != 0) {
+ err = mip->mi_setpromisc(mip->mi_driver, B_FALSE);
+ if (err != 0) {
mip->mi_devpromisc++;
goto done;
}
@@ -838,28 +743,28 @@ void
mac_resources(mac_handle_t mh)
{
mac_impl_t *mip = (mac_impl_t *)mh;
- mac_t *mp = mip->mi_mp;
-
- ASSERT(mp->m_resources != NULL);
/*
- * Call the driver to register its resources.
+ * If the driver supports resource registration, call the driver to
+ * ask it to register its resources.
*/
- mp->m_resources(mp->m_driver);
+ if (mip->mi_callbacks->mc_callbacks & MC_RESOURCES)
+ mip->mi_resources(mip->mi_driver);
}
void
mac_ioctl(mac_handle_t mh, queue_t *wq, mblk_t *bp)
{
mac_impl_t *mip = (mac_impl_t *)mh;
- mac_t *mp = mip->mi_mp;
-
- ASSERT(mp->m_ioctl != NULL);
/*
- * Call the driver to handle the ioctl.
+ * Call the driver to handle the ioctl. The driver may not support
+ * any ioctls, in which case we reply with a NAK on its behalf.
*/
- mp->m_ioctl(mp->m_driver, wq, bp);
+ if (mip->mi_callbacks->mc_callbacks & MC_IOCTL)
+ mip->mi_ioctl(mip->mi_driver, wq, bp);
+ else
+ miocnak(wq, bp, 0, EINVAL);
}
const mac_txinfo_t *
@@ -886,7 +791,6 @@ mac_tx_get(mac_handle_t mh)
* MAC_PROMISC prior to calling mac_txloop_remove().
*/
mtp = &mip->mi_txinfo;
-
}
rw_exit(&mip->mi_txloop_lock);
@@ -896,12 +800,7 @@ mac_tx_get(mac_handle_t mh)
link_state_t
mac_link_get(mac_handle_t mh)
{
- mac_impl_t *mip = (mac_impl_t *)mh;
-
- /*
- * Return the current link state.
- */
- return (mip->mi_link);
+ return (((mac_impl_t *)mh)->mi_linkstate);
}
mac_notify_handle_t
@@ -1082,53 +981,217 @@ mac_resource_set(mac_handle_t mh, mac_resource_add_t add, void *arg)
* Driver support functions.
*/
+mac_register_t *
+mac_alloc(uint_t mac_version)
+{
+ mac_register_t *mregp;
+
+ /*
+ * Make sure there isn't a version mismatch between the driver and
+ * the framework. In the future, if multiple versions are
+ * supported, this check could become more sophisticated.
+ */
+ if (mac_version != MAC_VERSION)
+ return (NULL);
+
+ mregp = kmem_zalloc(sizeof (mac_register_t), KM_SLEEP);
+ mregp->m_version = mac_version;
+ return (mregp);
+}
+
+void
+mac_free(mac_register_t *mregp)
+{
+ kmem_free(mregp, sizeof (mac_register_t));
+}
+
+/*
+ * mac_register() is how drivers register new MACs with the GLDv3
+ * framework. The mregp argument is allocated by drivers using the
+ * mac_alloc() function, and can be freed using mac_free() immediately upon
+ * return from mac_register(). Upon success (0 return value), the mhp
+ * opaque pointer becomes the driver's handle to its MAC interface, and is
+ * the argument to all other mac module entry points.
+ */
+/* ARGSUSED */
int
-mac_register(mac_t *mp)
+mac_register(mac_register_t *mregp, mac_handle_t *mhp)
{
- int err, instance;
- char name[MAXNAMELEN], devname[MAXNAMELEN];
- const char *drvname;
+ mac_impl_t *mip;
+ mactype_t *mtype;
+ int err;
struct devnames *dnp;
- minor_t minor;
+ minor_t minor;
+ mod_hash_val_t val;
+ boolean_t style1_created = B_FALSE, style2_created = B_FALSE;
+
+ /* Find the required MAC-Type plugin. */
+ if ((mtype = i_mactype_getplugin(mregp->m_type_ident)) == NULL)
+ return (EINVAL);
+
+ /* Create a mac_impl_t to represent this MAC. */
+ mip = kmem_cache_alloc(i_mac_impl_cachep, KM_SLEEP);
+
+ /*
+ * The mac is not ready for open yet.
+ */
+ mip->mi_disabled = B_TRUE;
- drvname = ddi_driver_name(mp->m_dip);
- instance = ddi_get_instance(mp->m_dip);
+ mip->mi_drvname = ddi_driver_name(mregp->m_dip);
+ /*
+ * Some drivers such as aggr need to register multiple MACs. Such
+ * drivers must supply a non-zero "instance" argument so that each
+ * MAC can be assigned a unique MAC name and can have unique
+ * kstats.
+ */
+ mip->mi_instance = ((mregp->m_instance == 0) ?
+ ddi_get_instance(mregp->m_dip) : mregp->m_instance);
- if (strcmp(mp->m_ident, MAC_IDENT) != 0) {
- cmn_err(CE_WARN, "%s%d/%d: possible mac interface mismatch",
- drvname, instance, mp->m_port);
+ /* Construct the MAC name as <drvname><instance> */
+ (void) snprintf(mip->mi_name, sizeof (mip->mi_name), "%s%d",
+ mip->mi_drvname, mip->mi_instance);
+
+ 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);
+ rw_exit(&i_mac_impl_lock);
+ return (EEXIST);
}
+ i_mac_impl_count++;
+
+ mip->mi_driver = mregp->m_driver;
+
+ mip->mi_type = mtype;
+ mip->mi_info.mi_media = mtype->mt_type;
+ mip->mi_info.mi_sdu_min = mregp->m_min_sdu;
+ if (mregp->m_max_sdu <= mregp->m_min_sdu) {
+ err = EINVAL;
+ goto fail;
+ }
+ mip->mi_info.mi_sdu_max = mregp->m_max_sdu;
+ mip->mi_info.mi_addr_length = mip->mi_type->mt_addr_length;
/*
- * Create a new mac_impl_t to pair with the mac_t.
+ * If the media supports a broadcast address, cache a pointer to it
+ * in the mac_info_t so that upper layers can use it.
*/
- if ((err = i_mac_create(mp)) != 0)
- return (err);
+ mip->mi_info.mi_brdcst_addr = mip->mi_type->mt_brdcst_addr;
- err = EEXIST;
- if (ddi_create_minor_node(mp->m_dip, (char *)drvname, S_IFCHR, 0,
- DDI_NT_NET, CLONE_DEV) != DDI_SUCCESS)
- goto fail1;
+ /*
+ * Copy the unicast source address into the mac_info_t, but only if
+ * the MAC-Type defines a non-zero address length. We need to
+ * handle MAC-Types that have an address length of 0
+ * (point-to-point protocol MACs for example).
+ */
+ if (mip->mi_type->mt_addr_length > 0) {
+ if (mregp->m_src_addr == NULL) {
+ err = EINVAL;
+ goto fail;
+ }
+ mip->mi_info.mi_unicst_addr =
+ kmem_alloc(mip->mi_type->mt_addr_length, KM_SLEEP);
+ bcopy(mregp->m_src_addr, mip->mi_info.mi_unicst_addr,
+ mip->mi_type->mt_addr_length);
- (void) snprintf(devname, MAXNAMELEN, "%s%d", drvname, instance);
+ /*
+ * Copy the fixed 'factory' MAC address from the immutable
+ * info. This is taken to be the MAC address currently in
+ * use.
+ */
+ bcopy(mip->mi_info.mi_unicst_addr, mip->mi_addr,
+ mip->mi_type->mt_addr_length);
+ /* Copy the destination address if one is provided. */
+ if (mregp->m_dst_addr != NULL) {
+ bcopy(mregp->m_dst_addr, mip->mi_dstaddr,
+ mip->mi_type->mt_addr_length);
+ }
+ } else if (mregp->m_src_addr != NULL) {
+ err = EINVAL;
+ goto fail;
+ }
- 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;
+ /*
+ * The format of the m_pdata is specific to the plugin. It is
+ * passed in as an argument to all of the plugin callbacks. The
+ * driver can update this information by calling
+ * mac_pdata_update().
+ */
+ if (mregp->m_pdata != NULL) {
+ /*
+ * Verify that the plugin supports MAC plugin data and that
+ * the supplied data is valid.
+ */
+ if (!(mip->mi_type->mt_ops.mtops_ops & MTOPS_PDATA_VERIFY)) {
+ err = EINVAL;
+ goto fail;
+ }
+ if (!mip->mi_type->mt_ops.mtops_pdata_verify(mregp->m_pdata,
+ mregp->m_pdata_size)) {
+ err = EINVAL;
+ goto fail;
+ }
+ mip->mi_pdata = kmem_alloc(mregp->m_pdata_size, KM_SLEEP);
+ bcopy(mregp->m_pdata, mip->mi_pdata, mregp->m_pdata_size);
+ mip->mi_pdata_size = mregp->m_pdata_size;
}
- if (ddi_create_minor_node(mp->m_dip, name, S_IFCHR, minor,
+ /*
+ * Stash the driver callbacks into the mac_impl_t, but first sanity
+ * check to make sure all mandatory callbacks are set.
+ */
+ if (mregp->m_callbacks->mc_getstat == NULL ||
+ mregp->m_callbacks->mc_start == NULL ||
+ mregp->m_callbacks->mc_stop == NULL ||
+ mregp->m_callbacks->mc_setpromisc == NULL ||
+ mregp->m_callbacks->mc_multicst == NULL ||
+ mregp->m_callbacks->mc_unicst == NULL ||
+ mregp->m_callbacks->mc_tx == NULL) {
+ err = EINVAL;
+ goto fail;
+ }
+ mip->mi_callbacks = mregp->m_callbacks;
+
+ mip->mi_dip = mregp->m_dip;
+
+ /*
+ * Set up the two possible transmit routines.
+ */
+ mip->mi_txinfo.mt_fn = mip->mi_tx;
+ mip->mi_txinfo.mt_arg = mip->mi_driver;
+ mip->mi_txloopinfo.mt_fn = mac_txloop;
+ mip->mi_txloopinfo.mt_arg = mip;
+
+ /*
+ * Initialize the kstats for this device.
+ */
+ mac_stat_create(mip);
+
+ err = EEXIST;
+ /* Create a style-2 DLPI device */
+ if (ddi_create_minor_node(mip->mi_dip, (char *)mip->mi_drvname,
+ S_IFCHR, 0, DDI_NT_NET, CLONE_DEV) != DDI_SUCCESS)
+ goto fail;
+ style2_created = B_TRUE;
+
+ /* Create a style-1 DLPI device */
+ minor = (minor_t)mip->mi_instance + 1;
+ if (ddi_create_minor_node(mip->mi_dip, mip->mi_name, S_IFCHR, minor,
DDI_NT_NET, 0) != DDI_SUCCESS)
- goto fail2;
+ goto fail;
+ style1_created = B_TRUE;
- if ((err = dls_create(name, devname, mp->m_port)) != 0)
- goto fail3;
+ /*
+ * Create a link for this MAC. The link name will be the same as
+ * the MAC name.
+ */
+ err = dls_create(mip->mi_name, mip->mi_name,
+ ddi_get_instance(mip->mi_dip));
+ if (err != 0)
+ goto fail;
/* set the gldv3 flag in dn_flags */
- dnp = &devnamesp[ddi_driver_major(mp->m_dip)];
+ dnp = &devnamesp[ddi_driver_major(mip->mi_dip)];
LOCK_DEV_OPS(&dnp->dn_lock);
dnp->dn_flags |= DN_GLDV3_DRIVER;
UNLOCK_DEV_OPS(&dnp->dn_lock);
@@ -1136,37 +1199,59 @@ mac_register(mac_t *mp)
/*
* Mark the MAC to be ready for open.
*/
- rw_enter(&i_mac_impl_lock, RW_WRITER);
- ((mac_impl_t *)mp->m_impl)->mi_disabled = B_FALSE;
- rw_exit(&i_mac_impl_lock);
+ mip->mi_disabled = B_FALSE;
- cmn_err(CE_NOTE, "!%s%d/%d registered", drvname, instance, mp->m_port);
+ cmn_err(CE_NOTE, "!%s registered", mip->mi_name);
+ rw_exit(&i_mac_impl_lock);
+ *mhp = (mac_handle_t)mip;
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);
+fail:
+ (void) mod_hash_remove(i_mac_impl_hash, (mod_hash_key_t)mip->mi_name,
+ &val);
+ ASSERT(mip == (mac_impl_t *)val);
+ i_mac_impl_count--;
+
+ if (mip->mi_info.mi_unicst_addr != NULL) {
+ kmem_free(mip->mi_info.mi_unicst_addr,
+ mip->mi_type->mt_addr_length);
+ mip->mi_info.mi_unicst_addr = NULL;
+ }
+ if (style1_created)
+ ddi_remove_minor_node(mip->mi_dip, mip->mi_name);
+ if (style2_created)
+ ddi_remove_minor_node(mip->mi_dip, (char *)mip->mi_drvname);
+
+ mac_stat_destroy(mip);
+
+ if (mip->mi_type != NULL) {
+ mip->mi_type->mt_ref--;
+ mip->mi_type = NULL;
+ }
+
+ if (mip->mi_pdata != NULL) {
+ kmem_free(mip->mi_pdata, mip->mi_pdata_size);
+ mip->mi_pdata = NULL;
+ mip->mi_pdata_size = 0;
+ }
+
+ kmem_cache_free(i_mac_impl_cachep, mip);
+ rw_exit(&i_mac_impl_lock);
return (err);
}
int
-mac_unregister(mac_t *mp)
+mac_unregister(mac_handle_t mh)
{
- 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);
+ int err;
+ mac_impl_t *mip = (mac_impl_t *)mh;
+ mod_hash_val_t val;
+ mac_multicst_addr_t *p, *nextp;
/*
* See if there are any other references to this mac_t (e.g., VLAN's).
* If not, set mi_disabled to prevent any new VLAN's from being
- * created before we can perform the i_mac_destroy() below.
+ * created while we're destroying this mac.
*/
rw_enter(&i_mac_impl_lock, RW_WRITER);
if (mip->mi_ref > 0) {
@@ -1184,12 +1269,7 @@ mac_unregister(mac_t *mp)
cv_wait(&mip->mi_notify_cv, &mip->mi_notify_ref_lock);
mutex_exit(&mip->mi_notify_ref_lock);
- if (strcmp(drvname, "aggr") == 0)
- (void) snprintf(name, MAXNAMELEN, "aggr%u", mp->m_port);
- else
- (void) snprintf(name, MAXNAMELEN, "%s%d", drvname, instance);
-
- if ((err = dls_destroy(name)) != 0) {
+ if ((err = dls_destroy(mip->mi_name)) != 0) {
rw_enter(&i_mac_impl_lock, RW_WRITER);
mip->mi_disabled = B_FALSE;
rw_exit(&i_mac_impl_lock);
@@ -1197,25 +1277,54 @@ mac_unregister(mac_t *mp)
}
/*
- * Destroy the mac_impl_t.
+ * Remove both style 1 and style 2 minor nodes
*/
- i_mac_destroy(mp);
+ ddi_remove_minor_node(mip->mi_dip, (char *)mip->mi_drvname);
+ ddi_remove_minor_node(mip->mi_dip, mip->mi_name);
+
+ ASSERT(!mip->mi_activelink);
+
+ mac_stat_destroy(mip);
+
+ (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--;
+
+ if (mip->mi_pdata != NULL)
+ kmem_free(mip->mi_pdata, mip->mi_pdata_size);
+ mip->mi_pdata = NULL;
+ mip->mi_pdata_size = 0;
/*
- * Remove both style 1 and style 2 minor nodes
+ * Free the list of multicast addresses.
*/
- ddi_remove_minor_node(mp->m_dip, (char *)drvname);
- ddi_remove_minor_node(mp->m_dip, name);
+ for (p = mip->mi_mmap; p != NULL; p = nextp) {
+ nextp = p->mma_nextp;
+ kmem_free(p, sizeof (mac_multicst_addr_t));
+ }
+ mip->mi_mmap = NULL;
+
+ mip->mi_linkstate = LINK_STATE_UNKNOWN;
+ kmem_free(mip->mi_info.mi_unicst_addr, mip->mi_type->mt_addr_length);
+ mip->mi_info.mi_unicst_addr = NULL;
+
+ mip->mi_type->mt_ref--;
+ mip->mi_type = NULL;
+
+ cmn_err(CE_NOTE, "!%s unregistered", mip->mi_name);
+
+ kmem_cache_free(i_mac_impl_cachep, mip);
- cmn_err(CE_NOTE, "!%s%d/%d unregistered", drvname, instance,
- mp->m_port);
return (0);
}
void
-mac_rx(mac_t *mp, mac_resource_handle_t mrh, mblk_t *bp)
+mac_rx(mac_handle_t mh, mac_resource_handle_t mrh, mblk_t *bp)
{
- mac_impl_t *mip = mp->m_impl;
+ mac_impl_t *mip = (mac_impl_t *)mh;
mac_rx_fn_t *mrfp;
/*
@@ -1252,7 +1361,6 @@ mblk_t *
mac_txloop(void *arg, mblk_t *bp)
{
mac_impl_t *mip = arg;
- mac_t *mp = mip->mi_mp;
mac_txloop_fn_t *mtfp;
mblk_t *loop_bp, *resid_bp, *next_bp;
@@ -1263,7 +1371,7 @@ mac_txloop(void *arg, mblk_t *bp)
if ((loop_bp = copymsg(bp)) == NULL)
goto noresources;
- if ((resid_bp = mp->m_tx(mp->m_driver, bp)) != NULL) {
+ if ((resid_bp = mip->mi_tx(mip->mi_driver, bp)) != NULL) {
ASSERT(resid_bp == bp);
freemsg(loop_bp);
goto noresources;
@@ -1303,16 +1411,14 @@ noresources:
}
void
-mac_link_update(mac_t *mp, link_state_t link)
+mac_link_update(mac_handle_t mh, link_state_t link)
{
- mac_impl_t *mip = mp->m_impl;
-
- ASSERT(mip->mi_mp == mp);
+ mac_impl_t *mip = (mac_impl_t *)mh;
/*
* Save the link state.
*/
- mip->mi_link = link;
+ mip->mi_linkstate = link;
/*
* Send a MAC_NOTE_LINK notification.
@@ -1321,16 +1427,17 @@ mac_link_update(mac_t *mp, link_state_t link)
}
void
-mac_unicst_update(mac_t *mp, const uint8_t *addr)
+mac_unicst_update(mac_handle_t mh, const uint8_t *addr)
{
- mac_impl_t *mip = mp->m_impl;
+ mac_impl_t *mip = (mac_impl_t *)mh;
- ASSERT(mip->mi_mp == mp);
+ if (mip->mi_type->mt_addr_length == 0)
+ return;
/*
* Save the address.
*/
- bcopy(addr, mip->mi_addr, mip->mi_addr_length);
+ bcopy(addr, mip->mi_addr, mip->mi_type->mt_addr_length);
/*
* Send a MAC_NOTE_UNICST notification.
@@ -1339,35 +1446,27 @@ mac_unicst_update(mac_t *mp, const uint8_t *addr)
}
void
-mac_tx_update(mac_t *mp)
+mac_tx_update(mac_handle_t mh)
{
- mac_impl_t *mip = mp->m_impl;
-
- ASSERT(mip->mi_mp == mp);
-
/*
* Send a MAC_NOTE_TX notification.
*/
- i_mac_notify(mip, MAC_NOTE_TX);
+ i_mac_notify((mac_impl_t *)mh, MAC_NOTE_TX);
}
void
-mac_resource_update(mac_t *mp)
+mac_resource_update(mac_handle_t mh)
{
- mac_impl_t *mip = mp->m_impl;
-
- ASSERT(mip->mi_mp == mp);
-
/*
* Send a MAC_NOTE_RESOURCE notification.
*/
- i_mac_notify(mip, MAC_NOTE_RESOURCE);
+ i_mac_notify((mac_impl_t *)mh, MAC_NOTE_RESOURCE);
}
mac_resource_handle_t
-mac_resource_add(mac_t *mp, mac_resource_t *mrp)
+mac_resource_add(mac_handle_t mh, mac_resource_t *mrp)
{
- mac_impl_t *mip = mp->m_impl;
+ mac_impl_t *mip = (mac_impl_t *)mh;
mac_resource_handle_t mrh;
mac_resource_add_t add;
void *arg;
@@ -1385,11 +1484,41 @@ mac_resource_add(mac_t *mp, mac_resource_t *mrp)
return (mrh);
}
+int
+mac_pdata_update(mac_handle_t mh, void *mac_pdata, size_t dsize)
+{
+ mac_impl_t *mip = (mac_impl_t *)mh;
+
+ /*
+ * Verify that the plugin supports MAC plugin data and that the
+ * supplied data is valid.
+ */
+ if (!(mip->mi_type->mt_ops.mtops_ops & MTOPS_PDATA_VERIFY))
+ return (EINVAL);
+ if (!mip->mi_type->mt_ops.mtops_pdata_verify(mac_pdata, dsize))
+ return (EINVAL);
+
+ if (mip->mi_pdata != NULL)
+ kmem_free(mip->mi_pdata, mip->mi_pdata_size);
+
+ mip->mi_pdata = kmem_alloc(dsize, KM_SLEEP);
+ bcopy(mac_pdata, mip->mi_pdata, dsize);
+ mip->mi_pdata_size = dsize;
+
+ /*
+ * Since the MAC plugin data is used to construct MAC headers that
+ * were cached in fast-path headers, we need to flush fast-path
+ * information for links associated with this mac.
+ */
+ i_mac_notify(mip, MAC_NOTE_FASTPATH_FLUSH);
+ return (0);
+}
+
void
-mac_multicst_refresh(mac_t *mp, mac_multicst_t refresh, void *arg,
+mac_multicst_refresh(mac_handle_t mh, mac_multicst_t refresh, void *arg,
boolean_t add)
{
- mac_impl_t *mip = mp->m_impl;
+ mac_impl_t *mip = (mac_impl_t *)mh;
mac_multicst_addr_t *p;
/*
@@ -1397,8 +1526,8 @@ mac_multicst_refresh(mac_t *mp, mac_multicst_t refresh, void *arg,
* driver's m_multicst entry point.
*/
if (refresh == NULL) {
- refresh = mp->m_multicst;
- arg = mp->m_driver;
+ refresh = mip->mi_multicst;
+ arg = mip->mi_driver;
}
ASSERT(refresh != NULL);
@@ -1413,16 +1542,16 @@ mac_multicst_refresh(mac_t *mp, mac_multicst_t refresh, void *arg,
}
void
-mac_unicst_refresh(mac_t *mp, mac_unicst_t refresh, void *arg)
+mac_unicst_refresh(mac_handle_t mh, mac_unicst_t refresh, void *arg)
{
- mac_impl_t *mip = mp->m_impl;
+ mac_impl_t *mip = (mac_impl_t *)mh;
/*
* If no specific refresh function was given then default to the
- * driver's m_unicst entry point.
+ * driver's mi_unicst entry point.
*/
if (refresh == NULL) {
- refresh = mp->m_unicst;
- arg = mp->m_driver;
+ refresh = mip->mi_unicst;
+ arg = mip->mi_driver;
}
ASSERT(refresh != NULL);
@@ -1433,17 +1562,17 @@ mac_unicst_refresh(mac_t *mp, mac_unicst_t refresh, void *arg)
}
void
-mac_promisc_refresh(mac_t *mp, mac_promisc_t refresh, void *arg)
+mac_promisc_refresh(mac_handle_t mh, mac_setpromisc_t refresh, void *arg)
{
- mac_impl_t *mip = mp->m_impl;
+ mac_impl_t *mip = (mac_impl_t *)mh;
/*
* If no specific refresh function was given then default to the
* driver's m_promisc entry point.
*/
if (refresh == NULL) {
- refresh = mp->m_promisc;
- arg = mp->m_driver;
+ refresh = mip->mi_setpromisc;
+ arg = mip->mi_driver;
}
ASSERT(refresh != NULL);
@@ -1502,10 +1631,10 @@ i_mac_info_walker(mod_hash_key_t key, mod_hash_val_t *val, void *arg)
return (MH_WALK_CONTINUE);
if (strcmp(statep->mi_name,
- ddi_driver_name(mip->mi_mp->m_dip)) != 0)
+ ddi_driver_name(mip->mi_dip)) != 0)
return (MH_WALK_CONTINUE);
- statep->mi_infop = &mip->mi_mp->m_info;
+ statep->mi_infop = &mip->mi_info;
return (MH_WALK_TERMINATE);
}
@@ -1527,6 +1656,74 @@ mac_info_get(const char *name, mac_info_t *minfop)
return (B_TRUE);
}
+boolean_t
+mac_capab_get(mac_handle_t mh, mac_capab_t cap, void *cap_data)
+{
+ mac_impl_t *mip = (mac_impl_t *)mh;
+
+ if (mip->mi_callbacks->mc_callbacks & MC_GETCAPAB)
+ return (mip->mi_getcapab(mip->mi_driver, cap, cap_data));
+ else
+ return (B_FALSE);
+}
+
+boolean_t
+mac_sap_verify(mac_handle_t mh, uint32_t sap, uint32_t *bind_sap)
+{
+ mac_impl_t *mip = (mac_impl_t *)mh;
+ return (mip->mi_type->mt_ops.mtops_sap_verify(sap, bind_sap,
+ mip->mi_pdata));
+}
+
+mblk_t *
+mac_header(mac_handle_t mh, const uint8_t *daddr, uint32_t sap, mblk_t *payload,
+ size_t extra_len)
+{
+ mac_impl_t *mip = (mac_impl_t *)mh;
+ return (mip->mi_type->mt_ops.mtops_header(mip->mi_addr, daddr, sap,
+ mip->mi_pdata, payload, extra_len));
+}
+
+int
+mac_header_info(mac_handle_t mh, mblk_t *mp, mac_header_info_t *mhip)
+{
+ mac_impl_t *mip = (mac_impl_t *)mh;
+ return (mip->mi_type->mt_ops.mtops_header_info(mp, mip->mi_pdata,
+ mhip));
+}
+
+mblk_t *
+mac_header_cook(mac_handle_t mh, mblk_t *mp)
+{
+ mac_impl_t *mip = (mac_impl_t *)mh;
+ if (mip->mi_type->mt_ops.mtops_ops & MTOPS_HEADER_COOK) {
+ if (DB_REF(mp) > 1) {
+ mblk_t *newmp = copymsg(mp);
+ freemsg(mp);
+ mp = newmp;
+ }
+ return (mip->mi_type->mt_ops.mtops_header_cook(mp,
+ mip->mi_pdata));
+ }
+ return (mp);
+}
+
+mblk_t *
+mac_header_uncook(mac_handle_t mh, mblk_t *mp)
+{
+ mac_impl_t *mip = (mac_impl_t *)mh;
+ if (mip->mi_type->mt_ops.mtops_ops & MTOPS_HEADER_UNCOOK) {
+ if (DB_REF(mp) > 1) {
+ mblk_t *newmp = copymsg(mp);
+ freemsg(mp);
+ mp = newmp;
+ }
+ return (mip->mi_type->mt_ops.mtops_header_uncook(mp,
+ mip->mi_pdata));
+ }
+ return (mp);
+}
+
void
mac_init_ops(struct dev_ops *ops, const char *name)
{
@@ -1538,3 +1735,129 @@ mac_fini_ops(struct dev_ops *ops)
{
dld_fini_ops(ops);
}
+
+/*
+ * MAC Type Plugin functions.
+ */
+
+mactype_register_t *
+mactype_alloc(uint_t mactype_version)
+{
+ mactype_register_t *mtrp;
+
+ /*
+ * Make sure there isn't a version mismatch between the plugin and
+ * the framework. In the future, if multiple versions are
+ * supported, this check could become more sophisticated.
+ */
+ if (mactype_version != MACTYPE_VERSION)
+ return (NULL);
+
+ mtrp = kmem_zalloc(sizeof (mactype_register_t), KM_SLEEP);
+ mtrp->mtr_version = mactype_version;
+ return (mtrp);
+}
+
+void
+mactype_free(mactype_register_t *mtrp)
+{
+ kmem_free(mtrp, sizeof (mactype_register_t));
+}
+
+int
+mactype_register(mactype_register_t *mtrp)
+{
+ mactype_t *mtp;
+ mactype_ops_t *ops = mtrp->mtr_ops;
+
+ /* Do some sanity checking before we register this MAC type. */
+ if (mtrp->mtr_ident == NULL || ops == NULL || mtrp->mtr_addrlen == 0)
+ return (EINVAL);
+
+ /*
+ * Verify that all mandatory callbacks are set in the ops
+ * vector.
+ */
+ if (ops->mtops_unicst_verify == NULL ||
+ ops->mtops_multicst_verify == NULL ||
+ ops->mtops_sap_verify == NULL ||
+ ops->mtops_header == NULL ||
+ ops->mtops_header_info == NULL) {
+ return (EINVAL);
+ }
+
+ mtp = kmem_zalloc(sizeof (*mtp), KM_SLEEP);
+ mtp->mt_ident = mtrp->mtr_ident;
+ mtp->mt_ops = *ops;
+ mtp->mt_type = mtrp->mtr_mactype;
+ mtp->mt_addr_length = mtrp->mtr_addrlen;
+ if (mtrp->mtr_brdcst_addr != NULL) {
+ mtp->mt_brdcst_addr = kmem_alloc(mtrp->mtr_addrlen, KM_SLEEP);
+ bcopy(mtrp->mtr_brdcst_addr, mtp->mt_brdcst_addr,
+ mtrp->mtr_addrlen);
+ }
+
+ mtp->mt_stats = mtrp->mtr_stats;
+ mtp->mt_statcount = mtrp->mtr_statcount;
+
+ /*
+ * A MAC-Type plugin only registers when i_mactype_getplugin() does
+ * an explicit modload() as a result of a driver requesting to use
+ * that plugin in mac_register(). We pre-emptively set the initial
+ * reference count to 1 here to prevent the plugin module from
+ * unloading before the driver's mac_register() completes. If we
+ * were to initialize the reference count to 0, then there would be
+ * a window during which the module could unload before the
+ * reference count could be bumped up to 1.
+ */
+ mtp->mt_ref = 1;
+
+ if (mod_hash_insert(i_mactype_hash,
+ (mod_hash_key_t)mtp->mt_ident, (mod_hash_val_t)mtp) != 0) {
+ kmem_free(mtp->mt_brdcst_addr, mtp->mt_addr_length);
+ kmem_free(mtp, sizeof (*mtp));
+ return (EEXIST);
+ }
+ return (0);
+}
+
+int
+mactype_unregister(const char *ident)
+{
+ mactype_t *mtp;
+ mod_hash_val_t val;
+ int err;
+
+ /*
+ * Let's not allow MAC drivers to use this plugin while we're
+ * trying to unregister it...
+ */
+ rw_enter(&i_mac_impl_lock, RW_WRITER);
+
+ if ((err = mod_hash_find(i_mactype_hash, (mod_hash_key_t)ident,
+ (mod_hash_val_t *)&mtp)) != 0) {
+ /* A plugin is trying to unregister, but it never registered. */
+ rw_exit(&i_mac_impl_lock);
+ return (ENXIO);
+ }
+
+ if (mtp->mt_ref > 0) {
+ rw_exit(&i_mac_impl_lock);
+ return (EBUSY);
+ }
+
+ err = mod_hash_remove(i_mactype_hash, (mod_hash_key_t)ident, &val);
+ ASSERT(err == 0);
+ if (err != 0) {
+ /* This should never happen, thus the ASSERT() above. */
+ rw_exit(&i_mac_impl_lock);
+ return (EINVAL);
+ }
+ ASSERT(mtp == (mactype_t *)val);
+
+ kmem_free(mtp->mt_brdcst_addr, mtp->mt_addr_length);
+ kmem_free(mtp, sizeof (mactype_t));
+ rw_exit(&i_mac_impl_lock);
+
+ return (0);
+}
diff --git a/usr/src/uts/common/io/mac/mac_stat.c b/usr/src/uts/common/io/mac/mac_stat.c
index b972eb58d9..85d716c1ef 100644
--- a/usr/src/uts/common/io/mac/mac_stat.c
+++ b/usr/src/uts/common/io/mac/mac_stat.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -37,81 +36,49 @@
#include <sys/mac.h>
#include <sys/mac_impl.h>
-typedef struct i_mac_stat_info_s {
- enum mac_stat msi_stat;
- char *msi_name;
- uint_t msi_type;
-} i_mac_stat_info_t;
-
-static i_mac_stat_info_t i_mac_si[] = {
- { MAC_STAT_IFSPEED, "ifspeed", KSTAT_DATA_UINT64 },
- { MAC_STAT_MULTIRCV, "multircv", KSTAT_DATA_UINT32 },
- { MAC_STAT_BRDCSTRCV, "brdcstrcv", KSTAT_DATA_UINT32 },
- { MAC_STAT_MULTIXMT, "multixmt", KSTAT_DATA_UINT32 },
- { MAC_STAT_BRDCSTXMT, "brdcstxmt", KSTAT_DATA_UINT32 },
- { MAC_STAT_NORCVBUF, "norcvbuf", KSTAT_DATA_UINT32 },
- { MAC_STAT_IERRORS, "ierrors", KSTAT_DATA_UINT32 },
- { MAC_STAT_UNKNOWNS, "unknowns", KSTAT_DATA_UINT32 },
- { MAC_STAT_NOXMTBUF, "noxmtbuf", KSTAT_DATA_UINT32 },
- { MAC_STAT_OERRORS, "oerrors", KSTAT_DATA_UINT32 },
- { MAC_STAT_COLLISIONS, "collisions", KSTAT_DATA_UINT32 },
- { MAC_STAT_RBYTES, "rbytes", KSTAT_DATA_UINT32 },
- { MAC_STAT_IPACKETS, "ipackets", KSTAT_DATA_UINT32 },
- { MAC_STAT_OBYTES, "obytes", KSTAT_DATA_UINT32 },
- { MAC_STAT_OPACKETS, "opackets", KSTAT_DATA_UINT32 },
- { MAC_STAT_RBYTES, "rbytes64", KSTAT_DATA_UINT64 },
- { MAC_STAT_IPACKETS, "ipackets64", KSTAT_DATA_UINT64 },
- { MAC_STAT_OBYTES, "obytes64", KSTAT_DATA_UINT64 },
- { MAC_STAT_OPACKETS, "opackets64", KSTAT_DATA_UINT64 },
- { MAC_STAT_ALIGN_ERRORS, "align_errors", KSTAT_DATA_UINT32 },
- { MAC_STAT_FCS_ERRORS, "fcs_errors", KSTAT_DATA_UINT32 },
- { MAC_STAT_FIRST_COLLISIONS, "first_collsions", KSTAT_DATA_UINT32 },
- { MAC_STAT_MULTI_COLLISIONS, "multi_collsions", KSTAT_DATA_UINT32 },
- { MAC_STAT_SQE_ERRORS, "sqe_errors", KSTAT_DATA_UINT32 },
- { MAC_STAT_DEFER_XMTS, "defer_xmts", KSTAT_DATA_UINT32 },
- { MAC_STAT_TX_LATE_COLLISIONS, "tx_late_collsions", KSTAT_DATA_UINT32 },
- { MAC_STAT_EX_COLLISIONS, "ex_collsions", KSTAT_DATA_UINT32 },
- { MAC_STAT_MACXMT_ERRORS, "macxmt_errors", KSTAT_DATA_UINT32 },
- { MAC_STAT_CARRIER_ERRORS, "carrier_errors", KSTAT_DATA_UINT32 },
- { MAC_STAT_TOOLONG_ERRORS, "toolong_errors", KSTAT_DATA_UINT32 },
- { MAC_STAT_MACRCV_ERRORS, "macrcv_errors", KSTAT_DATA_UINT32 },
- { MAC_STAT_XCVR_ADDR, "xcvr_addr", KSTAT_DATA_UINT32 },
- { MAC_STAT_XCVR_ID, "xcvr_id", KSTAT_DATA_UINT32 },
- { MAC_STAT_XCVR_INUSE, "xcvr_inuse", KSTAT_DATA_UINT32 },
- { MAC_STAT_CAP_1000FDX, "cap_1000fdx", KSTAT_DATA_UINT32 },
- { MAC_STAT_CAP_1000HDX, "cap_1000hdx", KSTAT_DATA_UINT32 },
- { MAC_STAT_CAP_100FDX, "cap_100fdx", KSTAT_DATA_UINT32 },
- { MAC_STAT_CAP_100HDX, "cap_100hdx", KSTAT_DATA_UINT32 },
- { MAC_STAT_CAP_10FDX, "cap_10fdx", KSTAT_DATA_UINT32 },
- { MAC_STAT_CAP_10HDX, "cap_10hdx", KSTAT_DATA_UINT32 },
- { MAC_STAT_CAP_ASMPAUSE, "cap_asmpause", KSTAT_DATA_UINT32 },
- { MAC_STAT_CAP_PAUSE, "cap_pause", KSTAT_DATA_UINT32 },
- { MAC_STAT_CAP_AUTONEG, "cap_autoneg", KSTAT_DATA_UINT32 },
- { MAC_STAT_ADV_CAP_1000FDX, "adv_cap_1000fdx", KSTAT_DATA_UINT32 },
- { MAC_STAT_ADV_CAP_1000HDX, "adv_cap_1000hdx", KSTAT_DATA_UINT32 },
- { MAC_STAT_ADV_CAP_100FDX, "adv_cap_100fdx", KSTAT_DATA_UINT32 },
- { MAC_STAT_ADV_CAP_100HDX, "adv_cap_100hdx", KSTAT_DATA_UINT32 },
- { MAC_STAT_ADV_CAP_10FDX, "adv_cap_10fdx", KSTAT_DATA_UINT32 },
- { MAC_STAT_ADV_CAP_10HDX, "adv_cap_10hdx", KSTAT_DATA_UINT32 },
- { MAC_STAT_ADV_CAP_ASMPAUSE, "adv_cap_asmpause", KSTAT_DATA_UINT32 },
- { MAC_STAT_ADV_CAP_PAUSE, "adv_cap_pause", KSTAT_DATA_UINT32 },
- { MAC_STAT_ADV_CAP_AUTONEG, "adv_cap_autoneg", KSTAT_DATA_UINT32 },
- { MAC_STAT_LP_CAP_1000FDX, "lp_cap_1000fdx", KSTAT_DATA_UINT32 },
- { MAC_STAT_LP_CAP_1000HDX, "lp_cap_1000hdx", KSTAT_DATA_UINT32 },
- { MAC_STAT_LP_CAP_100FDX, "lp_cap_100fdx", KSTAT_DATA_UINT32 },
- { MAC_STAT_LP_CAP_100HDX, "lp_cap_100hdx", KSTAT_DATA_UINT32 },
- { MAC_STAT_LP_CAP_10FDX, "lp_cap_10fdx", KSTAT_DATA_UINT32 },
- { MAC_STAT_LP_CAP_10HDX, "lp_cap_10hdx", KSTAT_DATA_UINT32 },
- { MAC_STAT_LP_CAP_ASMPAUSE, "lp_cap_asmpause", KSTAT_DATA_UINT32 },
- { MAC_STAT_LP_CAP_PAUSE, "lp_cap_pause", KSTAT_DATA_UINT32 },
- { MAC_STAT_LP_CAP_AUTONEG, "lp_cap_autoneg", KSTAT_DATA_UINT32 },
- { MAC_STAT_LINK_ASMPAUSE, "link_asmpause", KSTAT_DATA_UINT32 },
- { MAC_STAT_LINK_PAUSE, "link_pause", KSTAT_DATA_UINT32 },
- { MAC_STAT_LINK_AUTONEG, "link_autoneg", KSTAT_DATA_UINT32 },
- { MAC_STAT_LINK_DUPLEX, "link_duplex", KSTAT_DATA_UINT32 }
+#define MAC_KSTAT_NAME "mac"
+#define MAC_KSTAT_CLASS "net"
+
+typedef int (*ks_update_fnp)(struct kstat *, int);
+
+static mac_stat_info_t i_mac_si[] = {
+ { MAC_STAT_IFSPEED, "ifspeed", KSTAT_DATA_UINT64, 0 },
+ { MAC_STAT_MULTIRCV, "multircv", KSTAT_DATA_UINT32, 0 },
+ { MAC_STAT_BRDCSTRCV, "brdcstrcv", KSTAT_DATA_UINT32, 0 },
+ { MAC_STAT_MULTIXMT, "multixmt", KSTAT_DATA_UINT32, 0 },
+ { MAC_STAT_BRDCSTXMT, "brdcstxmt", KSTAT_DATA_UINT32, 0 },
+ { MAC_STAT_NORCVBUF, "norcvbuf", KSTAT_DATA_UINT32, 0 },
+ { MAC_STAT_IERRORS, "ierrors", KSTAT_DATA_UINT32, 0 },
+ { MAC_STAT_UNKNOWNS, "unknowns", KSTAT_DATA_UINT32, 0 },
+ { MAC_STAT_NOXMTBUF, "noxmtbuf", KSTAT_DATA_UINT32, 0 },
+ { MAC_STAT_OERRORS, "oerrors", KSTAT_DATA_UINT32, 0 },
+ { MAC_STAT_COLLISIONS, "collisions", KSTAT_DATA_UINT32, 0 },
+ { MAC_STAT_RBYTES, "rbytes", KSTAT_DATA_UINT32, 0 },
+ { MAC_STAT_IPACKETS, "ipackets", KSTAT_DATA_UINT32, 0 },
+ { MAC_STAT_OBYTES, "obytes", KSTAT_DATA_UINT32, 0 },
+ { MAC_STAT_OPACKETS, "opackets", KSTAT_DATA_UINT32, 0 },
+ { MAC_STAT_RBYTES, "rbytes64", KSTAT_DATA_UINT64, 0 },
+ { MAC_STAT_IPACKETS, "ipackets64", KSTAT_DATA_UINT64, 0 },
+ { MAC_STAT_OBYTES, "obytes64", KSTAT_DATA_UINT64, 0 },
+ { MAC_STAT_OPACKETS, "opackets64", KSTAT_DATA_UINT64, 0 }
};
-#define STAT_INFO_COUNT (sizeof (i_mac_si) / sizeof (i_mac_si[0]))
+#define MAC_NKSTAT \
+ (sizeof (i_mac_si) / sizeof (mac_stat_info_t))
+
+static mac_stat_info_t i_mac_mod_si[] = {
+ { MAC_STAT_LINK_STATE, "link_state", KSTAT_DATA_UINT32,
+ (uint64_t)LINK_STATE_UNKNOWN },
+ { MAC_STAT_LINK_UP, "link_up", KSTAT_DATA_UINT32, 0 },
+ { MAC_STAT_PROMISC, "promisc", KSTAT_DATA_UINT32, 0 }
+};
+
+#define MAC_MOD_NKSTAT \
+ (sizeof (i_mac_mod_si) / sizeof (mac_stat_info_t))
+
+#define MAC_MOD_KSTAT_OFFSET 0
+#define MAC_KSTAT_OFFSET MAC_MOD_KSTAT_OFFSET + MAC_MOD_NKSTAT
+#define MAC_TYPE_KSTAT_OFFSET MAC_KSTAT_OFFSET + MAC_NKSTAT
/*
* Private functions.
@@ -121,22 +88,29 @@ static int
i_mac_stat_update(kstat_t *ksp, int rw)
{
mac_impl_t *mip = ksp->ks_private;
- mac_t *mp = mip->mi_mp;
- kstat_named_t *knp;
+ kstat_named_t *knp = ksp->ks_data;
uint_t i;
uint64_t val;
+ mac_stat_info_t *msi;
+ uint_t msi_index;
if (rw != KSTAT_READ)
return (EACCES);
- knp = ksp->ks_data;
- for (i = 0; i < STAT_INFO_COUNT; i++) {
- if (!(mp->m_info.mi_stat[i_mac_si[i].msi_stat]))
- continue;
-
- val = mac_stat_get((mac_handle_t)mip, i_mac_si[i].msi_stat);
+ for (i = 0; i < mip->mi_kstat_count; i++, msi_index++) {
+ if (i == MAC_MOD_KSTAT_OFFSET) {
+ msi_index = 0;
+ msi = i_mac_mod_si;
+ } else if (i == MAC_KSTAT_OFFSET) {
+ msi_index = 0;
+ msi = i_mac_si;
+ } else if (i == MAC_TYPE_KSTAT_OFFSET) {
+ msi_index = 0;
+ msi = mip->mi_type->mt_stats;
+ }
- switch (i_mac_si[i].msi_type) {
+ val = mac_stat_get((mac_handle_t)mip, msi[msi_index].msi_stat);
+ switch (msi[msi_index].msi_type) {
case KSTAT_DATA_UINT64:
knp->value.ui64 = val;
break;
@@ -151,55 +125,56 @@ i_mac_stat_update(kstat_t *ksp, int rw)
knp++;
}
- (knp++)->value.ui32 = mip->mi_link;
- (knp++)->value.ui32 = (mip->mi_link == LINK_STATE_UP);
- knp->value.ui32 = (mip->mi_devpromisc != 0);
-
return (0);
}
+static void
+i_mac_kstat_init(kstat_named_t *knp, mac_stat_info_t *si, uint_t count)
+{
+ int i;
+ for (i = 0; i < count; i++) {
+ kstat_named_init(knp, si[i].msi_name, si[i].msi_type);
+ knp++;
+ }
+}
+
/*
* Exported functions.
*/
+/*
+ * Create the "mac" kstat. The "mac" kstat is comprised of three kinds of
+ * statistics: statistics maintained by the mac module itself, generic mac
+ * statistics maintained by the driver, and MAC-type specific statistics
+ * also maintained by the driver.
+ */
void
mac_stat_create(mac_impl_t *mip)
{
- mac_t *mp = mip->mi_mp;
kstat_t *ksp;
kstat_named_t *knp;
- uint_t i;
uint_t count;
- count = 0;
- for (i = 0; i < STAT_INFO_COUNT; i++) {
- if (mp->m_info.mi_stat[i_mac_si[i].msi_stat])
- count++;
- }
-
- if ((ksp = kstat_create(mip->mi_dev, mip->mi_port, mip->mi_name,
- "mac", KSTAT_TYPE_NAMED, count + 3, 0)) == NULL)
+ count = MAC_MOD_NKSTAT + MAC_NKSTAT + mip->mi_type->mt_statcount;
+ ksp = kstat_create((char *)mip->mi_drvname, mip->mi_instance,
+ MAC_KSTAT_NAME, MAC_KSTAT_CLASS, KSTAT_TYPE_NAMED, count, 0);
+ if (ksp == NULL)
return;
ksp->ks_update = i_mac_stat_update;
- ksp->ks_private = (void *)mip;
+ ksp->ks_private = mip;
mip->mi_ksp = ksp;
+ mip->mi_kstat_count = count;
knp = (kstat_named_t *)ksp->ks_data;
- for (i = 0; i < STAT_INFO_COUNT; i++) {
- if (!(mp->m_info.mi_stat[i_mac_si[i].msi_stat]))
- continue;
-
- kstat_named_init(knp, i_mac_si[i].msi_name,
- i_mac_si[i].msi_type);
- knp++;
- --count;
+ i_mac_kstat_init(knp, i_mac_mod_si, MAC_MOD_NKSTAT);
+ knp += MAC_MOD_NKSTAT;
+ i_mac_kstat_init(knp, i_mac_si, MAC_NKSTAT);
+ if (mip->mi_type->mt_statcount > 0) {
+ knp += MAC_NKSTAT;
+ i_mac_kstat_init(knp, mip->mi_type->mt_stats,
+ mip->mi_type->mt_statcount);
}
- ASSERT(count == 0);
-
- kstat_named_init(knp++, "link_state", KSTAT_DATA_UINT32);
- kstat_named_init(knp++, "link_up", KSTAT_DATA_UINT32);
- kstat_named_init(knp, "promisc", KSTAT_DATA_UINT32);
kstat_install(ksp);
}
@@ -208,6 +183,23 @@ mac_stat_create(mac_impl_t *mip)
void
mac_stat_destroy(mac_impl_t *mip)
{
- kstat_delete(mip->mi_ksp);
- mip->mi_ksp = NULL;
+ if (mip->mi_ksp != NULL) {
+ kstat_delete(mip->mi_ksp);
+ mip->mi_ksp = NULL;
+ mip->mi_kstat_count = 0;
+ }
+}
+
+uint64_t
+mac_stat_default(mac_impl_t *mip, uint_t stat)
+{
+ uint_t stat_index;
+
+ if (IS_MAC_STAT(stat)) {
+ stat_index = stat - MAC_STAT_MIN;
+ return (i_mac_si[stat_index].msi_default);
+ }
+ ASSERT(IS_MACTYPE_STAT(stat));
+ stat_index = stat - MACTYPE_STAT_MIN;
+ return (mip->mi_type->mt_stats[stat_index].msi_default);
}
diff --git a/usr/src/uts/common/io/mac/plugins/mac_ether.c b/usr/src/uts/common/io/mac/plugins/mac_ether.c
new file mode 100644
index 0000000000..7636fa996a
--- /dev/null
+++ b/usr/src/uts/common/io/mac/plugins/mac_ether.c
@@ -0,0 +1,278 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * 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 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * DL_ETHER MAC Type plugin for the Nemo mac module
+ */
+
+#include <sys/types.h>
+#include <sys/modctl.h>
+#include <sys/dlpi.h>
+#include <sys/mac.h>
+#include <sys/mac_ether.h>
+#include <sys/dls.h>
+#include <sys/ethernet.h>
+#include <sys/byteorder.h>
+#include <sys/strsun.h>
+#include <inet/common.h>
+
+static uint8_t ether_brdcst[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
+
+static mac_stat_info_t ether_stats[] = {
+ /* RFC1643 stats */
+ { ETHER_STAT_ALIGN_ERRORS, "align_errors", KSTAT_DATA_UINT32, 0 },
+ { ETHER_STAT_FCS_ERRORS, "fcs_errors", KSTAT_DATA_UINT32, 0 },
+ { ETHER_STAT_FIRST_COLLISIONS, "first_collsions", KSTAT_DATA_UINT32,
+ 0 },
+ { ETHER_STAT_MULTI_COLLISIONS, "multi_collsions", KSTAT_DATA_UINT32,
+ 0 },
+ { ETHER_STAT_SQE_ERRORS, "sqe_errors", KSTAT_DATA_UINT32, 0},
+ { ETHER_STAT_DEFER_XMTS, "defer_xmts", KSTAT_DATA_UINT32, 0},
+ { ETHER_STAT_TX_LATE_COLLISIONS, "tx_late_collsions",
+ KSTAT_DATA_UINT32, 0 },
+ { ETHER_STAT_EX_COLLISIONS, "ex_collsions", KSTAT_DATA_UINT32, 0 },
+ { ETHER_STAT_MACXMT_ERRORS, "macxmt_errors", KSTAT_DATA_UINT32, 0 },
+ { ETHER_STAT_CARRIER_ERRORS, "carrier_errors", KSTAT_DATA_UINT32, 0 },
+ { ETHER_STAT_TOOLONG_ERRORS, "toolong_errors", KSTAT_DATA_UINT32, 0 },
+ { ETHER_STAT_MACRCV_ERRORS, "macrcv_errors", KSTAT_DATA_UINT32, 0 },
+
+ /* Statistics described in the ieee802.3(5) man page */
+ { ETHER_STAT_XCVR_ADDR, "xcvr_addr", KSTAT_DATA_UINT32, 0 },
+ { ETHER_STAT_XCVR_ID, "xcvr_id", KSTAT_DATA_UINT32, 0 },
+ { ETHER_STAT_XCVR_INUSE, "xcvr_inuse", KSTAT_DATA_UINT32, 0 },
+ { ETHER_STAT_CAP_1000FDX, "cap_1000fdx", KSTAT_DATA_UINT32, 0 },
+ { ETHER_STAT_CAP_1000HDX, "cap_1000hdx", KSTAT_DATA_UINT32, 0 },
+ { ETHER_STAT_CAP_100FDX, "cap_100fdx", KSTAT_DATA_UINT32, 0 },
+ { ETHER_STAT_CAP_100HDX, "cap_100hdx", KSTAT_DATA_UINT32, 0 },
+ { ETHER_STAT_CAP_10FDX, "cap_10fdx", KSTAT_DATA_UINT32, 0 },
+ { ETHER_STAT_CAP_10HDX, "cap_10hdx", KSTAT_DATA_UINT32, 0 },
+ { ETHER_STAT_CAP_ASMPAUSE, "cap_asmpause", KSTAT_DATA_UINT32, 0 },
+ { ETHER_STAT_CAP_PAUSE, "cap_pause", KSTAT_DATA_UINT32, 0 },
+ { ETHER_STAT_CAP_AUTONEG, "cap_autoneg", KSTAT_DATA_UINT32, 0 },
+ { ETHER_STAT_ADV_CAP_1000FDX, "adv_cap_1000fdx", KSTAT_DATA_UINT32, 0 },
+ { ETHER_STAT_ADV_CAP_1000HDX, "adv_cap_1000hdx", KSTAT_DATA_UINT32, 0 },
+ { ETHER_STAT_ADV_CAP_100FDX, "adv_cap_100fdx", KSTAT_DATA_UINT32, 0},
+ { ETHER_STAT_ADV_CAP_100HDX, "adv_cap_100hdx", KSTAT_DATA_UINT32, 0},
+ { ETHER_STAT_ADV_CAP_10FDX, "adv_cap_10fdx", KSTAT_DATA_UINT32, 0 },
+ { ETHER_STAT_ADV_CAP_10HDX, "adv_cap_10hdx", KSTAT_DATA_UINT32, 0 },
+ { ETHER_STAT_ADV_CAP_ASMPAUSE, "adv_cap_asmpause", KSTAT_DATA_UINT32,
+ 0 },
+ { ETHER_STAT_ADV_CAP_PAUSE, "adv_cap_pause", KSTAT_DATA_UINT32, 0 },
+ { ETHER_STAT_ADV_CAP_AUTONEG, "adv_cap_autoneg", KSTAT_DATA_UINT32, 0 },
+ { ETHER_STAT_LP_CAP_1000FDX, "lp_cap_1000fdx", KSTAT_DATA_UINT32, 0 },
+ { ETHER_STAT_LP_CAP_1000HDX, "lp_cap_1000hdx", KSTAT_DATA_UINT32, 0 },
+ { ETHER_STAT_LP_CAP_100FDX, "lp_cap_100fdx", KSTAT_DATA_UINT32, 0 },
+ { ETHER_STAT_LP_CAP_100HDX, "lp_cap_100hdx", KSTAT_DATA_UINT32, 0 },
+ { ETHER_STAT_LP_CAP_10FDX, "lp_cap_10fdx", KSTAT_DATA_UINT32, 0 },
+ { ETHER_STAT_LP_CAP_10HDX, "lp_cap_10hdx", KSTAT_DATA_UINT32, 0 },
+ { ETHER_STAT_LP_CAP_ASMPAUSE, "lp_cap_asmpause", KSTAT_DATA_UINT32, 0 },
+ { ETHER_STAT_LP_CAP_PAUSE, "lp_cap_pause", KSTAT_DATA_UINT32, 0 },
+ { ETHER_STAT_LP_CAP_AUTONEG, "lp_cap_autoneg", KSTAT_DATA_UINT32, 0 },
+ { ETHER_STAT_LINK_ASMPAUSE, "link_asmpause", KSTAT_DATA_UINT32, 0 },
+ { ETHER_STAT_LINK_PAUSE, "link_pause", KSTAT_DATA_UINT32, 0 },
+ { ETHER_STAT_LINK_AUTONEG, "link_autoneg", KSTAT_DATA_UINT32, 0 },
+ { ETHER_STAT_LINK_DUPLEX, "link_duplex", KSTAT_DATA_UINT32, 0 }
+};
+
+static struct modlmisc mac_ether_modlmisc = {
+ &mod_miscops,
+ "DL_ETHER MAC Type plugin"
+};
+
+static struct modlinkage mac_ether_modlinkage = {
+ MODREV_1,
+ &mac_ether_modlmisc,
+ NULL
+};
+
+static mactype_ops_t mac_ether_type_ops;
+
+int
+_init(void)
+{
+ mactype_register_t *mtrp;
+ int err;
+
+ if ((mtrp = mactype_alloc(MACTYPE_VERSION)) == NULL)
+ return (ENOTSUP);
+ mtrp->mtr_ident = MAC_PLUGIN_IDENT_ETHER;
+ mtrp->mtr_ops = &mac_ether_type_ops;
+ mtrp->mtr_mactype = DL_ETHER;
+ mtrp->mtr_addrlen = ETHERADDRL;
+ mtrp->mtr_brdcst_addr = ether_brdcst;
+ mtrp->mtr_stats = ether_stats;
+ mtrp->mtr_statcount = A_CNT(ether_stats);
+ if ((err = mactype_register(mtrp)) == 0) {
+ if ((err = mod_install(&mac_ether_modlinkage)) != 0)
+ (void) mactype_unregister(MAC_PLUGIN_IDENT_ETHER);
+ }
+ mactype_free(mtrp);
+ return (err);
+}
+
+int
+_fini(void)
+{
+ int err;
+
+ if ((err = mactype_unregister(MAC_PLUGIN_IDENT_ETHER)) != 0)
+ return (err);
+ return (mod_remove(&mac_ether_modlinkage));
+}
+
+int
+_info(struct modinfo *modinfop)
+{
+ return (mod_info(&mac_ether_modlinkage, modinfop));
+}
+
+/*
+ * MAC Type plugin operations
+ */
+
+/* ARGSUSED */
+int
+mac_ether_unicst_verify(const void *addr, void *mac_pdata)
+{
+ /* If it's not a group address, then it's a valid unicast address. */
+ return (((((uint8_t *)addr)[0] & 0x01) != 0) ? EINVAL : 0);
+}
+
+/* ARGSUSED */
+int
+mac_ether_multicst_verify(const void *addr, void *mac_pdata)
+{
+ /* The address must be a group address. */
+ if ((((uint8_t *)addr)[0] & 0x01) == 0)
+ return (EINVAL);
+ /* The address must not be the media broadcast address. */
+ if (bcmp(addr, ether_brdcst, ETHERADDRL) == 0)
+ return (EINVAL);
+ return (0);
+}
+
+/*
+ * Check the legality of an Ethernet SAP value. The following values are
+ * allowed, as specified by PSARC 2003/150:
+ *
+ * 0..ETHERMTU (1500) 802 semantics
+ * ETHERTYPE_802_MIN (1536)..ETHERTYPE_MAX (65535) ethertype semantics
+ *
+ * Note that SAP values less than or equal to ETHERMTU (1500) represent LLC
+ * channels. (See PSARC 2003/150). We strictly use SAP 0 to represent LLC
+ * channels.
+ */
+/* ARGSUSED */
+boolean_t
+mac_ether_sap_verify(uint32_t sap, uint32_t *bind_sap, void *mac_pdata)
+{
+ if (sap >= ETHERTYPE_802_MIN && sap <= ETHERTYPE_MAX) {
+ if (bind_sap != NULL)
+ *bind_sap = sap;
+ return (B_TRUE);
+ }
+
+ if (sap <= ETHERMTU) {
+ if (bind_sap != NULL)
+ *bind_sap = DLS_SAP_LLC;
+ return (B_TRUE);
+ }
+ return (B_FALSE);
+}
+
+/* ARGSUSED */
+mblk_t *
+mac_ether_header(const void *saddr, const void *daddr, uint32_t sap,
+ void *mac_pdata, mblk_t *payload, size_t extra_len)
+{
+ struct ether_header *ehp;
+ mblk_t *mp;
+ uint32_t bind_sap;
+
+ if (!mac_ether_sap_verify(sap, &bind_sap, NULL))
+ return (NULL);
+
+ mp = allocb(sizeof (struct ether_header) + extra_len, BPRI_HI);
+ if (mp == NULL)
+ return (NULL);
+
+ ehp = (struct ether_header *)mp->b_rptr;
+ bcopy(daddr, &(ehp->ether_dhost), ETHERADDRL);
+ bcopy(saddr, &(ehp->ether_shost), ETHERADDRL);
+
+ /*
+ * sap <= ETHERMTU indicates that LLC is being used. If that's the
+ * case, then the ether_type needs to be set to the payload length.
+ */
+ if ((bind_sap == DLS_SAP_LLC) && (payload != NULL))
+ sap = msgdsize(payload);
+ ehp->ether_type = htons(sap);
+
+ mp->b_wptr += sizeof (struct ether_header);
+ return (mp);
+}
+
+/* ARGSUSED */
+int
+mac_ether_header_info(mblk_t *mp, void *mac_pdata, mac_header_info_t *hdr_info)
+{
+ struct ether_header *ehp;
+ uint16_t ether_type;
+
+ if (MBLKL(mp) < sizeof (struct ether_header))
+ return (EINVAL);
+
+ ehp = (struct ether_header *)mp->b_rptr;
+ ether_type = ntohs(ehp->ether_type);
+
+ hdr_info->mhi_hdrsize = sizeof (struct ether_header);
+ hdr_info->mhi_daddr = (const uint8_t *)&(ehp->ether_dhost);
+ hdr_info->mhi_saddr = (const uint8_t *)&(ehp->ether_shost);
+ hdr_info->mhi_origsap = ether_type;
+ hdr_info->mhi_bindsap = (ether_type > ETHERMTU) ?
+ ether_type : DLS_SAP_LLC;
+ hdr_info->mhi_pktsize = (hdr_info->mhi_bindsap == DLS_SAP_LLC) ?
+ hdr_info->mhi_hdrsize + ether_type : 0;
+
+ if (mac_ether_unicst_verify(hdr_info->mhi_daddr, NULL) == 0)
+ hdr_info->mhi_dsttype = MAC_ADDRTYPE_UNICAST;
+ else if (mac_ether_multicst_verify(hdr_info->mhi_daddr, NULL) == 0)
+ hdr_info->mhi_dsttype = MAC_ADDRTYPE_MULTICAST;
+ else
+ hdr_info->mhi_dsttype = MAC_ADDRTYPE_BROADCAST;
+
+ return (0);
+}
+
+static mactype_ops_t mac_ether_type_ops = {
+ 0,
+ mac_ether_unicst_verify,
+ mac_ether_multicst_verify,
+ mac_ether_sap_verify,
+ mac_ether_header,
+ mac_ether_header_info
+};
diff --git a/usr/src/uts/common/io/rge/rge.h b/usr/src/uts/common/io/rge/rge.h
index 067cc35a1e..7f5f4c29c6 100755
--- a/usr/src/uts/common/io/rge/rge.h
+++ b/usr/src/uts/common/io/rge/rge.h
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -64,6 +63,7 @@ extern "C" {
#include <sys/sunddi.h>
#include <sys/mac.h>
+#include <sys/mac_ether.h>
/*
* Reconfiguring the network devices requires the net_config privilege
@@ -387,7 +387,7 @@ typedef struct rge_stats {
*/
typedef struct rge {
dev_info_t *devinfo; /* device instance */
- mac_t *macp; /* MAC structure */
+ mac_handle_t mh; /* mac module handle */
ddi_acc_handle_t cfg_handle; /* DDI I/O handle */
ddi_acc_handle_t io_handle; /* DDI I/O handle */
caddr_t io_regs; /* mapped registers */
@@ -735,7 +735,7 @@ void rge_phy_update(rge_t *rgep);
/* rge_kstats.c */
void rge_init_kstats(rge_t *rgep, int instance);
void rge_fini_kstats(rge_t *rgep);
-uint64_t rge_m_stat(void *arg, enum mac_stat stat);
+int rge_m_stat(void *arg, uint_t stat, uint64_t *val);
/* rge_log.c */
#if RGE_DEBUGGING
diff --git a/usr/src/uts/common/io/rge/rge_chip.c b/usr/src/uts/common/io/rge/rge_chip.c
index 0c9483d9c8..5942f1df8a 100755
--- a/usr/src/uts/common/io/rge/rge_chip.c
+++ b/usr/src/uts/common/io/rge/rge_chip.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -1463,7 +1462,7 @@ rge_chip_factotum(caddr_t arg)
* Note: can't do this while still holding the mutex.
*/
if (linkchg)
- mac_link_update(rgep->macp, rgep->param_link_up);
+ mac_link_update(rgep->mh, rgep->param_link_up);
return (result);
}
diff --git a/usr/src/uts/common/io/rge/rge_kstats.c b/usr/src/uts/common/io/rge/rge_kstats.c
index d36649b9cc..996d4b4888 100755
--- a/usr/src/uts/common/io/rge/rge_kstats.c
+++ b/usr/src/uts/common/io/rge/rge_kstats.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -197,12 +196,11 @@ rge_fini_kstats(rge_t *rgep)
}
}
-uint64_t
-rge_m_stat(void *arg, enum mac_stat stat)
+int
+rge_m_stat(void *arg, uint_t stat, uint64_t *val)
{
rge_t *rgep = arg;
rge_hw_stats_t *bstp;
- uint64_t val = 0;
mutex_enter(rgep->genlock);
rge_hw_stats_dump(rgep);
@@ -211,167 +209,160 @@ rge_m_stat(void *arg, enum mac_stat stat)
switch (stat) {
case MAC_STAT_IFSPEED:
- val = rgep->param_link_speed * 1000000ull;
+ *val = rgep->param_link_speed * 1000000ull;
break;
case MAC_STAT_MULTIRCV:
- val = RGE_BSWAP_32(bstp->multi_rcv);
+ *val = RGE_BSWAP_32(bstp->multi_rcv);
break;
case MAC_STAT_BRDCSTRCV:
- val = RGE_BSWAP_64(bstp->brdcst_rcv);
+ *val = RGE_BSWAP_64(bstp->brdcst_rcv);
break;
case MAC_STAT_NORCVBUF:
- val = RGE_BSWAP_16(bstp->in_discards);
+ *val = RGE_BSWAP_16(bstp->in_discards);
break;
case MAC_STAT_IERRORS:
- val = RGE_BSWAP_32(bstp->rcv_err);
+ *val = RGE_BSWAP_32(bstp->rcv_err);
break;
case MAC_STAT_OERRORS:
- val = RGE_BSWAP_64(bstp->xmt_err);
+ *val = RGE_BSWAP_64(bstp->xmt_err);
break;
case MAC_STAT_COLLISIONS:
- val = RGE_BSWAP_32(bstp->xmt_1col + bstp->xmt_mcol);
+ *val = RGE_BSWAP_32(bstp->xmt_1col + bstp->xmt_mcol);
break;
case MAC_STAT_RBYTES:
- val = rgep->stats.rbytes;
+ *val = rgep->stats.rbytes;
break;
case MAC_STAT_IPACKETS:
- val = RGE_BSWAP_64(bstp->rcv_ok);
+ *val = RGE_BSWAP_64(bstp->rcv_ok);
break;
case MAC_STAT_OBYTES:
- val = rgep->stats.obytes;
+ *val = rgep->stats.obytes;
break;
case MAC_STAT_OPACKETS:
- val = RGE_BSWAP_64(bstp->xmt_ok);
+ *val = RGE_BSWAP_64(bstp->xmt_ok);
break;
- case MAC_STAT_ALIGN_ERRORS:
- val = RGE_BSWAP_16(bstp->frame_err);
+ case ETHER_STAT_ALIGN_ERRORS:
+ *val = RGE_BSWAP_16(bstp->frame_err);
break;
- case MAC_STAT_FIRST_COLLISIONS:
- val = RGE_BSWAP_32(bstp->xmt_1col);
+ case ETHER_STAT_FIRST_COLLISIONS:
+ *val = RGE_BSWAP_32(bstp->xmt_1col);
break;
- case MAC_STAT_MULTI_COLLISIONS:
- val = RGE_BSWAP_32(bstp->xmt_mcol);
+ case ETHER_STAT_MULTI_COLLISIONS:
+ *val = RGE_BSWAP_32(bstp->xmt_mcol);
break;
- case MAC_STAT_DEFER_XMTS:
- val = rgep->stats.defer;
+ case ETHER_STAT_DEFER_XMTS:
+ *val = rgep->stats.defer;
break;
- case MAC_STAT_XCVR_ADDR:
- val = rgep->phy_mii_addr;
+ case ETHER_STAT_XCVR_ADDR:
+ *val = rgep->phy_mii_addr;
break;
- case MAC_STAT_XCVR_ID:
+ case ETHER_STAT_XCVR_ID:
mutex_enter(rgep->genlock);
- val = rge_mii_get16(rgep, MII_PHYIDH);
- val <<= 16;
- val |= rge_mii_get16(rgep, MII_PHYIDL);
+ *val = rge_mii_get16(rgep, MII_PHYIDH);
+ *val <<= 16;
+ *val |= rge_mii_get16(rgep, MII_PHYIDL);
mutex_exit(rgep->genlock);
break;
- case MAC_STAT_XCVR_INUSE:
- val = XCVR_1000T;
+ case ETHER_STAT_XCVR_INUSE:
+ *val = XCVR_1000T;
break;
- case MAC_STAT_CAP_1000FDX:
- val = 1;
+ case ETHER_STAT_CAP_1000FDX:
+ *val = 1;
break;
- case MAC_STAT_CAP_1000HDX:
- val = 0;
+ case ETHER_STAT_CAP_1000HDX:
+ *val = 0;
break;
- case MAC_STAT_CAP_100FDX:
- val = 1;
+ case ETHER_STAT_CAP_100FDX:
+ *val = 1;
break;
- case MAC_STAT_CAP_100HDX:
- val = 1;
+ case ETHER_STAT_CAP_100HDX:
+ *val = 1;
break;
- case MAC_STAT_CAP_10FDX:
- val = 1;
+ case ETHER_STAT_CAP_10FDX:
+ *val = 1;
break;
- case MAC_STAT_CAP_10HDX:
- val = 1;
+ case ETHER_STAT_CAP_10HDX:
+ *val = 1;
break;
- case MAC_STAT_CAP_ASMPAUSE:
- val = 1;
+ case ETHER_STAT_CAP_ASMPAUSE:
+ *val = 1;
break;
- case MAC_STAT_CAP_PAUSE:
- val = 1;
+ case ETHER_STAT_CAP_PAUSE:
+ *val = 1;
break;
- case MAC_STAT_CAP_AUTONEG:
- val = 1;
+ case ETHER_STAT_CAP_AUTONEG:
+ *val = 1;
break;
- case MAC_STAT_ADV_CAP_1000FDX:
- val = rgep->param_adv_1000fdx;
+ case ETHER_STAT_ADV_CAP_1000FDX:
+ *val = rgep->param_adv_1000fdx;
break;
- case MAC_STAT_ADV_CAP_1000HDX:
- val = rgep->param_adv_1000hdx;
+ case ETHER_STAT_ADV_CAP_1000HDX:
+ *val = rgep->param_adv_1000hdx;
break;
- case MAC_STAT_ADV_CAP_100FDX:
- val = rgep->param_adv_100fdx;
+ case ETHER_STAT_ADV_CAP_100FDX:
+ *val = rgep->param_adv_100fdx;
break;
- case MAC_STAT_ADV_CAP_100HDX:
- val = rgep->param_adv_100hdx;
+ case ETHER_STAT_ADV_CAP_100HDX:
+ *val = rgep->param_adv_100hdx;
break;
- case MAC_STAT_ADV_CAP_10FDX:
- val = rgep->param_adv_10fdx;
+ case ETHER_STAT_ADV_CAP_10FDX:
+ *val = rgep->param_adv_10fdx;
break;
- case MAC_STAT_ADV_CAP_10HDX:
- val = rgep->param_adv_10hdx;
+ case ETHER_STAT_ADV_CAP_10HDX:
+ *val = rgep->param_adv_10hdx;
break;
- case MAC_STAT_ADV_CAP_ASMPAUSE:
- val = rgep->param_adv_asym_pause;
+ case ETHER_STAT_ADV_CAP_ASMPAUSE:
+ *val = rgep->param_adv_asym_pause;
break;
- case MAC_STAT_ADV_CAP_PAUSE:
- val = rgep->param_adv_pause;
+ case ETHER_STAT_ADV_CAP_PAUSE:
+ *val = rgep->param_adv_pause;
break;
- case MAC_STAT_ADV_CAP_AUTONEG:
- val = rgep->param_adv_autoneg;
+ case ETHER_STAT_ADV_CAP_AUTONEG:
+ *val = rgep->param_adv_autoneg;
break;
- case MAC_STAT_LINK_DUPLEX:
- val = rgep->param_link_duplex;
+ case ETHER_STAT_LINK_DUPLEX:
+ *val = rgep->param_link_duplex;
break;
-#ifdef DEBUG
default:
- /*
- * Shouldn't reach here...
- */
- cmn_err(CE_PANIC,
- "rge_m_stat: unrecognized parameter value = %d",
- stat);
-#endif
+ return (ENOTSUP);
}
- return (val);
+ return (0);
}
diff --git a/usr/src/uts/common/io/rge/rge_main.c b/usr/src/uts/common/io/rge/rge_main.c
index ac296cc3cd..329f54fb61 100755
--- a/usr/src/uts/common/io/rge/rge_main.c
+++ b/usr/src/uts/common/io/rge/rge_main.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -100,15 +99,35 @@ static ddi_device_acc_attr_t rge_buf_accattr = {
DDI_DEFAULT_ACC
};
-static ether_addr_t rge_broadcast_addr = {
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
-};
-
/*
* Property names
*/
static char debug_propname[] = "rge-debug-flags";
+static int rge_m_start(void *);
+static void rge_m_stop(void *);
+static int rge_m_promisc(void *, boolean_t);
+static int rge_m_multicst(void *, boolean_t, const uint8_t *);
+static int rge_m_unicst(void *, const uint8_t *);
+static void rge_m_resources(void *);
+static void rge_m_ioctl(void *, queue_t *, mblk_t *);
+static boolean_t rge_m_getcapab(void *, mac_capab_t, void *);
+
+#define RGE_M_CALLBACK_FLAGS (MC_RESOURCES | MC_IOCTL | MC_GETCAPAB)
+
+static mac_callbacks_t rge_m_callbacks = {
+ RGE_M_CALLBACK_FLAGS,
+ rge_m_stat,
+ rge_m_start,
+ rge_m_stop,
+ rge_m_promisc,
+ rge_m_multicst,
+ rge_m_unicst,
+ rge_m_tx,
+ rge_m_resources,
+ rge_m_ioctl,
+ rge_m_getcapab
+};
/*
* Allocate an area of memory and a DMA handle for accessing it
@@ -1205,11 +1224,33 @@ rge_m_resources(void *arg)
mrf.mrf_arg = (void *)rgep;
mrf.mrf_normal_blank_time = RGE_RX_INT_TIME;
mrf.mrf_normal_pkt_count = RGE_RX_INT_PKTS;
- rgep->handle = mac_resource_add(rgep->macp, (mac_resource_t *)&mrf);
+ rgep->handle = mac_resource_add(rgep->mh, (mac_resource_t *)&mrf);
mutex_exit(rgep->genlock);
}
+/* ARGSUSED */
+static boolean_t
+rge_m_getcapab(void *arg, mac_capab_t cap, void *cap_data)
+{
+ switch (cap) {
+ case MAC_CAPAB_HCKSUM: {
+ uint32_t *hcksum_txflags = cap_data;
+ *hcksum_txflags = HCKSUM_INET_FULL_V4 | HCKSUM_IPHDRCKSUM;
+ break;
+ }
+ case MAC_CAPAB_POLL:
+ /*
+ * There's nothing for us to fill in, simply returning
+ * B_TRUE stating that we support polling is sufficient.
+ */
+ break;
+ default:
+ return (B_FALSE);
+ }
+ return (B_TRUE);
+}
+
/*
* ========== Per-instance setup/teardown code ==========
*/
@@ -1220,8 +1261,6 @@ rge_m_resources(void *arg)
static void
rge_unattach(rge_t *rgep)
{
- mac_t *macp;
-
/*
* Flag that no more activity may be initiated
*/
@@ -1276,8 +1315,6 @@ rge_unattach(rge_t *rgep)
pci_config_teardown(&rgep->cfg_handle);
ddi_remove_minor_node(rgep->devinfo, NULL);
- macp = rgep->macp;
- kmem_free(macp, sizeof (*macp));
kmem_free(rgep, sizeof (*rgep));
}
@@ -1330,8 +1367,7 @@ static int
rge_attach(dev_info_t *devinfo, ddi_attach_cmd_t cmd)
{
rge_t *rgep; /* Our private data */
- mac_t *macp;
- mac_info_t *mip;
+ mac_register_t *macp;
chip_id_t *cidp;
cyc_handler_t cychand;
cyc_time_t cyctime;
@@ -1364,17 +1400,9 @@ rge_attach(dev_info_t *devinfo, ddi_attach_cmd_t cmd)
break;
}
- /*
- * Allocate mac_t and RGE private structures, and
- * cross-link them so that given either one of these or
- * the devinfo the others can be derived.
- */
- macp = kmem_zalloc(sizeof (*macp), KM_SLEEP);
rgep = kmem_zalloc(sizeof (*rgep), KM_SLEEP);
ddi_set_driver_private(devinfo, rgep);
rgep->devinfo = devinfo;
- rgep->macp = macp;
- macp->m_driver = rgep;
/*
* Initialize more fields in RGE private data
@@ -1529,72 +1557,23 @@ rge_attach(dev_info_t *devinfo, ddi_attach_cmd_t cmd)
rge_init_kstats(rgep, instance);
rgep->progress |= PROGRESS_KSTATS;
- /*
- * Initialize pointers to device specific functions which
- * will be used by the generic layer.
- */
- mip = &(macp->m_info);
- mip->mi_media = DL_ETHER;
- mip->mi_sdu_min = 0;
- mip->mi_sdu_max = rgep->param_default_mtu;
- mip->mi_cksum = HCKSUM_INET_FULL_V4 | HCKSUM_IPHDRCKSUM;
- mip->mi_poll = DL_CAPAB_POLL;
-
- mip->mi_addr_length = ETHERADDRL;
- bcopy(rge_broadcast_addr, mip->mi_brdcst_addr, ETHERADDRL);
- bcopy(rgep->netaddr, mip->mi_unicst_addr, ETHERADDRL);
-
- /*
- * Register h/w supported statistics
- */
- MAC_STAT_MIB(mip->mi_stat);
- mip->mi_stat[MAC_STAT_MULTIXMT] = B_FALSE;
- mip->mi_stat[MAC_STAT_BRDCSTXMT] = B_FALSE;
- mip->mi_stat[MAC_STAT_UNKNOWNS] = B_FALSE;
- mip->mi_stat[MAC_STAT_NOXMTBUF] = B_FALSE;
-
- MAC_STAT_ETHER(mip->mi_stat);
- mip->mi_stat[MAC_STAT_FCS_ERRORS] = B_FALSE;
- mip->mi_stat[MAC_STAT_SQE_ERRORS] = B_FALSE;
- mip->mi_stat[MAC_STAT_TX_LATE_COLLISIONS] = B_FALSE;
- mip->mi_stat[MAC_STAT_EX_COLLISIONS] = B_FALSE;
- mip->mi_stat[MAC_STAT_MACXMT_ERRORS] = B_FALSE;
- mip->mi_stat[MAC_STAT_CARRIER_ERRORS] = B_FALSE;
- mip->mi_stat[MAC_STAT_TOOLONG_ERRORS] = B_FALSE;
- mip->mi_stat[MAC_STAT_MACRCV_ERRORS] = B_FALSE;
-
- MAC_STAT_MII(mip->mi_stat);
- mip->mi_stat[MAC_STAT_LP_CAP_1000FDX] = B_FALSE;
- mip->mi_stat[MAC_STAT_LP_CAP_1000HDX] = B_FALSE;
- mip->mi_stat[MAC_STAT_LP_CAP_100FDX] = B_FALSE;
- mip->mi_stat[MAC_STAT_LP_CAP_100HDX] = B_FALSE;
- mip->mi_stat[MAC_STAT_LP_CAP_10FDX] = B_FALSE;
- mip->mi_stat[MAC_STAT_LP_CAP_10HDX] = B_FALSE;
- mip->mi_stat[MAC_STAT_LP_CAP_ASMPAUSE] = B_FALSE;
- mip->mi_stat[MAC_STAT_LP_CAP_PAUSE] = B_FALSE;
- mip->mi_stat[MAC_STAT_LP_CAP_AUTONEG] = B_FALSE;
- mip->mi_stat[MAC_STAT_LINK_ASMPAUSE] = B_FALSE;
- mip->mi_stat[MAC_STAT_LINK_PAUSE] = B_FALSE;
- mip->mi_stat[MAC_STAT_LINK_AUTONEG] = B_FALSE;
-
- macp->m_stat = rge_m_stat;
- macp->m_stop = rge_m_stop;
- macp->m_start = rge_m_start;
- macp->m_unicst = rge_m_unicst;
- macp->m_multicst = rge_m_multicst;
- macp->m_promisc = rge_m_promisc;
- macp->m_tx = rge_m_tx;
- macp->m_resources = rge_m_resources;
- macp->m_ioctl = rge_m_ioctl;
-
+ if ((macp = mac_alloc(MAC_VERSION)) == NULL)
+ goto attach_fail;
+ macp->m_type_ident = MAC_PLUGIN_IDENT_ETHER;
+ macp->m_driver = rgep;
macp->m_dip = devinfo;
- macp->m_ident = MAC_IDENT;
+ macp->m_src_addr = rgep->netaddr;
+ macp->m_callbacks = &rge_m_callbacks;
+ macp->m_min_sdu = 0;
+ macp->m_max_sdu = rgep->param_default_mtu;
/*
* Finally, we're ready to register ourselves with the MAC layer
* interface; if this succeeds, we're all ready to start()
*/
- if (mac_register(macp) != 0)
+ err = mac_register(macp, &rgep->mh);
+ mac_free(macp);
+ if (err != 0)
goto attach_fail;
cychand.cyh_func = rge_chip_cyclic;
@@ -1666,7 +1645,7 @@ rge_detach(dev_info_t *devinfo, ddi_detach_cmd_t cmd)
* in which case we just return failure without shutting
* down chip operations.
*/
- if (mac_unregister(rgep->macp) != 0)
+ if (mac_unregister(rgep->mh) != 0)
return (DDI_FAILURE);
/*
diff --git a/usr/src/uts/common/io/rge/rge_rxtx.c b/usr/src/uts/common/io/rge/rge_rxtx.c
index 6619bfdd94..376f831dd9 100755
--- a/usr/src/uts/common/io/rge/rge_rxtx.c
+++ b/usr/src/uts/common/io/rge/rge_rxtx.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -372,7 +371,7 @@ rge_receive(rge_t *rgep)
mutex_exit(rgep->rx_lock);
if (mp != NULL)
- mac_rx(rgep->macp, rgep->handle, mp);
+ mac_rx(rgep->mh, rgep->handle, mp);
}
@@ -686,7 +685,7 @@ rge_reschedule(caddr_t arg)
rslt = DDI_INTR_UNCLAIMED;
if (rgep->rge_mac_state == RGE_MAC_STARTED && rgep->resched_needed) {
- mac_tx_update(rgep->macp);
+ mac_tx_update(rgep->mh);
rgep->resched_needed = B_FALSE;
rslt = DDI_INTR_CLAIMED;
}
diff --git a/usr/src/uts/common/io/xge/drv/xge.c b/usr/src/uts/common/io/xge/drv/xge.c
index e3a07a7590..379522cec7 100644
--- a/usr/src/uts/common/io/xge/drv/xge.c
+++ b/usr/src/uts/common/io/xge/drv/xge.c
@@ -81,7 +81,7 @@ xge_event(xge_queue_item_t *item)
if (lldev->is_initialized) {
if (__hal_channel_dtr_count(lldev->fifo_channel)
>= XGELL_TX_LEVEL_HIGH) {
- mac_tx_update(lldev->macp);
+ mac_tx_update(lldev->mh);
xge_debug_osdep(XGE_TRACE,
"mac_tx_update happened!");
}
diff --git a/usr/src/uts/common/io/xge/drv/xgell.c b/usr/src/uts/common/io/xge/drv/xgell.c
index 5ea55f8b36..e9b8885d89 100644
--- a/usr/src/uts/common/io/xge/drv/xgell.c
+++ b/usr/src/uts/common/io/xge/drv/xgell.c
@@ -41,11 +41,9 @@
#include <netinet/ip.h>
#include <netinet/tcp.h>
-#define XGELL_MAX_FRAME_SIZE(macp) ((macp->m_info.mi_sdu_max) + \
+#define XGELL_MAX_FRAME_SIZE(hldev) ((hldev)->config.mtu + \
sizeof (struct ether_vlan_header))
-u8 xge_broadcast_addr[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
-
#define HEADROOM 2 /* for DIX-only packets */
#ifdef XGELL_L3_ALIGNED
@@ -126,6 +124,32 @@ struct ddi_dma_attr hal_dma_attr_aligned = {
struct ddi_dma_attr *p_hal_dma_attr = &hal_dma_attr;
struct ddi_dma_attr *p_hal_dma_attr_aligned = &hal_dma_attr_aligned;
+static int xgell_m_stat(void *, uint_t, uint64_t *);
+static int xgell_m_start(void *);
+static void xgell_m_stop(void *);
+static int xgell_m_promisc(void *, boolean_t);
+static int xgell_m_multicst(void *, boolean_t, const uint8_t *);
+static int xgell_m_unicst(void *, const uint8_t *);
+static void xgell_m_ioctl(void *, queue_t *, mblk_t *);
+static mblk_t *xgell_m_tx(void *, mblk_t *);
+static boolean_t xgell_m_getcapab(void *, mac_capab_t, void *);
+
+#define XGELL_M_CALLBACK_FLAGS (MC_IOCTL | MC_GETCAPAB)
+
+static mac_callbacks_t xgell_m_callbacks = {
+ XGELL_M_CALLBACK_FLAGS,
+ xgell_m_stat,
+ xgell_m_start,
+ xgell_m_stop,
+ xgell_m_promisc,
+ xgell_m_multicst,
+ xgell_m_unicst,
+ xgell_m_tx,
+ NULL,
+ xgell_m_ioctl,
+ xgell_m_getcapab
+};
+
/*
* xge_device_poll
*
@@ -174,7 +198,7 @@ xgell_callback_link_up(void *userdata)
{
xgelldev_t *lldev = (xgelldev_t *)userdata;
- mac_link_update(lldev->macp, LINK_STATE_UP);
+ mac_link_update(lldev->mh, LINK_STATE_UP);
/* Link states should be reported to user whenever it changes */
cmn_err(CE_NOTE, "!%s%d: Link is up [10 Gbps Full Duplex]",
XGELL_IFNAME, lldev->instance);
@@ -190,7 +214,7 @@ xgell_callback_link_down(void *userdata)
{
xgelldev_t *lldev = (xgelldev_t *)userdata;
- mac_link_update(lldev->macp, LINK_STATE_DOWN);
+ mac_link_update(lldev->mh, LINK_STATE_DOWN);
/* Link states should be reported to user whenever it changes */
cmn_err(CE_NOTE, "!%s%d: Link is down", XGELL_IFNAME,
lldev->instance);
@@ -299,7 +323,7 @@ xgell_rx_buffer_alloc(xgelldev_t *lldev)
extern ddi_device_acc_attr_t *p_xge_dev_attr;
xgell_rx_buffer_t *rx_buffer;
- hldev = (xge_hal_device_t *)lldev->devh;
+ hldev = lldev->devh;
if (ddi_dma_alloc_handle(hldev->pdev, p_hal_dma_attr, DDI_DMA_SLEEP,
0, &dma_handle) != DDI_SUCCESS) {
@@ -427,16 +451,14 @@ xgell_rx_destroy_buffer_pool(xgelldev_t *lldev)
static int
xgell_rx_create_buffer_pool(xgelldev_t *lldev)
{
- mac_t *macp;
xge_hal_device_t *hldev;
xgell_rx_buffer_t *rx_buffer;
int i;
- macp = lldev->macp;
- hldev = macp->m_driver;
+ hldev = (xge_hal_device_t *)lldev->devh;
lldev->bf_pool.total = 0;
- lldev->bf_pool.size = XGELL_MAX_FRAME_SIZE(lldev->macp);
+ lldev->bf_pool.size = XGELL_MAX_FRAME_SIZE(hldev);
lldev->bf_pool.head = NULL;
lldev->bf_pool.free = 0;
lldev->bf_pool.post = 0;
@@ -477,9 +499,7 @@ xgell_rx_dtr_replenish(xge_hal_channel_h channelh, xge_hal_dtr_h dtr, int index,
void *userdata, xge_hal_channel_reopen_e reopen)
{
xgell_ring_t *ring = userdata;
- mac_t *macp = ring->macp;
- xge_hal_device_t *hldev = (xge_hal_device_t *)macp->m_driver;
- xgelldev_t *lldev = xge_hal_device_private(hldev);
+ xgelldev_t *lldev = ring->lldev;
xgell_rx_buffer_t *rx_buffer;
xgell_rxd_priv_t *rxd_priv;
@@ -742,10 +762,8 @@ static xge_hal_status_e
xgell_rx_1b_compl(xge_hal_channel_h channelh, xge_hal_dtr_h dtr, u8 t_code,
void *userdata)
{
- mac_t *macp = ((xgell_ring_t *)userdata)->macp;
+ xgelldev_t *lldev = ((xgell_ring_t *)userdata)->lldev;
xgell_rx_buffer_t *rx_buffer;
- xge_hal_device_t *hldev = (xge_hal_device_t *)macp->m_driver;
- xgelldev_t *lldev = xge_hal_device_private(hldev);
mblk_t *mp_head = NULL;
mblk_t *mp_end = NULL;
@@ -845,7 +863,7 @@ xgell_rx_1b_compl(xge_hal_channel_h channelh, xge_hal_dtr_h dtr, u8 t_code,
XGE_HAL_OK);
if (mp_head) {
- mac_rx(macp, ((xgell_ring_t *)userdata)->handle, mp_head);
+ mac_rx(lldev->mh, ((xgell_ring_t *)userdata)->handle, mp_head);
}
/*
@@ -1048,7 +1066,7 @@ _begin:
continue;
}
- ret = ddi_dma_alloc_handle(lldev->macp->m_dip, &tx_dma_attr,
+ ret = ddi_dma_alloc_handle(lldev->dev_info, &tx_dma_attr,
DDI_DMA_DONTWAIT, 0, &dma_handle);
if (ret != DDI_SUCCESS) {
xge_debug_ll(XGE_ERR,
@@ -1335,7 +1353,7 @@ xgell_rx_open(xgelldev_t *lldev)
return (B_FALSE);
}
- lldev->ring_main.macp = lldev->macp;
+ lldev->ring_main.lldev = lldev;
attr.userdata = &lldev->ring_main;
status = xge_hal_channel_open(lldev->devh, &attr,
@@ -1353,10 +1371,8 @@ static int
xgell_initiate_start(xgelldev_t *lldev)
{
xge_hal_status_e status;
-#ifdef XGELL_TX_NOMAP_COPY
xge_hal_device_t *hldev = lldev->devh;
-#endif
- int maxpkt = lldev->macp->m_info.mi_sdu_max;
+ int maxpkt = hldev->config.mtu;
/* check initial mtu before enabling the device */
status = xge_hal_device_mtu_check(lldev->devh, maxpkt);
@@ -1399,7 +1415,7 @@ xgell_initiate_start(xgelldev_t *lldev)
}
#ifdef XGELL_TX_NOMAP_COPY
- hldev->config.fifo.alignment_size = XGELL_MAX_FRAME_SIZE(lldev->macp);
+ hldev->config.fifo.alignment_size = XGELL_MAX_FRAME_SIZE(hldev);
#endif
if (!xgell_tx_open(lldev)) {
@@ -1702,108 +1718,107 @@ xgell_m_promisc(void *arg, boolean_t on)
}
/*
- * xgell_m_stats
+ * xgell_m_stat
* @arg: pointer to device private strucutre(hldev)
- * @msp: pointer to mac_stats_t strucutre
*
- * This function is called by MAC Layer to get network statistics
+ * This function is called by MAC Layer to get network statistics
* from the driver.
*/
-static uint64_t
-xgell_m_stat(void *arg, enum mac_stat stat)
+static int
+xgell_m_stat(void *arg, uint_t stat, uint64_t *val)
{
xge_hal_stats_hw_info_t *hw_info;
xge_hal_device_t *hldev = (xge_hal_device_t *)arg;
xgelldev_t *lldev = xge_hal_device_private(hldev);
- uint64_t val;
xge_debug_ll(XGE_TRACE, "%s", "MAC_STATS_GET");
if (!mutex_tryenter(&lldev->genlock))
- return (0);
+ return (EAGAIN);
if (!lldev->is_initialized) {
mutex_exit(&lldev->genlock);
- return (0);
+ return (EAGAIN);
}
if (xge_hal_stats_hw(hldev, &hw_info) != XGE_HAL_OK) {
mutex_exit(&lldev->genlock);
- return (0);
+ return (EAGAIN);
}
switch (stat) {
case MAC_STAT_IFSPEED:
- val = 10000000000ull; /* 10G */
- break;
-
- case MAC_STAT_LINK_DUPLEX:
- val = LINK_DUPLEX_FULL;
+ *val = 10000000000ull; /* 10G */
break;
case MAC_STAT_MULTIRCV:
- val = hw_info->rmac_vld_mcst_frms;
+ *val = hw_info->rmac_vld_mcst_frms;
break;
case MAC_STAT_BRDCSTRCV:
- val = hw_info->rmac_vld_bcst_frms;
+ *val = hw_info->rmac_vld_bcst_frms;
break;
case MAC_STAT_MULTIXMT:
- val = hw_info->tmac_mcst_frms;
+ *val = hw_info->tmac_mcst_frms;
break;
case MAC_STAT_BRDCSTXMT:
- val = hw_info->tmac_bcst_frms;
+ *val = hw_info->tmac_bcst_frms;
break;
case MAC_STAT_RBYTES:
- val = hw_info->rmac_ttl_octets;
+ *val = hw_info->rmac_ttl_octets;
break;
case MAC_STAT_NORCVBUF:
- val = hw_info->rmac_drop_frms;
+ *val = hw_info->rmac_drop_frms;
break;
case MAC_STAT_IERRORS:
- val = hw_info->rmac_discarded_frms;
+ *val = hw_info->rmac_discarded_frms;
break;
case MAC_STAT_OBYTES:
- val = hw_info->tmac_ttl_octets;
+ *val = hw_info->tmac_ttl_octets;
break;
case MAC_STAT_NOXMTBUF:
- val = hw_info->tmac_drop_frms;
+ *val = hw_info->tmac_drop_frms;
break;
case MAC_STAT_OERRORS:
- val = hw_info->tmac_any_err_frms;
+ *val = hw_info->tmac_any_err_frms;
break;
case MAC_STAT_IPACKETS:
- val = hw_info->rmac_vld_frms;
+ *val = hw_info->rmac_vld_frms;
break;
case MAC_STAT_OPACKETS:
- val = hw_info->tmac_frms;
+ *val = hw_info->tmac_frms;
+ break;
+
+ case ETHER_STAT_FCS_ERRORS:
+ *val = hw_info->rmac_fcs_err_frms;
break;
- case MAC_STAT_FCS_ERRORS:
- val = hw_info->rmac_fcs_err_frms;
+ case ETHER_STAT_TOOLONG_ERRORS:
+ *val = hw_info->rmac_long_frms;
break;
- case MAC_STAT_TOOLONG_ERRORS:
- val = hw_info->rmac_long_frms;
+ case ETHER_STAT_LINK_DUPLEX:
+ *val = LINK_DUPLEX_FULL;
break;
default:
- ASSERT(B_FALSE);
+ mutex_exit(&lldev->genlock);
+ return (ENOTSUP);
}
mutex_exit(&lldev->genlock);
- return (val);
+ return (0);
}
/*
@@ -1825,7 +1840,6 @@ xgell_device_alloc(xge_hal_device_h devh,
lldev = kmem_zalloc(sizeof (xgelldev_t), KM_SLEEP);
/* allocate mac */
- lldev->macp = kmem_zalloc(sizeof (mac_t), KM_SLEEP);
lldev->devh = hldev;
lldev->instance = instance;
lldev->dev_info = dev_info;
@@ -1846,8 +1860,6 @@ xgell_device_free(xgelldev_t *lldev)
xge_debug_ll(XGE_TRACE, "freeing device %s%d",
XGELL_IFNAME, lldev->instance);
- kmem_free(lldev->macp, sizeof (*(lldev->macp)));
-
kmem_free(lldev, sizeof (xgelldev_t));
}
@@ -1929,29 +1941,28 @@ xgell_m_ioctl(void *arg, queue_t *wq, mblk_t *mp)
}
}
-static void
-xgell_m_blank(void *arg, time_t ticks, uint_t count)
-{
-}
-
-#define XGE_RX_INTPT_TIME 128
-#define XGE_RX_PKT_CNT 8
-
-static void
-xgell_m_resources(void *arg)
+/* ARGSUSED */
+static boolean_t
+xgell_m_getcapab(void *arg, mac_capab_t cap, void *cap_data)
{
- xge_hal_device_t *hldev = (xge_hal_device_t *)arg;
- xgelldev_t *lldev = xge_hal_device_private(hldev);
- mac_rx_fifo_t mrf;
-
- mrf.mrf_type = MAC_RX_FIFO;
- mrf.mrf_blank = xgell_m_blank;
- mrf.mrf_arg = (void *)hldev;
- mrf.mrf_normal_blank_time = XGE_RX_INTPT_TIME;
- mrf.mrf_normal_pkt_count = XGE_RX_PKT_CNT;
-
- lldev->ring_main.handle = mac_resource_add(lldev->macp,
- (mac_resource_t *)&mrf);
+ switch (cap) {
+ case MAC_CAPAB_HCKSUM: {
+ uint32_t *hcksum_txflags = cap_data;
+ *hcksum_txflags = HCKSUM_INET_FULL_V4 | HCKSUM_INET_FULL_V6 |
+ HCKSUM_IPHDRCKSUM;
+ break;
+ }
+ case MAC_CAPAB_POLL:
+ /*
+ * Fallthrough to default, as we don't support GLDv3
+ * polling. When blanking is implemented, we will need to
+ * change this to return B_TRUE in addition to registering
+ * an mc_resources callback.
+ */
+ default:
+ return (B_FALSE);
+ }
+ return (B_TRUE);
}
static int
@@ -2231,100 +2242,39 @@ xgell_devconfig_get(queue_t *q, mblk_t *mp, caddr_t cp, cred_t *credp)
int
xgell_device_register(xgelldev_t *lldev, xgell_config_t *config)
{
- mac_t *macp = lldev->macp;
+ mac_register_t *macp;
xge_hal_device_t *hldev = (xge_hal_device_t *)lldev->devh;
- mac_info_t *mip;
-
- mip = &(macp->m_info);
-
- mip->mi_media = DL_ETHER;
- mip->mi_sdu_min = 0;
- mip->mi_sdu_max = hldev->config.mtu;
- mip->mi_cksum = HCKSUM_INET_FULL_V4 | HCKSUM_INET_FULL_V6 |
- HCKSUM_IPHDRCKSUM;
+ int err;
- /*
- * When xgell_m_blank() has a valid implementation, this
- * should be changed to enable polling by add DL_CAPAB_POLL
- * to mp_poll.
- */
- mip->mi_poll = 0;
- mip->mi_addr_length = ETHERADDRL;
- bcopy(xge_broadcast_addr, mip->mi_brdcst_addr, ETHERADDRL);
- bcopy(&hldev->macaddr[0], mip->mi_unicst_addr, ETHERADDRL);
-
- MAC_STAT_MIB(mip->mi_stat);
- mip->mi_stat[MAC_STAT_UNKNOWNS] = B_FALSE;
- mip->mi_stat[MAC_STAT_COLLISIONS] = B_FALSE;
-
- mip->mi_stat[MAC_STAT_FCS_ERRORS] = B_TRUE;
- mip->mi_stat[MAC_STAT_TOOLONG_ERRORS] = B_TRUE;
-
- mip->mi_stat[MAC_STAT_LINK_DUPLEX] = B_TRUE;
-
- macp->m_stat = xgell_m_stat;
- macp->m_stop = xgell_m_stop;
- macp->m_start = xgell_m_start;
- macp->m_unicst = xgell_m_unicst;
- macp->m_multicst = xgell_m_multicst;
- macp->m_promisc = xgell_m_promisc;
- macp->m_tx = xgell_m_tx;
- macp->m_resources = xgell_m_resources;
- macp->m_ioctl = xgell_m_ioctl;
-
- macp->m_dip = hldev->pdev;
- macp->m_driver = (caddr_t)hldev;
- macp->m_ident = MAC_IDENT;
if (nd_load(&lldev->ndp, "pciconf", xgell_pciconf_get, NULL,
- (caddr_t)lldev) == B_FALSE) {
- nd_free(&lldev->ndp);
- xge_debug_ll(XGE_ERR, "%s", "unable to load ndd parameter");
- return (DDI_FAILURE);
- }
+ (caddr_t)lldev) == B_FALSE)
+ goto xgell_ndd_fail;
if (nd_load(&lldev->ndp, "about", xgell_about_get, NULL,
- (caddr_t)lldev) == B_FALSE) {
- nd_free(&lldev->ndp);
- xge_debug_ll(XGE_ERR, "%s", "unable to load ndd parameter");
- return (DDI_FAILURE);
- }
+ (caddr_t)lldev) == B_FALSE)
+ goto xgell_ndd_fail;
if (nd_load(&lldev->ndp, "stats", xgell_stats_get, NULL,
- (caddr_t)lldev) == B_FALSE) {
- nd_free(&lldev->ndp);
- xge_debug_ll(XGE_ERR, "%s", "unable to load ndd parameter");
- return (DDI_FAILURE);
- }
+ (caddr_t)lldev) == B_FALSE)
+ goto xgell_ndd_fail;
if (nd_load(&lldev->ndp, "bar0", xgell_bar0_get, xgell_bar0_set,
- (caddr_t)lldev) == B_FALSE) {
- nd_free(&lldev->ndp);
- xge_debug_ll(XGE_ERR, "%s", "unable to load ndd parameter");
- return (DDI_FAILURE);
- }
+ (caddr_t)lldev) == B_FALSE)
+ goto xgell_ndd_fail;
if (nd_load(&lldev->ndp, "debug_level", xgell_debug_level_get,
- xgell_debug_level_set, (caddr_t)lldev) == B_FALSE) {
- nd_free(&lldev->ndp);
- xge_debug_ll(XGE_ERR, "%s", "unable to load ndd parameter");
- return (DDI_FAILURE);
- }
+ xgell_debug_level_set, (caddr_t)lldev) == B_FALSE)
+ goto xgell_ndd_fail;
if (nd_load(&lldev->ndp, "debug_module_mask",
xgell_debug_module_mask_get, xgell_debug_module_mask_set,
- (caddr_t)lldev) == B_FALSE) {
- nd_free(&lldev->ndp);
- xge_debug_ll(XGE_ERR, "%s", "unable to load ndd parameter");
- return (DDI_FAILURE);
- }
+ (caddr_t)lldev) == B_FALSE)
+ goto xgell_ndd_fail;
if (nd_load(&lldev->ndp, "devconfig", xgell_devconfig_get, NULL,
- (caddr_t)lldev) == B_FALSE) {
- nd_free(&lldev->ndp);
- xge_debug_ll(XGE_ERR, "%s", "unable to load ndd parameter");
- return (DDI_FAILURE);
- }
+ (caddr_t)lldev) == B_FALSE)
+ goto xgell_ndd_fail;
bcopy(config, &lldev->config, sizeof (xgell_config_t));
@@ -2336,24 +2286,41 @@ xgell_device_register(xgelldev_t *lldev, xgell_config_t *config)
mutex_init(&lldev->genlock, NULL, MUTEX_DRIVER, hldev->irqh);
+ if ((macp = mac_alloc(MAC_VERSION)) == NULL)
+ goto xgell_register_fail;
+ macp->m_type_ident = MAC_PLUGIN_IDENT_ETHER;
+ macp->m_driver = hldev;
+ macp->m_dip = lldev->dev_info;
+ macp->m_src_addr = hldev->macaddr[0];
+ macp->m_callbacks = &xgell_m_callbacks;
+ macp->m_min_sdu = 0;
+ macp->m_max_sdu = hldev->config.mtu;
/*
* Finally, we're ready to register ourselves with the Nemo
* interface; if this succeeds, we're all ready to start()
*/
- if (mac_register(macp) != 0) {
- nd_free(&lldev->ndp);
- mutex_destroy(&lldev->genlock);
- /* Ignore return value, since RX not start */
- (void) xgell_rx_destroy_buffer_pool(lldev);
- xge_debug_ll(XGE_ERR, "%s",
- "unable to register networking device");
- return (DDI_FAILURE);
- }
+ err = mac_register(macp, &lldev->mh);
+ mac_free(macp);
+ if (err != 0)
+ goto xgell_register_fail;
xge_debug_ll(XGE_TRACE, "etherenet device %s%d registered",
XGELL_IFNAME, lldev->instance);
return (DDI_SUCCESS);
+
+xgell_ndd_fail:
+ nd_free(&lldev->ndp);
+ xge_debug_ll(XGE_ERR, "%s", "unable to load ndd parameter");
+ return (DDI_FAILURE);
+
+xgell_register_fail:
+ nd_free(&lldev->ndp);
+ mutex_destroy(&lldev->genlock);
+ /* Ignore return value, since RX not start */
+ (void) xgell_rx_destroy_buffer_pool(lldev);
+ xge_debug_ll(XGE_ERR, "%s", "unable to register networking device");
+ return (DDI_FAILURE);
}
/*
@@ -2373,7 +2340,7 @@ xgell_device_unregister(xgelldev_t *lldev)
return (DDI_FAILURE);
}
- if (mac_unregister(lldev->macp) != 0) {
+ if (mac_unregister(lldev->mh) != 0) {
xge_debug_ll(XGE_ERR, "unable to unregister device %s%d",
XGELL_IFNAME, lldev->instance);
return (DDI_FAILURE);
diff --git a/usr/src/uts/common/io/xge/drv/xgell.h b/usr/src/uts/common/io/xge/drv/xgell.h
index 060f8f8213..7b3fbb43f0 100644
--- a/usr/src/uts/common/io/xge/drv/xgell.h
+++ b/usr/src/uts/common/io/xge/drv/xgell.h
@@ -63,6 +63,7 @@
#include <sys/strsun.h>
#include <sys/mac.h>
+#include <sys/mac_ether.h>
#ifdef __cplusplus
extern "C" {
@@ -251,15 +252,17 @@ typedef struct xgell_rx_buffer_pool_t {
spinlock_t pool_lock; /* buffer pool lock */
} xgell_rx_buffer_pool_t;
+typedef struct xgelldev xgelldev_t;
+
typedef struct xgell_ring_t {
xge_hal_channel_h channelh;
- mac_t *macp;
+ xgelldev_t *lldev;
mac_resource_handle_t handle; /* per ring cookie */
} xgell_ring_t;
-typedef struct {
+struct xgelldev {
caddr_t ndp;
- mac_t *macp;
+ mac_handle_t mh;
int instance;
dev_info_t *dev_info;
xge_hal_device_h devh;
@@ -274,7 +277,7 @@ typedef struct {
volatile int in_reset;
timeout_id_t timeout_id;
kmutex_t genlock;
-} xgelldev_t;
+};
typedef struct {
mblk_t *mblk;
diff --git a/usr/src/uts/common/sys/aggr.h b/usr/src/uts/common/sys/aggr.h
index d41899a3de..1b6f14b5ce 100644
--- a/usr/src/uts/common/sys/aggr.h
+++ b/usr/src/uts/common/sys/aggr.h
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -109,7 +108,6 @@ typedef union {
/* one of the ports of a link aggregation group */
typedef struct laioc_port {
char lp_devname[MAXNAMELEN + 1];
- uint_t lp_port;
} laioc_port_t;
#define LAIOC_CREATE LAIOC(1)
@@ -168,7 +166,6 @@ typedef enum aggr_link_state {
typedef struct laioc_info_port {
char lp_devname[MAXNAMELEN + 1];
- uint32_t lp_port;
uchar_t lp_mac[ETHERADDRL];
aggr_port_state_t lp_state;
aggr_lacp_state_t lp_lacp_state;
diff --git a/usr/src/uts/common/sys/aggr_impl.h b/usr/src/uts/common/sys/aggr_impl.h
index 0aa5da2315..1c062304e5 100644
--- a/usr/src/uts/common/sys/aggr_impl.h
+++ b/usr/src/uts/common/sys/aggr_impl.h
@@ -30,6 +30,7 @@
#include <sys/types.h>
#include <sys/mac.h>
+#include <sys/mac_ether.h>
#include <sys/aggr_lacp.h>
#ifdef __cplusplus
@@ -64,7 +65,6 @@ typedef struct aggr_port_s {
lp_promisc_on : 1,
lp_pad_bits : 28;
uint32_t lp_closing;
- uint_t lp_port;
mac_handle_t lp_mh;
const mac_info_t *lp_mip;
mac_notify_handle_t lp_mnh;
@@ -75,6 +75,7 @@ typedef struct aggr_port_s {
link_state_t lp_link_state;
link_duplex_t lp_link_duplex;
uint64_t lp_stat[MAC_NSTAT];
+ uint64_t lp_ether_stat[ETHER_NSTAT];
aggr_lacp_port_t lp_lacp; /* LACP state */
lacp_stats_t lp_lacp_stats;
const mac_txinfo_t *lp_txinfo;
@@ -107,10 +108,11 @@ typedef struct aggr_grp_s {
lg_addr_fixed : 1, /* fixed MAC address? */
lg_started : 1, /* group started? */
lg_promisc : 1, /* in promiscuous mode? */
- lg_pad_bits : 12;
+ lg_gldv3_polling : 1,
+ lg_pad_bits : 11;
aggr_port_t *lg_ports; /* list of configured ports */
aggr_port_t *lg_mac_addr_port;
- mac_t lg_mac;
+ mac_handle_t lg_mh;
uint_t lg_rx_resources;
uint_t lg_nattached_ports;
uint_t lg_ntx_ports;
@@ -121,8 +123,10 @@ typedef struct aggr_grp_s {
link_state_t lg_link_state;
link_duplex_t lg_link_duplex;
uint64_t lg_stat[MAC_NSTAT];
+ uint64_t lg_ether_stat[ETHER_NSTAT];
aggr_lacp_mode_t lg_lacp_mode; /* off, active, or passive */
Agg_t aggr; /* 802.3ad data */
+ uint32_t lg_hcksum_txflags;
} aggr_grp_t;
#define AGGR_LACP_LOCK(grp) mutex_enter(&(grp)->aggr.gl_lock);
@@ -158,8 +162,8 @@ 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);
-typedef int (*aggr_grp_info_new_port_fn_t)(void *, char *, uint32_t,
- uchar_t *, aggr_port_state_t, aggr_lacp_state_t *);
+typedef int (*aggr_grp_info_new_port_fn_t)(void *, char *, uchar_t *,
+ aggr_port_state_t, aggr_lacp_state_t *);
extern void aggr_grp_init(void);
extern void aggr_grp_fini(void);
@@ -185,7 +189,7 @@ extern uint_t aggr_grp_count(void);
extern void aggr_port_init(void);
extern void aggr_port_fini(void);
-extern int aggr_port_create(const char *, uint_t, aggr_port_t **);
+extern int aggr_port_create(const char *, aggr_port_t **);
extern void aggr_port_delete(aggr_port_t *);
extern void aggr_port_free(aggr_port_t *);
extern int aggr_port_start(aggr_port_t *);
@@ -193,7 +197,7 @@ extern void aggr_port_stop(aggr_port_t *);
extern int aggr_port_promisc(aggr_port_t *, boolean_t);
extern int aggr_port_unicst(aggr_port_t *, uint8_t *);
extern int aggr_port_multicst(void *, boolean_t, const uint8_t *);
-extern uint64_t aggr_port_stat(aggr_port_t *, enum mac_stat);
+extern uint64_t aggr_port_stat(aggr_port_t *, uint_t);
extern boolean_t aggr_port_notify_link(aggr_grp_t *, aggr_port_t *, boolean_t);
extern void aggr_port_init_callbacks(aggr_port_t *);
diff --git a/usr/src/uts/common/sys/bge_impl2.h b/usr/src/uts/common/sys/bge_impl2.h
index 6c0bb03e76..c2a1536a75 100644
--- a/usr/src/uts/common/sys/bge_impl2.h
+++ b/usr/src/uts/common/sys/bge_impl2.h
@@ -73,6 +73,7 @@ extern "C" {
#include <sys/fm/io/ddi.h>
#include <sys/mac.h>
+#include <sys/mac_ether.h>
#ifdef __amd64
#include <sys/x86_archext.h>
@@ -742,7 +743,7 @@ typedef struct bge {
* These fields are set by attach() and unchanged thereafter ...
*/
dev_info_t *devinfo; /* device instance */
- mac_t *macp; /* MAC structure */
+ mac_handle_t mh; /* mac module handle */
ddi_acc_handle_t cfg_handle; /* DDI I/O handle */
ddi_acc_handle_t io_handle; /* DDI I/O handle */
void *io_regs; /* mapped registers */
@@ -1211,7 +1212,7 @@ void bge_chip_msi_trig(bge_t *bgep);
/* bge_kstats.c */
void bge_init_kstats(bge_t *bgep, int instance);
void bge_fini_kstats(bge_t *bgep);
-uint64_t bge_m_stat(void *arg, enum mac_stat stat);
+int bge_m_stat(void *arg, uint_t stat, uint64_t *val);
/* bge_log.c */
#if BGE_DEBUGGING
diff --git a/usr/src/uts/common/sys/dld.h b/usr/src/uts/common/sys/dld.h
index 1feba1e027..4e32398c21 100644
--- a/usr/src/uts/common/sys/dld.h
+++ b/usr/src/uts/common/sys/dld.h
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -95,7 +94,6 @@ 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;
@@ -103,7 +101,6 @@ typedef struct dld_ioc_attr {
typedef struct dld_ioc_vlan {
char div_name[IFNAMSIZ];
- uint_t div_port;
uint_t div_count;
} dld_ioc_vlan_t;
diff --git a/usr/src/uts/common/sys/dld_impl.h b/usr/src/uts/common/sys/dld_impl.h
index a7d2ecad86..6c1c3ade21 100644
--- a/usr/src/uts/common/sys/dld_impl.h
+++ b/usr/src/uts/common/sys/dld_impl.h
@@ -155,8 +155,8 @@ struct dld_str {
/*
* Cached MAC unicast addresses.
*/
- uint8_t ds_fact_addr[MAXADDRLEN];
- uint8_t ds_curr_addr[MAXADDRLEN];
+ uint8_t ds_fact_addr[MAXMACADDRLEN];
+ uint8_t ds_curr_addr[MAXMACADDRLEN];
/*
* Mode: unitdata, fast-path or raw.
@@ -249,7 +249,6 @@ 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); \
diff --git a/usr/src/uts/common/sys/dls.h b/usr/src/uts/common/sys/dls.h
index fe781f3c12..12f9a6a8a2 100644
--- a/usr/src/uts/common/sys/dls.h
+++ b/usr/src/uts/common/sys/dls.h
@@ -51,21 +51,7 @@ extern "C" {
#define DLS_INFO "Data-Link Services v%I%"
/*
- * Check the legality of a DLSAP value. The following values are allowed,
- * as specified by PSARC 2003/150:
- *
- * 0 802 semantics
- * ETHERTYPE_802_MIN (1536)..ETHERTYPE_MAX (65535) ethertype semantics
- * 1..ETHERMTU (1500) 802 semantics, for
- * DL_ETHER only.
- */
-#define SAP_LEGAL(type, sap) \
- (((sap) >= ETHERTYPE_802_MIN && (sap) < ETHERTYPE_MAX) || \
- ((sap) == 0) || \
- ((sap) <= ETHERMTU && (type) == DL_ETHER))
-
-/*
- * Macros for converting a ppa to an instance#, vlan ID, or minor.
+ * Macros for converting ppas to instance #s, Vlan ID, or minor.
*/
#define DLS_PPA2INST(ppa) ((int)((ppa) % 1000))
#define DLS_PPA2VID(ppa) ((uint16_t)((ppa) / 1000))
@@ -92,7 +78,7 @@ extern uint16_t dls_vid(dls_channel_t);
#define DLS_SAP_LLC 0
#define DLS_SAP_PROMISC (1 << 16)
-extern int dls_bind(dls_channel_t, uint16_t);
+extern int dls_bind(dls_channel_t, uint32_t);
extern void dls_unbind(dls_channel_t);
#define DLS_PROMISC_SAP 0x00000001
@@ -104,18 +90,9 @@ extern int dls_promisc(dls_channel_t, uint32_t);
extern int dls_multicst_add(dls_channel_t, const uint8_t *);
extern int dls_multicst_remove(dls_channel_t, const uint8_t *);
-extern mblk_t *dls_header(dls_channel_t, const uint8_t *, uint16_t, uint_t);
-
-typedef struct dls_header_info {
- size_t dhi_length;
- const uint8_t *dhi_daddr;
- const uint8_t *dhi_saddr;
- uint16_t dhi_ethertype;
- uint16_t dhi_vid;
- boolean_t dhi_isgroup;
-} dls_header_info_t;
-
-extern void dls_header_info(dls_channel_t, mblk_t *, dls_header_info_t *);
+extern mblk_t *dls_header(dls_channel_t, const uint8_t *, uint16_t, uint_t,
+ mblk_t *);
+extern int dls_header_info(dls_channel_t, mblk_t *, mac_header_info_t *);
typedef void (*dls_rx_t)(void *, mac_resource_handle_t, mblk_t *, size_t);
diff --git a/usr/src/uts/common/sys/dls_impl.h b/usr/src/uts/common/sys/dls_impl.h
index cf26f5cb21..ad97fe72da 100644
--- a/usr/src/uts/common/sys/dls_impl.h
+++ b/usr/src/uts/common/sys/dls_impl.h
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -46,15 +45,14 @@ typedef struct dls_multicst_addr_s dls_multicst_addr_t;
struct dls_multicst_addr_s {
dls_multicst_addr_t *dma_nextp;
- uint8_t dma_addr[MAXADDRLEN];
+ uint8_t dma_addr[MAXMACADDRLEN];
};
typedef struct dls_link_s dls_link_t;
struct dls_link_s {
char dl_name[MAXNAMELEN];
- char dl_dev[MAXNAMELEN];
- uint_t dl_port;
+ uint_t dl_ddi_instance;
mac_handle_t dl_mh;
const mac_info_t *dl_mip;
mac_rx_handle_t dl_mrh;
@@ -64,7 +62,7 @@ struct dls_link_s {
mod_hash_t *dl_impl_hash;
krwlock_t dl_impl_lock;
uint_t dl_impl_count;
- mac_txloop_t dl_loopback;
+ mac_txloop_t dl_txloop;
kmutex_t dl_promisc_lock;
uint_t dl_npromisc;
uint_t dl_nactive;
@@ -83,11 +81,6 @@ typedef struct dls_vlan_s {
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);
-typedef void (*dls_priv_header_info_t)(dls_impl_t *,
- mblk_t *, dls_header_info_t *);
-
struct dls_impl_s {
dls_impl_t *di_nextp;
dls_head_t *di_headp;
@@ -106,9 +99,7 @@ struct dls_impl_s {
boolean_t di_bound;
boolean_t di_removing;
boolean_t di_active;
- uint8_t di_unicst_addr[MAXADDRLEN];
- dls_priv_header_t di_header;
- dls_priv_header_info_t di_header_info;
+ uint8_t di_unicst_addr[MAXMACADDRLEN];
soft_ring_t **di_soft_ring_list;
uint_t di_soft_ring_size;
int di_soft_ring_fanout_type;
@@ -126,6 +117,8 @@ extern int dls_link_hold(const char *, uint_t, dls_link_t **);
extern void dls_link_rele(dls_link_t *);
extern void dls_link_add(dls_link_t *, uint32_t, dls_impl_t *);
extern void dls_link_remove(dls_link_t *, dls_impl_t *);
+extern int dls_link_header_info(dls_link_t *, mblk_t *,
+ mac_header_info_t *, uint16_t *);
extern int dls_mac_hold(dls_link_t *);
extern void dls_mac_rele(dls_link_t *);
@@ -143,10 +136,9 @@ extern int dls_vlan_walk(int (*)(dls_vlan_t *, void *), void *);
extern void dls_init(void);
extern int dls_fini(void);
-extern boolean_t dls_accept(dls_impl_t *, const uint8_t *,
- dls_rx_t *, void **);
-extern boolean_t dls_accept_loopback(dls_impl_t *, const uint8_t *,
+extern boolean_t dls_accept(dls_impl_t *, mac_header_info_t *,
dls_rx_t *, void **);
+extern boolean_t dls_accept_loopback(dls_impl_t *, dls_rx_t *, void **);
#ifdef __cplusplus
}
diff --git a/usr/src/uts/common/sys/mac.h b/usr/src/uts/common/sys/mac.h
index 59e493f9bd..d6031a37c0 100644
--- a/usr/src/uts/common/sys/mac.h
+++ b/usr/src/uts/common/sys/mac.h
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -42,14 +41,22 @@ extern "C" {
#endif
/*
- * Module name.
+ * MAC Information (text emitted by modinfo(1m))
*/
-#define MAC_MODULE_NAME "mac"
+#define MAC_INFO "MAC Services v%I%"
/*
- * MAC Information (text emitted by modinfo(1m))
+ * MAC version identifier. This is used by mac_alloc() mac_register() to
+ * verify that incompatible drivers don't register.
*/
-#define MAC_INFO "MAC Services v%I%"
+#define MAC_VERSION 0x1
+
+/*
+ * MAC-Type version identifier. This is used by mactype_alloc() and
+ * mactype_register() to verify that incompatible MAC-Type plugins don't
+ * register.
+ */
+#define MACTYPE_VERSION 0x1
/*
* Statistics
@@ -78,11 +85,30 @@ typedef enum {
#ifdef _KERNEL
-enum mac_stat {
- /*
- * PSARC 1997/198 (MIB-II kstats)
- */
- MAC_STAT_IFSPEED,
+typedef struct mac_stat_info_s {
+ uint_t msi_stat;
+ char *msi_name;
+ uint_t msi_type; /* as defined in kstat_named_init(9F) */
+ uint64_t msi_default;
+} mac_stat_info_t;
+
+/*
+ * There are three ranges of statistics values. 0 to 1 - MAC_STAT_MIN are
+ * interface statistics maintained by the mac module. MAC_STAT_MIN to 1 -
+ * MACTYPE_STAT_MIN are common MAC statistics defined by the mac module and
+ * maintained by each driver. MACTYPE_STAT_MIN and above are statistics
+ * defined by MAC-Type plugins and maintained by each driver.
+ */
+#define MAC_STAT_MIN 1000
+#define MACTYPE_STAT_MIN 2000
+
+#define IS_MAC_STAT(stat) \
+ (stat >= MAC_STAT_MIN && stat < MACTYPE_STAT_MIN)
+#define IS_MACTYPE_STAT(stat) (stat >= MACTYPE_STAT_MIN)
+
+enum mac_driver_stat {
+ /* MIB-II stats (RFC 1213 and RFC 1573) */
+ MAC_STAT_IFSPEED = MAC_STAT_MIN,
MAC_STAT_MULTIRCV,
MAC_STAT_BRDCSTRCV,
MAC_STAT_MULTIXMT,
@@ -96,68 +122,31 @@ enum mac_stat {
MAC_STAT_RBYTES,
MAC_STAT_IPACKETS,
MAC_STAT_OBYTES,
- MAC_STAT_OPACKETS,
-
- /*
- * PSARC 1997/247 (RFC 1643 kstats)
- */
- MAC_STAT_ALIGN_ERRORS,
- MAC_STAT_FCS_ERRORS,
- MAC_STAT_FIRST_COLLISIONS,
- MAC_STAT_MULTI_COLLISIONS,
- MAC_STAT_SQE_ERRORS,
- MAC_STAT_DEFER_XMTS,
- MAC_STAT_TX_LATE_COLLISIONS,
- MAC_STAT_EX_COLLISIONS,
- MAC_STAT_MACXMT_ERRORS,
- MAC_STAT_CARRIER_ERRORS,
- MAC_STAT_TOOLONG_ERRORS,
- MAC_STAT_MACRCV_ERRORS,
-
- /*
- * PSARC 2003/581 (MII/GMII kstats)
- */
- MAC_STAT_XCVR_ADDR,
- MAC_STAT_XCVR_ID,
- MAC_STAT_XCVR_INUSE,
- MAC_STAT_CAP_1000FDX,
- MAC_STAT_CAP_1000HDX,
- MAC_STAT_CAP_100FDX,
- MAC_STAT_CAP_100HDX,
- MAC_STAT_CAP_10FDX,
- MAC_STAT_CAP_10HDX,
- MAC_STAT_CAP_ASMPAUSE,
- MAC_STAT_CAP_PAUSE,
- MAC_STAT_CAP_AUTONEG,
- MAC_STAT_ADV_CAP_1000FDX,
- MAC_STAT_ADV_CAP_1000HDX,
- MAC_STAT_ADV_CAP_100FDX,
- MAC_STAT_ADV_CAP_100HDX,
- MAC_STAT_ADV_CAP_10FDX,
- MAC_STAT_ADV_CAP_10HDX,
- MAC_STAT_ADV_CAP_ASMPAUSE,
- MAC_STAT_ADV_CAP_PAUSE,
- MAC_STAT_ADV_CAP_AUTONEG,
- MAC_STAT_LP_CAP_1000FDX,
- MAC_STAT_LP_CAP_1000HDX,
- MAC_STAT_LP_CAP_100FDX,
- MAC_STAT_LP_CAP_100HDX,
- MAC_STAT_LP_CAP_10FDX,
- MAC_STAT_LP_CAP_10HDX,
- MAC_STAT_LP_CAP_ASMPAUSE,
- MAC_STAT_LP_CAP_PAUSE,
- MAC_STAT_LP_CAP_AUTONEG,
- MAC_STAT_LINK_ASMPAUSE,
- MAC_STAT_LINK_PAUSE,
- MAC_STAT_LINK_AUTONEG,
- MAC_STAT_LINK_DUPLEX,
- MAC_NSTAT /* must be the last entry */
+ MAC_STAT_OPACKETS
};
+#define MAC_NSTAT (MAC_STAT_OPACKETS - MAC_STAT_IFSPEED + 1)
+
+#define MAC_STAT_ISACOUNTER(_stat) ( \
+ (_stat) == MAC_STAT_MULTIRCV || \
+ (_stat) == MAC_STAT_BRDCSTRCV || \
+ (_stat) == MAC_STAT_MULTIXMT || \
+ (_stat) == MAC_STAT_BRDCSTXMT || \
+ (_stat) == MAC_STAT_NORCVBUF || \
+ (_stat) == MAC_STAT_IERRORS || \
+ (_stat) == MAC_STAT_UNKNOWNS || \
+ (_stat) == MAC_STAT_NOXMTBUF || \
+ (_stat) == MAC_STAT_OERRORS || \
+ (_stat) == MAC_STAT_COLLISIONS || \
+ (_stat) == MAC_STAT_RBYTES || \
+ (_stat) == MAC_STAT_IPACKETS || \
+ (_stat) == MAC_STAT_OBYTES || \
+ (_stat) == MAC_STAT_OPACKETS)
+
/*
* Maximum MAC address length
*/
-#define MAXADDRLEN 20
+#define MAXMACADDRLEN 20
/*
* Immutable information. (This may not be modified after registration).
@@ -166,150 +155,90 @@ typedef struct mac_info_s {
uint_t mi_media;
uint_t mi_sdu_min;
uint_t mi_sdu_max;
- uint32_t mi_cksum;
- uint32_t mi_poll;
uint_t mi_addr_length;
- uint8_t mi_unicst_addr[MAXADDRLEN];
- uint8_t mi_brdcst_addr[MAXADDRLEN];
- boolean_t mi_stat[MAC_NSTAT];
+ uint8_t *mi_unicst_addr;
+ uint8_t *mi_brdcst_addr;
} mac_info_t;
-#define MAC_STAT_MIB(_mi_stat) \
-{ \
- (_mi_stat)[MAC_STAT_IFSPEED] = B_TRUE; \
- (_mi_stat)[MAC_STAT_MULTIRCV] = B_TRUE; \
- (_mi_stat)[MAC_STAT_BRDCSTRCV] = B_TRUE; \
- (_mi_stat)[MAC_STAT_MULTIXMT] = B_TRUE; \
- (_mi_stat)[MAC_STAT_BRDCSTXMT] = B_TRUE; \
- (_mi_stat)[MAC_STAT_NORCVBUF] = B_TRUE; \
- (_mi_stat)[MAC_STAT_IERRORS] = B_TRUE; \
- (_mi_stat)[MAC_STAT_UNKNOWNS] = B_TRUE; \
- (_mi_stat)[MAC_STAT_NOXMTBUF] = B_TRUE; \
- (_mi_stat)[MAC_STAT_OERRORS] = B_TRUE; \
- (_mi_stat)[MAC_STAT_COLLISIONS] = B_TRUE; \
- (_mi_stat)[MAC_STAT_RBYTES] = B_TRUE; \
- (_mi_stat)[MAC_STAT_IPACKETS] = B_TRUE; \
- (_mi_stat)[MAC_STAT_OBYTES] = B_TRUE; \
- (_mi_stat)[MAC_STAT_OPACKETS] = B_TRUE; \
-}
-
-#define MAC_STAT_ETHER(_mi_stat) \
-{ \
- (_mi_stat)[MAC_STAT_ALIGN_ERRORS] = B_TRUE; \
- (_mi_stat)[MAC_STAT_FCS_ERRORS] = B_TRUE; \
- (_mi_stat)[MAC_STAT_FIRST_COLLISIONS] = B_TRUE; \
- (_mi_stat)[MAC_STAT_MULTI_COLLISIONS] = B_TRUE; \
- (_mi_stat)[MAC_STAT_SQE_ERRORS] = B_TRUE; \
- (_mi_stat)[MAC_STAT_DEFER_XMTS] = B_TRUE; \
- (_mi_stat)[MAC_STAT_TX_LATE_COLLISIONS] = B_TRUE; \
- (_mi_stat)[MAC_STAT_EX_COLLISIONS] = B_TRUE; \
- (_mi_stat)[MAC_STAT_MACXMT_ERRORS] = B_TRUE; \
- (_mi_stat)[MAC_STAT_CARRIER_ERRORS] = B_TRUE; \
- (_mi_stat)[MAC_STAT_TOOLONG_ERRORS] = B_TRUE; \
- (_mi_stat)[MAC_STAT_MACRCV_ERRORS] = B_TRUE; \
-}
-
-#define MAC_STAT_MII(_mi_stat) \
-{ \
- (_mi_stat)[MAC_STAT_XCVR_ADDR] = B_TRUE; \
- (_mi_stat)[MAC_STAT_XCVR_ID] = B_TRUE; \
- (_mi_stat)[MAC_STAT_XCVR_INUSE] = B_TRUE; \
- (_mi_stat)[MAC_STAT_CAP_1000FDX] = B_TRUE; \
- (_mi_stat)[MAC_STAT_CAP_1000HDX] = B_TRUE; \
- (_mi_stat)[MAC_STAT_CAP_100FDX] = B_TRUE; \
- (_mi_stat)[MAC_STAT_CAP_100HDX] = B_TRUE; \
- (_mi_stat)[MAC_STAT_CAP_10FDX] = B_TRUE; \
- (_mi_stat)[MAC_STAT_CAP_10HDX] = B_TRUE; \
- (_mi_stat)[MAC_STAT_CAP_ASMPAUSE] = B_TRUE; \
- (_mi_stat)[MAC_STAT_CAP_PAUSE] = B_TRUE; \
- (_mi_stat)[MAC_STAT_CAP_AUTONEG] = B_TRUE; \
- (_mi_stat)[MAC_STAT_ADV_CAP_1000FDX] = B_TRUE; \
- (_mi_stat)[MAC_STAT_ADV_CAP_1000HDX] = B_TRUE; \
- (_mi_stat)[MAC_STAT_ADV_CAP_100FDX] = B_TRUE; \
- (_mi_stat)[MAC_STAT_ADV_CAP_100HDX] = B_TRUE; \
- (_mi_stat)[MAC_STAT_ADV_CAP_10FDX] = B_TRUE; \
- (_mi_stat)[MAC_STAT_ADV_CAP_10HDX] = B_TRUE; \
- (_mi_stat)[MAC_STAT_ADV_CAP_ASMPAUSE] = B_TRUE; \
- (_mi_stat)[MAC_STAT_ADV_CAP_PAUSE] = B_TRUE; \
- (_mi_stat)[MAC_STAT_ADV_CAP_AUTONEG] = B_TRUE; \
- (_mi_stat)[MAC_STAT_LP_CAP_1000FDX] = B_TRUE; \
- (_mi_stat)[MAC_STAT_LP_CAP_1000HDX] = B_TRUE; \
- (_mi_stat)[MAC_STAT_LP_CAP_100FDX] = B_TRUE; \
- (_mi_stat)[MAC_STAT_LP_CAP_100HDX] = B_TRUE; \
- (_mi_stat)[MAC_STAT_LP_CAP_10FDX] = B_TRUE; \
- (_mi_stat)[MAC_STAT_LP_CAP_10HDX] = B_TRUE; \
- (_mi_stat)[MAC_STAT_LP_CAP_ASMPAUSE] = B_TRUE; \
- (_mi_stat)[MAC_STAT_LP_CAP_PAUSE] = B_TRUE; \
- (_mi_stat)[MAC_STAT_LP_CAP_AUTONEG] = B_TRUE; \
- (_mi_stat)[MAC_STAT_LINK_ASMPAUSE] = B_TRUE; \
- (_mi_stat)[MAC_STAT_LINK_PAUSE] = B_TRUE; \
- (_mi_stat)[MAC_STAT_LINK_AUTONEG] = B_TRUE; \
- (_mi_stat)[MAC_STAT_LINK_DUPLEX] = B_TRUE; \
-}
-
/*
- * MAC version identifer (for debugging)
+ * MAC layer capabilities. These capabilities are handled by the drivers'
+ * mc_capab_get() callbacks. Some capabilities require the driver to fill
+ * in a given data structure, and others are simply boolean capabilities.
+ * Note that capability values must be powers of 2 so that consumers and
+ * providers of this interface can keep track of which capabilities they
+ * care about by keeping a bitfield of these things around somewhere.
*/
-#define MAC_IDENT "%I%"
+typedef enum {
+ MAC_CAPAB_HCKSUM = 0x01, /* data is a uint32_t for the txflags */
+ MAC_CAPAB_POLL = 0x02 /* boolean only, no data */
+ /* add new capabilities here */
+} mac_capab_t;
/*
* MAC driver entry point types.
*/
-typedef uint64_t (*mac_stat_t)(void *, enum mac_stat);
+typedef int (*mac_getstat_t)(void *, uint_t, uint64_t *);
typedef int (*mac_start_t)(void *);
typedef void (*mac_stop_t)(void *);
-typedef int (*mac_promisc_t)(void *, boolean_t);
+typedef int (*mac_setpromisc_t)(void *, boolean_t);
typedef int (*mac_multicst_t)(void *, boolean_t, const uint8_t *);
typedef int (*mac_unicst_t)(void *, const uint8_t *);
-typedef void (*mac_resources_t)(void *);
typedef void (*mac_ioctl_t)(void *, queue_t *, mblk_t *);
+typedef void (*mac_resources_t)(void *);
typedef mblk_t *(*mac_tx_t)(void *, mblk_t *);
+typedef boolean_t (*mac_getcapab_t)(void *, mac_capab_t, void *);
/*
- * MAC extensions. (Currently there are non defined).
+ * Drivers must set all of these callbacks except for mc_resources,
+ * mc_ioctl, and mc_getcapab, which are optional. If any of these optional
+ * callbacks are set, their appropriate flags must be set in mc_callbacks.
+ * Any future additions to this list must also be accompanied by an
+ * associated mc_callbacks flag so that the framework can grow without
+ * affecting the binary compatibility of the interface.
*/
-typedef struct mac_ext_s mac_ext_t;
+typedef struct mac_callbacks_s {
+ uint_t mc_callbacks; /* Denotes which callbacks are set */
+ mac_getstat_t mc_getstat; /* Get the value of a statistic */
+ mac_start_t mc_start; /* Start the device */
+ mac_stop_t mc_stop; /* Stop the device */
+ mac_setpromisc_t mc_setpromisc; /* Enable or disable promiscuous mode */
+ mac_multicst_t mc_multicst; /* Enable or disable a multicast addr */
+ mac_unicst_t mc_unicst; /* Set the unicast MAC address */
+ mac_tx_t mc_tx; /* Transmit a packet */
+ mac_resources_t mc_resources; /* Get the device resources */
+ mac_ioctl_t mc_ioctl; /* Process an unknown ioctl */
+ mac_getcapab_t mc_getcapab; /* Get capability information */
+} mac_callbacks_t;
/*
- * MAC implementation private data.
+ * Flags for mc_callbacks. Requiring drivers to set the flags associated
+ * with optional callbacks initialized in the structure allows the mac
+ * module to add optional callbacks in the future without requiring drivers
+ * to recompile.
*/
-typedef struct mac_impl_s mac_impl_t;
+#define MC_RESOURCES 0x001
+#define MC_IOCTL 0x002
+#define MC_GETCAPAB 0x004
-/*
- * MAC structure: supplied by the driver.
- */
-typedef struct mac {
- const char *m_ident; /* MAC_IDENT */
- mac_ext_t *m_extp;
- mac_impl_t *m_impl; /* MAC private data */
+typedef struct mac_register_s {
+ uint_t m_version; /* set by mac_alloc() */
+ const char *m_type_ident;
void *m_driver; /* Driver private data */
-
dev_info_t *m_dip;
- uint_t m_port;
-
- mac_info_t m_info;
-
- mac_stat_t m_stat;
- mac_start_t m_start;
- mac_stop_t m_stop;
- mac_promisc_t m_promisc;
- mac_multicst_t m_multicst;
- mac_unicst_t m_unicst;
- mac_resources_t m_resources;
- mac_ioctl_t m_ioctl;
- mac_tx_t m_tx;
-} mac_t;
-
-/*
- * Construct the name of a MAC interface.
- */
-#define MAC_NAME(_name, _dev, _port) \
- (void) snprintf((_name), MAXNAMELEN - 1, "%s/%u", (_dev), (_port))
+ uint_t m_instance;
+ uint8_t *m_src_addr;
+ uint8_t *m_dst_addr;
+ mac_callbacks_t *m_callbacks;
+ uint_t m_min_sdu;
+ uint_t m_max_sdu;
+ void *m_pdata;
+ size_t m_pdata_size;
+} mac_register_t;
/*
* Opaque handle types.
*/
-typedef struct __mac_handle *mac_handle_t;
+typedef struct mac_t *mac_handle_t;
typedef struct __mac_notify_handle *mac_notify_handle_t;
typedef struct __mac_rx_handle *mac_rx_handle_t;
typedef struct __mac_txloop_handle *mac_txloop_handle_t;
@@ -325,6 +254,7 @@ typedef enum {
MAC_NOTE_TX,
MAC_NOTE_RESOURCE,
MAC_NOTE_DEVPROMISC,
+ MAC_NOTE_FASTPATH_FLUSH,
MAC_NNOTE /* must be the last entry */
} mac_notify_type_t;
@@ -368,6 +298,113 @@ typedef union mac_resource_u {
typedef mac_resource_handle_t (*mac_resource_add_t)(void *, mac_resource_t *);
+typedef enum {
+ MAC_ADDRTYPE_UNICAST,
+ MAC_ADDRTYPE_MULTICAST,
+ MAC_ADDRTYPE_BROADCAST
+} mac_addrtype_t;
+
+typedef struct mac_header_info_s {
+ size_t mhi_hdrsize;
+ size_t mhi_pktsize;
+ const uint8_t *mhi_daddr;
+ const uint8_t *mhi_saddr;
+ uint32_t mhi_origsap;
+ uint32_t mhi_bindsap;
+ mac_addrtype_t mhi_dsttype;
+} mac_header_info_t;
+
+/*
+ * MAC-Type plugin interfaces
+ */
+
+typedef int (*mtops_addr_verify_t)(const void *, void *);
+typedef boolean_t (*mtops_sap_verify_t)(uint32_t, uint32_t *, void *);
+typedef mblk_t *(*mtops_header_t)(const void *, const void *,
+ uint32_t, void *, mblk_t *, size_t);
+typedef int (*mtops_header_info_t)(mblk_t *, void *,
+ mac_header_info_t *);
+typedef boolean_t (*mtops_pdata_verify_t)(void *, size_t);
+typedef mblk_t *(*mtops_header_modify_t)(mblk_t *, void *);
+
+typedef struct mactype_ops_s {
+ uint_t mtops_ops;
+ /*
+ * mtops_unicst_verify() returns 0 if the given address is a valid
+ * unicast address, or a non-zero errno otherwise.
+ */
+ mtops_addr_verify_t mtops_unicst_verify;
+ /*
+ * mtops_multicst_verify() returns 0 if the given address is a
+ * valid multicast address, or a non-zero errno otherwise. If the
+ * media doesn't support multicast, ENOTSUP should be returned (for
+ * example).
+ */
+ mtops_addr_verify_t mtops_multicst_verify;
+ /*
+ * mtops_sap_verify() returns B_TRUE if the given SAP is a valid
+ * SAP value, or B_FALSE otherwise.
+ */
+ mtops_sap_verify_t mtops_sap_verify;
+ /*
+ * mtops_header() is used to allocate and construct a MAC header.
+ */
+ mtops_header_t mtops_header;
+ /*
+ * mtops_header_info() is used to gather information on a given MAC
+ * header.
+ */
+ mtops_header_info_t mtops_header_info;
+ /*
+ * mtops_pdata_verify() is used to verify the validity of MAC
+ * plugin data. It is called by mac_register() if the driver has
+ * supplied MAC plugin data, and also by mac_pdata_update() when
+ * drivers update the data.
+ */
+ mtops_pdata_verify_t mtops_pdata_verify;
+ /*
+ * mtops_header_cook() is an optional callback that converts (or
+ * "cooks") the given raw header (as sent by a raw DLPI consumer)
+ * into one that is appropriate to send down to the MAC driver.
+ * Following the example above, an Ethernet header sent down by a
+ * DLPI consumer would be converted to whatever header the MAC
+ * driver expects.
+ */
+ mtops_header_modify_t mtops_header_cook;
+ /*
+ * mtops_header_uncook() is an optional callback that does the
+ * opposite of mtops_header_cook(). It "uncooks" a given MAC
+ * header (as received from the driver) for consumption by raw DLPI
+ * consumers. For example, for a non-Ethernet plugin that wants
+ * raw DLPI consumers to be fooled into thinking that the device
+ * provides Ethernet access, this callback would modify the given
+ * mblk_t such that the MAC header is converted to an Ethernet
+ * header.
+ */
+ mtops_header_modify_t mtops_header_uncook;
+} mactype_ops_t;
+
+/*
+ * mtops_ops exists for the plugin to enumerate the optional callback
+ * entrypoints it has defined. This allows the mac module to define
+ * additional plugin entrypoints in mactype_ops_t without breaking backward
+ * compatibility with old plugins.
+ */
+#define MTOPS_PDATA_VERIFY 0x001
+#define MTOPS_HEADER_COOK 0x002
+#define MTOPS_HEADER_UNCOOK 0x004
+
+typedef struct mactype_register_s {
+ uint_t mtr_version; /* set by mactype_alloc() */
+ const char *mtr_ident;
+ mactype_ops_t *mtr_ops;
+ uint_t mtr_mactype;
+ uint_t mtr_addrlen;
+ uint8_t *mtr_brdcst_addr;
+ mac_stat_info_t *mtr_stats;
+ size_t mtr_statcount;
+} mactype_register_t;
+
/*
* Client interface functions.
*/
@@ -375,7 +412,7 @@ 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 uint64_t mac_stat_get(mac_handle_t, uint_t);
extern int mac_start(mac_handle_t);
extern void mac_stop(mac_handle_t);
extern int mac_promisc_set(mac_handle_t, boolean_t,
@@ -387,6 +424,7 @@ extern int mac_multicst_remove(mac_handle_t,
const uint8_t *);
extern int mac_unicst_set(mac_handle_t, const uint8_t *);
extern void mac_unicst_get(mac_handle_t, uint8_t *);
+extern void mac_dest_get(mac_handle_t, uint8_t *);
extern void mac_resources(mac_handle_t);
extern void mac_ioctl(mac_handle_t, queue_t *, mblk_t *);
extern const mac_txinfo_t *mac_tx_get(mac_handle_t);
@@ -408,27 +446,47 @@ 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);
+extern boolean_t mac_capab_get(mac_handle_t, mac_capab_t,
+ void *);
+extern boolean_t mac_sap_verify(mac_handle_t, uint32_t,
+ uint32_t *);
+extern mblk_t *mac_header(mac_handle_t, const uint8_t *,
+ uint32_t, mblk_t *, size_t);
+extern int mac_header_info(mac_handle_t, mblk_t *,
+ mac_header_info_t *);
+extern mblk_t *mac_header_cook(mac_handle_t, mblk_t *);
+extern mblk_t *mac_header_uncook(mac_handle_t, mblk_t *);
/*
* Driver interface functions.
*/
-extern int mac_register(mac_t *);
-extern int mac_unregister(mac_t *);
-extern void mac_rx(mac_t *, mac_resource_handle_t,
+extern mac_register_t *mac_alloc(uint_t);
+extern void mac_free(mac_register_t *);
+extern int mac_register(mac_register_t *, mac_handle_t *);
+extern int mac_unregister(mac_handle_t);
+extern void mac_rx(mac_handle_t, mac_resource_handle_t,
mblk_t *);
-extern void mac_link_update(mac_t *, link_state_t);
-extern void mac_unicst_update(mac_t *, const uint8_t *);
-extern void mac_tx_update(mac_t *);
-extern void mac_resource_update(mac_t *);
-extern mac_resource_handle_t mac_resource_add(mac_t *, mac_resource_t *);
-extern void mac_multicst_refresh(mac_t *, mac_multicst_t,
- void *, boolean_t);
-extern void mac_unicst_refresh(mac_t *, mac_unicst_t,
- void *);
-extern void mac_promisc_refresh(mac_t *, mac_promisc_t,
+extern void mac_link_update(mac_handle_t, link_state_t);
+extern void mac_unicst_update(mac_handle_t,
+ const uint8_t *);
+extern void mac_tx_update(mac_handle_t);
+extern void mac_resource_update(mac_handle_t);
+extern mac_resource_handle_t mac_resource_add(mac_handle_t,
+ mac_resource_t *);
+extern int mac_pdata_update(mac_handle_t, void *,
+ size_t);
+extern void mac_multicst_refresh(mac_handle_t,
+ mac_multicst_t, void *, boolean_t);
+extern void mac_unicst_refresh(mac_handle_t, mac_unicst_t,
void *);
+extern void mac_promisc_refresh(mac_handle_t,
+ mac_setpromisc_t, void *);
extern void mac_init_ops(struct dev_ops *, const char *);
extern void mac_fini_ops(struct dev_ops *);
+extern mactype_register_t *mactype_alloc(uint_t);
+extern void mactype_free(mactype_register_t *);
+extern int mactype_register(mactype_register_t *);
+extern int mactype_unregister(const char *);
#endif /* _KERNEL */
diff --git a/usr/src/uts/common/sys/mac_ether.h b/usr/src/uts/common/sys/mac_ether.h
new file mode 100644
index 0000000000..dbb5053306
--- /dev/null
+++ b/usr/src/uts/common/sys/mac_ether.h
@@ -0,0 +1,157 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * 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 2006 Sun Microsystems, Inc. All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef _SYS_MAC_ETHER_H
+#define _SYS_MAC_ETHER_H
+
+#pragma ident "%Z%%M% %I% %E% SMI"
+
+/*
+ * Ethernet MAC Plugin
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef _KERNEL
+
+#define MAC_PLUGIN_IDENT_ETHER "mac_ether"
+
+enum ether_stat {
+ /* RFC 1643 stats */
+ ETHER_STAT_ALIGN_ERRORS = MACTYPE_STAT_MIN,
+ ETHER_STAT_FCS_ERRORS,
+ ETHER_STAT_FIRST_COLLISIONS,
+ ETHER_STAT_MULTI_COLLISIONS,
+ ETHER_STAT_SQE_ERRORS,
+ ETHER_STAT_DEFER_XMTS,
+ ETHER_STAT_TX_LATE_COLLISIONS,
+ ETHER_STAT_EX_COLLISIONS,
+ ETHER_STAT_MACXMT_ERRORS,
+ ETHER_STAT_CARRIER_ERRORS,
+ ETHER_STAT_TOOLONG_ERRORS,
+ ETHER_STAT_MACRCV_ERRORS,
+
+ /* MII/GMII stats */
+ ETHER_STAT_XCVR_ADDR,
+ ETHER_STAT_XCVR_ID,
+ ETHER_STAT_XCVR_INUSE,
+ ETHER_STAT_CAP_1000FDX,
+ ETHER_STAT_CAP_1000HDX,
+ ETHER_STAT_CAP_100FDX,
+ ETHER_STAT_CAP_100HDX,
+ ETHER_STAT_CAP_10FDX,
+ ETHER_STAT_CAP_10HDX,
+ ETHER_STAT_CAP_ASMPAUSE,
+ ETHER_STAT_CAP_PAUSE,
+ ETHER_STAT_CAP_AUTONEG,
+ ETHER_STAT_ADV_CAP_1000FDX,
+ ETHER_STAT_ADV_CAP_1000HDX,
+ ETHER_STAT_ADV_CAP_100FDX,
+ ETHER_STAT_ADV_CAP_100HDX,
+ ETHER_STAT_ADV_CAP_10FDX,
+ ETHER_STAT_ADV_CAP_10HDX,
+ ETHER_STAT_ADV_CAP_ASMPAUSE,
+ ETHER_STAT_ADV_CAP_PAUSE,
+ ETHER_STAT_ADV_CAP_AUTONEG,
+ ETHER_STAT_LP_CAP_1000FDX,
+ ETHER_STAT_LP_CAP_1000HDX,
+ ETHER_STAT_LP_CAP_100FDX,
+ ETHER_STAT_LP_CAP_100HDX,
+ ETHER_STAT_LP_CAP_10FDX,
+ ETHER_STAT_LP_CAP_10HDX,
+ ETHER_STAT_LP_CAP_ASMPAUSE,
+ ETHER_STAT_LP_CAP_PAUSE,
+ ETHER_STAT_LP_CAP_AUTONEG,
+ ETHER_STAT_LINK_ASMPAUSE,
+ ETHER_STAT_LINK_PAUSE,
+ ETHER_STAT_LINK_AUTONEG,
+ ETHER_STAT_LINK_DUPLEX
+};
+
+#define ETHER_NSTAT (ETHER_STAT_LINK_DUPLEX - ETHER_STAT_ALIGN_ERRORS + 1)
+
+#define ETHER_STAT_ISACOUNTER(_ether_stat) \
+ ((_ether_stat) == ETHER_STAT_ALIGN_ERRORS || \
+ (_ether_stat) == ETHER_STAT_FCS_ERRORS || \
+ (_ether_stat) == ETHER_STAT_FIRST_COLLISIONS || \
+ (_ether_stat) == ETHER_STAT_MULTI_COLLISIONS || \
+ (_ether_stat) == ETHER_STAT_SQE_ERRORS || \
+ (_ether_stat) == ETHER_STAT_DEFER_XMTS || \
+ (_ether_stat) == ETHER_STAT_TX_LATE_COLLISIONS || \
+ (_ether_stat) == ETHER_STAT_EX_COLLISIONS || \
+ (_ether_stat) == ETHER_STAT_MACXMT_ERRORS || \
+ (_ether_stat) == ETHER_STAT_CARRIER_ERRORS || \
+ (_ether_stat) == ETHER_STAT_TOOLONG_ERRORS || \
+ (_ether_stat) == ETHER_STAT_MACRCV_ERRORS)
+
+/*
+ * Some drivers have a need to determine if a particular stat is a MII/GMII
+ * physical layer 802.3 stat.
+ */
+#define ETHER_STAT_ISMII(_ether_stat) \
+ ((_ether_stat) == ETHER_STAT_XCVR_ADDR || \
+ (_ether_stat) == ETHER_STAT_XCVR_ID || \
+ (_ether_stat) == ETHER_STAT_XCVR_INUSE || \
+ (_ether_stat) == ETHER_STAT_CAP_1000FDX || \
+ (_ether_stat) == ETHER_STAT_CAP_1000HDX || \
+ (_ether_stat) == ETHER_STAT_CAP_100FDX || \
+ (_ether_stat) == ETHER_STAT_CAP_100HDX || \
+ (_ether_stat) == ETHER_STAT_CAP_10FDX || \
+ (_ether_stat) == ETHER_STAT_CAP_10HDX || \
+ (_ether_stat) == ETHER_STAT_CAP_ASMPAUSE || \
+ (_ether_stat) == ETHER_STAT_CAP_PAUSE || \
+ (_ether_stat) == ETHER_STAT_CAP_AUTONEG || \
+ (_ether_stat) == ETHER_STAT_ADV_CAP_1000FDX || \
+ (_ether_stat) == ETHER_STAT_ADV_CAP_1000HDX || \
+ (_ether_stat) == ETHER_STAT_ADV_CAP_100FDX || \
+ (_ether_stat) == ETHER_STAT_ADV_CAP_100HDX || \
+ (_ether_stat) == ETHER_STAT_ADV_CAP_10FDX || \
+ (_ether_stat) == ETHER_STAT_ADV_CAP_10HDX || \
+ (_ether_stat) == ETHER_STAT_ADV_CAP_ASMPAUSE || \
+ (_ether_stat) == ETHER_STAT_ADV_CAP_PAUSE || \
+ (_ether_stat) == ETHER_STAT_ADV_CAP_AUTONEG || \
+ (_ether_stat) == ETHER_STAT_LP_CAP_1000FDX || \
+ (_ether_stat) == ETHER_STAT_LP_CAP_1000HDX || \
+ (_ether_stat) == ETHER_STAT_LP_CAP_100FDX || \
+ (_ether_stat) == ETHER_STAT_LP_CAP_100HDX || \
+ (_ether_stat) == ETHER_STAT_LP_CAP_10FDX || \
+ (_ether_stat) == ETHER_STAT_LP_CAP_10HDX || \
+ (_ether_stat) == ETHER_STAT_LP_CAP_ASMPAUSE || \
+ (_ether_stat) == ETHER_STAT_LP_CAP_PAUSE || \
+ (_ether_stat) == ETHER_STAT_LP_CAP_AUTONEG || \
+ (_ether_stat) == ETHER_STAT_LINK_ASMPAUSE || \
+ (_ether_stat) == ETHER_STAT_LINK_PAUSE || \
+ (_ether_stat) == ETHER_STAT_LINK_AUTONEG || \
+ (_ether_stat) == ETHER_STAT_LINK_DUPLEX)
+
+#endif /* _KERNEL */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _SYS_MAC_ETHER_H */
diff --git a/usr/src/uts/common/sys/mac_impl.h b/usr/src/uts/common/sys/mac_impl.h
index 8d22031682..9bf6b21d60 100644
--- a/usr/src/uts/common/sys/mac_impl.h
+++ b/usr/src/uts/common/sys/mac_impl.h
@@ -29,17 +29,30 @@
#pragma ident "%Z%%M% %I% %E% SMI"
#include <sys/mac.h>
+#include <net/if.h>
#ifdef __cplusplus
extern "C" {
#endif
+/*
+ * Statistics of class MAC_INTERFACE_STAT, maintained internally by the mac
+ * module.
+ */
+enum mac_interface_stat {
+ MAC_STAT_LINK_STATE,
+ MAC_STAT_LINK_UP,
+ MAC_STAT_PROMISC,
+
+ MAC_INTERFACE_NSTAT /* Must be the last entry */
+};
+
typedef struct mac_multicst_addr_s mac_multicst_addr_t;
struct mac_multicst_addr_s {
mac_multicst_addr_t *mma_nextp;
uint_t mma_ref;
- uint8_t mma_addr[MAXADDRLEN];
+ uint8_t mma_addr[MAXMACADDRLEN];
};
typedef struct mac_notify_fn_s mac_notify_fn_t;
@@ -66,60 +79,72 @@ struct mac_txloop_fn_s {
void *mtf_arg;
};
-typedef boolean_t (*mac_unicst_verify_t)(mac_impl_t *,
- const uint8_t *);
-typedef boolean_t (*mac_multicst_verify_t)(mac_impl_t *,
- const uint8_t *);
-
-struct mac_impl_s {
- mac_t *mi_mp;
- char mi_dev[MAXNAMELEN];
- uint_t mi_port;
- char mi_name[MAXNAMELEN];
+typedef struct mactype_s {
+ const char *mt_ident;
+ uint32_t mt_ref;
+ uint_t mt_type;
+ size_t mt_addr_length;
+ uint8_t *mt_brdcst_addr;
+ mactype_ops_t mt_ops;
+ mac_stat_info_t *mt_stats; /* array of mac_stat_info_t elements */
+ size_t mt_statcount; /* number of elements in mt_stats */
+} mactype_t;
+/*
+ * Each registered MAC is associated with a mac_t structure.
+ */
+typedef struct mac_impl_s {
+ char mi_name[LIFNAMSIZ];
+ const char *mi_drvname;
+ uint_t mi_instance;
+ void *mi_driver; /* Driver private data */
+ mac_info_t mi_info;
+ mactype_t *mi_type;
+ void *mi_pdata;
+ size_t mi_pdata_size;
+ mac_callbacks_t *mi_callbacks;
+ dev_info_t *mi_dip;
uint32_t mi_ref;
boolean_t mi_disabled;
-
krwlock_t mi_state_lock;
uint_t mi_active;
-
krwlock_t mi_data_lock;
- link_state_t mi_link;
+ link_state_t mi_linkstate;
uint_t mi_promisc;
uint_t mi_devpromisc;
- uint8_t mi_addr[MAXADDRLEN];
+ uint8_t mi_addr[MAXMACADDRLEN];
+ uint8_t mi_dstaddr[MAXMACADDRLEN];
mac_multicst_addr_t *mi_mmap;
-
- uint_t mi_addr_length;
-
krwlock_t mi_notify_lock;
mac_notify_fn_t *mi_mnfp;
-
kmutex_t mi_notify_ref_lock;
uint32_t mi_notify_ref;
kcondvar_t mi_notify_cv;
-
krwlock_t mi_rx_lock;
mac_rx_fn_t *mi_mrfp;
-
krwlock_t mi_txloop_lock;
mac_txloop_fn_t *mi_mtfp;
-
krwlock_t mi_resource_lock;
mac_resource_add_t mi_resource_add;
void *mi_resource_add_arg;
-
kstat_t *mi_ksp;
-
- mac_unicst_verify_t mi_unicst_verify;
- mac_multicst_verify_t mi_multicst_verify;
-
+ uint_t mi_kstat_count;
kmutex_t mi_activelink_lock;
boolean_t mi_activelink;
-
mac_txinfo_t mi_txinfo;
mac_txinfo_t mi_txloopinfo;
-};
+} mac_impl_t;
+
+#define mi_getstat mi_callbacks->mc_getstat
+#define mi_start mi_callbacks->mc_start
+#define mi_stop mi_callbacks->mc_stop
+#define mi_setpromisc mi_callbacks->mc_setpromisc
+#define mi_multicst mi_callbacks->mc_multicst
+#define mi_unicst mi_callbacks->mc_unicst
+#define mi_resources mi_callbacks->mc_resources
+#define mi_tx mi_callbacks->mc_tx
+#define mi_ioctl mi_callbacks->mc_ioctl
+#define mi_getcapab mi_callbacks->mc_getcapab
typedef struct mac_notify_task_arg {
mac_impl_t *mnt_mip;
@@ -131,6 +156,7 @@ extern int mac_fini(void);
extern void mac_stat_create(mac_impl_t *);
extern void mac_stat_destroy(mac_impl_t *);
+extern uint64_t mac_stat_default(mac_impl_t *, uint_t);
#ifdef __cplusplus
}
diff --git a/usr/src/uts/intel/Makefile.intel.shared b/usr/src/uts/intel/Makefile.intel.shared
index 2c78d2f80c..bfdd71fd9a 100644
--- a/usr/src/uts/intel/Makefile.intel.shared
+++ b/usr/src/uts/intel/Makefile.intel.shared
@@ -569,3 +569,8 @@ DACF_KMODS += usb_ac_dacf
# Performance Counter BackEnd modules (/usr/kernel/pcbe)
#
PCBE_KMODS += p123_pcbe p4_pcbe opteron_pcbe
+
+#
+# MAC-Type Plugin Modules (/kernel/mac)
+#
+MAC_KMODS += mac_ether
diff --git a/usr/src/uts/intel/mac_ether/Makefile b/usr/src/uts/intel/mac_ether/Makefile
new file mode 100644
index 0000000000..457887004a
--- /dev/null
+++ b/usr/src/uts/intel/mac_ether/Makefile
@@ -0,0 +1,87 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# 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 2006 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+#ident "%Z%%M% %I% %E% SMI"
+#
+#
+# This makefile drives the production of the mac_ether MAC-Type plugin
+# kernel module.
+#
+
+#
+# Path to the base of the uts directory tree (usually /usr/src/uts).
+#
+UTSBASE = ../..
+
+#
+# Define the module and object file sets.
+#
+MODULE = mac_ether
+OBJECTS = $(MAC_ETHER_OBJS:%=$(OBJS_DIR)/%)
+LINTS = $(MAC_ETHER_OBJS:%.o=$(LINTS_DIR)/%.ln)
+ROOTMODULE = $(ROOT_MAC_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)
+LDFLAGS += -dy -N misc/mac
+
+#
+# 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/sparc/Makefile.sparc.shared b/usr/src/uts/sparc/Makefile.sparc.shared
index 9ace7cd3d3..d2e7dde3c3 100644
--- a/usr/src/uts/sparc/Makefile.sparc.shared
+++ b/usr/src/uts/sparc/Makefile.sparc.shared
@@ -429,3 +429,8 @@ $(CLOSED_BUILD)CLOSED_XMODS = \
# 'Dacf' Modules (/kernel/dacf):
#
DACF_KMODS += usb_ac_dacf
+
+#
+# MAC-Type Plugin Modules (/kernel/mac)
+#
+MAC_KMODS += mac_ether
diff --git a/usr/src/uts/sparc/mac_ether/Makefile b/usr/src/uts/sparc/mac_ether/Makefile
new file mode 100644
index 0000000000..ff3094f471
--- /dev/null
+++ b/usr/src/uts/sparc/mac_ether/Makefile
@@ -0,0 +1,87 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# 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 2006 Sun Microsystems, Inc. All rights reserved.
+# Use is subject to license terms.
+#
+#ident "%Z%%M% %I% %E% SMI"
+#
+#
+# This makefile drives the production of the mac_ether MAC-Type plugin
+# kernel module.
+#
+
+#
+# Path to the base of the uts directory tree (usually /usr/src/uts).
+#
+UTSBASE = ../..
+
+#
+# Define the module and object file sets.
+#
+MODULE = mac_ether
+OBJECTS = $(MAC_ETHER_OBJS:%=$(OBJS_DIR)/%)
+LINTS = $(MAC_ETHER_OBJS:%.o=$(LINTS_DIR)/%.ln)
+ROOTMODULE = $(ROOT_MAC_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)
+LDFLAGS += -dy -N misc/mac
+
+#
+# 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/sun4v/io/vnet.c b/usr/src/uts/sun4v/io/vnet.c
index 96bfb613f6..29ebf6bc59 100644
--- a/usr/src/uts/sun4v/io/vnet.c
+++ b/usr/src/uts/sun4v/io/vnet.c
@@ -41,6 +41,7 @@
#include <sys/dlpi.h>
#include <net/if.h>
#include <sys/mac.h>
+#include <sys/mac_ether.h>
#include <sys/ddi.h>
#include <sys/sunddi.h>
#include <sys/strsun.h>
@@ -57,14 +58,12 @@ static int vnetattach(dev_info_t *, ddi_attach_cmd_t);
static int vnetdetach(dev_info_t *, ddi_detach_cmd_t);
/* MAC entrypoints */
-static uint64_t vnet_m_stat(void *arg, enum mac_stat stat);
+static int vnet_m_stat(void *, uint_t, uint64_t *);
static int vnet_m_start(void *);
static void vnet_m_stop(void *);
static int vnet_m_promisc(void *, boolean_t);
static int vnet_m_multicst(void *, boolean_t, const uint8_t *);
static int vnet_m_unicst(void *, const uint8_t *);
-static void vnet_m_resources(void *);
-static void vnet_m_ioctl(void *, queue_t *, mblk_t *);
mblk_t *vnet_m_tx(void *, mblk_t *);
/* vnet internal functions */
@@ -81,12 +80,28 @@ void vnet_del_fdb(void *arg, uint8_t *macaddr);
void vnet_modify_fdb(void *arg, uint8_t *macaddr, mac_tx_t m_tx, void *txarg);
void vnet_add_def_rte(void *arg, mac_tx_t m_tx, void *txarg);
void vnet_del_def_rte(void *arg);
+void vnet_rx(void *arg, mac_resource_handle_t mrh, mblk_t *mp);
+void vnet_tx_update(void *arg);
/* externs */
-extern int vgen_init(void *vnetp, dev_info_t *vnetdip, void *vnetmacp,
- const uint8_t *macaddr, mac_t **vgenmacp);
+extern int vgen_init(void *vnetp, dev_info_t *vnetdip, const uint8_t *macaddr,
+ mac_register_t **vgenmacp);
extern void vgen_uninit(void *arg);
+static mac_callbacks_t vnet_m_callbacks = {
+ 0,
+ vnet_m_stat,
+ vnet_m_start,
+ vnet_m_stop,
+ vnet_m_promisc,
+ vnet_m_multicst,
+ vnet_m_unicst,
+ vnet_m_tx,
+ NULL,
+ NULL,
+ NULL
+};
+
/*
* Linked list of "vnet_t" structures - one per instance.
*/
@@ -107,18 +122,6 @@ uint32_t vnet_nfdb_hash = VNET_NFDB_HASH; /* size of fdb hash table */
*/
static char macaddr_propname[] = "local-mac-address";
-static struct ether_addr etherbroadcastaddr = {
- 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
-};
-
-/*
- * MIB II broadcast/multicast packets
- */
-#define IS_BROADCAST(ehp) \
- (ether_cmp(&ehp->ether_dhost, &etherbroadcastaddr) == 0)
-#define IS_MULTICAST(ehp) \
- ((ehp->ether_dhost.ether_addr_octet[0] & 01) == 1)
-
/*
* This is the string displayed by modinfo(1m).
*/
@@ -288,17 +291,15 @@ _info(struct modinfo *modinfop)
static int
vnetattach(dev_info_t *dip, ddi_attach_cmd_t cmd)
{
- mac_t *macp;
vnet_t *vnetp;
vp_tl_t *vp_tlp;
int instance;
int status;
enum { AST_init = 0x0, AST_vnet_alloc = 0x1,
- AST_mac_alloc = 0x2, AST_read_macaddr = 0x4,
- AST_vgen_init = 0x8, AST_vptl_alloc = 0x10,
- AST_fdbh_alloc = 0x20 }
+ AST_read_macaddr = 0x2, AST_vgen_init = 0x4,
+ AST_vptl_alloc = 0x8, AST_fdbh_alloc = 0x10 }
attach_state;
- mac_t *vgenmacp = NULL;
+ mac_register_t *vgenmacp = NULL;
uint32_t nfdbh = 0;
attach_state = AST_init;
@@ -319,14 +320,9 @@ vnetattach(dev_info_t *dip, ddi_attach_cmd_t cmd)
vnetp = kmem_zalloc(sizeof (vnet_t), KM_SLEEP);
attach_state |= AST_vnet_alloc;
- macp = kmem_zalloc(sizeof (mac_t), KM_SLEEP);
- attach_state |= AST_mac_alloc;
-
/* setup links to vnet_t from both devinfo and mac_t */
ddi_set_driver_private(dip, (caddr_t)vnetp);
- macp->m_driver = vnetp;
vnetp->dip = dip;
- vnetp->macp = macp;
vnetp->instance = instance;
/* read the mac address */
@@ -349,8 +345,8 @@ vnetattach(dev_info_t *dip, ddi_attach_cmd_t cmd)
* will use hardware specific driver to communicate directly over the
* physical device to reach remote hosts without going through vswitch.
*/
- status = vgen_init(vnetp, vnetp->dip, vnetp->macp,
- (uint8_t *)vnetp->curr_macaddr, &vgenmacp);
+ status = vgen_init(vnetp, vnetp->dip, (uint8_t *)vnetp->curr_macaddr,
+ &vgenmacp);
if (status != DDI_SUCCESS) {
DERR((vnetp, "vgen_init() failed\n"));
goto vnet_attach_fail;
@@ -406,9 +402,6 @@ vnet_attach_fail:
if (attach_state & AST_vgen_init) {
vgen_uninit(vgenmacp->m_driver);
}
- if (attach_state & AST_mac_alloc) {
- KMEM_FREE(macp);
- }
if (attach_state & AST_vnet_alloc) {
KMEM_FREE(vnetp);
}
@@ -448,7 +441,7 @@ vnetdetach(dev_info_t *dip, ddi_detach_cmd_t cmd)
* particular if there are DLPI style-2 streams still open -
* in which case we just return failure.
*/
- if (mac_unregister(vnetp->macp) != 0)
+ if (mac_unregister(vnetp->mh) != 0)
goto vnet_detach_fail;
/* unlink from instance(vnet_t) list */
@@ -472,7 +465,6 @@ vnetdetach(dev_info_t *dip, ddi_detach_cmd_t cmd)
}
RW_EXIT(&vnetp->trwlock);
- KMEM_FREE(vnetp->macp);
KMEM_FREE(vnetp);
return (DDI_SUCCESS);
@@ -487,7 +479,8 @@ vnet_m_start(void *arg)
{
vnet_t *vnetp = arg;
vp_tl_t *vp_tlp;
- mac_t *vp_macp;
+ mac_register_t *vp_macp;
+ mac_callbacks_t *cbp;
DBG1((vnetp, "vnet_m_start: enter\n"));
@@ -504,7 +497,8 @@ vnet_m_start(void *arg)
WRITE_ENTER(&vnetp->trwlock);
for (vp_tlp = vnetp->tlp; vp_tlp != NULL; vp_tlp = vp_tlp->nextp) {
vp_macp = vp_tlp->macp;
- vp_macp->m_start(vp_macp->m_driver);
+ cbp = vp_macp->m_callbacks;
+ cbp->mc_start(vp_macp->m_driver);
}
RW_EXIT(&vnetp->trwlock);
@@ -519,14 +513,16 @@ vnet_m_stop(void *arg)
{
vnet_t *vnetp = arg;
vp_tl_t *vp_tlp;
- mac_t *vp_macp;
+ mac_register_t *vp_macp;
+ mac_callbacks_t *cbp;
DBG1((vnetp, "vnet_m_stop: enter\n"));
WRITE_ENTER(&vnetp->trwlock);
for (vp_tlp = vnetp->tlp; vp_tlp != NULL; vp_tlp = vp_tlp->nextp) {
vp_macp = vp_tlp->macp;
- vp_macp->m_stop(vp_macp->m_driver);
+ cbp = vp_macp->m_callbacks;
+ cbp->mc_stop(vp_macp->m_driver);
}
RW_EXIT(&vnetp->trwlock);
@@ -558,7 +554,8 @@ vnet_m_multicst(void *arg, boolean_t add, const uint8_t *mca)
vnet_t *vnetp = arg;
vp_tl_t *vp_tlp;
- mac_t *vp_macp;
+ mac_register_t *vp_macp;
+ mac_callbacks_t *cbp;
int rv = VNET_SUCCESS;
DBG1((vnetp, "vnet_m_multicst: enter\n"));
@@ -566,7 +563,8 @@ vnet_m_multicst(void *arg, boolean_t add, const uint8_t *mca)
for (vp_tlp = vnetp->tlp; vp_tlp != NULL; vp_tlp = vp_tlp->nextp) {
if (strcmp(vnetp->vgen_name, vp_tlp->name) == 0) {
vp_macp = vp_tlp->macp;
- rv = vp_macp->m_multicst(vp_macp->m_driver, add, mca);
+ cbp = vp_macp->m_callbacks;
+ rv = cbp->mc_multicst(vp_macp->m_driver, add, mca);
break;
}
}
@@ -673,123 +671,65 @@ vnet_m_tx(void *arg, mblk_t *mp)
return (mp);
}
-/* register resources with mac layer */
-static void
-vnet_m_resources(void *arg)
-{
- vnet_t *vnetp = arg;
- vp_tl_t *vp_tlp;
- mac_t *vp_macp;
-
- DBG1((vnetp, "vnet_m_resources: enter\n"));
-
- WRITE_ENTER(&vnetp->trwlock);
- for (vp_tlp = vnetp->tlp; vp_tlp != NULL; vp_tlp = vp_tlp->nextp) {
- vp_macp = vp_tlp->macp;
- vp_macp->m_resources(vp_macp->m_driver);
- }
- RW_EXIT(&vnetp->trwlock);
-
- DBG1((vnetp, "vnet_m_resources: exit\n"));
-}
-
-/*
- * vnet specific ioctls
- */
-static void
-vnet_m_ioctl(void *arg, queue_t *wq, mblk_t *mp)
-{
- vnet_t *vnetp = (vnet_t *)arg;
- struct iocblk *iocp;
- int cmd;
-
- DBG1((vnetp, "vnet_m_ioctl: enter\n"));
-
- iocp = (struct iocblk *)mp->b_rptr;
- iocp->ioc_error = 0;
- cmd = iocp->ioc_cmd;
- switch (cmd) {
- default:
- miocnak(wq, mp, 0, EINVAL);
- break;
- }
- DBG1((vnetp, "vnet_m_ioctl: exit\n"));
-}
-
/* get statistics from the device */
-uint64_t
-vnet_m_stat(void *arg, enum mac_stat stat)
+int
+vnet_m_stat(void *arg, uint_t stat, uint64_t *val)
{
vnet_t *vnetp = arg;
vp_tl_t *vp_tlp;
- mac_t *vp_macp;
- uint64_t val = 0;
+ mac_register_t *vp_macp;
+ mac_callbacks_t *cbp;
+ uint64_t val_total = 0;
DBG1((vnetp, "vnet_m_stat: enter\n"));
/*
- * get the specified statistic from each transport
- * and return the aggregate val
+ * get the specified statistic from each transport and return the
+ * aggregate val. This obviously only works for counters.
*/
+ if ((IS_MAC_STAT(stat) && !MAC_STAT_ISACOUNTER(stat)) ||
+ (IS_MACTYPE_STAT(stat) && !ETHER_STAT_ISACOUNTER(stat))) {
+ return (ENOTSUP);
+ }
READ_ENTER(&vnetp->trwlock);
for (vp_tlp = vnetp->tlp; vp_tlp != NULL; vp_tlp = vp_tlp->nextp) {
vp_macp = vp_tlp->macp;
- val += vp_macp->m_stat(vp_macp->m_driver, stat);
+ cbp = vp_macp->m_callbacks;
+ if (cbp->mc_getstat(vp_macp->m_driver, stat, val) == 0)
+ val_total += *val;
}
RW_EXIT(&vnetp->trwlock);
+ *val = val_total;
+
DBG1((vnetp, "vnet_m_stat: exit\n"));
- return (val);
+ return (0);
}
/* wrapper function for mac_register() */
static int
vnet_mac_register(vnet_t *vnetp)
{
- mac_info_t *mip;
- mac_t *macp;
-
- macp = vnetp->macp;
-
- mip = &(macp->m_info);
- mip->mi_media = DL_ETHER;
- mip->mi_sdu_min = 0;
- mip->mi_sdu_max = ETHERMTU;
- mip->mi_cksum = 0;
- mip->mi_poll = 0; /* DL_CAPAB_POLL ? */
- mip->mi_addr_length = ETHERADDRL;
- bcopy(&etherbroadcastaddr, mip->mi_brdcst_addr, ETHERADDRL);
- bcopy(vnetp->curr_macaddr, mip->mi_unicst_addr, ETHERADDRL);
-
- MAC_STAT_MIB(mip->mi_stat);
- mip->mi_stat[MAC_STAT_UNKNOWNS] = B_FALSE;
- MAC_STAT_ETHER(mip->mi_stat);
- mip->mi_stat[MAC_STAT_SQE_ERRORS] = B_FALSE;
- mip->mi_stat[MAC_STAT_MACRCV_ERRORS] = B_FALSE;
-
- macp->m_stat = vnet_m_stat;
- macp->m_start = vnet_m_start;
- macp->m_stop = vnet_m_stop;
- macp->m_promisc = vnet_m_promisc;
- macp->m_multicst = vnet_m_multicst;
- macp->m_unicst = vnet_m_unicst;
- macp->m_resources = vnet_m_resources;
- macp->m_ioctl = vnet_m_ioctl;
- macp->m_tx = vnet_m_tx;
+ mac_register_t *macp;
+ int err;
+ if ((macp = mac_alloc(MAC_VERSION)) == NULL)
+ return (DDI_FAILURE);
+ macp->m_type_ident = MAC_PLUGIN_IDENT_ETHER;
+ macp->m_driver = vnetp;
macp->m_dip = vnetp->dip;
- macp->m_ident = MAC_IDENT;
+ macp->m_src_addr = vnetp->curr_macaddr;
+ macp->m_callbacks = &vnet_m_callbacks;
+ macp->m_min_sdu = 0;
+ macp->m_max_sdu = ETHERMTU;
/*
* Finally, we're ready to register ourselves with the MAC layer
* interface; if this succeeds, we're all ready to start()
*/
- if (mac_register(macp) != 0) {
- KMEM_FREE(macp);
- return (DDI_FAILURE);
- }
-
- return (DDI_SUCCESS);
+ err = mac_register(macp, &vnetp->mh);
+ mac_free(macp);
+ return (err == 0 ? DDI_SUCCESS : DDI_FAILURE);
}
/* add vp_tl to the list */
@@ -1044,3 +984,17 @@ vnet_del_def_rte(void *arg)
RW_EXIT(&fdbhp->rwlock);
}
+
+void
+vnet_rx(void *arg, mac_resource_handle_t mrh, mblk_t *mp)
+{
+ vnet_t *vnetp = arg;
+ mac_rx(vnetp->mh, mrh, mp);
+}
+
+void
+vnet_tx_update(void *arg)
+{
+ vnet_t *vnetp = arg;
+ mac_tx_update(vnetp->mh);
+}
diff --git a/usr/src/uts/sun4v/io/vnet_gen.c b/usr/src/uts/sun4v/io/vnet_gen.c
index e93f064eee..9d01b82837 100644
--- a/usr/src/uts/sun4v/io/vnet_gen.c
+++ b/usr/src/uts/sun4v/io/vnet_gen.c
@@ -43,6 +43,7 @@
#include <sys/strsun.h>
#include <sys/note.h>
#include <sys/mac.h>
+#include <sys/mac_ether.h>
#include <sys/ldc.h>
#include <sys/mach_descrip.h>
#include <sys/mdeg.h>
@@ -61,18 +62,17 @@
* Function prototypes.
*/
/* vgen proxy entry points */
-int vgen_init(void *vnetp, dev_info_t *vnetdip, void *vnetmacp,
- const uint8_t *macaddr, mac_t **vgenmacp);
+int vgen_init(void *vnetp, dev_info_t *vnetdip, const uint8_t *macaddr,
+ mac_register_t **vgenmacp);
void vgen_uninit(void *arg);
static int vgen_start(void *arg);
static void vgen_stop(void *arg);
static mblk_t *vgen_tx(void *arg, mblk_t *mp);
-static void vgen_resources(void *arg);
static int vgen_multicst(void *arg, boolean_t add,
const uint8_t *mca);
static int vgen_promisc(void *arg, boolean_t on);
static int vgen_unicst(void *arg, const uint8_t *mca);
-static uint64_t vgen_stat(void *arg, enum mac_stat stat);
+static int vgen_stat(void *arg, uint_t stat, uint64_t *val);
static void vgen_ioctl(void *arg, queue_t *wq, mblk_t *mp);
/* externs - functions provided by vnet to add/remove/modify entries in fdb */
@@ -81,6 +81,8 @@ void vnet_del_fdb(void *arg, uint8_t *macaddr);
void vnet_modify_fdb(void *arg, uint8_t *macaddr, mac_tx_t m_tx, void *txarg);
void vnet_add_def_rte(void *arg, mac_tx_t m_tx, void *txarg);
void vnet_del_def_rte(void *arg);
+void vnet_rx(void *arg, mac_resource_handle_t mrh, mblk_t *mp);
+void vnet_tx_update(void *arg);
/* vgen internal functions */
static void vgen_detach_ports(vgen_t *vgenp);
@@ -99,7 +101,7 @@ static int vgen_port_attach_mdeg(vgen_t *vgenp, int port_num, uint64_t *ldcids,
static void vgen_port_detach_mdeg(vgen_port_t *portp);
static int vgen_update_port(vgen_t *vgenp, md_t *curr_mdp,
mde_cookie_t curr_mdex, md_t *prev_mdp, mde_cookie_t prev_mdex);
-static uint64_t vgen_port_stat(vgen_port_t *portp, enum mac_stat stat);
+static uint64_t vgen_port_stat(vgen_port_t *portp, uint_t stat);
static int vgen_ldc_attach(vgen_port_t *portp, uint64_t ldc_id);
static void vgen_ldc_detach(vgen_ldc_t *ldcp);
@@ -117,8 +119,7 @@ static int vgen_init_tbufs(vgen_ldc_t *ldcp);
static void vgen_uninit_tbufs(vgen_ldc_t *ldcp);
static void vgen_clobber_tbufs(vgen_ldc_t *ldcp);
static void vgen_clobber_rxds(vgen_ldc_t *ldcp);
-static uint64_t vgen_ldc_stat(vgen_ldc_t *ldcp, enum mac_stat stat);
-static void vgen_init_macp(vgen_t *vgenp, mac_t *macp);
+static uint64_t vgen_ldc_stat(vgen_ldc_t *ldcp, uint_t stat);
static uint_t vgen_ldc_cb(uint64_t event, caddr_t arg);
static int vgen_portsend(vgen_port_t *portp, mblk_t *mp);
static int vgen_ldcsend(vgen_ldc_t *ldcp, mblk_t *mp);
@@ -281,6 +282,20 @@ static mdeg_prop_spec_t vgen_prop_template[] = {
static int vgen_mdeg_cb(void *cb_argp, mdeg_result_t *resp);
+static mac_callbacks_t vgen_m_callbacks = {
+ 0,
+ vgen_stat,
+ vgen_start,
+ vgen_stop,
+ vgen_promisc,
+ vgen_multicst,
+ vgen_unicst,
+ vgen_tx,
+ NULL,
+ NULL,
+ NULL
+};
+
/* externs */
extern uint32_t vnet_ntxds;
extern uint32_t vnet_reclaim_lowat;
@@ -362,18 +377,18 @@ vgen_ver_t dbg_vgen_versions[VGEN_NUM_VER] =
* vgen_init() is called by an instance of vnet driver to initialize the
* corresponding generic proxy transport layer. The arguments passed by vnet
* are - an opaque pointer to the vnet instance, pointers to dev_info_t and
- * mac_t of the vnet device, mac address of the vnet device, and a pointer to
- * the mac_t of the generic transport is returned in the last argument.
+ * the mac address of the vnet device, and a pointer to mac_register_t of
+ * the generic transport is returned in the last argument.
*/
int
-vgen_init(void *vnetp, dev_info_t *vnetdip, void *vnetmacp,
- const uint8_t *macaddr, mac_t **vgenmacp)
+vgen_init(void *vnetp, dev_info_t *vnetdip, const uint8_t *macaddr,
+ mac_register_t **vgenmacp)
{
vgen_t *vgenp;
- mac_t *macp;
+ mac_register_t *macp;
int instance;
- if ((vnetp == NULL) || (vnetdip == NULL) ||(vnetmacp == NULL))
+ if ((vnetp == NULL) || (vnetdip == NULL))
return (DDI_FAILURE);
instance = ddi_get_instance(vnetdip);
@@ -384,9 +399,21 @@ vgen_init(void *vnetp, dev_info_t *vnetdip, void *vnetmacp,
vgenp->vnetp = vnetp;
vgenp->vnetdip = vnetdip;
- vgenp->vnetmacp = vnetmacp;
bcopy(macaddr, &(vgenp->macaddr), ETHERADDRL);
+ if ((macp = mac_alloc(MAC_VERSION)) == NULL) {
+ KMEM_FREE(vgenp);
+ return (DDI_FAILURE);
+ }
+ macp->m_type_ident = MAC_PLUGIN_IDENT_ETHER;
+ macp->m_driver = vgenp;
+ macp->m_dip = vnetdip;
+ macp->m_src_addr = (uint8_t *)&(vgenp->macaddr);
+ macp->m_callbacks = &vgen_m_callbacks;
+ macp->m_min_sdu = 0;
+ macp->m_max_sdu = ETHERMTU;
+ vgenp->macp = macp;
+
/* allocate multicast table */
vgenp->mctab = kmem_zalloc(VGEN_INIT_MCTAB_SIZE *
sizeof (struct ether_addr), KM_SLEEP);
@@ -400,15 +427,13 @@ vgen_init(void *vnetp, dev_info_t *vnetdip, void *vnetmacp,
mutex_destroy(&vgenp->lock);
kmem_free(vgenp->mctab, VGEN_INIT_MCTAB_SIZE *
sizeof (struct ether_addr));
+ mac_free(vgenp->macp);
KMEM_FREE(vgenp);
return (DDI_FAILURE);
}
- macp = &vgenp->vgenmac;
- vgen_init_macp(vgenp, macp);
-
- /* register mac_t of this vgen_t with vnet */
- *vgenmacp = macp;
+ /* register macp of this vgen_t with vnet */
+ *vgenmacp = vgenp->macp;
DBG1((vnetp, "vgen_init: exit vnet_instance(%d)\n", instance));
return (DDI_SUCCESS);
@@ -444,6 +469,8 @@ vgen_uninit(void *arg)
/* free multicast table */
kmem_free(vgenp->mctab, vgenp->mcsize * sizeof (struct ether_addr));
+ mac_free(vgenp->macp);
+
mutex_exit(&vgenp->lock);
mutex_destroy(&vgenp->lock);
@@ -454,7 +481,7 @@ vgen_uninit(void *arg)
}
/* enable transmit/receive for the device */
-static int
+int
vgen_start(void *arg)
{
vgen_t *vgenp = (vgen_t *)arg;
@@ -471,7 +498,7 @@ vgen_start(void *arg)
}
/* stop transmit/receive */
-static void
+void
vgen_stop(void *arg)
{
vgen_t *vgenp = (vgen_t *)arg;
@@ -678,7 +705,7 @@ vgen_ldcsend(vgen_ldc_t *ldcp, mblk_t *mp)
txdp->nbytes = size;
txdp->ncookies = tbufp->ncookies;
bcopy((tbufp->memcookie), (txdp->memcookie),
- tbufp->ncookies * sizeof (ldc_mem_cookie_t));
+ tbufp->ncookies * sizeof (ldc_mem_cookie_t));
/* send dring datamsg to the peer */
start = end = i;
@@ -721,28 +748,8 @@ vgen_tx_exit:
return (VGEN_TX_SUCCESS);
}
-/* register resources */
-static void
-vgen_resources(void *arg)
-{
- vgen_t *vgenp;
- mac_rx_fifo_t mrf;
-
- vgenp = (vgen_t *)arg;
- DBG1((vgenp->vnetp, "vgen_resources: enter\n"));
-
- mrf.mrf_type = MAC_RX_FIFO;
- mrf.mrf_blank = NULL;
- mrf.mrf_arg = NULL;
- mrf.mrf_normal_blank_time = 0;
- mrf.mrf_normal_pkt_count = 0;
- vgenp->mrh = mac_resource_add(vgenp->vnetmacp, (mac_resource_t *)&mrf);
-
- DBG1((vgenp->vnetp, "vgen_resources: exit\n"));
-}
-
/* enable/disable a multicast address */
-static int
+int
vgen_multicst(void *arg, boolean_t add, const uint8_t *mca)
{
vgen_t *vgenp;
@@ -884,26 +891,25 @@ vgen_unicst(void *arg, const uint8_t *mca)
}
/* get device statistics */
-static uint64_t
-vgen_stat(void *arg, enum mac_stat stat)
+int
+vgen_stat(void *arg, uint_t stat, uint64_t *val)
{
vgen_t *vgenp = (vgen_t *)arg;
vgen_port_t *portp;
vgen_portlist_t *plistp;
- uint64_t val;
- val = 0;
+ *val = 0;
plistp = &(vgenp->vgenports);
READ_ENTER(&plistp->rwlock);
for (portp = plistp->headp; portp != NULL; portp = portp->nextp) {
- val += vgen_port_stat(portp, stat);
+ *val += vgen_port_stat(portp, stat);
}
RW_EXIT(&plistp->rwlock);
- return (val);
+ return (0);
}
static void
@@ -1492,7 +1498,7 @@ vgen_update_port(vgen_t *vgenp, md_t *curr_mdp, mde_cookie_t curr_mdex,
}
static uint64_t
-vgen_port_stat(vgen_port_t *portp, enum mac_stat stat)
+vgen_port_stat(vgen_port_t *portp, uint_t stat)
{
vgen_ldclist_t *ldclp;
vgen_ldc_t *ldcp;
@@ -1983,13 +1989,13 @@ vgen_init_tbufs(vgen_ldc_t *ldcp)
tbufp->datap = datap;
if ((ncookies == 0) ||
- (ncookies > (uint64_t)MAX_COOKIES)) {
+ (ncookies > (uint64_t)MAX_COOKIES)) {
goto init_tbufs_failed;
}
for (ci = 1; ci < ncookies; ci++) {
rv = ldc_mem_nextcookie(tbufp->memhandle,
- &(tbufp->memcookie[ci]));
+ &(tbufp->memcookie[ci]));
if (rv != 0) {
goto init_tbufs_failed;
}
@@ -2156,7 +2162,7 @@ vgen_init_rxds(vgen_ldc_t *ldcp, uint32_t num_desc, uint32_t desc_size,
/* get channel statistics */
static uint64_t
-vgen_ldc_stat(vgen_ldc_t *ldcp, enum mac_stat stat)
+vgen_ldc_stat(vgen_ldc_t *ldcp, uint_t stat)
{
vgen_stats_t *statsp;
uint64_t val;
@@ -2218,50 +2224,50 @@ vgen_ldc_stat(vgen_ldc_t *ldcp, enum mac_stat stat)
/* stats not relevant to ldc, return 0 */
case MAC_STAT_IFSPEED:
- case MAC_STAT_ALIGN_ERRORS:
- case MAC_STAT_FCS_ERRORS:
- case MAC_STAT_FIRST_COLLISIONS:
- case MAC_STAT_MULTI_COLLISIONS:
- case MAC_STAT_DEFER_XMTS:
- case MAC_STAT_TX_LATE_COLLISIONS:
- case MAC_STAT_EX_COLLISIONS:
- case MAC_STAT_MACXMT_ERRORS:
- case MAC_STAT_CARRIER_ERRORS:
- case MAC_STAT_TOOLONG_ERRORS:
- case MAC_STAT_XCVR_ADDR:
- case MAC_STAT_XCVR_ID:
- case MAC_STAT_XCVR_INUSE:
- case MAC_STAT_CAP_1000FDX:
- case MAC_STAT_CAP_1000HDX:
- case MAC_STAT_CAP_100FDX:
- case MAC_STAT_CAP_100HDX:
- case MAC_STAT_CAP_10FDX:
- case MAC_STAT_CAP_10HDX:
- case MAC_STAT_CAP_ASMPAUSE:
- case MAC_STAT_CAP_PAUSE:
- case MAC_STAT_CAP_AUTONEG:
- case MAC_STAT_ADV_CAP_1000FDX:
- case MAC_STAT_ADV_CAP_1000HDX:
- case MAC_STAT_ADV_CAP_100FDX:
- case MAC_STAT_ADV_CAP_100HDX:
- case MAC_STAT_ADV_CAP_10FDX:
- case MAC_STAT_ADV_CAP_10HDX:
- case MAC_STAT_ADV_CAP_ASMPAUSE:
- case MAC_STAT_ADV_CAP_PAUSE:
- case MAC_STAT_ADV_CAP_AUTONEG:
- case MAC_STAT_LP_CAP_1000FDX:
- case MAC_STAT_LP_CAP_1000HDX:
- case MAC_STAT_LP_CAP_100FDX:
- case MAC_STAT_LP_CAP_100HDX:
- case MAC_STAT_LP_CAP_10FDX:
- case MAC_STAT_LP_CAP_10HDX:
- case MAC_STAT_LP_CAP_ASMPAUSE:
- case MAC_STAT_LP_CAP_PAUSE:
- case MAC_STAT_LP_CAP_AUTONEG:
- case MAC_STAT_LINK_ASMPAUSE:
- case MAC_STAT_LINK_PAUSE:
- case MAC_STAT_LINK_AUTONEG:
- case MAC_STAT_LINK_DUPLEX:
+ case ETHER_STAT_ALIGN_ERRORS:
+ case ETHER_STAT_FCS_ERRORS:
+ case ETHER_STAT_FIRST_COLLISIONS:
+ case ETHER_STAT_MULTI_COLLISIONS:
+ case ETHER_STAT_DEFER_XMTS:
+ case ETHER_STAT_TX_LATE_COLLISIONS:
+ case ETHER_STAT_EX_COLLISIONS:
+ case ETHER_STAT_MACXMT_ERRORS:
+ case ETHER_STAT_CARRIER_ERRORS:
+ case ETHER_STAT_TOOLONG_ERRORS:
+ case ETHER_STAT_XCVR_ADDR:
+ case ETHER_STAT_XCVR_ID:
+ case ETHER_STAT_XCVR_INUSE:
+ case ETHER_STAT_CAP_1000FDX:
+ case ETHER_STAT_CAP_1000HDX:
+ case ETHER_STAT_CAP_100FDX:
+ case ETHER_STAT_CAP_100HDX:
+ case ETHER_STAT_CAP_10FDX:
+ case ETHER_STAT_CAP_10HDX:
+ case ETHER_STAT_CAP_ASMPAUSE:
+ case ETHER_STAT_CAP_PAUSE:
+ case ETHER_STAT_CAP_AUTONEG:
+ case ETHER_STAT_ADV_CAP_1000FDX:
+ case ETHER_STAT_ADV_CAP_1000HDX:
+ case ETHER_STAT_ADV_CAP_100FDX:
+ case ETHER_STAT_ADV_CAP_100HDX:
+ case ETHER_STAT_ADV_CAP_10FDX:
+ case ETHER_STAT_ADV_CAP_10HDX:
+ case ETHER_STAT_ADV_CAP_ASMPAUSE:
+ case ETHER_STAT_ADV_CAP_PAUSE:
+ case ETHER_STAT_ADV_CAP_AUTONEG:
+ case ETHER_STAT_LP_CAP_1000FDX:
+ case ETHER_STAT_LP_CAP_1000HDX:
+ case ETHER_STAT_LP_CAP_100FDX:
+ case ETHER_STAT_LP_CAP_100HDX:
+ case ETHER_STAT_LP_CAP_10FDX:
+ case ETHER_STAT_LP_CAP_10HDX:
+ case ETHER_STAT_LP_CAP_ASMPAUSE:
+ case ETHER_STAT_LP_CAP_PAUSE:
+ case ETHER_STAT_LP_CAP_AUTONEG:
+ case ETHER_STAT_LINK_ASMPAUSE:
+ case ETHER_STAT_LINK_PAUSE:
+ case ETHER_STAT_LINK_AUTONEG:
+ case ETHER_STAT_LINK_DUPLEX:
default:
val = 0;
break;
@@ -2270,21 +2276,6 @@ vgen_ldc_stat(vgen_ldc_t *ldcp, enum mac_stat stat)
return (val);
}
-static void
-vgen_init_macp(vgen_t *vgenp, mac_t *macp)
-{
- macp->m_driver = (void *)vgenp;
- macp->m_start = vgen_start;
- macp->m_stop = vgen_stop;
- macp->m_tx = vgen_tx;
- macp->m_resources = vgen_resources;
- macp->m_multicst = vgen_multicst;
- macp->m_promisc = vgen_promisc;
- macp->m_unicst = vgen_unicst;
- macp->m_stat = vgen_stat;
- macp->m_ioctl = vgen_ioctl;
-}
-
/* Interrupt handler for the channel */
static uint_t
vgen_ldc_cb(uint64_t event, caddr_t arg)
@@ -2480,7 +2471,7 @@ vgen_ldc_cb(uint64_t event, caddr_t arg)
mp->b_next = mp->b_prev = NULL;
DBG2((vnetp, "vgen_ldc_cb: id(%lx) rx pkt len (%lx)\n",
ldcp->ldc_id, MBLKL(mp)));
- mac_rx((mac_t *)vgenp->vnetmacp, vgenp->mrh, mp);
+ vnet_rx(vgenp->vnetp, NULL, mp);
}
DBG1((vnetp, "vgen_ldc_cb exit: ldcid (%lx)\n", ldcp->ldc_id));
@@ -4396,7 +4387,7 @@ vgen_reclaim_dring(vgen_ldc_t *ldcp)
if (ldcp->need_resched) {
ldcp->need_resched = B_FALSE;
#ifdef VGEN_USE_MAC_TX_UPDATE
- mac_tx_update(vgenp->vnetmacp);
+ vnet_tx_update(vgenp->vnetp);
#endif
}
}
@@ -4484,7 +4475,7 @@ vgen_ldc_watchdog(void *arg)
if (ldcp->need_resched) {
ldcp->need_resched = B_FALSE;
#ifdef VGEN_USE_MAC_TX_UPDATE
- mac_tx_update(ldcp->vgenp->vnetmacp);
+ vnet_tx_update(ldcp->vgenp->vnetp);
#endif
}
}
diff --git a/usr/src/uts/sun4v/io/vsw.c b/usr/src/uts/sun4v/io/vsw.c
index 6038ea2874..d82d31c79f 100644
--- a/usr/src/uts/sun4v/io/vsw.c
+++ b/usr/src/uts/sun4v/io/vsw.c
@@ -56,6 +56,7 @@
#include <sys/modctl.h>
#include <sys/modhash.h>
#include <sys/mac.h>
+#include <sys/mac_ether.h>
#include <sys/taskq.h>
#include <sys/note.h>
#include <sys/mach_descrip.h>
@@ -86,15 +87,13 @@ static void vsw_rx_cb(void *, mac_resource_handle_t, mblk_t *);
static mblk_t *vsw_tx_msg(vsw_t *, mblk_t *);
static int vsw_mac_register(vsw_t *);
static int vsw_mac_unregister(vsw_t *);
-static uint64_t vsw_m_stat(void *arg, enum mac_stat);
+static int vsw_m_stat(void *, uint_t, uint64_t *);
static void vsw_m_stop(void *arg);
static int vsw_m_start(void *arg);
static int vsw_m_unicst(void *arg, const uint8_t *);
static int vsw_m_multicst(void *arg, boolean_t, const uint8_t *);
static int vsw_m_promisc(void *arg, boolean_t);
static mblk_t *vsw_m_tx(void *arg, mblk_t *);
-static void vsw_m_resources(void *arg);
-static void vsw_m_ioctl(void *arg, queue_t *q, mblk_t *mp);
/* MDEG routines */
static void vsw_mdeg_register(vsw_t *vswp);
@@ -214,6 +213,20 @@ int vsw_wretries = 100; /* # of write attempts */
void (*vsw_switch_frame)(vsw_t *, mblk_t *, int, vsw_port_t *,
mac_resource_handle_t);
+static mac_callbacks_t vsw_m_callbacks = {
+ 0,
+ vsw_m_stat,
+ vsw_m_start,
+ vsw_m_stop,
+ vsw_m_promisc,
+ vsw_m_multicst,
+ vsw_m_unicst,
+ vsw_m_tx,
+ NULL,
+ NULL,
+ NULL
+};
+
static struct cb_ops vsw_cb_ops = {
nulldev, /* cb_open */
nulldev, /* cb_close */
@@ -618,8 +631,6 @@ vsw_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
* Do this in both layer 2 and layer 3 mode.
*/
vswp->if_state &= ~VSW_IF_UP;
- vswp->if_macp = NULL;
- vswp->if_mrh = NULL;
if (vswp->mdprops & VSW_MD_MACADDR) {
if (vsw_mac_register(vswp) != 0) {
cmn_err(CE_WARN, "Unable to register as provider "
@@ -1073,6 +1084,9 @@ vsw_setup_layer3(vsw_t *vswp)
static int
vsw_mac_attach(vsw_t *vswp)
{
+ char drv[LIFNAMSIZ];
+ uint_t ddi_instance;
+
D1(vswp, "vsw_mac_attach: enter");
vswp->mh = NULL;
@@ -1081,7 +1095,11 @@ vsw_mac_attach(vsw_t *vswp)
ASSERT(vswp->mdprops & VSW_MD_PHYSNAME);
- if ((mac_open(vswp->physname, 0, &vswp->mh)) != 0) {
+ if (ddi_parse(vswp->physname, drv, &ddi_instance) != DDI_SUCCESS) {
+ cmn_err(CE_WARN, "invalid device name: %s", vswp->physname);
+ goto mac_fail_exit;
+ }
+ if ((mac_open(vswp->physname, ddi_instance, &vswp->mh)) != 0) {
cmn_err(CE_WARN, "mac_open %s failed", vswp->physname);
goto mac_fail_exit;
}
@@ -1269,54 +1287,24 @@ vsw_tx_msg(vsw_t *vswp, mblk_t *mp)
static int
vsw_mac_register(vsw_t *vswp)
{
- mac_t *macp = NULL;
- mac_info_t *mip = NULL;
- int rv = 0;
+ mac_register_t *macp;
+ int rv;
D1(vswp, "%s: enter", __func__);
- macp = kmem_zalloc(sizeof (mac_t), KM_SLEEP);
-
- /*
- * Setup the m_info fields.
- */
- mip = &(macp->m_info);
- mip->mi_media = DL_ETHER;
- mip->mi_sdu_min = 0;
- mip->mi_sdu_max = ETHERMTU;
- mip->mi_cksum = 0;
- mip->mi_poll = DL_CAPAB_POLL;
-
- mip->mi_addr_length = ETHERADDRL;
- bcopy(&etherbroadcastaddr, mip->mi_brdcst_addr, ETHERADDRL);
-
- READ_ENTER(&vswp->if_lockrw);
- bcopy(&vswp->if_addr, mip->mi_unicst_addr, ETHERADDRL);
- RW_EXIT(&vswp->if_lockrw);
-
- MAC_STAT_MIB(mip->mi_stat);
- MAC_STAT_ETHER(mip->mi_stat);
-
- /* entry points */
- macp->m_stat = vsw_m_stat;
- macp->m_stop = vsw_m_stop;
- macp->m_start = vsw_m_start;
- macp->m_unicst = vsw_m_unicst;
- macp->m_multicst = vsw_m_multicst;
- macp->m_promisc = vsw_m_promisc;
- macp->m_tx = vsw_m_tx;
- macp->m_resources = vsw_m_resources;
- macp->m_ioctl = vsw_m_ioctl;
-
- macp->m_port = 0;
- macp->m_dip = vswp->dip;
- macp->m_ident = MAC_IDENT;
+ if ((macp = mac_alloc(MAC_VERSION)) == NULL)
+ return (EINVAL);
+ macp->m_type_ident = MAC_PLUGIN_IDENT_ETHER;
macp->m_driver = vswp;
-
- vswp->if_macp = macp;
-
- /* register */
- rv = mac_register(macp);
+ macp->m_dip = vswp->dip;
+ macp->m_src_addr = (uint8_t *)&vswp->if_addr;
+ macp->m_callbacks = &vsw_m_callbacks;
+ macp->m_min_sdu = 0;
+ macp->m_max_sdu = ETHERMTU;
+ rv = mac_register(macp, &vswp->if_mh);
+ mac_free(macp);
+ if (rv == 0)
+ vswp->if_state |= VSW_IF_REG;
D1(vswp, "%s: exit", __func__);
@@ -1332,8 +1320,8 @@ vsw_mac_unregister(vsw_t *vswp)
WRITE_ENTER(&vswp->if_lockrw);
- if (vswp->if_macp != NULL) {
- rv = mac_unregister(vswp->if_macp);
+ if (vswp->if_state & VSW_IF_REG) {
+ rv = mac_unregister(vswp->if_mh);
if (rv != 0) {
DWARN(vswp, "%s: unable to unregister from MAC "
"framework", __func__);
@@ -1343,11 +1331,8 @@ vsw_mac_unregister(vsw_t *vswp)
return (rv);
}
- /* mark i/f as down and promisc off */
- vswp->if_state &= ~VSW_IF_UP;
-
- kmem_free(vswp->if_macp, sizeof (mac_t));
- vswp->if_macp = NULL;
+ /* mark i/f as down and unregistered */
+ vswp->if_state &= ~(VSW_IF_UP | VSW_IF_REG);
}
RW_EXIT(&vswp->if_lockrw);
@@ -1356,25 +1341,19 @@ vsw_mac_unregister(vsw_t *vswp)
return (rv);
}
-static uint64_t
-vsw_m_stat(void *arg, enum mac_stat stat)
+static int
+vsw_m_stat(void *arg, uint_t stat, uint64_t *val)
{
vsw_t *vswp = (vsw_t *)arg;
- const mac_info_t *mip;
D1(vswp, "%s: enter", __func__);
- if (vswp->mh != NULL)
- mip = mac_info(vswp->mh);
- else
- return (0);
-
- if (!mip->mi_stat[stat])
- return (0);
+ if (vswp->mh == NULL)
+ return (EINVAL);
/* return stats from underlying device */
- return (mac_stat_get(vswp->mh, stat));
-
+ *val = mac_stat_get(vswp->mh, stat);
+ return (0);
}
static void
@@ -1535,39 +1514,6 @@ vsw_m_tx(void *arg, mblk_t *mp)
return (NULL);
}
-static void
-vsw_m_resources(void *arg)
-{
- vsw_t *vswp = (vsw_t *)arg;
- mac_rx_fifo_t mrf;
-
- D1(vswp, "%s: enter", __func__);
-
- mrf.mrf_type = MAC_RX_FIFO;
- mrf.mrf_blank = NULL;
- mrf.mrf_arg = (void *)vswp;
- mrf.mrf_normal_blank_time = 0;
- mrf.mrf_normal_pkt_count = 0;
-
- WRITE_ENTER(&vswp->if_lockrw);
- vswp->if_mrh = mac_resource_add(vswp->if_macp, (mac_resource_t *)&mrf);
- RW_EXIT(&vswp->if_lockrw);
-
- D1(vswp, "%s: exit", __func__);
-}
-
-static void
-vsw_m_ioctl(void *arg, queue_t *q, mblk_t *mp)
-{
- vsw_t *vswp = (vsw_t *)arg;
-
- D1(vswp, "%s: enter", __func__);
-
- miocnak(q, mp, 0, ENOTSUP);
-
- D1(vswp, "%s: exit", __func__);
-}
-
/*
* Register for machine description (MD) updates.
*/
@@ -4702,7 +4648,7 @@ vsw_switch_l2_frame(vsw_t *vswp, mblk_t *mp, int caller,
if (caller != VSW_LOCALDEV) {
if (vswp->if_state & VSW_IF_UP) {
RW_EXIT(&vswp->if_lockrw);
- mac_rx(vswp->if_macp, mrh, mp);
+ mac_rx(vswp->if_mh, mrh, mp);
} else {
RW_EXIT(&vswp->if_lockrw);
/* Interface down, drop pkt */
@@ -4736,7 +4682,7 @@ vsw_switch_l2_frame(vsw_t *vswp, mblk_t *mp, int caller,
RW_EXIT(&vswp->if_lockrw);
nmp = copymsg(mp);
if (nmp)
- mac_rx(vswp->if_macp, mrh, nmp);
+ mac_rx(vswp->if_mh, mrh, nmp);
} else {
RW_EXIT(&vswp->if_lockrw);
}
@@ -4798,7 +4744,7 @@ vsw_switch_l2_frame(vsw_t *vswp, mblk_t *mp, int caller,
RW_EXIT(&vswp->if_lockrw);
nmp = copymsg(mp);
if (nmp)
- mac_rx(vswp->if_macp,
+ mac_rx(vswp->if_mh,
mrh, nmp);
} else {
RW_EXIT(&vswp->if_lockrw);
@@ -4819,7 +4765,7 @@ vsw_switch_l2_frame(vsw_t *vswp, mblk_t *mp, int caller,
READ_ENTER(&vswp->if_lockrw);
if (VSW_U_P(vswp->if_state)) {
RW_EXIT(&vswp->if_lockrw);
- mac_rx(vswp->if_macp, mrh, mp);
+ mac_rx(vswp->if_mh, mrh, mp);
} else {
RW_EXIT(&vswp->if_lockrw);
freemsg(mp);
@@ -4938,7 +4884,7 @@ vsw_switch_l3_frame(vsw_t *vswp, mblk_t *mp, int caller,
RW_EXIT(&vswp->if_lockrw);
D2(vswp, "%s: sending up",
__func__);
- mac_rx(vswp->if_macp, mrh, mp);
+ mac_rx(vswp->if_mh, mrh, mp);
} else {
RW_EXIT(&vswp->if_lockrw);
/* Interface down, drop pkt */
@@ -5001,7 +4947,7 @@ vsw_forward_all(vsw_t *vswp, mblk_t *mp, int caller, vsw_port_t *arg)
RW_EXIT(&vswp->if_lockrw);
nmp = copymsg(mp);
if (nmp)
- mac_rx(vswp->if_macp, vswp->if_mrh, nmp);
+ mac_rx(vswp->if_mh, NULL, nmp);
} else {
RW_EXIT(&vswp->if_lockrw);
}
@@ -5119,8 +5065,7 @@ vsw_forward_grp(vsw_t *vswp, mblk_t *mp, int caller, vsw_port_t *arg)
if (vswp->if_state & VSW_IF_UP) {
nmp = copymsg(mp);
if (nmp)
- mac_rx(vswp->if_macp,
- vswp->if_mrh, nmp);
+ mac_rx(vswp->if_mh, NULL, nmp);
check_if = B_FALSE;
D3(vswp, "%s: sending up stack"
" for addr 0x%llx", __func__,
@@ -5147,7 +5092,7 @@ vsw_forward_grp(vsw_t *vswp, mblk_t *mp, int caller, vsw_port_t *arg)
" for addr 0x%llx", __func__, caller, key);
nmp = copymsg(mp);
if (nmp)
- mac_rx(vswp->if_macp, vswp->if_mrh, nmp);
+ mac_rx(vswp->if_mh, NULL, nmp);
} else {
RW_EXIT(&vswp->if_lockrw);
}
diff --git a/usr/src/uts/sun4v/sys/vnet.h b/usr/src/uts/sun4v/sys/vnet.h
index b7b111eb61..c43af5bfab 100644
--- a/usr/src/uts/sun4v/sys/vnet.h
+++ b/usr/src/uts/sun4v/sys/vnet.h
@@ -52,7 +52,7 @@ extern "C" {
*/
typedef struct vp_tl {
struct vp_tl *nextp; /* next in list */
- mac_t *macp; /* transport ops */
+ mac_register_t *macp; /* transport ops */
char name[LIFNAMSIZ]; /* device name */
major_t major; /* driver major # */
uint_t instance; /* dev instance */
@@ -101,7 +101,7 @@ typedef struct vnet {
int instance; /* instance # */
dev_info_t *dip; /* dev_info */
struct vnet *nextp; /* next in list */
- mac_t *macp; /* MAC - macinfo */
+ mac_handle_t mh; /* handle to GLDv3 mac module */
uchar_t vendor_addr[ETHERADDRL]; /* orig macadr */
uchar_t curr_macaddr[ETHERADDRL]; /* current macadr */
vp_tl_t *tlp; /* list of vp_tl */
diff --git a/usr/src/uts/sun4v/sys/vnet_gen.h b/usr/src/uts/sun4v/sys/vnet_gen.h
index 77a088fcb0..c6ad5fe8c0 100644
--- a/usr/src/uts/sun4v/sys/vnet_gen.h
+++ b/usr/src/uts/sun4v/sys/vnet_gen.h
@@ -318,16 +318,14 @@ typedef struct vgen_portlist {
typedef struct vgen {
void *vnetp; /* associated vnet instance */
dev_info_t *vnetdip; /* dip of vnet */
- void *vnetmacp; /* mac_t of vnet */
uint8_t macaddr[ETHERADDRL]; /* mac addr of vnet */
- mac_resource_handle_t mrh; /* handle for mac_rx() */
kmutex_t lock; /* synchornize ops */
int flags; /* flags */
vgen_portlist_t vgenports; /* Port List */
mdeg_node_spec_t *mdeg_parentp;
mdeg_handle_t mdeg_hdl;
vgen_port_t *vsw_portp; /* port connected to vsw */
- mac_t vgenmac; /* vgen mac ops */
+ mac_register_t *macp; /* vgen mac ops */
struct ether_addr *mctab; /* multicast addr table */
uint32_t mcsize; /* allocated size of mctab */
uint32_t mccount; /* # of valid addrs in mctab */
diff --git a/usr/src/uts/sun4v/sys/vsw.h b/usr/src/uts/sun4v/sys/vsw.h
index d284db9dc6..fccb3c6fb8 100644
--- a/usr/src/uts/sun4v/sys/vsw.h
+++ b/usr/src/uts/sun4v/sys/vsw.h
@@ -366,8 +366,9 @@ typedef struct vsw_ctrl_task {
/*
* State of interface if switch plumbed as network device.
*/
-#define VSW_IF_UP 0x1 /* Interface UP */
-#define VSW_IF_PROMISC 0x2 /* Interface in promiscious mode */
+#define VSW_IF_REG 0x1 /* interface was registered */
+#define VSW_IF_UP 0x2 /* Interface UP */
+#define VSW_IF_PROMISC 0x4 /* Interface in promiscious mode */
#define VSW_U_P(state) \
(state == (VSW_IF_UP | VSW_IF_PROMISC))
@@ -420,8 +421,7 @@ typedef struct vsw {
mdeg_handle_t mdeg_hdl;
/* if configured as an ethernet interface */
- mac_t *if_macp; /* MAC structure */
- mac_resource_handle_t if_mrh;
+ mac_handle_t if_mh; /* MAC handle */
struct ether_addr if_addr; /* interface address */
krwlock_t if_lockrw;
uint8_t if_state; /* interface state */