/*
* 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
* 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
*/
/*
*/
#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#include <err.h>
#include <errno.h>
#include <fcntl.h>
#include <kstat.h>
#include <limits.h>
#include <unistd.h>
#include <signal.h>
#include <zone.h>
#include <vdp.h>
#include <vdp_vdpd.h>
#include <door.h>
#include <libdllink.h>
#include <libdlflow.h>
#include <libdlstat.h>
#include <libdlaggr.h>
#include <libinetutil.h>
#include <libdlvnic.h>
/*
* Include curses.h last.
*/
#if defined(ERR)
#endif
#include <curses.h>
struct flowlist {
int fd;
};
/*
* Search for flowlist entry in stattable which matches
* the flowname and linkid. If no match is found, use
* next available slot. If no slots are available,
* reallocate table with more slots.
*
* Return: *flowlist of matching flow
* NULL if realloc fails
*/
static struct flowlist *
{
int match = 0;
/* Look for match in the stattable */
break;
/* match the flowname */
== NULL)
return (flist);
/* match the linkid */
} else {
return (flist);
}
}
/*
* No match found in the table. Store statistics in the next slot.
* If necessary, make room for this entry.
*/
statentry++;
maxstatentries * sizeof (struct flowlist));
perror("realloc");
}
}
return (flist);
}
/*ARGSUSED*/
static void
{
double dlt;
int fcount;
if (first) {
(void) printw("please wait...\n");
return;
}
(void) printw("%9.2f %9.2f %9.2f %9.2f ",
(void) printw("\n");
}
}
}
/*ARGSUSED*/
static int
{
if (flowzoneid == getzoneid()) {
attr->fa_flowname);
} else {
ssize_t s;
/* need to check err code, if zone is halt */
if (s < 0)
return (DLADM_STATUS_NOTFOUND);
}
return (DLADM_WALK_CONTINUE);
/* lookup kstat entry */
return (DLADM_WALK_CONTINUE);
/* read packet and byte stats */
} else {
return (DLADM_WALK_CONTINUE);
}
return (DLADM_WALK_CONTINUE);
}
/*ARGSUSED*/
static void
{
double util;
double dlt;
int fcount;
if (first) {
(void) printw("please wait...\n");
return;
}
(void) printw("%9.2f %9.2f %9.2f %9.2f ",
else
util = (double)0;
(void) printw("\n");
}
}
}
/*
* This function is called through the dladm_walk_datalink_id() walker and
* calls the dladm_walk_flow() walker.
*/
/*ARGSUSED*/
static int
{
if (status == DLADM_STATUS_OK)
return (DLADM_WALK_CONTINUE);
else
return (DLADM_WALK_TERMINATE);
}
/*ARGSUSED*/
static int
{
/* find the flist entry */
return (DLADM_WALK_CONTINUE);
return (DLADM_WALK_CONTINUE);
if (class == DATALINK_CLASS_PHYS) {
return (DLADM_WALK_CONTINUE);
} else {
}
(void) kstat_chain_update(kcp);
}
/* lookup kstat entry */
return (DLADM_WALK_CONTINUE);
/* read packet and byte stats */
} else {
return (DLADM_WALK_CONTINUE);
}
return (DLADM_WALK_CONTINUE);
}
static void
{
int index = 0;
break;
}
}
/*ARGSUSED*/
static void
sig_break(int s)
{
handle_break = 1;
}
/*ARGSUSED*/
static void
sig_resize(int s)
{
handle_resize = 1;
}
static void
{
/* Install signal handlers */
/* Initialize ncurses */
(void) initscr();
(void) cbreak();
(void) noecho();
(void) curs_set(0);
timeout(0);
}
static void
{
(void) printw("\n");
(void) curs_set(1);
(void) nocbreak();
(void) endwin();
}
static void
{
return;
/* Handle window resizes */
if (handle_resize) {
(void) endwin();
(void) initscr();
(void) cbreak();
(void) noecho();
(void) curs_set(0);
timeout(0);
redraw = 1;
handle_resize = 0;
}
/* Print title */
(void) erase();
(void) move(0, 0);
if (opt == FLOW_REPORT)
(void) printw("%9.9s %9.9s %9.9s %9.9s ",
"iKb/s", "oKb/s", "iPk/s", "oPk/s");
if (opt == LINK_REPORT)
(void) printw("\n");
(void) move(2, 0);
/* Print stats for each link or flow */
if (opt == LINK_REPORT) {
/* Display all links */
if (linkid == DATALINK_ALL_LINKID) {
(void *)kcp, DATALINK_CLASS_ALL,
/* Display 1 link */
} else {
}
} else if (opt == FLOW_REPORT) {
/* Display 1 flow */
return;
/* Display all flows on all links */
} else if (linkid == DATALINK_ALL_LINKID) {
(void *)kcp, DATALINK_CLASS_ALL,
/* Display all flows on a link */
} else if (linkid != DATALINK_INVALID_LINKID) {
B_FALSE);
}
/* Print totals */
(void) printw("%9.2f %9.2f %9.2f %9.2f ",
}
if (redraw)
return;
if (redraw) {
redraw = 0;
}
}
/* Exported functions */
/*
* Continuously display link or flow statstics using a libcurses
* based display.
*/
void
{
warn("kstat open operation failed");
return;
}
curses_init();
for (;;) {
if (handle_break)
break;
}
closedevnet();
curses_fin();
(void) kstat_close(kcp);
}
/*
* dladm_kstat_lookup() is a modified version of kstat_lookup which
* adds the class as a selector.
*/
kstat_t *
{
/*
* For zonename prefixed linknames retrieve the linkname
* and set kstats instance to the zone ID. zonename prefixed
* linknames refer to NGZ datalinks and their kstats are
* exposed in the GZ under instance set to the zone ID.
* Callers can pass the linkname in either the module
* or name argument, the instance can be 0 or -1.
*/
NULL) {
ksname = kstat_name;
}
}
return (ksp);
}
return (NULL);
}
/*
* dladm_get_stats() populates the supplied pktsum_t structure with
* the input and output packet and byte kstats from the kstat_t
* found with dladm_kstat_lookup.
*/
void
{
return;
return;
}
return;
}
return;
}
return;
}
return;
}
return;
}
}
int
{
return (-1);
return (-1);
switch (type) {
case KSTAT_DATA_UINT64:
break;
case KSTAT_DATA_UINT32:
break;
default:
return (-1);
}
return (0);
}
{
return (status);
return (DLADM_STATUS_LINKINVAL);
if (status != DLADM_STATUS_OK)
return (status);
return (DLADM_STATUS_LINKINVAL);
warn("kstat_open operation failed");
return (-1);
}
/*
* The kstat query could fail if the underlying MAC
* driver was already detached.
*/
== NULL) {
goto bail;
}
goto bail;
goto bail;
(void) kstat_close(kcp);
return (DLADM_STATUS_OK);
bail:
(void) kstat_close(kcp);
return (dladm_errno2status(errno));
}
/* Compute sum of 2 pktsums (s1 = s2 + s3) */
void
{
}
/* Compute differences between 2 pktsums (s1 = s2 - s3) */
void
{
}
typedef struct {
const char *si_name;
} stat_info_t;
/* Definitions for rx lane stats */
};
};
/* Definitions for tx lane stats */
};
};
/* Definitions for rx ring stats */
};
/* Definitions for tx ring stats */
};
/* Definitions for total stats */
};
/* Definitions for aggr stats */
};
/* Definitions for VDP stats */
};
/* Definitions for ECP stats */
};
/* Definitions for flow stats */
};
/* Rx lane specific functions */
static boolean_t i_dlstat_rx_lane_match(void *, void *);
static void * i_dlstat_rx_lane_stat_entry_diff(void *, void *);
/* Tx lane specific functions */
static boolean_t i_dlstat_tx_lane_match(void *, void *);
static void * i_dlstat_tx_lane_stat_entry_diff(void *, void *);
/* Rx lane total specific functions */
/* Tx lane total specific functions */
/* Rx ring specific functions */
static boolean_t i_dlstat_rx_ring_match(void *, void *);
static void * i_dlstat_rx_ring_stat_entry_diff(void *, void *);
/* Tx ring specific functions */
static boolean_t i_dlstat_tx_ring_match(void *, void *);
static void * i_dlstat_tx_ring_stat_entry_diff(void *, void *);
/* Rx ring total specific functions */
/* Tx ring total specific functions */
/* Summary specific functions */
static boolean_t i_dlstat_total_match(void *, void *);
static void * i_dlstat_total_stat_entry_diff(void *, void *);
/* Aggr port specific functions */
static boolean_t i_dlstat_aggr_port_match(void *, void *);
static void * i_dlstat_aggr_port_stat_entry_diff(void *, void *);
/* VDP specific functions */
static boolean_t i_dlstat_vdp_match(void *, void *);
static void * i_dlstat_vdp_stat_entry_diff(void *, void *);
/* ECP specific functions */
static boolean_t i_dlstat_ecp_match(void *, void *);
static void * i_dlstat_ecp_stat_entry_diff(void *, void *);
/* Link stat specific functions */
typedef void * dladm_stat_diff_t(void *, void *);
typedef struct dladm_stat_desc_s {
/*
* dladm_stat_table has one entry for each supported stat. ds_querystat returns
* a chain of 'stat entries' for the queried stat.
* Each stat entry has set of identifiers (ids) and an object containing actual
* stat values. These stat entry objects are chained together in a linked list
* of datatype dladm_stat_chain_t. Head of this list is returned to the caller
* of dladm_link_stat_query.
*
* One node in the chain is shown below:
*
* -------------------------
* | dc_statentry |
* | -------------- |
* | | ids | |
* | -------------- |
* | | stat fields | |
* | -------------- |
* -------------------------
* | dc_next ---------|------> to next stat entry
* -------------------------
*
* In particular, for query DLADM_STAT_RX_LANE, dc_statentry carries pointer to
* object of type rx_lane_stat_entry_t.
*
* dladm_link_stat_query_all returns similar chain. However, instead of storing
* stat fields as raw numbers, it stores those as chain of <name, value> pairs.
* The resulting structure is depicted below:
*
* -------------------------
* | dc_statentry |
* | -------------- | ---------------
* | | nv_header | | | name, val |
* | -------------- | ---------------
* | | nve_stats---|----|-->| nv_nextstat--|---> to next name, val pair
* | -------------- | ---------------
* -------------------------
* | dc_next ---------|------> to next stat entry
* -------------------------
*/
/*
* We don't support -i <interval> for all link stat query. Several table fields
* are left uninitialized thus.
*/
0,
};
/* Internal functions */
static void *
{
}
static boolean_t
{
}
/* Diff between two stats */
static void
{
int i;
for (i = 0; i < size; i++) {
}
}
/*
* Perform diff = s1 - s2, where diff, s1, s2 are structure objects of same
* datatype. slist is list of offsets of the fields within the structure.
*/
} else { \
} \
}
/* Sum two stats */
static void
{
int i;
for (i = 0; i < size; i++) {
}
}
/* Given a linkid, resolve kstat name for querying link level stats */
static boolean_t
char *modname)
{
/* Query underlying datalink's (if applicable) link id */
/* Query underlying datalink's name (could be vanity name) */
DLPI_LINKNAME_MAX) != DLADM_STATUS_OK) {
return (B_FALSE);
}
if (class == DATALINK_CLASS_ETHERSTUB) {
return (B_FALSE);
}
} else if (class != DATALINK_CLASS_AGGR) {
/* Resolve vanity name to phys name */
return (B_FALSE);
}
}
return (B_TRUE);
}
/* Given a linkid, resolve kstat name for querying phys level stats */
static boolean_t
char *modname)
{
/*
* kstats corresponding to physical device rings continue to use
* device names even if the link is renamed using dladm rename-link.
* Thus, given a linkid, we lookup the physical device name.
* However, if an aggr is renamed, kstats corresponding to its
* pseudo rings are renamed as well.
*/
DLPI_LINKNAME_MAX) != DLADM_STATUS_OK) {
return (B_FALSE);
}
if (class != DATALINK_CLASS_AGGR) {
/* Resolve vanity name to phys name */
return (B_FALSE);
}
}
return (B_TRUE);
}
/* Look up kstat value */
static void
{
int i;
return;
for (i = 0; i < size; i++) {
KSTAT_DATA_UINT64, val) < 0)
return;
}
}
/* Append linked list list1 to linked list list2 and return resulting list */
static dladm_stat_chain_t *
{
return (list2);
/* list1 has at least one element, find last element in list1 */
return (list1);
}
typedef enum {
void
{
int i, j;
return;
for (j = 1; j < size; j++) {
}
}
/* Support for legacy drivers */
void
{
return;
(void) kstat_close(kcp);
}
void *
{
/* Query for dls stats */
/* Convert to desired data type */
if (rx_lane_stat_entry == NULL)
goto done;
/* Allocate memory for wrapper */
goto done;
}
done:
return (head);
}
void *
{
/* Query for dls stats */
/* Convert to desired data type */
if (tx_lane_stat_entry == NULL)
goto done;
/* Allocate memory for wrapper */
goto done;
}
done:
return (head);
}
static void
{
int i;
*psize = 0;
switch (idlist_type) {
case DLSTAT_RX_RING_IDLIST:
case DLSTAT_TX_RING_IDLIST: {
break;
for (i = 0; i < *psize; i++)
idlist[i] = i;
break;
}
case DLSTAT_RX_HWLANE_IDLIST:
case DLSTAT_TX_HWLANE_IDLIST: {
if (idlist_type == DLSTAT_RX_HWLANE_IDLIST) {
} else if (idlist_type == DLSTAT_TX_HWLANE_IDLIST) {
}
break;
}
default:
*psize = 0;
}
}
static dladm_stat_chain_t *
{
int i = 0;
warn("kstat_open operation failed");
return (NULL);
}
for (i = 0; i < idlist_size; i++) {
index);
continue;
break;
break;
}
sizeof (curr->dc_statheader));
else
}
done:
(void) kstat_close(kcp);
return (head);
}
static link_stat_entry_t *
{
return (NULL);
goto done;
if (link_stat_entry == NULL)
goto done;
done:
(void) kstat_close(kcp);
return (link_stat_entry);
}
/* Rx lane statistic specific functions */
static boolean_t
{
}
static void *
{
if (diff_entry == NULL)
goto done;
done:
return (diff_entry);
}
static void *
{
if (rx_lane_stat_entry == NULL)
goto done;
rx_lane_stat_entry->rle_index = i;
done:
return (rx_lane_stat_entry);
}
static dladm_stat_chain_t *
{
if (link_stat_entry == NULL)
goto done;
if (rx_lane_stat_entry == NULL)
goto done;
if (local_stats == NULL) {
goto done;
}
sizeof (local_stats->dc_statheader));
done:
return (local_stats);
}
static dladm_stat_chain_t *
{
if (link_stat_entry == NULL)
goto done;
if (rx_lane_stat_entry == NULL)
goto done;
goto done;
}
sizeof (head->dc_statheader));
done:
return (head);
}
static dladm_stat_chain_t *
{
/*
* For every hardware ring dedicated to a datalink, the datalink is said
* to have a hardware lane (hwlane). During the lifetime of a device
* instance (from device attach till detach), a device ring could be
* used by different datalinks (primary, vnics, vlans etc.). However,
* hwlane kstats are created only once - when the rings are initialized
* by the device attach. Thus, these kstats are *not* recreated even if
* a ring is moved from one datalink to another.
*
* These "persistent" (for the lifetime of device) kstats are named
* using the name of the underlying datalink and the id corresponding
* to the hardware ring. Thus, hwlane stat query on a datalink needs to
* dig in this information before it can issue a kstat query.
*/
/* Find name of the underlying link */
return (NULL);
/* Query for ids of dedicated rings for this datalink */
return (chain);
}
/*ARGSUSED*/
static dladm_stat_chain_t *
{
if (link_stat_entry == NULL)
goto done;
if (rx_lane_stat_entry == NULL)
goto done;
if (swlane_stats == NULL) {
goto done;
}
if (swlane_stats != NULL) {
sizeof (swlane_stats->dc_statheader));
}
done:
return (swlane_stats);
}
void *
{
DLPI_LINKNAME_MAX) != DLADM_STATUS_OK) {
goto done;
}
/* Check if it is legacy driver */
goto done;
}
if (is_legacy_driver) {
goto done;
}
if (lane_stats == NULL)
done:
return (head);
}
/* Tx lane statistic specific functions */
static boolean_t
{
}
static void *
{
if (diff_entry == NULL)
goto done;
done:
return (diff_entry);
}
static void *
{
if (tx_lane_stat_entry == NULL)
goto done;
tx_lane_stat_entry->tle_index = i;
done:
return (tx_lane_stat_entry);
}
static dladm_stat_chain_t *
{
if (link_stat_entry == NULL)
goto done;
if (tx_lane_stat_entry == NULL)
goto done;
if (local_stats == NULL) {
goto done;
}
sizeof (local_stats->dc_statheader));
done:
return (local_stats);
}
static dladm_stat_chain_t *
{
if (link_stat_entry == NULL)
goto done;
if (tx_lane_stat_entry == NULL)
goto done;
goto done;
}
sizeof (head->dc_statheader));
done:
return (head);
}
static dladm_stat_chain_t *
{
/*
* For every hardware ring dedicated to a datalink, the datalink is said
* to have a hardware lane (hwlane). During the lifetime of a device
* instance (from device attach till detach), a device ring could be
* used by different datalinks (primary, vnics, vlans etc.). However,
* hwlane kstats are created only once - when the rings are initialized
* by the device attach. Thus, these kstats are *not* recreated even if
* a ring is moved from one datalink to another.
*
* These "persistent" (for the lifetime of device) kstats are named
* using the name of the underlying datalink and the id corresponding
* to the hardware ring. Thus, hwlane stat query on a datalink needs to
* dig in this information before it can issue a kstat query.
*/
/* Find the name of the underlying link */
return (NULL);
/* Query for ids of dedicated rings for this datalink */
return (chain);
}
/*ARGSUSED*/
static dladm_stat_chain_t *
{
if (link_stat_entry == NULL)
goto done;
if (tx_lane_stat_entry == NULL)
goto done;
/*
* Swlane stat counts on-wire unicast traffic only. Thus,
* swlane = total tx traffic - (local + multicast + broadcast).
*/
if (swlane_stats == NULL) {
goto done;
}
sizeof (swlane_stats->dc_statheader));
done:
return (swlane_stats);
}
void *
{
DLPI_LINKNAME_MAX) != DLADM_STATUS_OK) {
goto done;
}
/* Check if it is legacy driver */
goto done;
}
if (is_legacy_driver) {
goto done;
}
if (lane_stats == NULL)
done:
return (head);
}
/* Rx lane total statistic specific functions */
void *
{
/* Query per mcip kstats (don't need to look at the underlying link) */
DLPI_LINKNAME_MAX) != DLADM_STATUS_OK) {
goto done;
}
goto done;
}
if (is_legacy_driver) {
goto done;
}
if (link_stat_entry == NULL)
goto done;
if (total_stats == NULL)
goto done;
if (total_head == NULL) {
goto done;
}
sizeof (total_head->dc_statheader));
done:
return (total_head);
}
/* Tx lane total statistic specific functions */
void *
{
/* Query per mcip kstats (don't need to look at the underlying link) */
DLPI_LINKNAME_MAX) != DLADM_STATUS_OK) {
return (NULL);
}
goto done;
}
if (is_legacy_driver) {
goto done;
}
if (link_stat_entry == NULL)
goto done;
if (total_stats == NULL)
goto done;
if (total_head == NULL) {
goto done;
}
sizeof (total_head->dc_statheader));
done:
return (total_head);
}
/* Rx ring statistic specific functions */
static boolean_t
{
}
static void *
{
if (diff_entry == NULL)
goto done;
done:
return (diff_entry);
}
static void *
{
if (rx_ring_stat_entry == NULL)
goto done;
rx_ring_stat_entry->re_index = i;
done:
return (rx_ring_stat_entry);
}
void *
{
void *chain;
return (NULL);
return (chain);
}
/* Tx ring statistic specific functions */
static boolean_t
{
}
static void *
{
if (diff_entry == NULL)
goto done;
done:
return (diff_entry);
}
static void *
{
if (tx_ring_stat_entry == NULL)
goto done;
tx_ring_stat_entry->re_index = i;
done:
return (tx_ring_stat_entry);
}
void *
{
void *chain;
return (NULL);
return (chain);
}
static total_stat_entry_t *
{
return (NULL);
warn("kstat open operation failed");
return (NULL);
}
NULL);
goto done;
if (total_stat_entry == NULL)
goto done;
done:
(void) kstat_close(kcp);
return (total_stat_entry);
}
static void *
{
char *modname;
char *statheader;
/*
* kstats corresponding to physical device rings continue to use
* device names even if the link is renamed using dladm rename-link.
* Thus, given a linkid, we lookup the physical device name.
* However, if an aggr is renamed, kstats corresponding to its
* pseudo rings are renamed as well.
*/
DLPI_LINKNAME_MAX) != DLADM_STATUS_OK) {
return (NULL);
}
if (class != DATALINK_CLASS_AGGR) {
return (NULL);
}
} else
if (total_stats == NULL)
return (NULL);
if (ring_stats == NULL)
goto done;
if (stattype == DLADM_STAT_RX_RING_TOTAL) {
} else if (stattype == DLADM_STAT_TX_RING_TOTAL) {
}
goto done;
if (ring_stats != NULL) {
"mac_rx_ring_total" : "mac_tx_ring_total";
sizeof (stat_head->dc_statheader));
}
done:
return (stat_head);
}
/* Rx ring total statistic specific functions */
void *
{
}
/* Tx ring total statistic specific functions */
void *
{
}
/* Summary statistic specific functions */
/*ARGSUSED*/
static boolean_t
{ /* Always single entry for total */
return (B_TRUE);
}
static void *
{
if (diff_entry == NULL)
goto done;
done:
return (diff_entry);
}
void *
{
/* Get total rx lane stats */
goto done;
/* Get total tx lane stats */
goto done;
/* Build total stat */
if (total_stat_entry == NULL)
goto done;
/* Extract total rx ipackets, rbytes */
/* Extract total tx opackets, obytes */
goto done;
}
sizeof (head->dc_statheader));
done:
return (head);
}
void *
{
/* Get total rx ring stats */
goto done;
/* Get total tx ring stats */
goto done;
/* Build total stat */
if (total_stat_entry == NULL)
goto done;
/* Extract total rx ipackets, rbytes */
/* Extract total tx opackets, obytes */
goto done;
}
sizeof (head->dc_statheader));
done:
return (head);
}
/* Aggr total statistic(summed across all component ports) specific functions */
void *
{
if (total_stats == NULL)
goto done;
}
if (total_head == NULL) {
goto done;
}
done:
return (total_head);
}
/* Aggr port statistic specific functions */
static boolean_t
{
}
static void *
{
if (diff_entry == NULL)
goto done;
done:
return (diff_entry);
}
/*
* Query dls stats for the aggr port. This results in query for stats into
* the corresponding device driver.
*/
static aggr_port_stat_entry_t *
{
return (NULL);
warn("kstat open operation failed");
return (NULL);
}
NULL);
goto done;
if (aggr_port_stat_entry == NULL)
goto done;
/* Save port's linkid */
done:
(void) kstat_close(kcp);
return (aggr_port_stat_entry);
}
void *
{
int i;
/* Get aggr info */
!= DLADM_STATUS_OK)
goto done;
/* For every port that is member of this aggr do */
DLADM_OPT_ACTIVE) != DLADM_STATUS_OK) {
goto done;
}
if (aggr_port_stat_entry == NULL)
break;
/* Create dladm_stat_chain_t object for this stat */
goto done;
}
sizeof (curr->dc_statheader));
/* Chain this aggr port stat entry */
/* head of the stat list */
else
}
done:
/*
* Prepend the stat list with cumulative aggr stats i.e. summed over all
* component ports
*/
if (total_stats != NULL) {
head = total_stats;
}
}
return (head);
}
/* Link stat specific functions */
void *
{
DLPI_LINKNAME_MAX) != DLADM_STATUS_OK) {
goto done;
}
if (link_stat_entry == NULL)
goto done;
goto done;
}
sizeof (head->dc_statheader));
done:
return (head);
}
/* VDP statistic specific functions */
static boolean_t
{
}
static void *
{
if (diff_entry == NULL)
return (NULL);
return (diff_entry);
}
void *
{
int dfd;
DLPI_LINKNAME_MAX) != DLADM_STATUS_OK) {
return (NULL);
}
return (NULL);
if (class == DATALINK_CLASS_VNIC) {
return (NULL);
}
} else {
}
if (dfd == -1) {
return (NULL);
}
return (NULL);
}
return (NULL);
}
if (vdp_stat_entry == NULL)
return (NULL);
/* Create dladm_stat_chain_t object for this stat */
return (NULL);
}
sizeof (head->dc_statheader));
return (head);
}
/* ECP statistic specific functions */
static boolean_t
{
}
static void *
{
if (diff_entry == NULL)
return (NULL);
return (diff_entry);
}
void *
{
int dfd;
DLPI_LINKNAME_MAX) != DLADM_STATUS_OK) {
return (NULL);
}
if (dfd == -1) {
return (NULL);
}
return (NULL);
}
return (NULL);
}
if (ecp_stat_entry == NULL)
return (NULL);
/* Create dladm_stat_chain_t object for this stat */
return (NULL);
}
sizeof (head->dc_statheader));
return (head);
}
/* Exported functions */
{
}
{
/* Perform op1 - op2, store result in diff */
break;
}
}
goto done;
/* prev iteration did not have this stat entry */
} else {
}
goto done;
}
else
}
done:
return (diff_head);
}
void
{
}
}
/* Query all link stats */
static name_value_stat_t *
{
int i;
for (i = 0; i < size; i++) {
break;
sizeof (curr_stat->nv_statname));
else
}
return (head_stat);
}
void *
{
void *statfields;
/* Allocate memory for query all stat entry */
if (name_value_stat_entry == NULL)
goto done;
/* Header for these stat fields */
sizeof (name_value_stat_entry->nve_header));
/* Extract stat fields from the statentry */
/* Convert curr_stat to <statname, statval> pair */
done:
return (name_value_stat_entry);
}
void *
{
/*
* For every stat in the chain, build header and convert all
* its stat fields
*/
if (nvstat_curr == NULL)
break;
break;
}
else
}
done:
return (nvstat_head);
}
{
/* Query the requested stat */
goto done;
/*
* Convert every statfield in every stat-entry of stat chain to
* <statname, statval> pair
*/
/* Free stat_head */
done:
return (nvstat_head);
}
void
{
}
}
}
/* flow stats specific routines */
{
return (NULL);
goto done;
}
done:
(void) kstat_close(kcp);
return (flow_stat);
}
{
goto done;
} else {
}
done:
return (diff_stat);
}
void
{
}
/* Query all flow stats */
{
/* Query flow stats */
goto done;
/* Allocate memory for query all stat entry */
if (name_value_stat_entry == NULL) {
goto done;
}
/* Header for these stat fields */
/* Convert every statfield in flow_stat to <statname, statval> pair */
/* Free flow_stat */
done:
return (name_value_stat_entry);
}
void
{
}
}