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

457 lines
14 KiB
C

/* m2Igmp.c - helper file for igmp Mib */
/* Copyright 2000 - 2005 Wind River Systems, Inc. */
/*
modification history
--------------------
01o,01apr05,kch Removed ROUTER_STACK define.
01n,02mar05,kc Fixed warning.
01m,12jan05,vvv osdep.h cleanup
01l,13sep04,rae fix hooks
01k,11aug04,rae fix VIRTUAL_STACK
01j,14jan03,rae Merged from velocecp branch
01i,11jul01,rae code clean up
01h,29mar01,spm file creation: copied from version 01g of tor2_0.open_stack
branch (wpwr VOB) for unified code base
01g,21jul00,gnn adjusted for include file move into a subdirectory of wrn
01f,20jul00,rae adjusted for move of src/WRN/include to h/wrn
01e,20jul00,rae added igmpMSem
01d,14jul00,rae turn off debug code
01c,22may00,kbw minor man page changes to allow refgen processing
01b,15may00,rae added VIRTUAL_STACK support
01a,08mar00,rae written
*/
/*
DESCRIPTION
This library provides an interface between the Berkeley multicast code
and the IGMP Mib code
INCLUDE FILES:
*/
/* includes */
#include "vxWorks.h"
#include "stdio.h"
#include "sysLib.h"
#include "logLib.h"
#include "semLib.h"
#include "errnoLib.h"
#include "stdlib.h"
#include "tickLib.h"
#include "m2Lib.h"
#include "netinet/in.h"
#include "netinet/in_var.h"
#include "netinet/igmp_var.h"
#include "net/protosw.h"
#include "IGMPv2/igmpR.h"
#include "IGMPv2/igmp_externs.h"
#include "IGMPv2/igmpRouterLib.h"
#include "IGMPv2/igmpPortLib.h"
#include "IGMPv2/igmpCacheLib.h"
#ifdef VIRTUAL_STACK
#include "netinet/vsLib.h"
#include "netinet/vsData.h"
#include "netinet/vsIgmpR.h"
#include "netinet/vsIgmp.h"
#endif
/* defines */
#define DEBUG noOperation /* change noOperation to printf for debugging */
/* externs */
/* globals */
#ifndef VIRTUAL_STACK
extern SEM_ID igmpMSem;
extern VOIDFUNCPTR _igmpJoinAlertHook;
extern VOIDFUNCPTR _igmpLeaveAlertHook;
extern VOIDFUNCPTR _igmpQuerierTimeUpdateHook;
#endif
/* locals */
/* forward declarations */
void igmpJoinAlert(int if_index);
void igmpLeaveAlert(int if_index);
void igmpQuerierTimeUpdate(int if_index, int time);
/*******************************************************************************
*
* noOperation - ignores its many arguments
*
* This do nothing code is replaced by printf, if debugging is enabled.
*
* NOMANUAL
*
* RETURNS: N/A
*/
void noOperation
(
const char *cptr_format,
...
)
{
}
/*******************************************************************************
*
* m2IgmpInit - fills in some hooks
*
* Fills in hooks with appropriate routines. For scalability.
*
* NOMANUAL
*
* RETURNS: OK always
*/
STATUS m2IgmpInit
(
void
)
{
_igmpJoinAlertHook = (VOIDFUNCPTR)igmpJoinAlert; /* fill in functions */
_igmpLeaveAlertHook = (VOIDFUNCPTR)igmpLeaveAlert;
_igmpQuerierTimeUpdateHook = (VOIDFUNCPTR)igmpQuerierTimeUpdate;
return (OK);
}
/*******************************************************************************
*
* m2IgmpCacheEntryGet - fills in M2_IGMP_CACHE struct with cache data
*
* Uses the cache address, and cache interface index to look up the cache entry
* associated with those values. Fills in provided structure with information
* from that entry.
*
* NOMANUAL
*
* RETURNS: OK or ERROR if if_index not valid
*/
STATUS m2IgmpCacheEntryGet
(
M2_IGMP_CACHE *pData /* this is filled in */
)
{
struct in_multi * inm;
struct ifnet * ifnet;
struct in_addr addr;
IGMP_GROUP_CLASS groupClass;
IGMP_GROUP_CLASS * pgroupClass = &groupClass;
if (igmpCacheGet (pData->igmpCacheAddress, pData->igmpCacheIfIndex,
(void*)&pgroupClass) != OK)
return ERROR;
if (pgroupClass == NULL)
{
DEBUG ("Null groupClass returned \n");
return ERROR;
}
if (semTake (igmpMSem, WAIT_FOREVER) == ERROR)
return ERROR;
addr.s_addr = htonl (pData->igmpCacheAddress);
if ((ifnet = portToIfnet (pgroupClass->port_number)) != NULL)
{
IN_LOOKUP_MULTI (addr, ifnet, inm); /* are we in this group? */
pData->igmpCacheSelf = inm ? M2_TRUE : M2_FALSE;
}
else
{
DEBUG ("lookup of ifnet failed on port %d\n", pgroupClass->port_number);
pData->igmpCacheSelf = M2_FALSE;
}
pData->igmpCacheLastReporter = pgroupClass->ip_address_of_last_reporter;
pData->igmpCacheUpTime = ((tickGet() - pgroupClass->start_time) * 100) /
sysClkRateGet();
if (pgroupClass->router_group.group_specific_timer.enabled)
pData->igmpCacheExpiryTime = (pgroupClass->
router_group.group_specific_timer.expiry_time -
pgroupClass->
router_group.group_specific_timer.second_counter) *
100;
else
pData->igmpCacheExpiryTime = 0;
pData->igmpCacheStatus = pgroupClass->enabled ? ROW_ACTIVE: ROW_NOTINSERVICE;
if (pgroupClass->router_group.v1_host_timer.enabled)
pData->igmpCacheVersion1HostTimer = (pgroupClass->
router_group.v1_host_timer.expiry_time -
pgroupClass->
router_group.v1_host_timer.second_counter) *
100;
else
pData->igmpCacheVersion1HostTimer = 0;
semGive (igmpMSem);
return OK;
}
/*******************************************************************************
*
* m2IgmpCacheEntryNextGet - fills in M2_IGMP_CACHE struct with cache data
*
* Uses the cache address, and cache interface index to look up the next cache entry
* lexicographically greater than those values. Fills in provided structure with
* information from that entry.
*
* NOMANUAL
*
* RETURNS: OK or ERROR if if_index not valid
*/
STATUS m2IgmpCacheEntryNextGet
(
M2_IGMP_CACHE *pData
)
{
UINT32 nextMcastAddr = 0;
UINT32 nextIfIndex =0;
IGMP_GROUP_CLASS groupClass;
IGMP_GROUP_CLASS * pGroupClass = &groupClass;
if (igmpCacheNextGet (pData->igmpCacheAddress, pData->igmpCacheIfIndex,
&nextMcastAddr, &nextIfIndex, (void*)&pGroupClass) != OK)
{
return ERROR;
}
pData->igmpCacheIfIndex = nextIfIndex;
pData->igmpCacheAddress = nextMcastAddr;
if (m2IgmpCacheEntryGet (pData) != OK)
{
return ERROR;
}
return OK;
}
/*******************************************************************************
*
* m2IgmpInterfaceEntryNextGet - fills in M2_IGMP struct with interface data
*
* Uses the compl argument (which is if_index) to look up the igmp port associated
* with the next interface. Fills in provided structure with information gathered
* from the interface.
*
* RETURNS: OK or ERROR if if_index not valid
*
* NOMANUAL
*/
STATUS m2IgmpInterfaceEntryNextGet
(
M2_IGMP * pData /* Interface Data structure */
)
{
UINT32 nextIndex;
UINT32 vif;
if (igmpPortNextGet (pData->igmpInterfaceIfIndex, &nextIndex, &vif) == ERROR)
{
DEBUG ("NextGet on if_index %d failed \n", (int)(pData->igmpInterfaceIfIndex));
return ERROR;
}
pData->igmpInterfaceIfIndex = nextIndex;
if (m2IgmpInterfaceEntryGet (pData) == ERROR)
{
DEBUG ("Get on index %d failed \n", nextIndex);
return ERROR;
}
return OK;
}
/*******************************************************************************
*
* m2IgmpInterfaceEntryGet - fills in M2_IGMP struct with interface data
*
* Uses the if_index to look up the igmp port associated
* with that interface. Fills in provided structure with information gathered
* from the interface.
*
* NOMANUAL
*
* RETURNS: OK or ERROR if if_index not valid
*/
STATUS m2IgmpInterfaceEntryGet
(
M2_IGMP *pData
)
{
UINT32 vif;
if (igmpPortGet (pData->igmpInterfaceIfIndex, &vif) == ERROR)
return ERROR;
if (semTake(igmpMSem, WAIT_FOREVER) == ERROR)
return ERROR;
pData->igmpInterfaceQueryInterval =
vs_igmp.port_table[vif].router_port.general_query_interval;
pData->igmpInterfaceStatus=
vs_igmp.port_table[vif].router_enabled ? ROW_ACTIVE : ROW_NOTINSERVICE;
pData->igmpInterfaceVersion=
vs_igmp.port_table[vif].version;
pData->igmpInterfaceQuerier=
vs_igmp.port_table[vif].igmpInterfaceEntry.igmpInterfaceQuerier;
pData->igmpInterfaceQueryMaxResponseTime=
vs_igmp.port_table[vif].router_port.general_query_max_response_time;
pData->igmpInterfaceQuerierPresentTimeout=
vs_igmp.port_table[vif].router_port.other_querier_present_timer.enabled ?
(vs_igmp.port_table[vif].router_port.other_querier_present_timer.expiry_time -
vs_igmp.port_table[vif].router_port.other_querier_present_timer.second_counter) *
100 : 0;
pData->igmpInterfaceVersion1QuerierTimer= /* updated by BSD code */
vs_igmp.port_table[vif].igmpInterfaceEntry.igmpInterfaceVersion1QuerierTimer;
pData->igmpInterfaceWrongVersionQueries=
vs_igmp.port_table[vif].igmpInterfaceEntry.igmpInterfaceWrongVersionQueries;
pData->igmpInterfaceJoins=
vs_igmp.port_table[vif].igmpInterfaceEntry.igmpInterfaceJoins;
pData->igmpInterfaceGroups=
vs_igmp.port_table[vif].igmpInterfaceEntry.igmpInterfaceGroups;
pData->igmpInterfaceRobustness=
vs_igmp.port_table[vif].robustness;
pData->igmpInterfaceQuerierUpTime=
((tickGet() -
vs_igmp.port_table[vif].igmpInterfaceEntry.igmpInterfaceQuerierUpTime) * 100) /
sysClkRateGet();
pData->igmpInterfaceLastMembQueryIntvl=
vs_igmp.port_table[vif].igmpInterfaceEntry.igmpInterfaceLastMembQueryIntvl;
semGive(igmpMSem);
return OK;
}
/*******************************************************************************
*
* m2IgmpInterfaceEntrySet - fills in interface data as per SNMP request
*
* Uses the if_index to look up the igmp port associated
* with that interface. Fills in interface structure with information provided
* by SNMP
*
* NOMANUAL
*
* RETURNS: OK or ERROR if if_index not valid
*/
STATUS m2IgmpInterfaceEntrySet
(
M2_IGMP *pData, /* the data from SNMP */
int varsToSet /* which of the above we really use */
)
{
UINT32 vif;
if (igmpPortGet (pData->igmpInterfaceIfIndex, &vif) == ERROR)
return ERROR;
if (semTake (igmpMSem, WAIT_FOREVER) == ERROR)
return ERROR;
if (varsToSet & M2_var_igmpInterfaceStatus)
{
/* bring if up or down */
}
if (varsToSet & M2_var_igmpInterfaceQueryInterval)
vs_igmp.port_table[vif].router_port.general_query_interval =
pData->igmpInterfaceQueryInterval;
if (varsToSet & M2_var_igmpInterfaceVersion)
vs_igmp.port_table[vif].version = pData->igmpInterfaceVersion;
if (varsToSet & M2_var_igmpInterfaceQueryMaxResponseTime)
vs_igmp.port_table[vif].router_port.general_query_max_response_time =
pData->igmpInterfaceQueryMaxResponseTime;
if (varsToSet & M2_var_igmpInterfaceRobustness)
vs_igmp.port_table[vif].robustness = pData->igmpInterfaceRobustness;
if (varsToSet & M2_var_igmpInterfaceLastMembQueryIntvl)
vs_igmp.port_table[vif].igmpInterfaceEntry.igmpInterfaceLastMembQueryIntvl =
pData->igmpInterfaceLastMembQueryIntvl;
semGive (igmpMSem);
return OK;
}
/******************************************************************************
*
* igmpJoinAlert - updates Mib variables on join
*
* Increments the igmpInterfaceJoins and igmpInterfaceGroups values on the given
* interface.
*
* RETURNS: N/A
*
* NOMANUAL
*/
void igmpJoinAlert
(
int if_index /* index of port on which to add */
)
{
UINT32 port;
if ((igmpPortGet (if_index, &port) == ERROR))
return;
semTake (igmpMSem, WAIT_FOREVER);
++vs_igmp.port_table[port].igmpInterfaceEntry.igmpInterfaceJoins;
++vs_igmp.port_table[port].igmpInterfaceEntry.igmpInterfaceGroups;
semGive (igmpMSem);
}
/******************************************************************************
*
* igmpLeaveAlert - update Mib variables on leave
*
* Decrements the igmpInterfaceGroups value on the given interface.
*
* RETURNS: N/A
*
* NOMANUAL
*/
void igmpLeaveAlert
(
int if_index /* index of port where leave occurred */
)
{
UINT32 port;
if ((igmpPortGet(if_index, &port) == ERROR))
return;
semTake (igmpMSem, WAIT_FOREVER);
--vs_igmp.port_table[port].igmpInterfaceEntry.igmpInterfaceGroups;
semGive (igmpMSem);
}
/******************************************************************************
*
* igmpQuerierTimeUpdate - update Mib variable for version one querier
*
* Sets the igmpInterfaceEntry.igmpInterfaceVersion1QuerierTimer to the
* new value.
*
* RETURNS: N/A
*
* NOMANUAL
*/
void igmpQuerierTimeUpdate
(
int if_index, /* index of port on which to add */
int time /* half seconds left until v1 querier timer expires */
)
{
UINT32 port;
if ((igmpPortGet (if_index, &port) == ERROR))
return;
if (time < 0) /* sanity check */
time = 0;
semTake (igmpMSem, WAIT_FOREVER);
vs_igmp.port_table[port].igmpInterfaceEntry.igmpInterfaceVersion1QuerierTimer =
(IGMP_AGE_THRESHOLD - time) * 100/PR_SLOWHZ;
semGive (igmpMSem);
/* must convert from halfs to hundredths */
}