
This decouples the build and packaging of guest-server, guest-agent from mtce, by splitting guest component into stx-nfv repo. This leaves existing C++ code, scripts, and resource files untouched, so there is no functional change. Code refactoring is beyond the scope of this update. Makefiles were modified to include devel headers directories /usr/include/mtce-common and /usr/include/mtce-daemon. This ensures there is no contamination with other system headers. The cgts-mtce-common package is renamed and split into: - repo stx-metal: mtce-common, mtce-common-dev - repo stx-metal: mtce - repo stx-nfv: mtce-guest - repo stx-ha: updates package dependencies to mtce-pmon for service-mgmt, sm, and sm-api mtce-common: - contains common and daemon shared source utility code mtce-common-dev: - based on mtce-common, contains devel package required to build mtce-guest and mtce - contains common library archives and headers mtce: - contains components: alarm, fsmon, fsync, heartbeat, hostw, hwmon, maintenance, mtclog, pmon, public, rmon mtce-guest: - contains guest component guest-server, guest-agent Story: 2002829 Task: 22748 Change-Id: I9c7a9b846fd69fd566b31aa3f12a043c08f19f1f Signed-off-by: Jim Gauld <james.gauld@windriver.com>
1184 lines
48 KiB
C++
1184 lines
48 KiB
C++
/*
|
|
* Copyright (c) 2013-2016 Wind River Systems, Inc.
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*
|
|
*/
|
|
|
|
/**
|
|
* @file
|
|
* Wind River CGCS Platform Resource Monitor Interface Handler
|
|
*/
|
|
#include <iostream>
|
|
#include <stdio.h>
|
|
#include <unistd.h>
|
|
#include <stdlib.h>
|
|
#include <dirent.h>
|
|
#include <list>
|
|
#include <syslog.h>
|
|
#include <sys/wait.h>
|
|
#include <time.h>
|
|
#include <fstream>
|
|
#include <sstream>
|
|
#include <dirent.h>
|
|
#include <signal.h>
|
|
#include "rmon.h" /* rmon header file */
|
|
#include <algorithm>
|
|
#include "nlEvent.h" /* for ... get_netlink_events */
|
|
#include <string.h>
|
|
#include <net/if.h>
|
|
|
|
/* Used to set interface alarms through the FM API */
|
|
static SFmAlarmDataT alarmData;
|
|
|
|
/* Used to set port alarms through the FM API */
|
|
static SFmAlarmDataT alarmDataPOne;
|
|
|
|
/* Used to set port alarms through the FM API */
|
|
static SFmAlarmDataT alarmDataPTwo;
|
|
|
|
const char rmonStages_str [RMON_STAGE__STAGES][32] =
|
|
{
|
|
"Handler-Init",
|
|
"Handler-Start",
|
|
"Manage-Restart",
|
|
"Monitor-Wait",
|
|
"Monitor-Resource",
|
|
"Restart-Wait",
|
|
"Ignore-Resource",
|
|
"Handler-Finish",
|
|
"Failed-Resource",
|
|
"Failed-Resource-clr",
|
|
} ;
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* Name : interfaceResourceStageChange
|
|
*
|
|
* Purpose : Put an interface resource in the requested stage for use by the
|
|
* interface resource handler
|
|
*
|
|
*******************************************}
|
|
**********************************/
|
|
int interfaceResourceStageChange ( interface_resource_config_type * ptr , rmonStage_enum newStage )
|
|
{
|
|
if (( newStage < RMON_STAGE__STAGES ) &&
|
|
( ptr->stage < RMON_STAGE__STAGES ))
|
|
{
|
|
clog ("%s %s -> %s (%d->%d)\n",
|
|
ptr->resource,
|
|
rmonStages_str[ptr->stage],
|
|
rmonStages_str[newStage],
|
|
ptr->stage, newStage);
|
|
ptr->stage = newStage ;
|
|
return (PASS);
|
|
}
|
|
else
|
|
{
|
|
slog ("%s Invalid Stage (now:%d new:%d)\n",
|
|
ptr->resource, ptr->stage, newStage );
|
|
ptr->stage = RMON_STAGE__FINISH ;
|
|
return (FAIL);
|
|
}
|
|
}
|
|
|
|
/************************************************************
|
|
*
|
|
* Name : get_iflink_interface
|
|
*
|
|
* Purpose : get the ifname of the linked parent interface
|
|
***********************************************************/
|
|
string get_iflink_interface (string ifname)
|
|
{
|
|
|
|
string iflink_file = INTERFACES_DIR + ifname + "/iflink";
|
|
|
|
ifstream finIflink ( iflink_file.c_str() );
|
|
string iflink_line;
|
|
string ret = "";
|
|
char iface_buffer [INTERFACE_NAME_LEN] = "";
|
|
int iflink = -1;
|
|
|
|
if (finIflink.is_open())
|
|
{
|
|
|
|
while ( getline (finIflink, iflink_line) ) {
|
|
iflink = atoi(iflink_line.c_str());
|
|
}
|
|
finIflink.close();
|
|
|
|
if_indextoname (iflink, iface_buffer);
|
|
|
|
if (iface_buffer[0] != '\0')
|
|
ret = iface_buffer;
|
|
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* Name : init_physical_interfaces
|
|
*
|
|
* Purpose : Map an interface (mgmt, oam or infra) to a physical port
|
|
*
|
|
*****************************************************************************/
|
|
void init_physical_interfaces ( interface_resource_config_type * ptr )
|
|
{
|
|
FILE * pFile;
|
|
char line_buf[50];
|
|
string str;
|
|
string physical_interface = "";
|
|
enum interface_type { single, vlan, bond };
|
|
interface_type ifaceType; // default assumption
|
|
|
|
memset(ptr->interface_one, 0, sizeof(ptr->interface_one));
|
|
memset(ptr->interface_two, 0, sizeof(ptr->interface_two));
|
|
memset(ptr->bond, 0, sizeof(ptr->bond));
|
|
|
|
if ( strcmp(ptr->resource, MGMT_INTERFACE_NAME) == 0 )
|
|
{
|
|
str = MGMT_INTERFACE_FULLNAME;
|
|
}
|
|
else if ( strcmp(ptr->resource, INFRA_INTERFACE_NAME) == 0 )
|
|
{
|
|
str = INFRA_INTERFACE_FULLNAME;
|
|
}
|
|
else if ( strcmp(ptr->resource, OAM_INTERFACE_NAME) == 0 )
|
|
{
|
|
str = OAM_INTERFACE_FULLNAME;
|
|
}
|
|
|
|
|
|
pFile = fopen (PLATFORM_DIR , "r");
|
|
/* get the physical interface */
|
|
if (pFile != NULL)
|
|
{
|
|
ifstream fin( PLATFORM_DIR );
|
|
string line;
|
|
while ( getline( fin, line ) )
|
|
{
|
|
|
|
if ( line.find(str) != string::npos )
|
|
{
|
|
stringstream ss( line );
|
|
getline( ss, physical_interface, '=' ); // token = string before =
|
|
getline( ss, physical_interface, '=' ); // token = string after =
|
|
|
|
// determine the interface type
|
|
string uevent_interface_file = INTERFACES_DIR +
|
|
physical_interface + "/uevent";
|
|
ifstream finUevent( uevent_interface_file.c_str() );
|
|
|
|
// if we cannot locate this file then instead of disabling
|
|
// Kernel interface monitoring all together, we will use
|
|
// use the interface naming convention to do a best effort
|
|
// estimate of the interface type... the show must go on!
|
|
if (!finUevent) {
|
|
elog ("Cannot find uevent interface file (%s) to "
|
|
"resolve interface type for resource %s. "
|
|
"Disabling monitoring\n" ,
|
|
uevent_interface_file.c_str(), ptr->resource);
|
|
|
|
ptr->interface_used = false;
|
|
fclose(pFile);
|
|
return;
|
|
}
|
|
else { // proceed with uevent method
|
|
string line;
|
|
ifaceType = single;
|
|
while( getline( finUevent, line ) )
|
|
{
|
|
if ( line.find ("DEVTYPE") == 0 )
|
|
{
|
|
if ( line.find ("=vlan") != string::npos )
|
|
ifaceType = vlan;
|
|
else if ( line.find ("=bond") != string::npos )
|
|
ifaceType = bond;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
switch (ifaceType) {
|
|
case single:
|
|
memcpy(ptr->interface_one,
|
|
physical_interface.c_str(),
|
|
physical_interface.size());
|
|
ilog("Interface : %s : %s \n",
|
|
ptr->interface_one, ptr->resource );
|
|
break;
|
|
case bond:
|
|
memcpy(ptr->bond,
|
|
physical_interface.c_str(),
|
|
physical_interface.size());
|
|
ilog("Bond Interface : %s : %s \n",
|
|
ptr->bond, ptr->resource );
|
|
break;
|
|
case vlan:
|
|
ilog("VLAN Interface : %s : %s \n",
|
|
physical_interface.c_str(), ptr->resource);
|
|
// if it is a VLAN interface, we need
|
|
// to determine its parent interface,
|
|
// which may be a single interface or
|
|
// a bonded interface
|
|
string parent_interface = get_iflink_interface(physical_interface);
|
|
if (!parent_interface.empty()) {
|
|
|
|
dlog ("Parent interface for VLAN : %s\n",
|
|
parent_interface.c_str());
|
|
|
|
physical_interface = parent_interface;
|
|
|
|
string uevent_parent_file = INTERFACES_DIR +
|
|
parent_interface + "/uevent";
|
|
|
|
ifstream finUevent2( uevent_parent_file.c_str() );
|
|
string line;
|
|
bool bond_configured = false;
|
|
while( getline( finUevent2, line ) )
|
|
{
|
|
// if this uevent does not have a DEVTYPE
|
|
// then its a single interface. If this
|
|
// does have a DEVTYPE then check explicity
|
|
// for bond. Since we don't allow vlan over
|
|
// vlan, for all other DEVTYPEs, assume
|
|
// this is a single interface.
|
|
if ( (line.find ("DEVTYPE") == 0) &&
|
|
(line.find ("=bond") != string::npos) ) {
|
|
|
|
ilog ("Parent interface of VLAN interface "
|
|
"resolved as Bond\n");
|
|
bond_configured = true;
|
|
break;
|
|
}
|
|
}
|
|
if (!bond_configured) {
|
|
memcpy(ptr->interface_one,
|
|
parent_interface.c_str(),
|
|
parent_interface.size());
|
|
}
|
|
}
|
|
break;
|
|
} // end of switch
|
|
break;
|
|
}
|
|
}
|
|
fclose(pFile);
|
|
}
|
|
|
|
/* Lagged interface */
|
|
if ((ptr->interface_one[0] == '\0') && (!physical_interface.empty()))
|
|
{
|
|
|
|
string lagged_interface_file = INTERFACES_DIR +
|
|
physical_interface + "/bonding/slaves";
|
|
|
|
ifstream finTwo( lagged_interface_file.c_str() );
|
|
if (!finTwo) {
|
|
elog ("Cannot find bond interface file (%s) to "
|
|
"resolve slave interfaces\n", lagged_interface_file.c_str());
|
|
}
|
|
else {
|
|
string line;
|
|
while( getline( finTwo, line ) )
|
|
{
|
|
strcpy(line_buf, line.c_str());
|
|
// the slave interfaces are listed as enXYYY enXYYY...
|
|
// starting with the primary. Read all other slaves
|
|
// as interface_two
|
|
sscanf(line_buf, "%19s %19s", ptr->interface_one, ptr->interface_two);
|
|
ilog("%s interface: %s, interface two: %s \n", ptr->resource,
|
|
ptr->interface_one, ptr->interface_two);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if ( ptr->interface_one[0] == '\0' )
|
|
{
|
|
ptr->interface_used = false;
|
|
}
|
|
else
|
|
{
|
|
ptr->interface_used = true;
|
|
if ( ptr->interface_two[0] == '\0' )
|
|
{
|
|
/* this is not a lagged interface */
|
|
ptr->lagged = false;
|
|
} else {
|
|
/* this is a lagged interface */
|
|
ptr->lagged = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* Name : service_resource_state
|
|
*
|
|
* Purpose : Set the interface resource in the correct state for the interface
|
|
* resource handler
|
|
*
|
|
*****************************************************************************/
|
|
void service_resource_state ( interface_resource_config_type * ptr )
|
|
{
|
|
|
|
if (ptr->lagged == true)
|
|
{
|
|
/* the lagged interface is initialized */
|
|
if ((ptr->resource_value == INTERFACE_UP) && (ptr->resource_value_lagged == INTERFACE_UP) &&
|
|
(ptr->failed == true ))
|
|
{
|
|
/* If both interfaces are up and there is a fault, it needs to be cleared */
|
|
ptr->sev = SEVERITY_CLEARED;
|
|
interfaceResourceStageChange ( ptr, RMON_STAGE__FINISH );
|
|
}
|
|
else if ((((ptr->resource_value == INTERFACE_UP) && (ptr->resource_value_lagged == INTERFACE_DOWN)) ||
|
|
((ptr->resource_value_lagged == INTERFACE_UP) && (ptr->resource_value == INTERFACE_DOWN))) &&
|
|
(ptr->sev != SEVERITY_MAJOR))
|
|
{
|
|
/* if one interface failed its a major condition */
|
|
|
|
if (ptr->sev == SEVERITY_CRITICAL)
|
|
{
|
|
/* need to clear port alarm but not interface alarm */
|
|
interfaceResourceStageChange ( ptr, RMON_STAGE__FAILED_CLR );
|
|
}
|
|
else
|
|
{
|
|
interfaceResourceStageChange ( ptr, RMON_STAGE__MANAGE);
|
|
}
|
|
|
|
ptr->failed = true;
|
|
ptr->sev = SEVERITY_MAJOR;
|
|
}
|
|
else if (((ptr->resource_value == INTERFACE_DOWN) && (ptr->resource_value_lagged == INTERFACE_DOWN)) &&
|
|
(ptr->sev != SEVERITY_CRITICAL))
|
|
{
|
|
/* both lagged interfaces failed, this is a critical condition */
|
|
ptr->failed = true;
|
|
ptr->sev = SEVERITY_CRITICAL ;
|
|
interfaceResourceStageChange ( ptr, RMON_STAGE__MANAGE);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* interface is not lagged */
|
|
if ( (ptr->resource_value == INTERFACE_DOWN) && (ptr->sev != SEVERITY_CRITICAL) )
|
|
{
|
|
/* the interface has failed */
|
|
ptr->failed = true;
|
|
ptr->sev = SEVERITY_CRITICAL ;
|
|
interfaceResourceStageChange ( ptr, RMON_STAGE__MANAGE);
|
|
}
|
|
else if ((ptr->resource_value == INTERFACE_UP) && (ptr->failed == true ))
|
|
{
|
|
/* If the interface is up and there is a fault, it needs to be cleared */
|
|
ptr->sev = SEVERITY_CLEARED;
|
|
interfaceResourceStageChange ( ptr, RMON_STAGE__FINISH );
|
|
}
|
|
}
|
|
}
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* Name : get_link_state
|
|
*
|
|
* Purpose : Check to see if the current interface link is up or down
|
|
*
|
|
*****************************************************************************/
|
|
int get_link_state ( int ioctl_socket, char iface[20], bool * running_ptr )
|
|
{
|
|
int get_link_state_throttle = 0 ;
|
|
struct ifreq if_data;
|
|
int rc = FAIL ;
|
|
|
|
if (iface[0] == '\0')
|
|
{
|
|
elog ("Null interface name\n");
|
|
return ( rc ) ;
|
|
}
|
|
|
|
memset( &if_data, 0, sizeof(if_data) );
|
|
sprintf( if_data.ifr_name, "%s", iface );
|
|
if( 0 <= ioctl( ioctl_socket, SIOCGIFFLAGS, &if_data ) )
|
|
{
|
|
if( if_data.ifr_flags & IFF_RUNNING )
|
|
{
|
|
*running_ptr = true;
|
|
}
|
|
else
|
|
{
|
|
*running_ptr = false;
|
|
}
|
|
|
|
/* reset log flood gate counter */
|
|
get_link_state_throttle = 0 ;
|
|
|
|
rc = PASS ;
|
|
}
|
|
else
|
|
{
|
|
wlog_throttled (get_link_state_throttle, 100,
|
|
"Failed to get %s (%s) interface state (%d:%s)\n",
|
|
iface, if_data.ifr_name, errno, strerror(errno));
|
|
}
|
|
return ( rc );
|
|
}
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* Name : service_interface_events
|
|
*
|
|
* Purpose : Service state changes for monitored interfaces
|
|
*
|
|
*****************************************************************************/
|
|
int service_interface_events ( int nl_socket , int ioctl_socket )
|
|
{
|
|
list<string> links_gone_down ;
|
|
list<string> links_gone_up ;
|
|
list<string>::iterator iter_curr_ptr ;
|
|
rmon_ctrl_type * _rmon_ctrl_ptr;
|
|
interface_resource_config_type * ptr;
|
|
|
|
_rmon_ctrl_ptr = get_rmon_ctrl_ptr();
|
|
if ( get_netlink_events ( nl_socket, links_gone_down, links_gone_up ) )
|
|
{
|
|
for (int i=0; i<_rmon_ctrl_ptr->interface_resources; i++)
|
|
{
|
|
ptr = get_interface_ptr(i);
|
|
if ( ptr->interface_used == true )
|
|
{
|
|
|
|
bool running = false ;
|
|
|
|
if ( !links_gone_down.empty() )
|
|
{
|
|
/* Look at the down list */
|
|
for ( iter_curr_ptr = links_gone_down.begin();
|
|
iter_curr_ptr != links_gone_down.end() ;
|
|
iter_curr_ptr++ )
|
|
{
|
|
if ( strcmp ( ptr->interface_one, iter_curr_ptr->c_str()) == 0 )
|
|
{
|
|
wlog ("link %s is down\n", ptr->interface_one );
|
|
|
|
if ( get_link_state ( ioctl_socket, iter_curr_ptr->c_str(), &running ) == PASS )
|
|
{
|
|
wlog ("%s is down (oper:%s)\n",
|
|
iter_curr_ptr->c_str(),
|
|
running ? "up" : "down" );
|
|
if (!running)
|
|
{
|
|
ptr->resource_value = INTERFACE_DOWN;
|
|
}
|
|
else
|
|
{
|
|
ptr->resource_value = INTERFACE_UP;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
wlog ("%s is down (driver query failed)\n", iter_curr_ptr->c_str() );
|
|
ptr->resource_value = INTERFACE_DOWN;
|
|
}
|
|
}
|
|
|
|
if (ptr->lagged == true)
|
|
{
|
|
if ( strcmp ( ptr->interface_two, iter_curr_ptr->c_str()) == 0 )
|
|
{
|
|
wlog ("link %s is down\n", ptr->interface_two);
|
|
|
|
if ( get_link_state ( ioctl_socket, iter_curr_ptr->c_str(), &running ) == PASS )
|
|
{
|
|
wlog ("%s is down (oper:%s)\n",
|
|
iter_curr_ptr->c_str(),
|
|
running ? "up" : "down" );
|
|
if (!running)
|
|
{
|
|
ptr->resource_value_lagged = INTERFACE_DOWN;
|
|
}
|
|
else
|
|
{
|
|
ptr->resource_value_lagged = INTERFACE_UP;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
wlog ("%s is down (driver query failed)\n", iter_curr_ptr->c_str() );
|
|
ptr->resource_value_lagged = INTERFACE_DOWN;
|
|
}
|
|
}
|
|
if ( strcmp ( ptr->bond, iter_curr_ptr->c_str()) == 0 )
|
|
{
|
|
wlog ("bond: %s is down\n", ptr->bond);
|
|
//ptr->resource_value_lagged = INTERFACE_DOWN;
|
|
//ptr->resource_value = INTERFACE_DOWN;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if ( !links_gone_up.empty() )
|
|
{
|
|
//wlog ("one or more links have dropped\n");
|
|
/* Look at the down list */
|
|
for ( iter_curr_ptr = links_gone_up.begin();
|
|
iter_curr_ptr != links_gone_up.end() ;
|
|
iter_curr_ptr++ )
|
|
{
|
|
|
|
if ( strcmp ( ptr->interface_one, iter_curr_ptr->c_str()) == 0 )
|
|
{
|
|
wlog ("link %s is up\n", ptr->interface_one );
|
|
|
|
if ( get_link_state ( ioctl_socket, iter_curr_ptr->c_str(), &running ) == PASS )
|
|
{
|
|
wlog ("%s is up (oper:%s)\n",
|
|
iter_curr_ptr->c_str(),
|
|
running ? "up" : "down" );
|
|
if (!running)
|
|
{
|
|
ptr->resource_value = INTERFACE_DOWN;
|
|
}
|
|
else
|
|
{
|
|
ptr->resource_value = INTERFACE_UP;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
wlog ("%s is down(driver query failed)\n", iter_curr_ptr->c_str() );
|
|
ptr->resource_value = INTERFACE_DOWN;
|
|
}
|
|
}
|
|
if (ptr->lagged == true)
|
|
{
|
|
if ( strcmp ( ptr->interface_two, iter_curr_ptr->c_str()) == 0 )
|
|
{
|
|
wlog ("link %s is up\n", ptr->interface_two );
|
|
|
|
if ( get_link_state ( ioctl_socket, iter_curr_ptr->c_str(), &running ) == PASS )
|
|
{
|
|
wlog ("%s is up (oper:%s)\n",
|
|
iter_curr_ptr->c_str(),
|
|
running ? "up" : "down" );
|
|
if (!running)
|
|
{
|
|
ptr->resource_value_lagged = INTERFACE_DOWN;
|
|
}
|
|
else
|
|
{
|
|
ptr->resource_value_lagged = INTERFACE_UP;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
wlog ("%s is down (driver query failed)\n", iter_curr_ptr->c_str() );
|
|
ptr->resource_value_lagged = INTERFACE_DOWN;
|
|
}
|
|
}
|
|
if ( strcmp ( ptr->bond, iter_curr_ptr->c_str()) == 0 )
|
|
{
|
|
wlog ("bond: %s is up\n", ptr->bond);
|
|
//ptr->resource_value_lagged = INTERFACE_UP;
|
|
//ptr->resource_value = INTERFACE_UP;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
/* set the states for the interface handler */
|
|
service_resource_state( ptr );
|
|
}
|
|
}
|
|
}
|
|
|
|
return (PASS);
|
|
}
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* Name : interface_alarming_init
|
|
*
|
|
* Purpose : Initializes any previously raised interface alarms if rmon is restarted
|
|
*
|
|
*****************************************************************************/
|
|
void interface_alarming_init ( interface_resource_config_type * ptr)
|
|
{
|
|
AlarmFilter alarmFilter;
|
|
ptr->failed = false;
|
|
rmon_ctrl_type * _rmon_ctrl_ptr;
|
|
|
|
_rmon_ctrl_ptr = get_rmon_ctrl_ptr();
|
|
|
|
/* handle active alarms for the interface ports */
|
|
SFmAlarmDataT *intf_alarms = NULL;
|
|
unsigned int num_intf_alarms = 0;
|
|
strcpy(alarmFilter.alarm_id, ptr->alarm_id_port);
|
|
strcpy(alarmFilter.entity_instance_id, _rmon_ctrl_ptr->my_hostname);
|
|
strcat(alarmFilter.entity_instance_id, ".port=");
|
|
|
|
if (rmon_fm_get(&alarmFilter, &intf_alarms, &num_intf_alarms) == FM_ERR_OK)
|
|
{
|
|
bool intf_one_found = false;
|
|
bool intf_two_found = false;
|
|
SFmAlarmDataT *a = intf_alarms;
|
|
|
|
for( unsigned int i = 0; i < num_intf_alarms; i++, a++ )
|
|
{
|
|
/* only handle specific port alarm */
|
|
if (strncmp(a->alarm_id, ptr->alarm_id_port, sizeof(a->alarm_id)) == 0)
|
|
{
|
|
/* check interface port one alarm */
|
|
if (!intf_one_found && ptr->interface_one[0] != '\0')
|
|
{
|
|
if (strstr(a->entity_instance_id, ptr->interface_one))
|
|
{
|
|
ptr->failed = true;
|
|
intf_one_found = true;
|
|
}
|
|
}
|
|
|
|
/* check interface port two alarm */
|
|
if (!intf_two_found && ptr->interface_two[0] != '\0')
|
|
{
|
|
if (strstr(a->entity_instance_id, ptr->interface_two))
|
|
{
|
|
ptr->failed = true;
|
|
intf_two_found = true;
|
|
}
|
|
}
|
|
|
|
/* clear this alarm as it is no longer valid as the interface ports have
|
|
changed */
|
|
if (!intf_one_found && !intf_two_found)
|
|
{
|
|
ilog("clearing alarm %s", a->entity_instance_id);
|
|
strcpy(alarmFilter.entity_instance_id, a->entity_instance_id);
|
|
rmon_fm_clear (&alarmFilter);
|
|
}
|
|
}
|
|
}
|
|
|
|
free(intf_alarms);
|
|
}
|
|
|
|
/* handle interface alarm */
|
|
SFmAlarmDataT *active_alarm = (SFmAlarmDataT*) malloc (sizeof (SFmAlarmDataT));
|
|
strcpy(alarmFilter.alarm_id, ptr->alarm_id);
|
|
strcpy(alarmFilter.entity_instance_id, _rmon_ctrl_ptr->my_hostname);
|
|
strcat(alarmFilter.entity_instance_id, ".interface=");
|
|
strcat(alarmFilter.entity_instance_id, ptr->resource);
|
|
|
|
if (fm_get_fault( &alarmFilter, active_alarm) == FM_ERR_OK)
|
|
{
|
|
if (active_alarm != NULL)
|
|
{
|
|
ptr->failed = true;
|
|
}
|
|
}
|
|
|
|
free(active_alarm);
|
|
|
|
/*
|
|
* If the interface is DOWN, and neither a port
|
|
* nor an interface alarm is found for that interface,
|
|
* then that implies that the interface was DOWN before
|
|
* RMON came up. Consider that as a failed case as well
|
|
*/
|
|
if (ptr->interface_used && !ptr->failed &&
|
|
(ptr->resource_value == INTERFACE_DOWN ||
|
|
ptr->resource_value_lagged == INTERFACE_DOWN)) {
|
|
ilog("Interface %s has initial state DOWN. Marked as failed\n",
|
|
ptr->resource);
|
|
ptr->failed = true;
|
|
}
|
|
|
|
/* service interface resource */
|
|
if (ptr->failed)
|
|
{
|
|
ptr->alarm_raised = true;
|
|
service_resource_state ( ptr );
|
|
}
|
|
}
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* Name : _set_alarm_defaults
|
|
*
|
|
* Purpose : Set the defaults for the interface and port alarms
|
|
* *****************************************************************************/
|
|
void _set_alarm_defaults( interface_resource_config_type * ptr, rmon_ctrl_type * _rmon_ctrl_ptr )
|
|
{
|
|
/* common data for all alarm messages */
|
|
|
|
/* Interface alarms */
|
|
strcpy(alarmData.uuid, "");
|
|
strcpy(alarmData.entity_type_id ,"system.host");
|
|
strcpy(alarmData.entity_instance_id, _rmon_ctrl_ptr->my_hostname);
|
|
strcat(alarmData.entity_instance_id, ".interface=");
|
|
alarmData.alarm_state = FM_ALARM_STATE_SET;
|
|
alarmData.alarm_type = FM_ALARM_OPERATIONAL;
|
|
alarmData.probable_cause = FM_ALARM_CAUSE_UNKNOWN;
|
|
snprintf(alarmData.proposed_repair_action , sizeof(alarmData.proposed_repair_action),
|
|
"Check cabling and far-end port configuration and status on adjacent equipment.");
|
|
alarmData.timestamp = 0;
|
|
alarmData.service_affecting = FM_TRUE;
|
|
alarmData.suppression = FM_TRUE;
|
|
strcpy(alarmData.alarm_id, ptr->alarm_id);
|
|
|
|
/* Port One alarms */
|
|
strcpy(alarmDataPOne.uuid, "");
|
|
strcpy(alarmDataPOne.entity_type_id ,"system.host");
|
|
strcpy(alarmDataPOne.entity_instance_id, _rmon_ctrl_ptr->my_hostname);
|
|
strcat(alarmDataPOne.entity_instance_id, ".port=");
|
|
alarmDataPOne.alarm_state = FM_ALARM_STATE_SET;
|
|
alarmDataPOne.alarm_type = FM_ALARM_OPERATIONAL;
|
|
alarmDataPOne.probable_cause = FM_ALARM_CAUSE_UNKNOWN;
|
|
snprintf(alarmDataPOne.proposed_repair_action , sizeof(alarmDataPOne.proposed_repair_action),
|
|
"Check cabling and far-end port configuration and status on adjacent equipment.");
|
|
alarmDataPOne.timestamp = 0;
|
|
alarmDataPOne.service_affecting = FM_TRUE;
|
|
alarmDataPOne.suppression = FM_TRUE;
|
|
strcpy(alarmDataPOne.alarm_id, ptr->alarm_id_port);
|
|
|
|
/* Port Two alarms */
|
|
strcpy(alarmDataPTwo.uuid, "");
|
|
strcpy(alarmDataPTwo.entity_type_id ,"system.host");
|
|
strcpy(alarmDataPTwo.entity_instance_id, _rmon_ctrl_ptr->my_hostname);
|
|
strcat(alarmDataPTwo.entity_instance_id, ".port=");
|
|
alarmDataPTwo.alarm_state = FM_ALARM_STATE_SET;
|
|
alarmDataPTwo.alarm_type = FM_ALARM_OPERATIONAL;
|
|
alarmDataPTwo.probable_cause = FM_ALARM_CAUSE_UNKNOWN;
|
|
snprintf(alarmDataPTwo.proposed_repair_action , sizeof(alarmDataPTwo.proposed_repair_action),
|
|
"Check cabling and far-end port configuration and status on adjacent equipment.");
|
|
alarmDataPTwo.timestamp = 0;
|
|
alarmDataPTwo.service_affecting = FM_TRUE;
|
|
alarmDataPTwo.suppression = FM_TRUE;
|
|
strcpy(alarmDataPTwo.alarm_id, ptr->alarm_id_port);
|
|
}
|
|
|
|
/*****************************************************************************
|
|
*
|
|
* Name : interface_handler
|
|
*
|
|
* Purpose : Handle the failed interfaces and raise alarms through
|
|
* the FM API as well as sending events to registered clients
|
|
*****************************************************************************/
|
|
void interface_handler( interface_resource_config_type * ptr )
|
|
{
|
|
#define MAX_CLEAR_COUNT (10)
|
|
AlarmFilter alarmFilter;
|
|
bool portOne = false;
|
|
bool portTwo = false;
|
|
|
|
rmon_ctrl_type * _rmon_ctrl_ptr;
|
|
|
|
_rmon_ctrl_ptr = get_rmon_ctrl_ptr();
|
|
|
|
if ( ptr->stage < RMON_STAGE__STAGES )
|
|
{
|
|
dlog2 ("%s %s Stage %d\n", ptr->resource, rmonStages_str[ptr->stage], ptr->stage );
|
|
}
|
|
else
|
|
{
|
|
interfaceResourceStageChange ( ptr, RMON_STAGE__FINISH );
|
|
}
|
|
|
|
switch ( ptr->stage )
|
|
{
|
|
case RMON_STAGE__START:
|
|
{
|
|
dlog ( "%s failed:%d set_cnt:%d debounce_cnt:%d\n",
|
|
ptr->resource,
|
|
ptr->failed,
|
|
ptr->count,
|
|
ptr->debounce_cnt);
|
|
break ;
|
|
}
|
|
case RMON_STAGE__MANAGE:
|
|
|
|
|
|
{
|
|
/* sets alarms if thresholds are crossed */
|
|
if (ptr->alarm_status == ALARM_ON)
|
|
{
|
|
|
|
_set_alarm_defaults( ptr, _rmon_ctrl_ptr );
|
|
|
|
/* Interface and Port alarming */
|
|
if (strcmp(ptr->resource, OAM_INTERFACE_NAME) == 0)
|
|
{
|
|
if ( ptr->sev == SEVERITY_CRITICAL )
|
|
{
|
|
alarmData.severity = FM_ALARM_SEVERITY_CRITICAL;
|
|
ilog ("'OAM' Interface failed. \n");
|
|
snprintf(alarmData.reason_text, sizeof(alarmData.reason_text),
|
|
"'OAM' Interface failed.");
|
|
}
|
|
else if ( ptr->sev == SEVERITY_MAJOR )
|
|
{
|
|
alarmData.severity = FM_ALARM_SEVERITY_MAJOR;
|
|
ilog ("'OAM' Interface degraded. \n");
|
|
snprintf(alarmData.reason_text, sizeof(alarmData.reason_text),
|
|
"'OAM' Interface degraded.");
|
|
}
|
|
|
|
if ((ptr->interface_one[0] != '\0') && (ptr->resource_value == INTERFACE_DOWN))
|
|
{
|
|
portOne = true;
|
|
ilog ("'OAM' Port failed. \n");
|
|
snprintf(alarmDataPOne.reason_text, sizeof(alarmDataPOne.reason_text),
|
|
"'OAM' Port failed.");
|
|
/* Set port name in entity instance ID */
|
|
strcat(alarmDataPOne.entity_instance_id, ptr->interface_one);
|
|
|
|
}
|
|
if ((ptr->interface_two[0] != '\0') && (ptr->resource_value_lagged == INTERFACE_DOWN))
|
|
{
|
|
portTwo = true;
|
|
ilog ("'OAM' Port failed. \n");
|
|
snprintf(alarmDataPTwo.reason_text, sizeof(alarmDataPTwo.reason_text),
|
|
"'OAM' Port failed.");
|
|
/* Set port name in entity instance ID */
|
|
strcat(alarmDataPTwo.entity_instance_id, ptr->interface_two);
|
|
}
|
|
}
|
|
else if (strcmp(ptr->resource, MGMT_INTERFACE_NAME) == 0)
|
|
{
|
|
if ( ptr->sev == SEVERITY_CRITICAL )
|
|
{
|
|
alarmData.severity = FM_ALARM_SEVERITY_CRITICAL;
|
|
ilog ("'MGMT' Interface failed. \n");
|
|
snprintf(alarmData.reason_text, sizeof(alarmData.reason_text),
|
|
"'MGMT' Interface failed.");
|
|
}
|
|
else if ( ptr->sev == SEVERITY_MAJOR )
|
|
{
|
|
alarmData.severity = FM_ALARM_SEVERITY_MAJOR;
|
|
ilog ("'MGMT' Interface degraded. \n");
|
|
snprintf(alarmData.reason_text, sizeof(alarmData.reason_text),
|
|
"'MGMT' Interface degraded.");
|
|
}
|
|
|
|
if ((ptr->interface_one[0] != '\0') && (ptr->resource_value == INTERFACE_DOWN))
|
|
{
|
|
portOne = true;
|
|
ilog ("'MGMT' Port failed. \n");
|
|
snprintf(alarmDataPOne.reason_text, sizeof(alarmDataPOne.reason_text),
|
|
"'MGMT' Port failed.");
|
|
/* Set port name in entity instance ID */
|
|
strcat(alarmDataPOne.entity_instance_id, ptr->interface_one);
|
|
|
|
}
|
|
if ((ptr->interface_two[0] != '\0') && (ptr->resource_value_lagged == INTERFACE_DOWN))
|
|
{
|
|
portTwo = true;
|
|
ilog ("'MGMT' Port failed. \n");
|
|
snprintf(alarmDataPTwo.reason_text, sizeof(alarmDataPTwo.reason_text),
|
|
"'MGMT' Port failed.");
|
|
/* Set port name in entity instance ID */
|
|
strcat(alarmDataPTwo.entity_instance_id, ptr->interface_two);
|
|
}
|
|
}
|
|
else if (strcmp(ptr->resource, INFRA_INTERFACE_NAME) == 0)
|
|
{
|
|
if ( ptr->sev == SEVERITY_CRITICAL )
|
|
{
|
|
alarmData.severity = FM_ALARM_SEVERITY_CRITICAL;
|
|
ilog ("'INFRA' Interface failed. \n");
|
|
snprintf(alarmData.reason_text, sizeof(alarmData.reason_text),
|
|
"'INFRA' Interface failed.");
|
|
}
|
|
else if ( ptr->sev == SEVERITY_MAJOR )
|
|
{
|
|
alarmData.severity = FM_ALARM_SEVERITY_MAJOR;
|
|
ilog ("'INFRA' Interface degraded. \n");
|
|
snprintf(alarmData.reason_text, sizeof(alarmData.reason_text),
|
|
"'INFRA' Interface degraded.");
|
|
}
|
|
|
|
if ((ptr->interface_one[0] != '\0') && (ptr->resource_value == INTERFACE_DOWN))
|
|
{
|
|
portOne = true;
|
|
ilog ("'INFRA' Port failed. \n");
|
|
snprintf(alarmDataPOne.reason_text, sizeof(alarmDataPOne.reason_text),
|
|
"'INFRA' Port failed.");
|
|
/* Set port name in entity instance ID */
|
|
strcat(alarmDataPOne.entity_instance_id, ptr->interface_one);
|
|
|
|
}
|
|
if ((ptr->interface_two[0] != '\0') && (ptr->resource_value_lagged == INTERFACE_DOWN))
|
|
{
|
|
portTwo = true;
|
|
ilog ("'INFRA' Port failed. \n");
|
|
snprintf(alarmDataPTwo.reason_text, sizeof(alarmDataPTwo.reason_text),
|
|
"'INFRA' Port failed.");
|
|
/* Set port name in entity instance ID */
|
|
strcat(alarmDataPTwo.entity_instance_id, ptr->interface_two);
|
|
}
|
|
}
|
|
snprintf(ptr->errorMsg, sizeof(ptr->errorMsg),
|
|
"%s major_threshold_set",ptr->resource);
|
|
|
|
/* Set interface name in entity instance ID */
|
|
strcat(alarmData.entity_instance_id, ptr->resource);
|
|
|
|
dlog("Creating Interface Alarm: %s \n", ptr->resource);
|
|
if (rmon_fm_set(&alarmData, NULL) == FM_ERR_OK )
|
|
{
|
|
ilog("Alarm created for resource: %s \n", ptr->resource);
|
|
ptr->alarm_raised = true;
|
|
}
|
|
else
|
|
{
|
|
ilog("Alarm create for resource: %s failed \n", ptr->resource);
|
|
}
|
|
|
|
|
|
if (portOne)
|
|
{
|
|
alarmDataPOne.severity = FM_ALARM_SEVERITY_MAJOR;
|
|
dlog("Creating Port One Alarm: %s \n", ptr->resource);
|
|
if (rmon_fm_set(&alarmDataPOne, NULL) == FM_ERR_OK )
|
|
{
|
|
ilog("Alarm created for resource: %s port one \n", ptr->resource);
|
|
} else
|
|
{
|
|
ilog("Alarm create for resource: %s port one failed \n", ptr->resource);
|
|
}
|
|
}
|
|
|
|
if (portTwo)
|
|
{
|
|
alarmDataPTwo.severity = FM_ALARM_SEVERITY_MAJOR;
|
|
dlog("Creating Port Two Alarm: %s \n", ptr->resource);
|
|
if (rmon_fm_set(&alarmDataPTwo, NULL) == FM_ERR_OK )
|
|
{
|
|
ilog("Alarm created for resource: %s port two \n", ptr->resource);
|
|
} else
|
|
{
|
|
ilog("Alarm create for resource: %s port two failed \n", ptr->resource);
|
|
}
|
|
}
|
|
|
|
|
|
if (ptr->alarm_raised)
|
|
{
|
|
if ((_rmon_ctrl_ptr->clients > 0) && (ptr->failed_send < MAX_FAIL_SEND))
|
|
{
|
|
if ( send_interface_msg ( ptr, _rmon_ctrl_ptr->clients ) != PASS )
|
|
{
|
|
wlog ("%s request send failed \n", ptr->resource);
|
|
ptr->failed_send++;
|
|
}
|
|
else
|
|
{
|
|
ptr->failed_send = 0;
|
|
}
|
|
interfaceResourceStageChange ( ptr, RMON_STAGE__MONITOR_WAIT );
|
|
}
|
|
else
|
|
{
|
|
ptr->failed_send = 0;
|
|
interfaceResourceStageChange ( ptr, RMON_STAGE__MONITOR_WAIT );
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
interfaceResourceStageChange ( ptr, RMON_STAGE__FINISH );
|
|
}
|
|
break;
|
|
}
|
|
|
|
case RMON_STAGE__MONITOR_WAIT:
|
|
{
|
|
if ((_rmon_ctrl_ptr->clients > 0) && (ptr->failed_send < MAX_FAIL_SEND) && (ptr->failed_send > 0))
|
|
{
|
|
if ( send_interface_msg ( ptr, _rmon_ctrl_ptr->clients ) != PASS )
|
|
{
|
|
wlog ("%s request send failed \n", ptr->resource);
|
|
ptr->failed_send++;
|
|
}
|
|
else
|
|
{
|
|
ptr->failed_send = 0;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
|
|
case RMON_STAGE__FAILED_CLR:
|
|
{
|
|
/* clear raised port alarms if one port comes back up */
|
|
if (ptr->alarm_raised)
|
|
{
|
|
SFmAlarmDataT *active_alarm = (SFmAlarmDataT*) malloc (sizeof (SFmAlarmDataT));
|
|
strcpy(alarmFilter.alarm_id, ptr->alarm_id_port);
|
|
|
|
if (ptr->interface_one[0] != '\0')
|
|
{
|
|
strcpy(alarmFilter.entity_instance_id, _rmon_ctrl_ptr->my_hostname);
|
|
strcat(alarmFilter.entity_instance_id, ".port=");
|
|
strcat(alarmFilter.entity_instance_id, ptr->interface_one);
|
|
|
|
if (fm_get_fault( &alarmFilter, active_alarm) == FM_ERR_OK)
|
|
{
|
|
if (active_alarm != NULL)
|
|
{
|
|
if ( ptr->resource_value == INTERFACE_UP )
|
|
{
|
|
if (rmon_fm_clear(&alarmFilter) == FM_ERR_OK)
|
|
{
|
|
ilog ("Cleared alarms for port one, interface: %s \n", ptr->resource);
|
|
}
|
|
else
|
|
{
|
|
ilog ("Failed to cleared alarms for port one, interface: %s \n", ptr->resource);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (ptr->interface_two[0] != '\0')
|
|
{
|
|
strcpy(alarmFilter.entity_instance_id, _rmon_ctrl_ptr->my_hostname);
|
|
strcat(alarmFilter.entity_instance_id, ".port=");
|
|
strcat(alarmFilter.entity_instance_id, ptr->interface_two);
|
|
|
|
if (fm_get_fault( &alarmFilter, active_alarm) == FM_ERR_OK)
|
|
{
|
|
if (active_alarm != NULL)
|
|
{
|
|
if ( ptr->resource_value_lagged == INTERFACE_UP )
|
|
{
|
|
if (rmon_fm_clear(&alarmFilter) == FM_ERR_OK)
|
|
{
|
|
ilog ("Cleared alarms for port two, interface: %s \n", ptr->resource);
|
|
}
|
|
else
|
|
{
|
|
ilog ("Failed to cleared alarms for port two, interface: %s \n", ptr->resource);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
free(active_alarm);
|
|
}
|
|
|
|
interfaceResourceStageChange ( ptr, RMON_STAGE__MANAGE);
|
|
break;
|
|
}
|
|
|
|
case RMON_STAGE__FINISH:
|
|
{
|
|
|
|
if ((ptr->alarm_status == ALARM_ON) && (ptr->alarm_raised))
|
|
{
|
|
strcpy(alarmFilter.alarm_id, ptr->alarm_id_port);
|
|
|
|
if (ptr->interface_one[0] != '\0')
|
|
{
|
|
/* clear port one alarm */
|
|
strcpy(alarmFilter.entity_instance_id,_rmon_ctrl_ptr->my_hostname);
|
|
strcat(alarmFilter.entity_instance_id, ".port=");
|
|
strcat(alarmFilter.entity_instance_id, ptr->interface_one);
|
|
|
|
EFmErrorT err = rmon_fm_clear(&alarmFilter);
|
|
if ((err == FM_ERR_OK) || (err == FM_ERR_ENTITY_NOT_FOUND))
|
|
{
|
|
ilog ("Cleared alarms for port one, interface: %s \n", ptr->resource);
|
|
}
|
|
else
|
|
{
|
|
ilog ("Failed to cleared alarm for port one, interface: %s (rc:%d)\n", ptr->resource, err);
|
|
}
|
|
}
|
|
if (ptr->interface_two[0] != '\0')
|
|
{
|
|
/* clear port two alarm */
|
|
strcpy(alarmFilter.entity_instance_id,_rmon_ctrl_ptr->my_hostname);
|
|
strcat(alarmFilter.entity_instance_id, ".port=");
|
|
strcat(alarmFilter.entity_instance_id, ptr->interface_two);
|
|
|
|
EFmErrorT err = rmon_fm_clear(&alarmFilter);
|
|
if ((err == FM_ERR_OK) || (err == FM_ERR_ENTITY_NOT_FOUND))
|
|
{
|
|
ilog ("Cleared alarms for port two, interface: %s \n", ptr->resource);
|
|
}
|
|
else
|
|
{
|
|
elog ("Failed to cleared alarms for port two, interface: %s (rc:%d)\n", ptr->resource, err );
|
|
}
|
|
}
|
|
|
|
/* clear interface alarm */
|
|
strcpy(alarmFilter.alarm_id, ptr->alarm_id);
|
|
strcpy(alarmFilter.entity_instance_id,_rmon_ctrl_ptr->my_hostname);
|
|
strcat(alarmFilter.entity_instance_id, ".interface=");
|
|
strcat(alarmFilter.entity_instance_id, ptr->resource);
|
|
|
|
EFmErrorT err = rmon_fm_clear(&alarmFilter);
|
|
if ((err == FM_ERR_OK) || (err == FM_ERR_ENTITY_NOT_FOUND))
|
|
{
|
|
ilog ("Cleared alarms for interface: %s \n", ptr->resource);
|
|
snprintf(ptr->errorMsg, sizeof(ptr->errorMsg),
|
|
"%s cleared_alarms_for_resource:", ptr->resource);
|
|
|
|
if ((_rmon_ctrl_ptr->clients > 0) && (ptr->failed_send < MAX_FAIL_SEND))
|
|
{
|
|
while (( send_interface_msg ( ptr, _rmon_ctrl_ptr->clients ) != PASS ) &&
|
|
( ptr->failed_send < MAX_FAIL_SEND ))
|
|
{
|
|
wlog ("%s request send failed \n", ptr->resource);
|
|
ptr->failed_send++;
|
|
}
|
|
ptr->alarm_raised = false;
|
|
ptr->failed_send = 0;
|
|
ptr->failed = false ;
|
|
ptr->count = 0;
|
|
ptr->sev = SEVERITY_CLEARED ;
|
|
ptr->stage = RMON_STAGE__START ;
|
|
}
|
|
else
|
|
{
|
|
ptr->alarm_raised = false;
|
|
ptr->failed_send = 0;
|
|
ptr->failed = false ;
|
|
ptr->count = 0 ;
|
|
ptr->sev = SEVERITY_CLEARED ;
|
|
ptr->stage = RMON_STAGE__START ;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
wlog ("%s alarm clear failed (rc:%d)\n", ptr->resource, err);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ptr->failed_send = 0;
|
|
ptr->failed = false ;
|
|
ptr->count = 0 ;
|
|
ptr->sev = SEVERITY_CLEARED ;
|
|
ptr->stage = RMON_STAGE__START ;
|
|
}
|
|
break ;
|
|
}
|
|
|
|
default:
|
|
{
|
|
slog ("%s Invalid stage (%d)\n", ptr->resource, ptr->stage );
|
|
|
|
/* Default to finish for invalid case.
|
|
* If there is an issue then it will be detected */
|
|
interfaceResourceStageChange ( ptr, RMON_STAGE__FINISH );
|
|
}
|
|
}
|
|
}
|