1192661Ssam/*- 2192661Ssam * Copyright (c) 2009 Sam Leffler, Errno Consulting 3192661Ssam * All rights reserved. 4192661Ssam * 5192661Ssam * Redistribution and use in source and binary forms, with or without 6192661Ssam * modification, are permitted provided that the following conditions 7192661Ssam * are met: 8192661Ssam * 1. Redistributions of source code must retain the above copyright 9192661Ssam * notice, this list of conditions and the following disclaimer, 10192661Ssam * without modification. 11192661Ssam * 2. Redistributions in binary form must reproduce at minimum a disclaimer 12192661Ssam * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any 13192661Ssam * redistribution must be conditioned upon including a substantially 14192661Ssam * similar Disclaimer requirement for further binary redistribution. 15192661Ssam * 16192661Ssam * NO WARRANTY 17192661Ssam * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18192661Ssam * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19192661Ssam * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY 20192661Ssam * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 21192661Ssam * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, 22192661Ssam * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 23192661Ssam * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24192661Ssam * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 25192661Ssam * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 26192661Ssam * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 27192661Ssam * THE POSSIBILITY OF SUCH DAMAGES. 28192661Ssam * 29192661Ssam * $FreeBSD$ 30192661Ssam */ 31192661Ssam 32192661Ssam/* 33192661Ssam * npe statistics class. 34192661Ssam */ 35192661Ssam#include <sys/types.h> 36192661Ssam#include <sys/sysctl.h> 37192661Ssam 38192661Ssam#include <stdio.h> 39192661Ssam#include <stdlib.h> 40192661Ssam#include <signal.h> 41192661Ssam#include <string.h> 42192661Ssam#include <unistd.h> 43192661Ssam#include <err.h> 44192661Ssam 45192661Ssam#include "npestats.h" 46192661Ssam 47192661Ssam#define AFTER(prev) ((prev)+1) 48192661Ssam 49192661Ssamstatic const struct fmt npestats[] = { 50192661Ssam#define S_ALIGN 0 51192661Ssam { 7, "align", "align", "alignment errors" }, 52192661Ssam#define S_FCS AFTER(S_ALIGN) 53192661Ssam { 7, "fcs", "fcs", "FCS errors" }, 54192661Ssam#define S_MACRX AFTER(S_FCS) 55192661Ssam { 7, "macrx", "macrx", "internal MAC rx errors" }, 56192661Ssam#define S_RXORN AFTER(S_MACRX) 57192661Ssam { 6, "overrun", "overrun", "rx overrun discards" }, 58192661Ssam#define S_LEARN AFTER(S_RXORN) 59192661Ssam { 5, "learn", "learn", "rx learned entry discards" }, 60192661Ssam#define S_LARGE AFTER(S_LEARN) 61192661Ssam { 5, "large", "large", "rx large frame discards" }, 62192661Ssam#define S_STP AFTER(S_LARGE) 63192661Ssam { 5, "stp", "stp", "rx STP blocked discards" }, 64192661Ssam#define S_RX_VLAN_TYPE AFTER(S_STP) 65192661Ssam { 5, "rx_vlan_type", "rx_vlant", "rx VLAN type filter discards" }, 66192661Ssam#define S_RX_VLAN_ID AFTER(S_RX_VLAN_TYPE) 67192661Ssam { 5, "rx_vlan_id", "rx_vlani", "rx VLAN Id filter discards" }, 68192661Ssam#define S_BADSRC AFTER(S_RX_VLAN_ID) 69192661Ssam { 5, "badsrc", "badsrc", "rx invalid source discards" }, 70192661Ssam#define S_BLACKLIST AFTER(S_BADSRC) 71192661Ssam { 5, "blacklist", "blacklist", "rx black list discards" }, 72192661Ssam#define S_WHITELIST AFTER(S_BLACKLIST) 73192661Ssam { 5, "whitelist", "whitelist", "rx white list discards" }, 74192661Ssam#define S_UNDERFLOW AFTER(S_WHITELIST) 75192661Ssam { 5, "underflow", "underflow", "rx underflow entry discards" }, 76192661Ssam#define S_COLL_SINGLE AFTER(S_UNDERFLOW) 77192661Ssam { 5, "collision1", "collision1", "single collision frames" }, 78192661Ssam#define S_COLL_MULTI AFTER(S_COLL_SINGLE) 79192661Ssam { 5, "collisionM", "collisionM", "multiple collision frames" }, 80192661Ssam#define S_DEFERRED AFTER(S_COLL_MULTI) 81192661Ssam { 5, "deferred", "deferred", "deferred transmissions" }, 82192661Ssam#define S_LATE AFTER(S_DEFERRED) 83192661Ssam { 5, "late", "late", "late collisions" }, 84192661Ssam#define S_EXCESSIVE AFTER(S_LATE) 85192661Ssam { 5, "excessive", "excessive", "excessive collisions" }, 86192661Ssam#define S_MACTX AFTER(S_EXCESSIVE) 87192661Ssam { 7, "mactx", "mactx", "internal MAC tx errors" }, 88192661Ssam#define S_CARRIER AFTER(S_MACTX) 89192661Ssam { 7, "carrier", "carrier", "carrier sense errors" }, 90192661Ssam#define S_TOOBIG AFTER(S_CARRIER) 91192661Ssam { 7, "toobig", "toobig", "tx large frame discards" }, 92192661Ssam#define S_TX_VLAN_ID AFTER(S_TOOBIG) 93192661Ssam { 7, "tx_vlan_id", "tx_vlani", "tx VLAN Id filter discards" }, 94192661Ssam}; 95192661Ssam#define S_LAST S_TX_VLAN_ID 96192661Ssam 97192661Ssam/* 98192661Ssam * Stat block returned by NPE with NPE_GETSTATS msg. 99192661Ssam */ 100192661Ssamstruct npestats { 101192661Ssam uint32_t dot3StatsAlignmentErrors; 102192661Ssam uint32_t dot3StatsFCSErrors; 103192661Ssam uint32_t dot3StatsInternalMacReceiveErrors; 104192661Ssam uint32_t RxOverrunDiscards; 105192661Ssam uint32_t RxLearnedEntryDiscards; 106192661Ssam uint32_t RxLargeFramesDiscards; 107192661Ssam uint32_t RxSTPBlockedDiscards; 108192661Ssam uint32_t RxVLANTypeFilterDiscards; 109192661Ssam uint32_t RxVLANIdFilterDiscards; 110192661Ssam uint32_t RxInvalidSourceDiscards; 111192661Ssam uint32_t RxBlackListDiscards; 112192661Ssam uint32_t RxWhiteListDiscards; 113192661Ssam uint32_t RxUnderflowEntryDiscards; 114192661Ssam uint32_t dot3StatsSingleCollisionFrames; 115192661Ssam uint32_t dot3StatsMultipleCollisionFrames; 116192661Ssam uint32_t dot3StatsDeferredTransmissions; 117192661Ssam uint32_t dot3StatsLateCollisions; 118192661Ssam uint32_t dot3StatsExcessiveCollisions; 119192661Ssam uint32_t dot3StatsInternalMacTransmitErrors; 120192661Ssam uint32_t dot3StatsCarrierSenseErrors; 121192661Ssam uint32_t TxLargeFrameDiscards; 122192661Ssam uint32_t TxVLANIdFilterDiscards; 123192661Ssam}; 124192661Ssam 125192661Ssamstruct npestatfoo_p { 126192661Ssam struct npestatfoo base; 127192661Ssam char oid[80]; 128192661Ssam int mib[4]; 129192661Ssam struct npestats cur; 130192661Ssam struct npestats total; 131192661Ssam}; 132192661Ssam 133192661Ssamstatic void 134192661Ssamnpe_setifname(struct npestatfoo *wf0, const char *ifname) 135192661Ssam{ 136192661Ssam struct npestatfoo_p *wf = (struct npestatfoo_p *) wf0; 137192661Ssam size_t len; 138192661Ssam 139192661Ssam snprintf(wf->oid, sizeof(wf->oid), "dev.npe.%s.stats", ifname+3); 140192661Ssam len = 4; 141192661Ssam if (sysctlnametomib(wf->oid, wf->mib, &len) < 0) 142192661Ssam err(1, "sysctlnametomib: %s", wf->oid); 143192661Ssam} 144192661Ssam 145192661Ssamstatic void 146192661Ssamnpe_collect(struct npestatfoo_p *wf, struct npestats *stats) 147192661Ssam{ 148192661Ssam size_t len = sizeof(struct npestats); 149192661Ssam if (sysctl(wf->mib, 4, stats, &len, NULL, 0) < 0) 150192661Ssam err(1, "sysctl: %s", wf->oid); 151192661Ssam} 152192661Ssam 153192661Ssamstatic void 154192661Ssamnpe_collect_cur(struct statfoo *sf) 155192661Ssam{ 156192661Ssam struct npestatfoo_p *wf = (struct npestatfoo_p *) sf; 157192661Ssam 158192661Ssam npe_collect(wf, &wf->cur); 159192661Ssam} 160192661Ssam 161192661Ssamstatic void 162192661Ssamnpe_collect_tot(struct statfoo *sf) 163192661Ssam{ 164192661Ssam struct npestatfoo_p *wf = (struct npestatfoo_p *) sf; 165192661Ssam 166192661Ssam npe_collect(wf, &wf->total); 167192661Ssam} 168192661Ssam 169192661Ssamstatic void 170192661Ssamnpe_update_tot(struct statfoo *sf) 171192661Ssam{ 172192661Ssam struct npestatfoo_p *wf = (struct npestatfoo_p *) sf; 173192661Ssam 174192661Ssam wf->total = wf->cur; 175192661Ssam} 176192661Ssam 177192661Ssamstatic int 178192661Ssamnpe_get_curstat(struct statfoo *sf, int s, char b[], size_t bs) 179192661Ssam{ 180192661Ssam struct npestatfoo_p *wf = (struct npestatfoo_p *) sf; 181192661Ssam#define STAT(x) \ 182192661Ssam snprintf(b, bs, "%u", wf->cur.x - wf->total.x); return 1 183192661Ssam 184192661Ssam switch (s) { 185192661Ssam case S_ALIGN: STAT(dot3StatsAlignmentErrors); 186192661Ssam case S_FCS: STAT(dot3StatsFCSErrors); 187192661Ssam case S_MACRX: STAT(dot3StatsInternalMacReceiveErrors); 188192661Ssam case S_RXORN: STAT(RxOverrunDiscards); 189192661Ssam case S_LEARN: STAT(RxLearnedEntryDiscards); 190192661Ssam case S_LARGE: STAT(RxLargeFramesDiscards); 191192661Ssam case S_STP: STAT(RxSTPBlockedDiscards); 192192661Ssam case S_RX_VLAN_TYPE: STAT(RxVLANTypeFilterDiscards); 193192661Ssam case S_RX_VLAN_ID: STAT(RxVLANIdFilterDiscards); 194192661Ssam case S_BADSRC: STAT(RxInvalidSourceDiscards); 195192661Ssam case S_BLACKLIST: STAT(RxBlackListDiscards); 196192661Ssam case S_WHITELIST: STAT(RxWhiteListDiscards); 197192661Ssam case S_UNDERFLOW: STAT(RxUnderflowEntryDiscards); 198192661Ssam case S_COLL_SINGLE: STAT(dot3StatsSingleCollisionFrames); 199192661Ssam case S_COLL_MULTI: STAT(dot3StatsMultipleCollisionFrames); 200192661Ssam case S_DEFERRED: STAT(dot3StatsDeferredTransmissions); 201192661Ssam case S_LATE: STAT(dot3StatsLateCollisions); 202192661Ssam case S_EXCESSIVE: STAT(dot3StatsExcessiveCollisions); 203192661Ssam case S_MACTX: STAT(dot3StatsInternalMacTransmitErrors); 204192661Ssam case S_CARRIER: STAT(dot3StatsCarrierSenseErrors); 205192661Ssam case S_TOOBIG: STAT(TxLargeFrameDiscards); 206192661Ssam case S_TX_VLAN_ID: STAT(TxVLANIdFilterDiscards); 207192661Ssam } 208192661Ssam b[0] = '\0'; 209192661Ssam return 0; 210192661Ssam#undef STAT 211192661Ssam} 212192661Ssam 213192661Ssamstatic int 214192661Ssamnpe_get_totstat(struct statfoo *sf, int s, char b[], size_t bs) 215192661Ssam{ 216192661Ssam struct npestatfoo_p *wf = (struct npestatfoo_p *) sf; 217192661Ssam#define STAT(x) \ 218192661Ssam snprintf(b, bs, "%u", wf->total.x); return 1 219192661Ssam 220192661Ssam switch (s) { 221192661Ssam case S_ALIGN: STAT(dot3StatsAlignmentErrors); 222192661Ssam case S_FCS: STAT(dot3StatsFCSErrors); 223192661Ssam case S_MACRX: STAT(dot3StatsInternalMacReceiveErrors); 224192661Ssam case S_RXORN: STAT(RxOverrunDiscards); 225192661Ssam case S_LEARN: STAT(RxLearnedEntryDiscards); 226192661Ssam case S_LARGE: STAT(RxLargeFramesDiscards); 227192661Ssam case S_STP: STAT(RxSTPBlockedDiscards); 228192661Ssam case S_RX_VLAN_TYPE: STAT(RxVLANTypeFilterDiscards); 229192661Ssam case S_RX_VLAN_ID: STAT(RxVLANIdFilterDiscards); 230192661Ssam case S_BADSRC: STAT(RxInvalidSourceDiscards); 231192661Ssam case S_BLACKLIST: STAT(RxBlackListDiscards); 232192661Ssam case S_WHITELIST: STAT(RxWhiteListDiscards); 233192661Ssam case S_UNDERFLOW: STAT(RxUnderflowEntryDiscards); 234192661Ssam case S_COLL_SINGLE: STAT(dot3StatsSingleCollisionFrames); 235192661Ssam case S_COLL_MULTI: STAT(dot3StatsMultipleCollisionFrames); 236192661Ssam case S_DEFERRED: STAT(dot3StatsDeferredTransmissions); 237192661Ssam case S_LATE: STAT(dot3StatsLateCollisions); 238192661Ssam case S_EXCESSIVE: STAT(dot3StatsExcessiveCollisions); 239192661Ssam case S_MACTX: STAT(dot3StatsInternalMacTransmitErrors); 240192661Ssam case S_CARRIER: STAT(dot3StatsCarrierSenseErrors); 241192661Ssam case S_TOOBIG: STAT(TxLargeFrameDiscards); 242192661Ssam case S_TX_VLAN_ID: STAT(TxVLANIdFilterDiscards); 243192661Ssam } 244192661Ssam b[0] = '\0'; 245192661Ssam return 0; 246192661Ssam#undef STAT 247192661Ssam} 248192661Ssam 249192661SsamSTATFOO_DEFINE_BOUNCE(npestatfoo) 250192661Ssam 251192661Ssamstruct npestatfoo * 252192661Ssamnpestats_new(const char *ifname, const char *fmtstring) 253192661Ssam{ 254192661Ssam#define N(a) (sizeof(a) / sizeof(a[0])) 255192661Ssam struct npestatfoo_p *wf; 256192661Ssam 257192661Ssam wf = calloc(1, sizeof(struct npestatfoo_p)); 258192661Ssam if (wf != NULL) { 259192661Ssam statfoo_init(&wf->base.base, "npestats", npestats, N(npestats)); 260192661Ssam /* override base methods */ 261192661Ssam wf->base.base.collect_cur = npe_collect_cur; 262192661Ssam wf->base.base.collect_tot = npe_collect_tot; 263192661Ssam wf->base.base.get_curstat = npe_get_curstat; 264192661Ssam wf->base.base.get_totstat = npe_get_totstat; 265192661Ssam wf->base.base.update_tot = npe_update_tot; 266192661Ssam 267192661Ssam /* setup bounce functions for public methods */ 268192661Ssam STATFOO_BOUNCE(wf, npestatfoo); 269192661Ssam 270192661Ssam /* setup our public methods */ 271192661Ssam wf->base.setifname = npe_setifname; 272192661Ssam 273192661Ssam npe_setifname(&wf->base, ifname); 274192661Ssam wf->base.setfmt(&wf->base, fmtstring); 275192661Ssam } 276192661Ssam return &wf->base; 277192661Ssam#undef N 278192661Ssam} 279