diff options
author | seb <none@none> | 2006-06-30 12:39:57 -0700 |
---|---|---|
committer | seb <none@none> | 2006-06-30 12:39:57 -0700 |
commit | ba2e4443695ee6a6f420a35cd4fc3d3346d22932 (patch) | |
tree | e3ebae9aaeecabfd5304f958583c09efb9b861c4 | |
parent | 17e9c21c2c124e74a7e4a7cd9fcaa3f2d31b7069 (diff) | |
download | illumos-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
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, ðerbroadcastaddr) == 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(ðerbroadcastaddr, 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(ðerbroadcastaddr, 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 */ |