| /* |
| * 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 2010 Sun Microsystems, Inc. All rights reserved. |
| * Use is subject to license terms. |
| */ |
| |
| /* |
| * MAC Services Module |
| */ |
| |
| #include <sys/types.h> |
| #include <sys/sysmacros.h> |
| #include <sys/stream.h> |
| #include <sys/kstat.h> |
| #include <sys/mac.h> |
| #include <sys/mac_impl.h> |
| #include <sys/mac_client_impl.h> |
| #include <sys/mac_stat.h> |
| #include <sys/mac_soft_ring.h> |
| #include <sys/vlan.h> |
| |
| #define MAC_KSTAT_NAME "mac" |
| #define MAC_KSTAT_CLASS "net" |
| |
| enum mac_stat { |
| MAC_STAT_LCL, |
| MAC_STAT_LCLBYTES, |
| MAC_STAT_INTRS, |
| MAC_STAT_INTRBYTES, |
| MAC_STAT_POLLS, |
| MAC_STAT_POLLBYTES, |
| MAC_STAT_RXSDROPS, |
| MAC_STAT_CHU10, |
| MAC_STAT_CH10T50, |
| MAC_STAT_CHO50, |
| MAC_STAT_BLOCK, |
| MAC_STAT_UNBLOCK, |
| MAC_STAT_TXSDROPS, |
| MAC_STAT_TX_ERRORS, |
| MAC_STAT_MACSPOOFED, |
| MAC_STAT_IPSPOOFED, |
| MAC_STAT_DHCPSPOOFED, |
| MAC_STAT_RESTRICTED, |
| MAC_STAT_DHCPDROPPED, |
| MAC_STAT_MULTIRCVBYTES, |
| MAC_STAT_BRDCSTRCVBYTES, |
| MAC_STAT_MULTIXMTBYTES, |
| MAC_STAT_BRDCSTXMTBYTES |
| }; |
| |
| 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_UNDERFLOWS, "uflo", KSTAT_DATA_UINT32, 0 }, |
| { MAC_STAT_OVERFLOWS, "oflo", 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 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 |
| |
| /* |
| * Definitions for per rx ring statistics |
| */ |
| static mac_stat_info_t i_mac_rx_ring_si[] = { |
| { MAC_STAT_RBYTES, "rbytes", KSTAT_DATA_UINT64, 0}, |
| { MAC_STAT_IPACKETS, "ipackets", KSTAT_DATA_UINT64, 0}, |
| { MAC_STAT_HDROPS, "hdrops", KSTAT_DATA_UINT64, 0} |
| }; |
| #define MAC_RX_RING_NKSTAT \ |
| (sizeof (i_mac_rx_ring_si) / sizeof (mac_stat_info_t)) |
| |
| /* |
| * Definitions for per tx ring statistics |
| */ |
| static mac_stat_info_t i_mac_tx_ring_si[] = { |
| { MAC_STAT_OBYTES, "obytes", KSTAT_DATA_UINT64, 0}, |
| { MAC_STAT_OPACKETS, "opackets", KSTAT_DATA_UINT64, 0} |
| }; |
| #define MAC_TX_RING_NKSTAT \ |
| (sizeof (i_mac_tx_ring_si) / sizeof (mac_stat_info_t)) |
| |
| |
| /* |
| * Definitions for per software lane tx statistics |
| */ |
| static mac_stat_info_t i_mac_tx_swlane_si[] = { |
| { MAC_STAT_OBYTES, "obytes", KSTAT_DATA_UINT64, 0}, |
| { MAC_STAT_OPACKETS, "opackets", KSTAT_DATA_UINT64, 0}, |
| { MAC_STAT_OERRORS, "oerrors", KSTAT_DATA_UINT64, 0}, |
| { MAC_STAT_BLOCK, "blockcnt", KSTAT_DATA_UINT64, 0}, |
| { MAC_STAT_UNBLOCK, "unblockcnt", KSTAT_DATA_UINT64, 0}, |
| { MAC_STAT_TXSDROPS, "txsdrops", KSTAT_DATA_UINT64, 0} |
| }; |
| #define MAC_TX_SWLANE_NKSTAT \ |
| (sizeof (i_mac_tx_swlane_si) / sizeof (mac_stat_info_t)) |
| |
| /* |
| * Definitions for per software lane rx statistics |
| */ |
| static mac_stat_info_t i_mac_rx_swlane_si[] = { |
| { MAC_STAT_IPACKETS, "ipackets", KSTAT_DATA_UINT64, 0}, |
| { MAC_STAT_RBYTES, "rbytes", KSTAT_DATA_UINT64, 0}, |
| { MAC_STAT_LCL, "local", KSTAT_DATA_UINT64, 0}, |
| { MAC_STAT_LCLBYTES, "localbytes", KSTAT_DATA_UINT64, 0}, |
| { MAC_STAT_INTRS, "intrs", KSTAT_DATA_UINT64, 0}, |
| { MAC_STAT_INTRBYTES, "intrbytes", KSTAT_DATA_UINT64, 0}, |
| { MAC_STAT_RXSDROPS, "rxsdrops", KSTAT_DATA_UINT64, 0} |
| }; |
| #define MAC_RX_SWLANE_NKSTAT \ |
| (sizeof (i_mac_rx_swlane_si) / sizeof (mac_stat_info_t)) |
| |
| /* |
| * Definitions for per hardware lane rx statistics |
| */ |
| static mac_stat_info_t i_mac_rx_hwlane_si[] = { |
| { MAC_STAT_IPACKETS, "ipackets", KSTAT_DATA_UINT64, 0}, |
| { MAC_STAT_RBYTES, "rbytes", KSTAT_DATA_UINT64, 0}, |
| { MAC_STAT_INTRS, "intrs", KSTAT_DATA_UINT64, 0}, |
| { MAC_STAT_INTRBYTES, "intrbytes", KSTAT_DATA_UINT64, 0}, |
| { MAC_STAT_POLLS, "polls", KSTAT_DATA_UINT64, 0}, |
| { MAC_STAT_POLLBYTES, "pollbytes", KSTAT_DATA_UINT64, 0}, |
| { MAC_STAT_RXSDROPS, "rxsdrops", KSTAT_DATA_UINT64, 0}, |
| { MAC_STAT_CHU10, "chainunder10", KSTAT_DATA_UINT64, 0}, |
| { MAC_STAT_CH10T50, "chain10to50", KSTAT_DATA_UINT64, 0}, |
| { MAC_STAT_CHO50, "chainover50", KSTAT_DATA_UINT64, 0} |
| }; |
| #define MAC_RX_HWLANE_NKSTAT \ |
| (sizeof (i_mac_rx_hwlane_si) / sizeof (mac_stat_info_t)) |
| |
| /* |
| * Definitions for misc statistics |
| */ |
| static mac_stat_info_t i_mac_misc_si[] = { |
| { MAC_STAT_MULTIRCV, "multircv", KSTAT_DATA_UINT64, 0}, |
| { MAC_STAT_BRDCSTRCV, "brdcstrcv", KSTAT_DATA_UINT64, 0}, |
| { MAC_STAT_MULTIXMT, "multixmt", KSTAT_DATA_UINT64, 0}, |
| { MAC_STAT_BRDCSTXMT, "brdcstxmt", KSTAT_DATA_UINT64, 0}, |
| { MAC_STAT_MULTIRCVBYTES, "multircvbytes", KSTAT_DATA_UINT64, 0}, |
| { MAC_STAT_BRDCSTRCVBYTES, "brdcstrcvbytes", KSTAT_DATA_UINT64, 0}, |
| { MAC_STAT_MULTIXMTBYTES, "multixmtbytes", KSTAT_DATA_UINT64, 0}, |
| { MAC_STAT_BRDCSTXMTBYTES, "brdcstxmtbytes", KSTAT_DATA_UINT64, 0}, |
| { MAC_STAT_TX_ERRORS, "txerrors", KSTAT_DATA_UINT64, 0}, |
| { MAC_STAT_MACSPOOFED, "macspoofed", KSTAT_DATA_UINT64, 0}, |
| { MAC_STAT_IPSPOOFED, "ipspoofed", KSTAT_DATA_UINT64, 0}, |
| { MAC_STAT_DHCPSPOOFED, "dhcpspoofed", KSTAT_DATA_UINT64, 0}, |
| { MAC_STAT_RESTRICTED, "restricted", KSTAT_DATA_UINT64, 0}, |
| { MAC_STAT_DHCPDROPPED, "dhcpdropped", KSTAT_DATA_UINT64, 0}, |
| { MAC_STAT_IPACKETS, "ipackets", KSTAT_DATA_UINT64, 0}, |
| { MAC_STAT_RBYTES, "rbytes", KSTAT_DATA_UINT64, 0}, |
| { MAC_STAT_LCL, "local", KSTAT_DATA_UINT64, 0}, |
| { MAC_STAT_LCLBYTES, "localbytes", KSTAT_DATA_UINT64, 0}, |
| { MAC_STAT_INTRS, "intrs", KSTAT_DATA_UINT64, 0}, |
| { MAC_STAT_INTRBYTES, "intrbytes", KSTAT_DATA_UINT64, 0}, |
| { MAC_STAT_POLLS, "polls", KSTAT_DATA_UINT64, 0}, |
| { MAC_STAT_POLLBYTES, "pollbytes", KSTAT_DATA_UINT64, 0}, |
| { MAC_STAT_RXSDROPS, "rxsdrops", KSTAT_DATA_UINT64, 0}, |
| { MAC_STAT_CHU10, "chainunder10", KSTAT_DATA_UINT64, 0}, |
| { MAC_STAT_CH10T50, "chain10to50", KSTAT_DATA_UINT64, 0}, |
| { MAC_STAT_CHO50, "chainover50", KSTAT_DATA_UINT64, 0}, |
| { MAC_STAT_OBYTES, "obytes", KSTAT_DATA_UINT64, 0}, |
| { MAC_STAT_OPACKETS, "opackets", KSTAT_DATA_UINT64, 0}, |
| { MAC_STAT_OERRORS, "oerrors", KSTAT_DATA_UINT64, 0}, |
| { MAC_STAT_BLOCK, "blockcnt", KSTAT_DATA_UINT64, 0}, |
| { MAC_STAT_UNBLOCK, "unblockcnt", KSTAT_DATA_UINT64, 0}, |
| { MAC_STAT_TXSDROPS, "txsdrops", KSTAT_DATA_UINT64, 0} |
| }; |
| #define MAC_SUMMARY_NKSTAT \ |
| (sizeof (i_mac_misc_si) / sizeof (mac_stat_info_t)) |
| |
| /* |
| * Definitions for per hardware lane tx statistics |
| */ |
| static mac_stat_info_t i_mac_tx_hwlane_si[] = { |
| { MAC_STAT_OBYTES, "obytes", KSTAT_DATA_UINT64, 0}, |
| { MAC_STAT_OPACKETS, "opackets", KSTAT_DATA_UINT64, 0}, |
| { MAC_STAT_OERRORS, "oerrors", KSTAT_DATA_UINT64, 0}, |
| { MAC_STAT_BLOCK, "blockcnt", KSTAT_DATA_UINT64, 0}, |
| { MAC_STAT_UNBLOCK, "unblockcnt", KSTAT_DATA_UINT64, 0}, |
| { MAC_STAT_TXSDROPS, "txsdrops", KSTAT_DATA_UINT64, 0} |
| }; |
| #define MAC_TX_HWLANE_NKSTAT \ |
| (sizeof (i_mac_tx_hwlane_si) / sizeof (mac_stat_info_t)) |
| |
| /* |
| * Definitions for per fanout rx statistics |
| */ |
| static mac_stat_info_t i_mac_rx_fanout_si[] = { |
| { MAC_STAT_RBYTES, "rbytes", KSTAT_DATA_UINT64, 0}, |
| { MAC_STAT_IPACKETS, "ipackets", KSTAT_DATA_UINT64, 0}, |
| }; |
| #define MAC_RX_FANOUT_NKSTAT \ |
| (sizeof (i_mac_rx_fanout_si) / sizeof (mac_stat_info_t)) |
| |
| /* |
| * Private functions. |
| */ |
| |
| typedef struct { |
| uint_t si_offset; |
| } stat_info_t; |
| |
| #define RX_SRS_STAT_OFF(f) (offsetof(mac_rx_stats_t, f)) |
| static stat_info_t rx_srs_stats_list[] = { |
| {RX_SRS_STAT_OFF(mrs_lclbytes)}, |
| {RX_SRS_STAT_OFF(mrs_lclcnt)}, |
| {RX_SRS_STAT_OFF(mrs_pollcnt)}, |
| {RX_SRS_STAT_OFF(mrs_pollbytes)}, |
| {RX_SRS_STAT_OFF(mrs_intrcnt)}, |
| {RX_SRS_STAT_OFF(mrs_intrbytes)}, |
| {RX_SRS_STAT_OFF(mrs_sdrops)}, |
| {RX_SRS_STAT_OFF(mrs_chaincntundr10)}, |
| {RX_SRS_STAT_OFF(mrs_chaincnt10to50)}, |
| {RX_SRS_STAT_OFF(mrs_chaincntover50)}, |
| {RX_SRS_STAT_OFF(mrs_ierrors)} |
| }; |
| #define RX_SRS_STAT_SIZE \ |
| (sizeof (rx_srs_stats_list) / sizeof (stat_info_t)) |
| |
| #define TX_SOFTRING_STAT_OFF(f) (offsetof(mac_tx_stats_t, f)) |
| static stat_info_t tx_softring_stats_list[] = { |
| {TX_SOFTRING_STAT_OFF(mts_obytes)}, |
| {TX_SOFTRING_STAT_OFF(mts_opackets)}, |
| {TX_SOFTRING_STAT_OFF(mts_oerrors)}, |
| {TX_SOFTRING_STAT_OFF(mts_blockcnt)}, |
| {TX_SOFTRING_STAT_OFF(mts_unblockcnt)}, |
| {TX_SOFTRING_STAT_OFF(mts_sdrops)}, |
| }; |
| #define TX_SOFTRING_STAT_SIZE \ |
| (sizeof (tx_softring_stats_list) / sizeof (stat_info_t)) |
| |
| static void |
| i_mac_add_stats(void *sum, void *op1, void *op2, |
| stat_info_t stats_list[], uint_t size) |
| { |
| int i; |
| |
| for (i = 0; i < size; i++) { |
| uint64_t *op1_val = (uint64_t *) |
| ((uchar_t *)op1 + stats_list[i].si_offset); |
| uint64_t *op2_val = (uint64_t *) |
| ((uchar_t *)op2 + stats_list[i].si_offset); |
| uint64_t *sum_val = (uint64_t *) |
| ((uchar_t *)sum + stats_list[i].si_offset); |
| |
| *sum_val = *op1_val + *op2_val; |
| } |
| } |
| |
| static int |
| i_mac_driver_stat_update(kstat_t *ksp, int rw) |
| { |
| mac_impl_t *mip = ksp->ks_private; |
| 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); |
| |
| 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; |
| } |
| |
| 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; |
| case KSTAT_DATA_UINT32: |
| knp->value.ui32 = (uint32_t)val; |
| break; |
| default: |
| ASSERT(B_FALSE); |
| break; |
| } |
| |
| knp++; |
| } |
| |
| 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++; |
| } |
| } |
| |
| static int |
| i_mac_stat_update(kstat_t *ksp, int rw, uint64_t (*fn)(void *, uint_t), |
| mac_stat_info_t *msi, uint_t count) |
| { |
| kstat_named_t *knp = ksp->ks_data; |
| uint_t i; |
| uint64_t val; |
| |
| if (rw != KSTAT_READ) |
| return (EACCES); |
| |
| for (i = 0; i < count; i++) { |
| val = fn(ksp->ks_private, msi[i].msi_stat); |
| |
| switch (msi[i].msi_type) { |
| case KSTAT_DATA_UINT64: |
| knp->value.ui64 = val; |
| break; |
| case KSTAT_DATA_UINT32: |
| knp->value.ui32 = (uint32_t)val; |
| break; |
| default: |
| ASSERT(B_FALSE); |
| break; |
| } |
| knp++; |
| } |
| return (0); |
| } |
| |
| /* |
| * Create kstat with given name - statname, update function - fn |
| * and initialize it with given names - init_stat_info |
| */ |
| static kstat_t * |
| i_mac_stat_create(void *handle, const char *modname, const char *statname, |
| int (*fn) (kstat_t *, int), |
| mac_stat_info_t *init_stat_info, uint_t count) |
| { |
| kstat_t *ksp; |
| kstat_named_t *knp; |
| |
| ksp = kstat_create(modname, 0, statname, "net", |
| KSTAT_TYPE_NAMED, count, 0); |
| |
| if (ksp == NULL) |
| return (NULL); |
| |
| ksp->ks_update = fn; |
| ksp->ks_private = handle; |
| |
| knp = (kstat_named_t *)ksp->ks_data; |
| i_mac_kstat_init(knp, init_stat_info, count); |
| kstat_install(ksp); |
| |
| return (ksp); |
| } |
| |
| /* |
| * Per rx ring statistics |
| */ |
| uint64_t |
| mac_rx_ring_stat_get(void *handle, uint_t stat) |
| { |
| mac_ring_t *ring = (mac_ring_t *)handle; |
| uint64_t val = 0; |
| |
| /* |
| * XXX Every ring-capable driver must implement an entry point to |
| * query per ring statistics. CR 6893122 tracks this work item. |
| * Once this bug is fixed, the framework should fail registration |
| * for a driver that does not implement this entry point and |
| * assert ring->mr_stat != NULL here. |
| */ |
| if (ring->mr_stat != NULL) |
| ring->mr_stat(ring->mr_driver, stat, &val); |
| |
| return (val); |
| } |
| |
| static int |
| i_mac_rx_ring_stat_update(kstat_t *ksp, int rw) |
| { |
| return (i_mac_stat_update(ksp, rw, mac_rx_ring_stat_get, |
| i_mac_rx_ring_si, MAC_RX_RING_NKSTAT)); |
| } |
| |
| static void |
| i_mac_rx_ring_stat_create(mac_ring_t *ring, const char *modname, |
| const char *statname) |
| { |
| kstat_t *ksp; |
| |
| ksp = i_mac_stat_create(ring, modname, statname, |
| i_mac_rx_ring_stat_update, i_mac_rx_ring_si, MAC_RX_RING_NKSTAT); |
| |
| ring->mr_ksp = ksp; |
| } |
| |
| /* |
| * Per tx ring statistics |
| */ |
| uint64_t |
| mac_tx_ring_stat_get(void *handle, uint_t stat) |
| { |
| mac_ring_t *ring = (mac_ring_t *)handle; |
| uint64_t val = 0; |
| |
| /* |
| * XXX Every ring-capable driver must implement an entry point to |
| * query per ring statistics. CR 6893122 tracks this work item. |
| * Once this bug is fixed, the framework should fail registration |
| * for a driver that does not implement this entry point and |
| * assert ring->mr_stat != NULL here. |
| */ |
| if (ring->mr_stat != NULL) |
| ring->mr_stat(ring->mr_driver, stat, &val); |
| |
| return (val); |
| } |
| |
| static int |
| i_mac_tx_ring_stat_update(kstat_t *ksp, int rw) |
| { |
| return (i_mac_stat_update(ksp, rw, mac_tx_ring_stat_get, |
| i_mac_tx_ring_si, MAC_TX_RING_NKSTAT)); |
| } |
| |
| static void |
| i_mac_tx_ring_stat_create(mac_ring_t *ring, const char *modname, |
| const char *statname) |
| { |
| kstat_t *ksp; |
| |
| ksp = i_mac_stat_create(ring, modname, statname, |
| i_mac_tx_ring_stat_update, i_mac_tx_ring_si, MAC_TX_RING_NKSTAT); |
| |
| ring->mr_ksp = ksp; |
| } |
| |
| /* |
| * Per software lane tx statistics |
| */ |
| static uint64_t |
| i_mac_tx_swlane_stat_get(void *handle, uint_t stat) |
| { |
| mac_soft_ring_set_t *mac_srs = (mac_soft_ring_set_t *)handle; |
| mac_tx_stats_t *mac_tx_stat = &mac_srs->srs_tx.st_stat; |
| |
| switch (stat) { |
| case MAC_STAT_OBYTES: |
| return (mac_tx_stat->mts_obytes); |
| |
| case MAC_STAT_OPACKETS: |
| return (mac_tx_stat->mts_opackets); |
| |
| case MAC_STAT_OERRORS: |
| return (mac_tx_stat->mts_oerrors); |
| |
| case MAC_STAT_BLOCK: |
| return (mac_tx_stat->mts_blockcnt); |
| |
| case MAC_STAT_UNBLOCK: |
| return (mac_tx_stat->mts_unblockcnt); |
| |
| case MAC_STAT_TXSDROPS: |
| return (mac_tx_stat->mts_sdrops); |
| |
| default: |
| return (0); |
| } |
| } |
| |
| static int |
| i_mac_tx_swlane_stat_update(kstat_t *ksp, int rw) |
| { |
| return (i_mac_stat_update(ksp, rw, i_mac_tx_swlane_stat_get, |
| i_mac_tx_swlane_si, MAC_TX_SWLANE_NKSTAT)); |
| } |
| |
| static void |
| i_mac_tx_swlane_stat_create(mac_soft_ring_set_t *mac_srs, const char *modname, |
| const char *statname) |
| { |
| kstat_t *ksp; |
| |
| ksp = i_mac_stat_create(mac_srs, modname, statname, |
| i_mac_tx_swlane_stat_update, i_mac_tx_swlane_si, |
| MAC_TX_SWLANE_NKSTAT); |
| |
| mac_srs->srs_ksp = ksp; |
| } |
| |
| /* |
| * Per software lane rx statistics |
| */ |
| static uint64_t |
| i_mac_rx_swlane_stat_get(void *handle, uint_t stat) |
| { |
| mac_soft_ring_set_t *mac_srs = (mac_soft_ring_set_t *)handle; |
| mac_rx_stats_t *mac_rx_stat = &mac_srs->srs_rx.sr_stat; |
| |
| switch (stat) { |
| case MAC_STAT_IPACKETS: |
| return (mac_rx_stat->mrs_intrcnt + |
| mac_rx_stat->mrs_lclcnt); |
| |
| case MAC_STAT_RBYTES: |
| return (mac_rx_stat->mrs_intrbytes + |
| mac_rx_stat->mrs_lclbytes); |
| |
| case MAC_STAT_LCL: |
| return (mac_rx_stat->mrs_lclcnt); |
| |
| case MAC_STAT_LCLBYTES: |
| return (mac_rx_stat->mrs_lclbytes); |
| |
| case MAC_STAT_INTRS: |
| return (mac_rx_stat->mrs_intrcnt); |
| |
| case MAC_STAT_INTRBYTES: |
| return (mac_rx_stat->mrs_intrbytes); |
| |
| case MAC_STAT_RXSDROPS: |
| return (mac_rx_stat->mrs_sdrops); |
| |
| default: |
| return (0); |
| } |
| } |
| |
| static int |
| i_mac_rx_swlane_stat_update(kstat_t *ksp, int rw) |
| { |
| return (i_mac_stat_update(ksp, rw, i_mac_rx_swlane_stat_get, |
| i_mac_rx_swlane_si, MAC_RX_SWLANE_NKSTAT)); |
| } |
| |
| static void |
| i_mac_rx_swlane_stat_create(mac_soft_ring_set_t *mac_srs, const char *modname, |
| const char *statname) |
| { |
| kstat_t *ksp; |
| |
| ksp = i_mac_stat_create(mac_srs, modname, statname, |
| i_mac_rx_swlane_stat_update, i_mac_rx_swlane_si, |
| MAC_RX_SWLANE_NKSTAT); |
| |
| mac_srs->srs_ksp = ksp; |
| } |
| |
| |
| /* |
| * Per hardware lane rx statistics |
| */ |
| static uint64_t |
| i_mac_rx_hwlane_stat_get(void *handle, uint_t stat) |
| { |
| mac_soft_ring_set_t *mac_srs = (mac_soft_ring_set_t *)handle; |
| mac_rx_stats_t *mac_rx_stat = &mac_srs->srs_rx.sr_stat; |
| |
| switch (stat) { |
| case MAC_STAT_IPACKETS: |
| return (mac_rx_stat->mrs_intrcnt + |
| mac_rx_stat->mrs_pollcnt); |
| |
| case MAC_STAT_RBYTES: |
| return (mac_rx_stat->mrs_intrbytes + |
| mac_rx_stat->mrs_pollbytes); |
| |
| case MAC_STAT_INTRS: |
| return (mac_rx_stat->mrs_intrcnt); |
| |
| case MAC_STAT_INTRBYTES: |
| return (mac_rx_stat->mrs_intrbytes); |
| |
| case MAC_STAT_POLLS: |
| return (mac_rx_stat->mrs_pollcnt); |
| |
| case MAC_STAT_POLLBYTES: |
| return (mac_rx_stat->mrs_pollbytes); |
| |
| case MAC_STAT_RXSDROPS: |
| return (mac_rx_stat->mrs_sdrops); |
| |
| case MAC_STAT_CHU10: |
| return (mac_rx_stat->mrs_chaincntundr10); |
| |
| case MAC_STAT_CH10T50: |
| return (mac_rx_stat->mrs_chaincnt10to50); |
| |
| case MAC_STAT_CHO50: |
| return (mac_rx_stat->mrs_chaincntover50); |
| |
| default: |
| return (0); |
| } |
| } |
| |
| static int |
| i_mac_rx_hwlane_stat_update(kstat_t *ksp, int rw) |
| { |
| return (i_mac_stat_update(ksp, rw, i_mac_rx_hwlane_stat_get, |
| i_mac_rx_hwlane_si, MAC_RX_HWLANE_NKSTAT)); |
| } |
| |
| static void |
| i_mac_rx_hwlane_stat_create(mac_soft_ring_set_t *mac_srs, const char *modname, |
| const char *statname) |
| { |
| kstat_t *ksp; |
| |
| ksp = i_mac_stat_create(mac_srs, modname, statname, |
| i_mac_rx_hwlane_stat_update, i_mac_rx_hwlane_si, |
| MAC_RX_HWLANE_NKSTAT); |
| |
| mac_srs->srs_ksp = ksp; |
| } |
| |
| |
| /* |
| * Misc statistics |
| * |
| * Counts for |
| * - Multicast/broadcast Rx/Tx counts |
| * - Tx errors |
| */ |
| static uint64_t |
| i_mac_misc_stat_get(void *handle, uint_t stat) |
| { |
| flow_entry_t *flent = handle; |
| mac_client_impl_t *mcip = flent->fe_mcip; |
| mac_misc_stats_t *mac_misc_stat = &mcip->mci_misc_stat; |
| mac_rx_stats_t *mac_rx_stat; |
| mac_tx_stats_t *mac_tx_stat; |
| |
| mac_rx_stat = &mac_misc_stat->mms_defunctrxlanestats; |
| mac_tx_stat = &mac_misc_stat->mms_defuncttxlanestats; |
| |
| switch (stat) { |
| case MAC_STAT_MULTIRCV: |
| return (mac_misc_stat->mms_multircv); |
| |
| case MAC_STAT_BRDCSTRCV: |
| return (mac_misc_stat->mms_brdcstrcv); |
| |
| case MAC_STAT_MULTIXMT: |
| return (mac_misc_stat->mms_multixmt); |
| |
| case MAC_STAT_BRDCSTXMT: |
| return (mac_misc_stat->mms_brdcstxmt); |
| |
| case MAC_STAT_MULTIRCVBYTES: |
| return (mac_misc_stat->mms_multircvbytes); |
| |
| case MAC_STAT_BRDCSTRCVBYTES: |
| return (mac_misc_stat->mms_brdcstrcvbytes); |
| |
| case MAC_STAT_MULTIXMTBYTES: |
| return (mac_misc_stat->mms_multixmtbytes); |
| |
| case MAC_STAT_BRDCSTXMTBYTES: |
| return (mac_misc_stat->mms_brdcstxmtbytes); |
| |
| case MAC_STAT_TX_ERRORS: |
| return (mac_misc_stat->mms_txerrors); |
| |
| case MAC_STAT_MACSPOOFED: |
| return (mac_misc_stat->mms_macspoofed); |
| |
| case MAC_STAT_IPSPOOFED: |
| return (mac_misc_stat->mms_ipspoofed); |
| |
| case MAC_STAT_DHCPSPOOFED: |
| return (mac_misc_stat->mms_dhcpspoofed); |
| |
| case MAC_STAT_RESTRICTED: |
| return (mac_misc_stat->mms_restricted); |
| |
| case MAC_STAT_DHCPDROPPED: |
| return (mac_misc_stat->mms_dhcpdropped); |
| |
| case MAC_STAT_IPACKETS: |
| return (mac_rx_stat->mrs_intrcnt + |
| mac_rx_stat->mrs_pollcnt); |
| |
| case MAC_STAT_RBYTES: |
| return (mac_rx_stat->mrs_intrbytes + |
| mac_rx_stat->mrs_pollbytes); |
| |
| case MAC_STAT_LCL: |
| return (mac_rx_stat->mrs_lclcnt); |
| |
| case MAC_STAT_LCLBYTES: |
| return (mac_rx_stat->mrs_lclbytes); |
| |
| case MAC_STAT_INTRS: |
| return (mac_rx_stat->mrs_intrcnt); |
| |
| case MAC_STAT_INTRBYTES: |
| return (mac_rx_stat->mrs_intrbytes); |
| |
| case MAC_STAT_POLLS: |
| return (mac_rx_stat->mrs_pollcnt); |
| |
| case MAC_STAT_POLLBYTES: |
| return (mac_rx_stat->mrs_pollbytes); |
| |
| case MAC_STAT_RXSDROPS: |
| return (mac_rx_stat->mrs_sdrops); |
| |
| case MAC_STAT_CHU10: |
| return (mac_rx_stat->mrs_chaincntundr10); |
| |
| case MAC_STAT_CH10T50: |
| return (mac_rx_stat->mrs_chaincnt10to50); |
| |
| case MAC_STAT_CHO50: |
| return (mac_rx_stat->mrs_chaincntover50); |
| |
| case MAC_STAT_OBYTES: |
| return (mac_tx_stat->mts_obytes); |
| |
| case MAC_STAT_OPACKETS: |
| return (mac_tx_stat->mts_opackets); |
| |
| case MAC_STAT_OERRORS: |
| return (mac_tx_stat->mts_oerrors); |
| |
| case MAC_STAT_BLOCK: |
| return (mac_tx_stat->mts_blockcnt); |
| |
| case MAC_STAT_UNBLOCK: |
| return (mac_tx_stat->mts_unblockcnt); |
| |
| case MAC_STAT_TXSDROPS: |
| return (mac_tx_stat->mts_sdrops); |
| |
| default: |
| return (0); |
| } |
| } |
| |
| static int |
| i_mac_misc_stat_update(kstat_t *ksp, int rw) |
| { |
| return (i_mac_stat_update(ksp, rw, i_mac_misc_stat_get, |
| i_mac_misc_si, MAC_SUMMARY_NKSTAT)); |
| } |
| |
| static void |
| i_mac_misc_stat_create(flow_entry_t *flent, const char *modname, |
| const char *statname) |
| { |
| kstat_t *ksp; |
| |
| ksp = i_mac_stat_create(flent, modname, statname, |
| i_mac_misc_stat_update, i_mac_misc_si, |
| MAC_SUMMARY_NKSTAT); |
| |
| flent->fe_misc_stat_ksp = ksp; |
| } |
| |
| /* |
| * Per hardware lane tx statistics |
| */ |
| static uint64_t |
| i_mac_tx_hwlane_stat_get(void *handle, uint_t stat) |
| { |
| mac_soft_ring_t *ringp = (mac_soft_ring_t *)handle; |
| mac_tx_stats_t *mac_tx_stat = &ringp->s_st_stat; |
| |
| switch (stat) { |
| case MAC_STAT_OBYTES: |
| return (mac_tx_stat->mts_obytes); |
| |
| case MAC_STAT_OPACKETS: |
| return (mac_tx_stat->mts_opackets); |
| |
| case MAC_STAT_OERRORS: |
| return (mac_tx_stat->mts_oerrors); |
| |
| case MAC_STAT_BLOCK: |
| return (mac_tx_stat->mts_blockcnt); |
| |
| case MAC_STAT_UNBLOCK: |
| return (mac_tx_stat->mts_unblockcnt); |
| |
| case MAC_STAT_TXSDROPS: |
| return (mac_tx_stat->mts_sdrops); |
| |
| default: |
| return (0); |
| } |
| } |
| |
| static int |
| i_mac_tx_hwlane_stat_update(kstat_t *ksp, int rw) |
| { |
| return (i_mac_stat_update(ksp, rw, i_mac_tx_hwlane_stat_get, |
| i_mac_tx_hwlane_si, MAC_TX_HWLANE_NKSTAT)); |
| } |
| |
| static void |
| i_mac_tx_hwlane_stat_create(mac_soft_ring_t *ringp, const char *modname, |
| const char *statname) |
| { |
| kstat_t *ksp; |
| |
| ksp = i_mac_stat_create(ringp, modname, statname, |
| i_mac_tx_hwlane_stat_update, i_mac_tx_hwlane_si, |
| MAC_TX_HWLANE_NKSTAT); |
| |
| ringp->s_ring_ksp = ksp; |
| } |
| |
| /* |
| * Per fanout rx statistics |
| */ |
| static uint64_t |
| i_mac_rx_fanout_stat_get(void *handle, uint_t stat) |
| { |
| mac_soft_ring_t *tcp_ringp = (mac_soft_ring_t *)handle; |
| mac_soft_ring_t *udp_ringp = NULL, *oth_ringp = NULL; |
| mac_soft_ring_set_t *mac_srs = tcp_ringp->s_ring_set; |
| int index; |
| uint64_t val; |
| |
| mutex_enter(&mac_srs->srs_lock); |
| /* Extract corresponding udp and oth ring pointers */ |
| for (index = 0; mac_srs->srs_tcp_soft_rings[index] != NULL; index++) { |
| if (mac_srs->srs_tcp_soft_rings[index] == tcp_ringp) { |
| udp_ringp = mac_srs->srs_udp_soft_rings[index]; |
| oth_ringp = mac_srs->srs_oth_soft_rings[index]; |
| break; |
| } |
| } |
| |
| ASSERT((udp_ringp != NULL) && (oth_ringp != NULL)); |
| |
| switch (stat) { |
| case MAC_STAT_RBYTES: |
| val = (tcp_ringp->s_ring_total_rbytes) + |
| (udp_ringp->s_ring_total_rbytes) + |
| (oth_ringp->s_ring_total_rbytes); |
| break; |
| |
| case MAC_STAT_IPACKETS: |
| val = (tcp_ringp->s_ring_total_inpkt) + |
| (udp_ringp->s_ring_total_inpkt) + |
| (oth_ringp->s_ring_total_inpkt); |
| break; |
| |
| default: |
| val = 0; |
| break; |
| } |
| mutex_exit(&mac_srs->srs_lock); |
| return (val); |
| } |
| |
| static int |
| i_mac_rx_fanout_stat_update(kstat_t *ksp, int rw) |
| { |
| return (i_mac_stat_update(ksp, rw, i_mac_rx_fanout_stat_get, |
| i_mac_rx_fanout_si, MAC_RX_FANOUT_NKSTAT)); |
| } |
| |
| static void |
| i_mac_rx_fanout_stat_create(mac_soft_ring_t *ringp, const char *modname, |
| const char *statname) |
| { |
| kstat_t *ksp; |
| |
| ksp = i_mac_stat_create(ringp, modname, statname, |
| i_mac_rx_fanout_stat_update, i_mac_rx_fanout_si, |
| MAC_RX_FANOUT_NKSTAT); |
| |
| ringp->s_ring_ksp = ksp; |
| } |
| |
| /* |
| * 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_driver_stat_create(mac_impl_t *mip) |
| { |
| kstat_t *ksp; |
| kstat_named_t *knp; |
| uint_t count; |
| major_t major = getmajor(mip->mi_phy_dev); |
| |
| count = MAC_MOD_NKSTAT + MAC_NKSTAT + mip->mi_type->mt_statcount; |
| ksp = kstat_create((const char *)ddi_major_to_name(major), |
| getminor(mip->mi_phy_dev) - 1, MAC_KSTAT_NAME, |
| MAC_KSTAT_CLASS, KSTAT_TYPE_NAMED, count, 0); |
| if (ksp == NULL) |
| return; |
| |
| ksp->ks_update = i_mac_driver_stat_update; |
| ksp->ks_private = mip; |
| mip->mi_ksp = ksp; |
| mip->mi_kstat_count = count; |
| |
| knp = (kstat_named_t *)ksp->ks_data; |
| 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); |
| } |
| |
| kstat_install(ksp); |
| } |
| |
| /*ARGSUSED*/ |
| void |
| mac_driver_stat_delete(mac_impl_t *mip) |
| { |
| if (mip->mi_ksp != NULL) { |
| kstat_delete(mip->mi_ksp); |
| mip->mi_ksp = NULL; |
| mip->mi_kstat_count = 0; |
| } |
| } |
| |
| uint64_t |
| mac_driver_stat_default(mac_impl_t *mip, uint_t stat) |
| { |
| uint_t stat_index; |
| |
| if (IS_MAC_STAT(stat)) { |
| stat_index = stat - MAC_STAT_MIN; |
| ASSERT(stat_index < MAC_NKSTAT); |
| return (i_mac_si[stat_index].msi_default); |
| } |
| ASSERT(IS_MACTYPE_STAT(stat)); |
| stat_index = stat - MACTYPE_STAT_MIN; |
| ASSERT(stat_index < mip->mi_type->mt_statcount); |
| return (mip->mi_type->mt_stats[stat_index].msi_default); |
| } |
| |
| void |
| mac_ring_stat_create(mac_ring_t *ring) |
| { |
| mac_impl_t *mip = ring->mr_mip; |
| char statname[MAXNAMELEN]; |
| char modname[MAXNAMELEN]; |
| |
| if (mip->mi_state_flags & MIS_IS_AGGR) { |
| (void) strlcpy(modname, mip->mi_clients_list->mci_name, |
| MAXNAMELEN); |
| } else |
| (void) strlcpy(modname, mip->mi_name, MAXNAMELEN); |
| |
| switch (ring->mr_type) { |
| case MAC_RING_TYPE_RX: |
| (void) snprintf(statname, sizeof (statname), "mac_rx_ring%d", |
| ring->mr_index); |
| i_mac_rx_ring_stat_create(ring, modname, statname); |
| break; |
| |
| case MAC_RING_TYPE_TX: |
| (void) snprintf(statname, sizeof (statname), "mac_tx_ring%d", |
| ring->mr_index); |
| i_mac_tx_ring_stat_create(ring, modname, statname); |
| break; |
| |
| default: |
| ASSERT(B_FALSE); |
| break; |
| } |
| } |
| |
| void |
| mac_srs_stat_create(mac_soft_ring_set_t *mac_srs) |
| { |
| flow_entry_t *flent = mac_srs->srs_flent; |
| char statname[MAXNAMELEN]; |
| boolean_t is_tx_srs; |
| |
| /* No hardware/software lanes for user defined flows */ |
| if ((flent->fe_type & FLOW_USER) != 0) |
| return; |
| |
| is_tx_srs = ((mac_srs->srs_type & SRST_TX) != 0); |
| |
| if (is_tx_srs) { |
| mac_srs_tx_t *srs_tx = &mac_srs->srs_tx; |
| mac_ring_t *ring = srs_tx->st_arg2; |
| |
| if (ring != NULL) { |
| (void) snprintf(statname, sizeof (statname), |
| "mac_tx_hwlane%d", ring->mr_index); |
| } else { |
| (void) snprintf(statname, sizeof (statname), |
| "mac_tx_swlane0"); |
| } |
| i_mac_tx_swlane_stat_create(mac_srs, flent->fe_flow_name, |
| statname); |
| } else { |
| mac_ring_t *ring = mac_srs->srs_ring; |
| |
| if (ring == NULL) { |
| (void) snprintf(statname, sizeof (statname), |
| "mac_rx_swlane0"); |
| i_mac_rx_swlane_stat_create(mac_srs, |
| flent->fe_flow_name, statname); |
| } else { |
| (void) snprintf(statname, sizeof (statname), |
| "mac_rx_hwlane%d", ring->mr_index); |
| i_mac_rx_hwlane_stat_create(mac_srs, |
| flent->fe_flow_name, statname); |
| } |
| } |
| } |
| |
| void |
| mac_misc_stat_create(flow_entry_t *flent) |
| { |
| char statname[MAXNAMELEN]; |
| |
| /* No misc stats for user defined or mcast/bcast flows */ |
| if (((flent->fe_type & FLOW_USER) != 0) || |
| ((flent->fe_type & FLOW_MCAST) != 0)) |
| return; |
| |
| (void) snprintf(statname, sizeof (statname), "mac_misc_stat"); |
| i_mac_misc_stat_create(flent, flent->fe_flow_name, statname); |
| } |
| |
| void |
| mac_soft_ring_stat_create(mac_soft_ring_t *ringp) |
| { |
| mac_soft_ring_set_t *mac_srs = ringp->s_ring_set; |
| flow_entry_t *flent = ringp->s_ring_mcip->mci_flent; |
| mac_ring_t *ring = (mac_ring_t *)ringp->s_ring_tx_arg2; |
| boolean_t is_tx_srs; |
| char statname[MAXNAMELEN]; |
| |
| /* No hardware/software lanes for user defined flows */ |
| if ((flent->fe_type & FLOW_USER) != 0) |
| return; |
| |
| is_tx_srs = ((mac_srs->srs_type & SRST_TX) != 0); |
| if (is_tx_srs) { /* tx side hardware lane */ |
| ASSERT(ring != NULL); |
| (void) snprintf(statname, sizeof (statname), "mac_tx_hwlane%d", |
| ring->mr_index); |
| i_mac_tx_hwlane_stat_create(ringp, flent->fe_flow_name, |
| statname); |
| } else { /* rx side fanout */ |
| /* Maintain single stat for (tcp, udp, oth) */ |
| if (ringp->s_ring_type & ST_RING_TCP) { |
| int index; |
| mac_soft_ring_t *softring; |
| |
| for (index = 0, softring = mac_srs->srs_soft_ring_head; |
| softring != NULL; |
| index++, softring = softring->s_ring_next) { |
| if (softring == ringp) |
| break; |
| } |
| |
| if (mac_srs->srs_ring == NULL) { |
| (void) snprintf(statname, sizeof (statname), |
| "mac_rx_swlane0_fanout%d", index/3); |
| } else { |
| (void) snprintf(statname, sizeof (statname), |
| "mac_rx_hwlane%d_fanout%d", |
| mac_srs->srs_ring->mr_index, index/3); |
| } |
| i_mac_rx_fanout_stat_create(ringp, flent->fe_flow_name, |
| statname); |
| } |
| } |
| } |
| |
| void |
| mac_ring_stat_delete(mac_ring_t *ring) |
| { |
| if (ring->mr_ksp != NULL) { |
| kstat_delete(ring->mr_ksp); |
| ring->mr_ksp = NULL; |
| } |
| } |
| |
| void |
| mac_srs_stat_delete(mac_soft_ring_set_t *mac_srs) |
| { |
| boolean_t is_tx_srs; |
| |
| is_tx_srs = ((mac_srs->srs_type & SRST_TX) != 0); |
| if (!is_tx_srs) { |
| /* |
| * Rx ring has been taken away. Before destroying corresponding |
| * SRS, save the stats recorded by that SRS. |
| */ |
| mac_client_impl_t *mcip = mac_srs->srs_mcip; |
| mac_misc_stats_t *mac_misc_stat = &mcip->mci_misc_stat; |
| mac_rx_stats_t *mac_rx_stat = &mac_srs->srs_rx.sr_stat; |
| |
| i_mac_add_stats(&mac_misc_stat->mms_defunctrxlanestats, |
| mac_rx_stat, &mac_misc_stat->mms_defunctrxlanestats, |
| rx_srs_stats_list, RX_SRS_STAT_SIZE); |
| } |
| |
| if (mac_srs->srs_ksp != NULL) { |
| kstat_delete(mac_srs->srs_ksp); |
| mac_srs->srs_ksp = NULL; |
| } |
| } |
| |
| void |
| mac_misc_stat_delete(flow_entry_t *flent) |
| { |
| if (flent->fe_misc_stat_ksp != NULL) { |
| kstat_delete(flent->fe_misc_stat_ksp); |
| flent->fe_misc_stat_ksp = NULL; |
| } |
| } |
| |
| void |
| mac_soft_ring_stat_delete(mac_soft_ring_t *ringp) |
| { |
| mac_soft_ring_set_t *mac_srs = ringp->s_ring_set; |
| boolean_t is_tx_srs; |
| |
| is_tx_srs = ((mac_srs->srs_type & SRST_TX) != 0); |
| if (is_tx_srs) { |
| /* |
| * Tx ring has been taken away. Before destroying corresponding |
| * soft ring, save the stats recorded by that soft ring. |
| */ |
| mac_client_impl_t *mcip = mac_srs->srs_mcip; |
| mac_misc_stats_t *mac_misc_stat = &mcip->mci_misc_stat; |
| mac_tx_stats_t *mac_tx_stat = &ringp->s_st_stat; |
| |
| i_mac_add_stats(&mac_misc_stat->mms_defuncttxlanestats, |
| mac_tx_stat, &mac_misc_stat->mms_defuncttxlanestats, |
| tx_softring_stats_list, TX_SOFTRING_STAT_SIZE); |
| } |
| |
| if (ringp->s_ring_ksp) { |
| kstat_delete(ringp->s_ring_ksp); |
| ringp->s_ring_ksp = NULL; |
| } |
| } |
| |
| void |
| mac_pseudo_ring_stat_rename(mac_impl_t *mip) |
| { |
| mac_group_t *group; |
| mac_ring_t *ring; |
| |
| /* Recreate pseudo rx ring kstats */ |
| for (group = mip->mi_rx_groups; group != NULL; |
| group = group->mrg_next) { |
| for (ring = group->mrg_rings; ring != NULL; |
| ring = ring->mr_next) { |
| mac_ring_stat_delete(ring); |
| mac_ring_stat_create(ring); |
| } |
| } |
| |
| /* Recreate pseudo tx ring kstats */ |
| for (group = mip->mi_tx_groups; group != NULL; |
| group = group->mrg_next) { |
| for (ring = group->mrg_rings; ring != NULL; |
| ring = ring->mr_next) { |
| mac_ring_stat_delete(ring); |
| mac_ring_stat_create(ring); |
| } |
| } |
| } |
| |
| void |
| mac_stat_rename(mac_client_impl_t *mcip) |
| { |
| flow_entry_t *flent = mcip->mci_flent; |
| mac_soft_ring_set_t *mac_srs; |
| mac_soft_ring_t *ringp; |
| int i, j; |
| |
| ASSERT(flent != NULL); |
| |
| /* Recreate rx SRSes kstats */ |
| for (i = 0; i < flent->fe_rx_srs_cnt; i++) { |
| mac_srs = (mac_soft_ring_set_t *)flent->fe_rx_srs[i]; |
| mac_srs_stat_delete(mac_srs); |
| mac_srs_stat_create(mac_srs); |
| |
| /* Recreate rx fanout kstats */ |
| for (j = 0; j < mac_srs->srs_tcp_ring_count; j++) { |
| ringp = mac_srs->srs_tcp_soft_rings[j]; |
| mac_soft_ring_stat_delete(ringp); |
| mac_soft_ring_stat_create(ringp); |
| } |
| } |
| |
| /* Recreate tx SRS kstats */ |
| mac_srs = (mac_soft_ring_set_t *)flent->fe_tx_srs; |
| mac_srs_stat_delete(mac_srs); |
| mac_srs_stat_create(mac_srs); |
| |
| /* Recreate tx sofring kstats */ |
| for (ringp = mac_srs->srs_soft_ring_head; ringp; |
| ringp = ringp->s_ring_next) { |
| mac_soft_ring_stat_delete(ringp); |
| mac_soft_ring_stat_create(ringp); |
| } |
| |
| /* Recreate misc kstats */ |
| mac_misc_stat_delete(flent); |
| mac_misc_stat_create(flent); |
| } |
| |
| void |
| mac_tx_srs_stat_recreate(mac_soft_ring_set_t *tx_srs, boolean_t add_stats) |
| { |
| mac_client_impl_t *mcip = tx_srs->srs_mcip; |
| mac_misc_stats_t *mac_misc_stat = &mcip->mci_misc_stat; |
| mac_tx_stats_t *mac_tx_stat = &tx_srs->srs_tx.st_stat; |
| |
| if (add_stats) { |
| /* Add the stats to cumulative stats */ |
| i_mac_add_stats(&mac_misc_stat->mms_defuncttxlanestats, |
| mac_tx_stat, &mac_misc_stat->mms_defuncttxlanestats, |
| tx_softring_stats_list, TX_SOFTRING_STAT_SIZE); |
| } |
| |
| bzero(mac_tx_stat, sizeof (mac_tx_stats_t)); |
| mac_srs_stat_delete(tx_srs); |
| mac_srs_stat_create(tx_srs); |
| } |