2N/A * The contents of this file are subject to the terms of the 2N/A * Common Development and Distribution License (the "License"). 2N/A * You may not use this file except in compliance with the License. 2N/A * See the License for the specific language governing permissions 2N/A * and limitations under the License. 2N/A * When distributing Covered Code, include this CDDL HEADER in each 2N/A * If applicable, add the following below this CDDL HEADER, with the 2N/A * fields enclosed by brackets "[]" replaced with your own identifying 2N/A * information: Portions Copyright [yyyy] [name of copyright owner] 2N/A * Copyright (c) 2008, 2012, Oracle and/or its affiliates. All rights reserved. 2N/A * Search for flowlist entry in stattable which matches 2N/A * the flowname and linkid. If no match is found, use 2N/A * next available slot. If no slots are available, 2N/A * reallocate table with more slots. 2N/A * Return: *flowlist of matching flow 2N/A * NULL if realloc fails 2N/A /* Look for match in the stattable */ 2N/A /* match the flowname */ 2N/A /* match the linkid */ 2N/A * No match found in the table. Store statistics in the next slot. 2N/A * If necessary, make room for this entry. 2N/A /* need to check err code, if zone is halt */ 2N/A /* lookup kstat entry */ 2N/A /* read packet and byte stats */ 2N/A * This function is called through the dladm_walk_datalink_id() walker and 2N/A * calls the dladm_walk_flow() walker. 2N/A /* find the flist entry */ 2N/A /* lookup kstat entry */ 2N/A /* read packet and byte stats */ 2N/A /* Install signal handlers */ 2N/A /* Initialize ncurses */ 2N/A /* Handle window resizes */ 2N/A "iKb/s",
"oKb/s",
"iPk/s",
"oPk/s");
2N/A /* Print stats for each link or flow */ 2N/A /* Display all links */ 2N/A /* Display 1 link */ 2N/A /* Display 1 flow */ 2N/A /* Display all flows on all links */ 2N/A /* Display all flows on a link */ 2N/A/* Exported functions */ 2N/A * Continuously display link or flow statstics using a libcurses 2N/A warn(
"kstat open operation failed");
2N/A * dladm_kstat_lookup() is a modified version of kstat_lookup which 2N/A * adds the class as a selector. 2N/A * For zonename prefixed linknames retrieve the linkname 2N/A * and set kstats instance to the zone ID. zonename prefixed 2N/A * linknames refer to NGZ datalinks and their kstats are 2N/A * exposed in the GZ under instance set to the zone ID. 2N/A * Callers can pass the linkname in either the module 2N/A * or name argument, the instance can be 0 or -1. 2N/A * dladm_get_stats() populates the supplied pktsum_t structure with 2N/A * the input and output packet and byte kstats from the kstat_t 2N/A * found with dladm_kstat_lookup. 2N/A warn(
"kstat_open operation failed");
2N/A * The kstat query could fail if the underlying MAC 2N/A * driver was already detached. 2N/A/* Compute sum of 2 pktsums (s1 = s2 + s3) */ 2N/A/* Compute differences between 2 pktsums (s1 = s2 - s3) */ 2N/A/* Definitions for rx lane stats */ 2N/A/* Definitions for tx lane stats */ 2N/A/* Definitions for tx/rx link stats */ 2N/A/* Definitions for rx ring stats */ 2N/A/* Definitions for tx ring stats */ 2N/A/* Definitions for total stats */ 2N/A/* Definitions for aggr stats */ 2N/A/* Definitions for VDP stats */ 2N/A/* Definitions for ECP stats */ 2N/A/* Definitions for flow stats */ 2N/A/* Rx lane specific functions */ 2N/A/* Tx lane specific functions */ 2N/A/* Rx lane total specific functions */ 2N/A/* Tx lane total specific functions */ 2N/A/* Rx ring specific functions */ 2N/A/* Tx ring specific functions */ 2N/A/* Rx ring total specific functions */ 2N/A/* Tx ring total specific functions */ 2N/A/* Summary specific functions */ 2N/A/* Aggr port specific functions */ 2N/A/* VDP specific functions */ 2N/A/* ECP specific functions */ 2N/A/* Link stat specific functions */ 2N/A * dladm_stat_table has one entry for each supported stat. ds_querystat returns 2N/A * a chain of 'stat entries' for the queried stat. 2N/A * Each stat entry has set of identifiers (ids) and an object containing actual 2N/A * stat values. These stat entry objects are chained together in a linked list 2N/A * of datatype dladm_stat_chain_t. Head of this list is returned to the caller 2N/A * of dladm_link_stat_query. 2N/A * One node in the chain is shown below: 2N/A * ------------------------- 2N/A * | -------------- | 2N/A * | -------------- | 2N/A * | | stat fields | | 2N/A * | -------------- | 2N/A * ------------------------- 2N/A * | dc_next ---------|------> to next stat entry 2N/A * ------------------------- 2N/A * In particular, for query DLADM_STAT_RX_LANE, dc_statentry carries pointer to 2N/A * object of type rx_lane_stat_entry_t. 2N/A * dladm_link_stat_query_all returns similar chain. However, instead of storing 2N/A * stat fields as raw numbers, it stores those as chain of <name, value> pairs. 2N/A * The resulting structure is depicted below: 2N/A * ------------------------- 2N/A * | -------------- | --------------- 2N/A * | | nv_header | | | name, val | 2N/A * | -------------- | --------------- 2N/A * | | nve_stats---|----|-->| nv_nextstat--|---> to next name, val pair 2N/A * | -------------- | --------------- 2N/A * ------------------------- 2N/A * | dc_next ---------|------> to next stat entry 2N/A * ------------------------- 2N/A * We don't support -i <interval> for all link stat query. Several table fields 2N/A * are left uninitialized thus. 2N/A/* Internal functions */ 2N/A/* Diff between two stats */ 2N/A * Perform diff = s1 - s2, where diff, s1, s2 are structure objects of same 2N/A * datatype. slist is list of offsets of the fields within the structure. 2N/A/* Given a linkid, resolve kstat name for querying link level stats */ 2N/A /* Query underlying datalink's (if applicable) link id */ 2N/A /* Query underlying datalink's name (could be vanity name) */ 2N/A /* Resolve vanity name to phys name */ 2N/A/* Given a linkid, resolve kstat name for querying phys level stats */ 2N/A * kstats corresponding to physical device rings continue to use 2N/A * device names even if the link is renamed using dladm rename-link. 2N/A * Thus, given a linkid, we lookup the physical device name. 2N/A * However, if an aggr is renamed, kstats corresponding to its 2N/A * pseudo rings are renamed as well. 2N/A /* Resolve vanity name to phys name */ 2N/A/* Look up kstat value */ 2N/A/* Append linked list list1 to linked list list2 and return resulting list */ 2N/A /* list1 has at least one element, find last element in list1 */ 2N/A/* Support for legacy drivers */ 2N/A /* Query for dls stats */ 2N/A /* Convert to desired data type */ 2N/A /* Allocate memory for wrapper */ 2N/A /* Query for dls stats */ 2N/A /* Convert to desired data type */ 2N/A /* Allocate memory for wrapper */ 2N/A warn(
"kstat_open operation failed");
2N/A/* Rx lane statistic specific functions */ 2N/A * For every hardware ring dedicated to a datalink, the datalink is said 2N/A * to have a hardware lane (hwlane). During the lifetime of a device 2N/A * instance (from device attach till detach), a device ring could be 2N/A * used by different datalinks (primary, vnics, vlans etc.). However, 2N/A * hwlane kstats are created only once - when the rings are initialized 2N/A * by the device attach. Thus, these kstats are *not* recreated even if 2N/A * a ring is moved from one datalink to another. 2N/A * These "persistent" (for the lifetime of device) kstats are named 2N/A * using the name of the underlying datalink and the id corresponding 2N/A * to the hardware ring. Thus, hwlane stat query on a datalink needs to 2N/A * dig in this information before it can issue a kstat query. 2N/A /* Find name of the underlying link */ 2N/A /* Query for ids of dedicated rings for this datalink */ 2N/A /* Check if it is legacy driver */ 2N/A/* Tx lane statistic specific functions */ 2N/A * For every hardware ring dedicated to a datalink, the datalink is said 2N/A * to have a hardware lane (hwlane). During the lifetime of a device 2N/A * instance (from device attach till detach), a device ring could be 2N/A * used by different datalinks (primary, vnics, vlans etc.). However, 2N/A * hwlane kstats are created only once - when the rings are initialized 2N/A * by the device attach. Thus, these kstats are *not* recreated even if 2N/A * a ring is moved from one datalink to another. 2N/A * These "persistent" (for the lifetime of device) kstats are named 2N/A * using the name of the underlying datalink and the id corresponding 2N/A * to the hardware ring. Thus, hwlane stat query on a datalink needs to 2N/A * dig in this information before it can issue a kstat query. 2N/A /* Find the name of the underlying link */ 2N/A /* Query for ids of dedicated rings for this datalink */ 2N/A * Swlane stat counts on-wire unicast traffic only. Thus, 2N/A * swlane = total tx traffic - (local + multicast + broadcast). 2N/A /* Check if it is legacy driver */ 2N/A/* Rx lane total statistic specific functions */ 2N/A /* Query per mcip kstats (don't need to look at the underlying link) */ 2N/A/* Tx lane total statistic specific functions */ 2N/A /* Query per mcip kstats (don't need to look at the underlying link) */ 2N/A/* Rx ring statistic specific functions */ 2N/A/* Tx ring statistic specific functions */ 2N/A warn(
"kstat open operation failed");
2N/A * kstats corresponding to physical device rings continue to use 2N/A * device names even if the link is renamed using dladm rename-link. 2N/A * Thus, given a linkid, we lookup the physical device name. 2N/A * However, if an aggr is renamed, kstats corresponding to its 2N/A * pseudo rings are renamed as well. 2N/A "mac_rx_ring_total" :
"mac_tx_ring_total";
2N/A/* Rx ring total statistic specific functions */ 2N/A/* Tx ring total statistic specific functions */ 2N/A/* Summary statistic specific functions */ 2N/A{
/* Always single entry for total */ 2N/A /* Get total rx lane stats */ 2N/A /* Get total tx lane stats */ 2N/A /* Build total stat */ 2N/A /* Extract total rx ipackets, rbytes */ 2N/A /* Extract total tx opackets, obytes */ 2N/A /* Get total rx ring stats */ 2N/A /* Get total tx ring stats */ 2N/A /* Build total stat */ 2N/A /* Extract total rx ipackets, rbytes */ 2N/A /* Extract total tx opackets, obytes */ 2N/A/* Aggr total statistic(summed across all component ports) specific functions */ 2N/A/* Aggr port statistic specific functions */ 2N/A * Query dls stats for the aggr port. This results in query for stats into 2N/A * the corresponding device driver. 2N/A warn(
"kstat open operation failed");
2N/A /* Save port's linkid */ 2N/A /* For every port that is member of this aggr do */ 2N/A /* Create dladm_stat_chain_t object for this stat */ 2N/A /* Chain this aggr port stat entry */ 2N/A /* head of the stat list */ 2N/A * Prepend the stat list with cumulative aggr stats i.e. summed over all 2N/A/* Link stat specific functions */ 2N/A/* VDP statistic specific functions */ 2N/A /* Create dladm_stat_chain_t object for this stat */ 2N/A/* ECP statistic specific functions */ 2N/A /* Create dladm_stat_chain_t object for this stat */ 2N/A/* Exported functions */ 2N/A /* Perform op1 - op2, store result in diff */ 2N/A /* prev iteration did not have this stat entry */ 2N/A/* Query all link stats */ 2N/A /* Allocate memory for query all stat entry */ 2N/A /* Header for these stat fields */ 2N/A /* Extract stat fields from the statentry */ 2N/A /* Convert curr_stat to <statname, statval> pair */ 2N/A * For every stat in the chain, build header and convert all 2N/A /* Query the requested stat */ 2N/A * Convert every statfield in every stat-entry of stat chain to 2N/A * <statname, statval> pair 2N/A /* Free stat_head */ 2N/A/* flow stats specific routines */ 2N/A/* Query all flow stats */ 2N/A /* Query flow stats */ 2N/A /* Allocate memory for query all stat entry */ 2N/A /* Header for these stat fields */ 2N/A /* Convert every statfield in flow_stat to <statname, statval> pair */ 2N/A /* Free flow_stat */