libdlstat.c revision 285e94f91fd7deba72e31d9ecf23ec4769a8323b
/*
* 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
*/
/*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#include <err.h>
#include <errno.h>
#include <kstat.h>
#include <unistd.h>
#include <signal.h>
#include <libdllink.h>
#include <libdlflow.h>
#include <libdlstat.h>
/*
* Include curses.h last.
*/
#if defined(ERR)
#endif
#include <curses.h>
struct flowlist {
char flowname[MAXFLOWNAMELEN];
};
#define STATGROWSIZE 16
/*
* Search for flowlist entry in stattable which matches
* the flowname and linkide. 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);
}
static void
{
double dlt;
int fcount;
if (first) {
(void) printw("please wait...\n");
return;
}
char linkname[MAXLINKNAMELEN];
(void) printw("%9.2f %9.2f %9.2f %9.2f ",
(void) printw("\n");
}
}
}
/*ARGSUSED*/
static int
{
} else {
return (DLADM_STATUS_FAILED);
}
/* lookup kstat entry */
return (DLADM_WALK_TERMINATE);
else
else {
}
return (DLADM_WALK_CONTINUE);
}
static void
{
double util;
double dlt;
int fcount;
if (first) {
(void) printw("please wait...\n");
return;
}
char linkname[MAXLINKNAMELEN];
(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
{
char linkname[MAXLINKNAMELEN];
/* find the flist entry */
} else {
return (DLADM_WALK_CONTINUE);
}
/* lookup kstat entry */
warn("no linkname for linkid");
return (DLADM_WALK_TERMINATE);
}
return (DLADM_WALK_TERMINATE);
else
/* read packet and byte stats */
else
return (DLADM_WALK_CONTINUE);
}
/*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;
}
(void) 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 *
{
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);
}
{
char module[DLPI_LINKNAME_MAX];
char link[DLPI_LINKNAME_MAX];
warn("kstat_open operation failed");
return (-1);
}
return (status);
return (DLADM_STATUS_LINKINVAL);
if (status != DLADM_STATUS_OK)
return (status);
if (status != DLADM_STATUS_OK)
return (status);
/*
* The kstat query could fail if the underlying MAC
* driver was already detached.
*/
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
{
}