Files
m241Neelima/components/ip_net2-6.9/vxcompat/src/m2IfLib.c
T
2026-07-30 11:19:44 +05:30

1470 lines
45 KiB
C

/* m2IfLib.c - MIB-II interface-group counter update API */
/*
* Copyright (c) 2001-2006 Wind River Systems, Inc.
*
* The right to copy, distribute, modify or otherwise make use
* of this software may be licensed only pursuant to the terms
* of an applicable Wind River license agreement.
*/
/*
modification history
--------------------
01w,29sep10,h_x Fix build and coverity warnings
01v,21jun10,h_x Fix WIND00217113
01u,01apr10,h_x Fix warnings
01t,11jul08,zhr updated for apigen
01s,22may08,dlk Use malloc()/free() instead of KHEAP_ALLOC()/KHEAP_FREE().
Minor clean-up.
01r,28mar08,zhr Migrated to IPNET
02q,12jun06,wap Modify m2IfDelete() to uninstall _m2SetIfLastChange and
_m2IfTableUpdate function pointers.
02p,06dec05,dlk Correct typo in m2PollStatsIfPoll().
02o,14jul05,dlk Remove reference to IN6_IFDATA_DS_ID. Clear
pIfIndex->pIn6IfInfo after freeing.
02n,20apr05,kch Merged from comp_wn_ipv6_mld_interim-dev branch.
02m,09feb05,dlk Fix broadcast check handling for 802.4/802.5 frames
in m2If8023PacketCount().
02l,25jan05,sar Modify sysuptime to be based on 64 bit ticks
Remove code to limit counters from rolling over (SPR102459)
02k,31jan05,niq Fix bug in freeing the M2_IF node
02j,26jan05,vvv fixed build errors
02i,12jan05,vvv osdep.h cleanup
02h,11jan05,vvv made _in6_ifdata creation independent of m2 (SPR #88606)
02g,09nov04,dlk Make m2IfTableUpdate() and rcvEtherAddrAdd() \NOMANUAL.
02f,01oct04,wap fix polling stats routine for base6 (SPR #101616)
02e,19sep04,spm updated virtual stack startup and shutdown: restored use of
published routines and removed packing/unpacking parameters
02d,26aug04,vvv fixed warning
02c,26aug04,niq unified stack merge
02b,13aug04,kc Added m2Ipv6Initialized bool variable.
02a,13aug04,kc Fixed m2IfTableUpdate to check if the IPV6 MIB IF is
initialized.
01z,11aug04,niq VS data structure reorganization
01y,16jul04,niq Fix bug in if_index handling (SPR 99100)
01x,19may04,niq Check for memory allocation failure + use if_index instead of
ifIndex.
01w,21apr04,rae replace if_index (internal) with ifIndex (external)
01v,05dec03,xli change include path
01u,02dec03,zl use avlUintLib instead of avlLib
01t,20nov03,niq osdep.h cleanup
01r,06nov03,rlm Ran batch header update for header re-org
01q,20oct03,zl changed for new avlLib without GENERIC_ARGUMENT.
01p,08sep03,vvv merged from ACCORDION_BASE6_MERGE_BASELINE
01o,23jul03,vvv fixed memory leak in m2IfTableUpdate (SPR #88481)
01n,01may03,spm Tornado 2.2 CP1 merge (from ver 02b,20mar03,wap:
TOR2_2-CP1-F label, tor2_2-patch branch, /wind/river VOB)
01m,10apr03,ijm fixed diab compiler warnings
01l,10jan03,ann moved some globals from m2Ipv6IfLib.c
01k,10feb03,vvv added INET6 protection
01j,30sep02,kbw making man page edits
01i,30sep02,vvv fixed problem in nextIndex (SPR #71316)
01h,25sep02,ham split m2IfLib to m2IfLib and m2IfMgtLib
01g,06aug02,ann moved the prototype for m2If8023PacketCount into m2Lib.h
optimized the packet count algorithm, disabled
64 bit counter updates temporarily
01f,05aug02,ann removed the LOCAL decleration of m2If8023PacketCount
01e,15jul02,nee RFC 2465 Trap routine related fixes
01d,18jun02,ann corrected the incorrect freeing of pIfIndex in m2IfTableUpdate
01c,18sep01,ann commenting out the ifTable stuff temporarily
01b,18sep01,ann resolving some symbols
01a,12sep01,ann ported to clarinet from AE 1.0 version 01v
*/
/*
DESCRIPTION
This library provides MIB-II services for the interface group. It
provides routines to initialize the group, access the group scalar
variables, read the table interfaces and change the state of the interfaces.
For a broader description of MIB-II services, see the manual entry for m2Lib.
To use this library, include the INCLUDE_MIB2_IF configuration component.
USING THIS LIBRARY
This library can be initialized and deleted by calling m2IfInit() and
m2IfDelete() respectively, if only the interface group's services are
needed. If full MIB-II support is used, this group and all other groups
can be initialized and deleted by calling m2Init() and m2Delete().
The interface group supports the Simple Network Management Protocol (SNMP)
concept of traps, as specified by RFC 1215. The traps supported by this
group are "link up" and "link down." This library enables an application
to register a hook routine and an argument. This hook routine can be
called by the library when a "link up" or "link down" condition is
detected. The hook routine must have the following prototype:
.CS
void TrapGenerator (int trapType, /@ M2_LINK_DOWN_TRAP or M2_LINK_UP_TRAP @/
int interfaceIndex,
void * myPrivateArg);
.CE
The trap routine and argument can be specified at initialization time as
input parameters to the routine m2IfInit() or to the routine m2Init().
Access the interface-group global variables as follows:
.CS
M2_INTERFACE ifVars;
if (m2IfGroupInfoGet (&ifVars) == OK)
/@ values in ifVars are valid @/
.CE
INCLUDE FILES: m2Lib.h
SEE ALSO: m2Lib, m2SysLib, m2IpLib, m2IcmpLib, m2UdpLib, m2TcpLib
*/
/* includes */
#include <vxWorks.h>
#include <stdlib.h>
#include <limits.h>
#include <errnoLib.h>
#include <stdio.h>
#include <string.h>
#include <tickLib.h>
#include <m2Lib.h>
#include <m2IfLib.h>
#include <private/muxLibP.h>
/* defines */
#define END_OBJ_MIB 1 /* Used in ifnetToEndFieldsGet() */
#define END_OBJ_FLAGS 2 /* Used in ifnetToEndFieldsGet() */
IMPORT int m2If64BitCounters;
/*
* m2IfIncr64Bit : increment a 64 bit counter
*
* This macro is used to increment a 64-bit counter. The counter
* to update is pointed to by <pStat>, and <inc>, a 32-bit quantity,
* specifies how much to increment the counter.
*/
#define m2IfIncr64Bit(pStat, inc) \
do { \
UI64_ADD32((pStat), (inc)); \
} while (FALSE)
#define M2_POLLINCR_64(flag, counter) \
if (pDrvConf->ifValidCounters & (flag)) \
{ \
(pMib2Data->mibIfTbl.if ## counter) += \
((Mib2_Counter)(pDrvCounters->if ## counter & 0xFFFFFFFF)); \
m2IfIncr64Bit (&(pMib2Data->mibXIfTbl.ifHC ## counter), \
pDrvCounters->if ## counter & 0xFFFFFFFF); \
}
#define M2_POLLINCR_64_X(flag, counter) \
if (pDrvConf->ifValidCounters & (flag)) \
{ \
(pMib2Data->mibXIfTbl.if ## counter) += \
((Mib2_Counter)(pDrvCounters->if ## counter & 0xFFFFFFFF)); \
m2IfIncr64Bit (&(pMib2Data->mibXIfTbl.ifHC ## counter), \
pDrvCounters->if ## counter & 0xFFFFFFFF); \
}
#define M2_POLLINCR_32(flag, srcCounter, dstCounter) \
if (pDrvConf->ifValidCounters & (flag)) \
{ \
(pMib2Data->mibIfTbl.if ## dstCounter) += \
((Mib2_Counter)(pDrvCounters->if ## srcCounter & 0xFFFFFFFF)); \
}
STATUS m2IfTableUpdate ();
/* globals */
M2_IFINDEX * pm2IfTable; /* Network I/F table (Allocated Dynamically) */
int m2IfCount = 0; /* Number of network interfaces */
int ifsInList = 0; /* Actual number of interfaces in our list */
IMPORT FUNCPTR pM2TrapRtn; /* Pointer to trap routine supplied by the user */
IMPORT void * pM2TrapRtnArg; /* Pointer to trap routine argument supplied by */
/* the user */
ULONG m2IfTableLastChange;
/* last time a row was added/removed from the ifStackTable or when the
* ifStackStatus was last changed */
ULONG m2IfStackLastChange;
/* Semaphore used to protect the Interface group */
SEM_ID m2InterfaceSem = NULL;
/*
* Global variable used to keep the group startup time in 64 bit ticks.
* The functionality here is the same as the functionality provided in the
* module m2SysLib.c. It is duplicated to allow for both modules to exist
* independently.
*/
LOCAL UINT64 priv_startTicks; /* 64 bit ticks at start */
/* externals */
extern UINT64 tick64Get (void); /* This should be removed when it is added
* to tickLib.h, until then we need it to
* ensure proper processing of 64 bit ticks */
/* locals */
/*static const UI64 U64_MAX = { UINT_MAX, UINT_MAX };*/
/*
* The zero object id is used throught out the MIB-II library to fill OID
* requests when an object ID is not provided by a group variable.
*/
LOCAL void m2IfCentiSecsStart (void);
Mib2_TimeTicks m2IfCentiSecsGet (void);
STATUS rcvEtherAddrAdd (M2_IFINDEX *, unsigned char *);
LOCAL STATUS m2IfGenericPacketCount (M2_ID *, UINT, UCHAR *, UINT);
LOCAL STATUS m2IfCounterUpdate (M2_ID *, UINT, UINT);
LOCAL STATUS m2IfVariableUpdate (M2_ID *, UINT, caddr_t);
/******************************************************************************
*
* m2IfInit - initialize MIB-II interface-group routines
*
* This routine allocates the resources needed to allow access to the
* MIB-II interface-group variables. This routine must be called before any
* interface variables can be accessed. The <pTrapRtn> argument is an
* optional pointer to a user-supplied SNMP trap generator. The <pTrapArg>
* argument is an optional argument to the trap generator. Only one
* trap generator is supported.
*
* RETURNS: OK if successful
* ERROR if an error occurred
*
* ERRNO:
* S_m2Lib_CANT_CREATE_IF_SEM
*
* SEE ALSO:
* m2IfGroupInfoGet(), m2IfTblEntryGet(), m2IfTblEntrySet(), m2IfDelete()
*/
STATUS m2IfInit
(
FUNCPTR pTrapRtn, /* link up/down -trap routine */
void * pTrapArg /* trap routine arg */
)
{
#ifdef VIRTUAL_STACK
/*
* The M2_IF data structure is now part of the core VS data. Simply
* initialize the variables if this is the first call to the init routine.
*/
if (pM2IfRootPtr == NULL)
{
/*
* Perform the static initialization which the compiler provides
* automatically for the non-virtual stack.
*/
pM2IfRoot = NULL;
pM2IfRootPtr = &pM2IfRoot;
}
#endif /* VIRTUAL_STACK */
/* Register the m2 APIs with the end library */
endMibIfInit ((FUNCPTR)m2IfTblInit, (FUNCPTR)mibIfAlloc,
(FUNCPTR)m2IfFree,
(FUNCPTR)m2CounterUpdate, (FUNCPTR)m2VariableUpdate);
/* Create the Interface semaphore */
if (m2InterfaceSem == NULL)
{
m2InterfaceSem = semMCreate (SEM_Q_PRIORITY | SEM_INVERSION_SAFE |
SEM_DELETE_SAFE);
if (m2InterfaceSem == NULL)
{
#ifdef VIRTUAL_STACK
pM2IfRootPtr = NULL;
#endif /* VIRTUAL_STACK */
errnoSet (S_m2Lib_CANT_CREATE_IF_SEM);
return (ERROR);
}
}
/* Take the interface semaphore, and initialize group global variables */
semTake (m2InterfaceSem, WAIT_FOREVER);
pM2TrapRtn = pTrapRtn;
pM2TrapRtnArg = pTrapArg;
m2IfTableLastChange = 0;
m2IfStackLastChange = 0;
semGive (m2InterfaceSem);
(void) m2IfCentiSecsStart(); /* Initialize group time reference */
return (OK);
}
/*******************************************************************************
*
* m2IfDestructor - Clean up the resources used by VS Portion of the code
*
* RETURNS: ERROR if it could not free the memory
* OK otherwise
*
* NOMANUAL
*/
#ifdef VIRTUAL_STACK
STATUS m2IfDestructor
(
VSNUM vsnum
)
{
m2IfDelete ();
return (OK);
}
#endif /* VIRTUAL_STACK */
/***************************************************************************
*
* mibIfAlloc - the generic interfaces MIB allocation routine
*
* This routine provides a very generic API to initialize the interface
* MIB structure. It expects the caller to provide the buffer in to which
* the pointer to the allocated MIB structure is stored.
*
* RETURNS: OK if successfully initialized,
* ERROR otherwise
*/
STATUS mibIfAlloc
(
M2_ID ** ppMib2Tbl, /* Buffer to store pointer to MIB */
ULONG ifType, /* If type of the interface */
UCHAR * pEnetAddr, /* Physical address of interface */
ULONG addrLen, /* Address length */
ULONG mtuSize, /* MTU of interface */
ULONG speed, /* Speed of the interface */
char * pName, /* Name of the device */
int unit /* Unit number of the device */
)
{
/* Perform a sanity check to see if the buffer is valid */
if (ppMib2Tbl == NULL)
return (ERROR);
*ppMib2Tbl = m2IfAlloc (ifType, pEnetAddr, addrLen,
mtuSize, speed, pName, unit);
if (*ppMib2Tbl == NULL)
return (ERROR);
return (OK);
}
/***************************************************************************
*
* m2IfAlloc - allocate the structure for the interface table
*
* This routine is called to allocate and initialize the interface table MIB
* structure. We also set the default update routines in the M2_ID struct.
* These fields can later be overloaded using the installed routines in the
* M2_ID. Once this function returns, it is the driver's responsibility to
* set the pMib2Tbl pointer in the END object to the new M2_ID.
*
* When this call returns, the calling routine must set the END_MIB_2233
* bit of the flags field in the END object.
*
* RETURNS: Pointer to the M2_ID structure upon success,
* NULL if an error occurred.
*/
M2_ID * m2IfAlloc
(
ULONG ifType, /* If type of the interface */
UCHAR * pEnetAddr, /* Physical address of interface */
ULONG addrLen, /* Address length */
ULONG mtuSize, /* MTU of interface */
ULONG speed, /* Speed of the interface */
char * pName, /* Name of the device */
int unit /* Unit number of the device */
)
{
M2_ID * pM2Id = NULL;
/* Allocate memory for the interface table */
pM2Id = (M2_ID *)malloc(sizeof(M2_ID));
if (!pM2Id)
return (NULL);
(void)m2IfTblInit (pM2Id, ifType, pEnetAddr, addrLen,
mtuSize, speed, pName, unit);
return (pM2Id);
}
/***************************************************************************
*
* m2IfTblInit - initialize the structure for the interface table
*
* This routine is called to initialize the interface table MIB
* structure. We also set the default update routines in the M2_ID struct.
* These fields can later be overloaded using the installed routines in the
* M2_ID. Once this function returns, it is the driver's responsibility to
* set the pMib2Tbl pointer in the END object to the new M2_ID.
*
* When this call returns, the calling routine must set the END_MIB_2233
* bit of the flags field in the END object.
*
* RETURNS: ERROR on an error (pM2ID is NULL)
* OK otherwise.
*/
STATUS m2IfTblInit
(
M2_ID * pM2Id, /* pointer to M2_ID interface table */
ULONG ifType, /* If type of the interface */
UCHAR * pEnetAddr, /* Physical address of interface */
ULONG addrLen, /* Address length */
ULONG mtuSize, /* MTU of interface */
ULONG speed, /* Speed of the interface */
char * pName, /* Name of the device */
int unit /* Unit number of the device */
)
{
M2_INTERFACETBL * pM2IfTbl = NULL;
M2_2233TBL * pM2XIfTbl = NULL;
if (pM2Id == NULL)
return ERROR;
bzero ((char *) pM2Id, sizeof (M2_ID));
/* Enter the values provided by the driver */
pM2IfTbl = &pM2Id->m2Data.mibIfTbl;
pM2XIfTbl = &pM2Id->m2Data.mibXIfTbl;
pM2IfTbl->ifType = (Mib2_Integer)ifType;
pM2IfTbl->ifMtu = (Mib2_Integer)mtuSize;
pM2IfTbl->ifSpeed = (Mib2_Gauge)speed;
memcpy (&pM2IfTbl->ifPhysAddress.phyAddress[0], pEnetAddr, addrLen);
pM2IfTbl->ifPhysAddress.addrLength = (Mib2_Integer)addrLen;
sprintf ((char *)&pM2XIfTbl->ifName[0], "%s%d", pName, unit);
sprintf ((char *)&pM2IfTbl->ifDescr[0], "%s%d", pName, unit);
/* Set the default update routines */
switch (ifType)
{
case M2_ifType_ethernet_csmacd:
case M2_ifType_iso88023_csmacd:
case M2_ifType_iso88024_tokenBus:
case M2_ifType_iso88025_tokenRing:
case M2_ifType_iso88026_man:
case M2_ifType_fddi:
pM2Id->m2PktCountRtn = m2If8023PacketCount;
break;
default:
pM2Id->m2PktCountRtn = m2IfGenericPacketCount;
break;
}
pM2Id->m2CtrUpdateRtn = m2IfCounterUpdate;
pM2Id->m2VarUpdateRtn = m2IfVariableUpdate;
pM2XIfTbl->ifLinkUpDownTrapEnable = M2_LINK_UP_DOWN_TRAP_DISABLED;
/*
* ifHighSpeed is measured in units of 10**6 bits/s
*/
pM2XIfTbl->ifHighSpeed = (Mib2_Gauge32)((speed + 500000) / 1000000);
pM2XIfTbl->ifPromiscuousMode = M2_PROMISCUOUS_MODE_OFF;
pM2XIfTbl->ifConnectorPresent = M2_CONNECTOR_NOT_PRESENT;
pM2Id->m2UsrCounter = NULL;
return (OK);
}
/***************************************************************************
*
* m2IfFree - free an interface data structure
*
* This routine frees the memory associated with the interface's MIB
* structure.
*
* RETURNS: OK if successful,
* ERROR otherwise
*/
STATUS m2IfFree
(
M2_ID * pId /* pointer to the driver's M2_ID object */
)
{
if (pId == NULL)
return (ERROR);
else
free((char *)pId);
return OK;
}
/***************************************************************************
*
* m2CounterUpdate - update the value of an interface MIB counter
*
* This is a generic function that increments the value of any interface
* MIB counter.
*
* If the <ctrl> parameter is M2_PACKET_IN or M2_PACKET_OUT, the API
* expects the <pPkt> pointer to contain a valid packet and the <value>
* field must contain the length of the packet.
*
* For all other counters, the <pPkt> field can be NULL, but the <value>
* field must contain the value to increment the counter by.
*
* RETURNS: OK upon success,
* ERROR otherwise
*/
STATUS m2CounterUpdate
(
M2_ID * pId, /* The pointer to the device M2_ID object */
UINT ctrl, /* Counter to update */
UINT value, /* Value to increment by . If <ctrl> is M2_PACKET_IN */
/* or M2_PACKET_OUT, the length must be passed. */
UCHAR * pPkt /* Pointer to packet, can be NULL if <ctrl> is not */
/* is not M2_PACKET_IN or M2_PACKET_OUT */
)
{
if (pId == NULL)
return (ERROR);
switch (ctrl)
{
case M2_PACKET_IN:
case M2_PACKET_OUT:
return (pId->m2PktCountRtn (pId, ctrl, pPkt, value));
default:
return (pId->m2CtrUpdateRtn (pId, ctrl, value));
}
}
/***************************************************************************
*
* m2VariableUpdate - update the value of an interface MIB variable
*
* This is a generic function that changes the value of any non-counter
* variable of the interface MIB.
*
* RETURNS: OK upon success,
* ERROR otherwise
*/
STATUS m2VariableUpdate
(
M2_ID * pId, /* The pointer to the device M2_ID object */
UINT varId, /* Variable to update */
caddr_t pData /* Data to use */
)
{
if (pId == NULL)
return (ERROR);
return (pId->m2VarUpdateRtn (pId, varId, pData));
}
/***************************************************************************
*
* m2IfGenericPacketCount - increment the interface packet counters
*
* This function is used to update basic interface counters for a packet. It
* has no idea of the underlying media so only the ifInOctets, ifHCInOctets,
* ifOutOctets and ifHCOutOctets variables are incremented. The ctrl
* argument specifies whether the packet is being sent or just received
* (M2_PACKET_IN or M2_PACKET_OUT).
*
* This function must never be called directly. It must be called via
* m2CounterUpdate().
*
* RETURNS: ERROR if the M2_ID is NULL,
* OK if the counters were updated.
* \NOMANUAL
*/
LOCAL STATUS m2IfGenericPacketCount
(
M2_ID * pId, /* The pointer to the device M2_ID object */
UINT ctrl, /* Update In or Out counters */
UCHAR * pPkt, /* The incoming/outgoing packet */
UINT pktLen /* Length of the packet */
)
{
M2_DATA * pMib2Data;
pMib2Data = &(pId->m2Data);
switch (ctrl)
{
case M2_PACKET_IN:
pMib2Data->mibIfTbl.ifInOctets += pktLen;
pMib2Data->mibIfTbl.ifInUcastPkts += 1;
if (m2If64BitCounters)
{
m2IfIncr64Bit(&(pMib2Data->mibXIfTbl.ifHCInOctets), pktLen);
m2IfIncr64Bit(&(pMib2Data->mibXIfTbl.ifHCInUcastPkts), 1);
}
break;
case M2_PACKET_OUT:
pMib2Data->mibIfTbl.ifOutOctets += pktLen;
pMib2Data->mibIfTbl.ifOutUcastPkts += 1;
if (m2If64BitCounters)
{
m2IfIncr64Bit(&(pMib2Data->mibXIfTbl.ifHCOutOctets), pktLen);
m2IfIncr64Bit(&(pMib2Data->mibXIfTbl.ifHCOutUcastPkts), 1);
}
break;
default:
return ERROR;
}
return OK;
}
/***************************************************************************
*
* m2If8023PacketCount - increment the 802.3 device interface packet counters
*
* This function is used to update basic interface counters for a packet.
* The <ctrl> argument specifies whether the packet is being sent or just
* received (M2_PACKET_IN or M2_PACKET_OUT). This function only works for
* 802.3 devices as it understand the Ethernet packet format. The
* following counters are updated:
*
* . ifInOctets
* . ifInUcastPkts
* . ifInNUcastPkts
* . ifOutOctets
* . ifOutUcastPkts
* . ifOutNUcastPkts
* . ifInMulticastPkts
* . ifInBroadcastPkts
* . ifOutMulticastPkts
* . ifOutBroadcastPkts
* . ifHCInOctets
* . ifHCInUcastPkts
* . ifHCOutOctets
* . ifHCOutUcastPkts
* . ifHCInMulticastPkts
* . ifHCInBroadcastPkts
* . ifHCOutMulticastPkts
* . ifHCOutBroadcastPkts
* . ifCounterDiscontinuityTime
*
* The first 6 bytes in the packet must contain the destination MAC
* address and the second 6 bytes of the packet must contain the source
* MAC address.
*
* The type of MAC address (i.e. broadcast, multicast, or unicast) is
* determined by the following:
*
* . broadcast address: ff:ff:ff:ff:ff:ff
* . multicast address: first bit is set
* . unicast address: any other address not matching the above
*
* This function must not be called directly. It is called from
* m2CounterUpdate().
*
* RETURNS: ERROR if the M2_ID is NULL or the <ctrl> is invalid,
* OK if the counters were updated.
*/
STATUS m2If8023PacketCount
(
M2_ID * pId, /* The pointer to the device M2_ID object */
UINT ctrl, /* Update In or Out counters */
UCHAR * pPkt, /* The incoming/outgoing packet */
UINT pktLen /* Length of the packet */
)
{
M2_DATA * pMib2Data;
UCHAR mcastBit = 0x01;
if (pId == NULL)
return ERROR;
pMib2Data = &(pId->m2Data);
/*
* Special handling for 802.4 and 802.5. In 802.4,
* the destination address is preceded by a single
* frame control byte. In 802.5, the destination
* address is preceded by an access control byte
* and a frame control byte.
*/
if (pMib2Data->mibIfTbl.ifType == M2_ifType_iso88024_tokenBus)
pPkt += 1;
else if (pMib2Data->mibIfTbl.ifType == M2_ifType_iso88025_tokenRing)
pPkt += 2;
switch (ctrl)
{
case M2_PACKET_IN:
{
pMib2Data->mibIfTbl.ifInOctets += pktLen;
if (m2If64BitCounters)
m2IfIncr64Bit(&(pMib2Data->mibXIfTbl.ifHCInOctets), pktLen);
/* the first 6 bytes is the destination MAC address */
if (pPkt[0] & mcastBit) /* multicast address */
{
if (pPkt[0] == 0xff && pPkt[1] == 0xff &&
pPkt[2] == 0xff && pPkt[3] == 0xff &&
pPkt[4] == 0xff && pPkt[5] == 0xff)
{
pMib2Data->mibXIfTbl.ifInBroadcastPkts += 1;
if (m2If64BitCounters)
m2IfIncr64Bit(
&(pMib2Data->mibXIfTbl.ifHCInBroadcastPkts), 1);
}
else
{
pMib2Data->mibXIfTbl.ifInMulticastPkts += 1;
if (m2If64BitCounters)
m2IfIncr64Bit(
&(pMib2Data->mibXIfTbl.ifHCInMulticastPkts), 1);
}
/*
* This counter seems redundant. One could just add
* mibXIfTbl.ifInBroadcastPkts and mibXIfTbl.ifInMulticastPkts.
* Also, we could derive the 32-bit quantities from the
* low-order portions of the 64-bit quantities.
*/
pMib2Data->mibIfTbl.ifInNUcastPkts += 1;
}
else /* unicast address */
{
pMib2Data->mibIfTbl.ifInUcastPkts += 1;
if (m2If64BitCounters)
m2IfIncr64Bit(&(pMib2Data->mibXIfTbl.ifHCInUcastPkts), 1);
}
break;
}
case M2_PACKET_OUT:
{
pMib2Data->mibIfTbl.ifOutOctets += pktLen;
if (m2If64BitCounters)
m2IfIncr64Bit(&(pMib2Data->mibXIfTbl.ifHCOutOctets), pktLen);
/* the first 6 bytes is the destination MAC address */
if (pPkt[0] & mcastBit) /* multicast address */
{
if (pPkt[0] == 0xff && pPkt[1] == 0xff &&
pPkt[2] == 0xff && pPkt[3] == 0xff &&
pPkt[4] == 0xff && pPkt[5] == 0xff)
{
pMib2Data->mibXIfTbl.ifOutBroadcastPkts += 1;
if (m2If64BitCounters)
m2IfIncr64Bit(&(pMib2Data->
mibXIfTbl.ifHCOutBroadcastPkts), 1);
}
else
{
pMib2Data->mibXIfTbl.ifOutMulticastPkts += 1;
if (m2If64BitCounters)
m2IfIncr64Bit(&(pMib2Data->
mibXIfTbl.ifHCOutMulticastPkts), 1);
}
pMib2Data->mibIfTbl.ifOutNUcastPkts += 1;
}
else /* unicast address */
{
pMib2Data->mibIfTbl.ifOutUcastPkts += 1;
if (m2If64BitCounters)
m2IfIncr64Bit(&(pMib2Data->mibXIfTbl.ifHCOutUcastPkts), 1);
}
break;
}
default:
return ERROR;
}
return OK;
}
/***************************************************************************
*
* m2IfCounterUpdate - increment interface counters
*
* This function is used to directly update any counter. The counter
* is specified by <ctrId> and the amount to increment it is specified
* by value.
*
* This routine is called from m2CounterUpdate().
*
* RETURNS: ERROR if the M2_ID is NULL,
* OK if the counter was updated.
* \NOMANUAL
*/
LOCAL STATUS m2IfCounterUpdate
(
M2_ID * pId, /* The pointer to the device M2_ID object */
UINT ctrId, /* Counter to update */
UINT value /* Amount to update the counter by */
)
{
M2_DATA * pMib2Data;
if (pId == NULL)
return ERROR;
pMib2Data = &(pId->m2Data);
switch (ctrId)
{
case M2_ctrId_ifInOctets:
pMib2Data->mibIfTbl.ifInOctets += value;
break;
case M2_ctrId_ifInUcastPkts:
pMib2Data->mibIfTbl.ifInUcastPkts += value;
break;
case M2_ctrId_ifInNUcastPkts:
pMib2Data->mibIfTbl.ifInNUcastPkts += value;
break;
case M2_ctrId_ifInDiscards:
pMib2Data->mibIfTbl.ifInDiscards += value;
break;
case M2_ctrId_ifInErrors:
pMib2Data->mibIfTbl.ifInErrors += value;
break;
case M2_ctrId_ifInUnknownProtos:
pMib2Data->mibIfTbl.ifInUnknownProtos += value;
break;
case M2_ctrId_ifOutOctets:
pMib2Data->mibIfTbl.ifOutOctets += value;
break;
case M2_ctrId_ifOutUcastPkts:
pMib2Data->mibIfTbl.ifOutUcastPkts += value;
break;
case M2_ctrId_ifOutNUcastPkts:
pMib2Data->mibIfTbl.ifOutNUcastPkts += value;
break;
case M2_ctrId_ifOutDiscards:
pMib2Data->mibIfTbl.ifOutDiscards += value;
break;
case M2_ctrId_ifOutErrors:
pMib2Data->mibIfTbl.ifOutErrors += value;
break;
case M2_ctrId_ifInMulticastPkts:
pMib2Data->mibXIfTbl.ifInMulticastPkts += value;
break;
case M2_ctrId_ifInBroadcastPkts:
pMib2Data->mibXIfTbl.ifInBroadcastPkts += value;
break;
case M2_ctrId_ifOutMulticastPkts:
pMib2Data->mibXIfTbl.ifOutMulticastPkts += value;
break;
case M2_ctrId_ifOutBroadcastPkts:
pMib2Data->mibXIfTbl.ifOutBroadcastPkts += value;
break;
case M2_ctrId_ifHCInOctets:
m2IfIncr64Bit(&(pMib2Data->mibXIfTbl.ifHCInOctets), value);
break;
case M2_ctrId_ifHCInUcastPkts:
m2IfIncr64Bit(&(pMib2Data->mibXIfTbl.ifHCInUcastPkts), value);
break;
case M2_ctrId_ifHCInMulticastPkts:
m2IfIncr64Bit(&(pMib2Data->mibXIfTbl.ifHCInMulticastPkts), value);
break;
case M2_ctrId_ifHCInBroadcastPkts:
m2IfIncr64Bit(&(pMib2Data->mibXIfTbl.ifHCInBroadcastPkts), value);
break;
case M2_ctrId_ifHCOutOctets:
m2IfIncr64Bit(&(pMib2Data->mibXIfTbl.ifHCOutOctets), value);
break;
case M2_ctrId_ifHCOutUcastPkts:
m2IfIncr64Bit(&(pMib2Data->mibXIfTbl.ifHCOutUcastPkts), value);
break;
case M2_ctrId_ifHCOutMulticastPkts:
m2IfIncr64Bit(&(pMib2Data->mibXIfTbl.ifHCOutMulticastPkts), value);
break;
case M2_ctrId_ifHCOutBroadcastPkts:
m2IfIncr64Bit(&(pMib2Data->mibXIfTbl.ifHCOutBroadcastPkts), value);
break;
default:
return ERROR;
}
return OK;
}
/***************************************************************************
*
* m2IfVariableUpdate - update the contents of an interface non-counter object
*
* This function is used to update an interface variable. The variable is
* specified by varId and the data to use is specified by pData. Note that
* different variable expect differnet types of data. Here is a list of the
* variables the the type of data expected. Therefore pData will be cast to the
* type listed below for each variable.
*
* . ifDescr char *
* . ifType UINT
* . ifMtu ULONG
* . ifSpeed ULONG
* . ifPhysAddress M2_PHYADDR *
* . ifAdminStatus ULONG
* . ifOperStatus ULONG
* . ifLastChange ULONG
* . ifOutQLen ULONG
* . ifSpecific M2_OBJECTID *
* . ifName char *
* . ifLinkUpDownTrapEnable UINT
* . ifHighSpeed ULONG
* . ifPromiscuousMode UINT
* . ifConnectorPresent UINT
* . ifAlias char *
*
* RETURNS: ERROR if the M2_ID is NULL, OK if the variable was updated.
* \NOMANUAL
*/
LOCAL STATUS m2IfVariableUpdate
(
M2_ID * pId, /* The pointer to the device M2_ID object */
UINT varId, /* Variable to update */
caddr_t pData /* Data to use */
)
{
M2_DATA * pMib2Data;
if (pId == NULL || pData == NULL)
return ERROR;
pMib2Data = &(pId->m2Data);
switch (varId)
{
case M2_varId_ifDescr:
if (strlen(pData) < M2DISPLAYSTRSIZE)
strcpy((char *)(pMib2Data->mibIfTbl.ifDescr), pData);
break;
case M2_varId_ifType:
pMib2Data->mibIfTbl.ifType = (Mib2_Integer)(ULONG)pData;
break;
case M2_varId_ifMtu:
pMib2Data->mibIfTbl.ifMtu = (Mib2_Integer)(ULONG)pData;
break;
case M2_varId_ifSpeed:
pMib2Data->mibIfTbl.ifSpeed = (Mib2_Gauge)(ULONG)pData;
break;
case M2_varId_ifPhysAddress:
memcpy(&(pMib2Data->mibIfTbl.ifPhysAddress), (M2_PHYADDR *)pData,
sizeof(M2_PHYADDR));
break;
case M2_varId_ifAdminStatus:
pMib2Data->mibIfTbl.ifAdminStatus = (Mib2_Integer)(ULONG)pData;
break;
case M2_varId_ifOperStatus:
/* ifLastChange must be updated if ifOperStatus changes */
if (pMib2Data->mibIfTbl.ifOperStatus != (Mib2_Integer)(ULONG)pData)
{
pMib2Data->mibIfTbl.ifLastChange = m2IfCentiSecsGet();
pMib2Data->mibIfTbl.ifOperStatus = (Mib2_Integer)(ULONG)pData;
}
break;
case M2_varId_ifLastChange:
pMib2Data->mibIfTbl.ifLastChange = (Mib2_TimeTicks)(ULONG)pData;
break;
case M2_varId_ifOutQLen:
pMib2Data->mibIfTbl.ifOutQLen = (Mib2_Counter)(ULONG)pData;
break;
case M2_varId_ifSpecific:
memcpy(&(pMib2Data->mibIfTbl.ifSpecific), (M2_OBJECTID *)pData,
sizeof(M2_OBJECTID));
break;
case M2_varId_ifName:
if (strlen(pData) < M2DISPLAYSTRSIZE)
strcpy((char *)(pMib2Data->mibXIfTbl.ifName), pData);
break;
case M2_varId_ifLinkUpDownTrapEnable:
pMib2Data->mibXIfTbl.ifLinkUpDownTrapEnable = (Mib2_Integer)(ULONG)pData;
break;
case M2_varId_ifHighSpeed:
pMib2Data->mibXIfTbl.ifHighSpeed = (Mib2_Gauge32)(ULONG)pData;
break;
case M2_varId_ifPromiscuousMode:
pMib2Data->mibXIfTbl.ifPromiscuousMode = (Mib2_TruthValue)(ULONG)pData;
break;
case M2_varId_ifConnectorPresent:
pMib2Data->mibXIfTbl.ifConnectorPresent = (Mib2_TruthValue)(ULONG)pData;
break;
case M2_varId_ifAlias:
if (strlen(pData) < M2DISPLAYSTRSIZE)
strcpy((char *)(pMib2Data->mibXIfTbl.ifAlias), pData);
break;
default:
return ERROR;
}
return OK;
}
/***************************************************************************
*
* m2IfPktCountRtnInstall - install an interface packet counter routine
*
* This function installs a routine in the M2_ID. This routine is a packet
* counter that is able to update all the interface counters.
*
* RETURNS: ERROR if the M2_ID is NULL,
* OK if the routine was installed.
*/
STATUS m2IfPktCountRtnInstall
(
M2_ID * pId,
M2_PKT_COUNT_RTN pRtn
)
{
if (pId == NULL)
return ERROR;
pId->m2PktCountRtn = pRtn;
return OK;
}
/***************************************************************************
*
* m2IfCtrUpdateRtnInstall - install an interface counter update routine
*
* This function installs a routine in the M2_ID. This routine is able to
* update a single specified interface counter.
*
* RETURNS: ERROR if the M2_ID is NULL,
* OK if the routine was installed.
*/
STATUS m2IfCtrUpdateRtnInstall
(
M2_ID * pId,
M2_CTR_UPDATE_RTN pRtn
)
{
if (pId == NULL)
return ERROR;
pId->m2CtrUpdateRtn = pRtn;
return OK;
}
/***************************************************************************
*
* m2IfVarUpdateRtnInstall - install an interface variable update routine
*
* This function installs a routine in the M2_ID. This routine is able to
* update a single specified interface variable.
*
* RETURNS: ERROR if the M2_ID is NULL, OK if the routine was installed.
*/
STATUS m2IfVarUpdateRtnInstall
(
M2_ID * pId,
M2_VAR_UPDATE_RTN pRtn
)
{
if (pId == NULL)
return ERROR;
pId->m2VarUpdateRtn = pRtn;
return OK;
}
/******************************************************************************
*
* m2IfCentiSecsStart - get the starting timestamp
*
* Set the timestamp we use to determine the starting point for sys up time.
*
* RETURNS: void
*
* SEE ALSO: N/A
*/
LOCAL void m2IfCentiSecsStart (void)
{
priv_startTicks = tick64Get();
return;
}
/******************************************************************************
*
* m2IfCentiSecsGet - get hundredths of a second
*
* The time, in hundredths of a second, since we started the network.
* m2IfCentiSecsStart is used to start the clock.
*
* RETURNS: Hundredths of a second since the group was initialized.
*
* SEE ALSO: N/A
*/
Mib2_TimeTicks m2IfCentiSecsGet (void)
{
UINT64 currCentiSecs;
currCentiSecs = ((tick64Get() - priv_startTicks) * 100) / sysClkRateGet();
return (Mib2_TimeTicks)(currCentiSecs & 0xFFFFFFFF);
}
/****************************************************************************
*
* rcvEtherAddrAdd - add a physical address into the linked list
*
* This function is a helper function for rcvEtherAddrGet. It is called to
* add a single physical address into the linked list of addresses maintained
* by the AVL node.
*
* RETURNS: OK if successful,
* ERROR otherwise
* \NOMANUAL
*/
STATUS rcvEtherAddrAdd
(
M2_IFINDEX * pIfIndexEntry, /* the avl node */
unsigned char * pEnetAddr /* the addr to be added */
)
{
M2_IFRCVADDRTBL * pIfRcvAddr = NULL;
M2_IFRCVADDRTBL ** ppTemp = &pIfIndexEntry->pRcvAddr;
if (pEnetAddr)
{
pIfRcvAddr = malloc (sizeof (M2_IFRCVADDRTBL));
if (!pIfRcvAddr)
return ERROR;
bcopy ((char *) pEnetAddr,
(char *) pIfRcvAddr->ifRcvAddrAddr.phyAddress,
ETHERADDRLEN);
pIfRcvAddr->ifRcvAddrAddr.addrLength = ETHERADDRLEN;
pIfRcvAddr->ifRcvAddrStatus = ROW_ACTIVE;
pIfRcvAddr->ifRcvAddrType = STORAGE_NONVOLATILE;
pIfRcvAddr->pNextEntry = NULL;
if (pIfIndexEntry->pRcvAddr)
{
while (*ppTemp)
{
if (memcmp (pEnetAddr, (*ppTemp)->ifRcvAddrAddr.phyAddress,
ETHERADDRLEN) > 0)
{
ppTemp = &(*ppTemp)->pNextEntry;
continue;
}
else
{
pIfRcvAddr->pNextEntry = *ppTemp;
break;
}
}
*ppTemp = pIfRcvAddr;
}
else
{
pIfIndexEntry->pRcvAddr = pIfRcvAddr;
}
return (OK);
}
return (ERROR);
}
/*******************************************************************************
*
* m2IfNodeFree - delete a node in the interface tree
*
* This routine frees memory allocated for a node in the interface tree.
* The routine assumes the AVL node is the first in M2_IFINDEX.
*
* RETURNS: OK, always
*
* NOMANUAL
*/
#if 0
LOCAL STATUS m2IfNodeFree
(
AVLU_NODE * pNode,
void * delArg
)
{
free (pNode);
return (OK);
}
#endif
/*******************************************************************************
*
* m2IfDelete - delete all resources used to access the interface group
*
* This routine frees all the resources allocated at the time the group was
* initialized. The interface group should not be accessed after this routine
* has been called.
*
* RETURNS: OK, always.
*
* SEE ALSO:
* m2IfInit(), m2IfGroupInfoGet(), m2IfTblEntryGet(), m2IfTblEntrySet()
*/
STATUS m2IfDelete (void)
{
pM2TrapRtn = NULL;
pM2TrapRtnArg = NULL;
return OK;
}
/*****************************************************************************
*
* m2PollStatsIfPoll - read statistics information from an interface's internal counters
*
* This function invokes the EIOCGPOLLSTATS ioctl on a specified
* interface and, if the ioctl succeeds, it updates its associated MIB2
* counters. Only those counters which are marked as valid in the
* interface's ifValidCounters field in the END_IFDRVCONF structure
* will be updated. This routine may be invoked either automatically
* via periodic watchdog timeout, or directly in order to force a
* counter update if the watchdog has not yet expired.
*
* RETURNS: ERROR if reading the counters fails, otherwise OK.
*/
STATUS m2PollStatsIfPoll
(
END_IFDRVCONF * pDrvConf
)
{
M2_ID * pId; /* The pointer to the device M2_ID object */
M2_DATA * pMib2Data;
END_IFCOUNTERS * pDrvCounters;
PROTOCOL_BINDING tmpBinding;
void * pCookie;
int error;
if (pDrvConf == NULL)
return (ERROR);
tmpBinding.pEnd = PDEVCOOKIE_TO_ENDOBJ(pDrvConf->ifMuxCookie);
if (tmpBinding.pEnd == NULL)
return(ERROR);
pCookie = (void *)&tmpBinding;
/* Get M2_ID from driver. */
error = muxIoctl (pCookie, EIOCGMIB2233, (caddr_t)&pId);
if (error)
return (error);
pMib2Data = &(pId->m2Data);
/* Get the stats info */
error = muxIoctl (pCookie, EIOCGPOLLSTATS, (caddr_t)&pDrvCounters);
if (error)
return (error);
/* Do the work */
M2_POLLINCR_64 (END_IFINUCASTPKTS_VALID, InUcastPkts);
M2_POLLINCR_64 (END_IFOUTUCASTPKTS_VALID, OutUcastPkts);
M2_POLLINCR_64 (END_IFINOCTETS_VALID, InOctets);
M2_POLLINCR_64 (END_IFOUTOCTETS_VALID, OutOctets);
M2_POLLINCR_32 (END_IFINERRORS_VALID, InErrors, InErrors);
M2_POLLINCR_32 (END_IFOUTERRORS_VALID, OutErrors, OutErrors);
M2_POLLINCR_32 (END_IFINDISCARDS_VALID, InDiscards, InDiscards);
M2_POLLINCR_32 (END_IFOUTDISCARDS_VALID, OutDiscards, OutDiscards);
M2_POLLINCR_32 (END_IFINUNKNOWNPROTOS_VALID,
InUnknownProtos, InUnknownProtos);
/*
* For the multicast and broadcast stats, we need to do the
* increment on a different table, hence the need for a separate
* macro. We also need to increment the non-unicast counters.
*/
M2_POLLINCR_64_X (END_IFINMULTICASTPKTS_VALID, InMulticastPkts);
M2_POLLINCR_32 (END_IFINMULTICASTPKTS_VALID,
InMulticastPkts, InNUcastPkts);
M2_POLLINCR_64_X (END_IFINBROADCASTPKTS_VALID, InBroadcastPkts);
M2_POLLINCR_32 (END_IFINBROADCASTPKTS_VALID,
InBroadcastPkts, InNUcastPkts);
M2_POLLINCR_64_X (END_IFOUTMULTICASTPKTS_VALID, OutMulticastPkts);
M2_POLLINCR_32 (END_IFOUTMULTICASTPKTS_VALID,
OutMulticastPkts, OutNUcastPkts);
M2_POLLINCR_64_X (END_IFOUTBROADCASTPKTS_VALID, OutBroadcastPkts);
M2_POLLINCR_32 (END_IFOUTBROADCASTPKTS_VALID,
OutBroadcastPkts, OutNUcastPkts);
return (OK);
}
/******************************************************************************
*
* m2IfUsrCountersInstall - install a pointer to user-defined counters
*
* This routine installs a pointer <pUsrCounters> in the M2_ID structure
* specified by <pM2Id>. The installed pointer can be used to add additional
* counters per interface to support RMON, rfc1643 or any other counters. If a
* counter already exists the installation fails. The counters can be accessed
* using the m2UsrCounter field in the M2_ID structure for the interface. The
* pointer will typically refer to a structure which contains all the counters.
* For example:
*
* .CS
* struct counters
* {
* u_long ctr1;
* u_long ctr2;
* };
* .CE
*
* It is the responsibility of the user to allocate and initialize the counter
* structure before calling this routine.
*
* RETURNS: OK, or ERROR
*
* ERRNO: S_m2Lib_INVALID_PARAMETER
*/
STATUS m2IfUsrCountersInstall
(
M2_ID * pM2Id, /* M2_ID structure for interface */
void * pUsrCounters /* pointer to structure containing counters */
)
{
if ((pM2Id == NULL) || (pUsrCounters == NULL))
{
errnoSet (S_m2Lib_INVALID_PARAMETER);
return (ERROR);
}
/* Install a new counter only if a counter does not exist. */
if (pM2Id->m2UsrCounter == NULL)
pM2Id->m2UsrCounter = pUsrCounters;
else
return (ERROR);
return (OK);
}
/******************************************************************************
*
* m2IfUsrCountersRemove - delete the pointer to the user-defined counters
*
* This routine removes the user-defined counters associated with the interface.
* It is the responsibility of the user to free the counter structure once it
* has been deleted.
*
* RETURNS: OK, or ERROR if <pM2Id> is NULL
*
* ERRNO: S_m2Lib_INVALID_PARAMETER
*/
STATUS m2IfUsrCountersRemove
(
M2_ID * pM2Id /* M2_ID structure for interface */
)
{
if (pM2Id == NULL)
{
errnoSet (S_m2Lib_INVALID_PARAMETER);
return (ERROR);
}
pM2Id->m2UsrCounter = NULL;
return (OK);
}