Add new Link Monitor (lmond) daemon to Mtce

This update introduces a new Link Monitor daemon to the Mtce
flock of daemons and disable rmon's interface monitoring.

This new daemon parses the platform.conf file and using the
interface names assigned to each monitored network (mgmt,
infra and oam) queries the kernel for their physical,
bonded and vlan interface names and then registers to listen
for netlink events.

All link/interface state change (netlink) events that correspond
to any of the interfaces or links assiciated with the monitored
networks are tracked by this new daemon.

This new daemon then also implements an http listener for
localhost initiated GET requests targeted to /mtce/lmond
on port 2122 and responds with a json link_info string that
contains a summary of monitored networks, links and their
current Up/Down status.

lmond behavioral summary:
  1. learn interface/port model,
  2. load initial link status for learned links,
  3. listen for link status change events
  4. provide link status info to http GET Query requests.

Another update to stx-integ implements the collectd interface
plugin that periodically issues the Link Status GET requests
for the purponse of alarming port and interface Down conditions,
clearing alarms on Up state changes, and storing sample data
that represents the percentage of active links for each monitored
network.

Test Plan:

PASS: Verify lmond process startup
PASS: Verify lmond logging and log rotation
PASS: Verify lmond process monitoring by pmon
PASS: Verify lmond interface learning on process startup
PASS: Verify lmond port learning on process startup
PASS: Verify lmond handling of vlan and bond interface types
PASS: Verify lmond http link info GET Query handling
PASS: Verify lmond has no memory leak during normal and eventfull operation

Change-Id: I58915644e60f31e3a12c3b451399c4f76ec2ea37
Story: 2002823
Task: 28635
Depends-On:
Signed-off-by: Eric MacDonald <eric.macdonald@windriver.com>
changes/64/633264/3
Eric MacDonald 4 years ago
parent ff8ef3ea8a
commit 7941ee5bbb
  1. 1
      centos_iso_image.inc
  2. 156
      mtce-common/src/common/httpUtil.cpp
  3. 15
      mtce-common/src/common/httpUtil.h
  4. 7
      mtce-common/src/common/logMacros.h
  5. 36
      mtce-common/src/common/nodeUtil.cpp
  6. 2
      mtce-common/src/common/nodeUtil.h
  7. 2
      mtce-common/src/daemon/daemon_config.cpp
  8. 2
      mtce/centos/build_srpm.data
  9. 67
      mtce/centos/mtce.spec
  10. 2
      mtce/src/Makefile
  11. 35
      mtce/src/lmon/Makefile
  12. 119
      mtce/src/lmon/lmon.h
  13. 769
      mtce/src/lmon/lmonHdlr.cpp
  14. 145
      mtce/src/lmon/lmonInit.cpp
  15. 415
      mtce/src/lmon/lmonUtil.cpp
  16. 83
      mtce/src/lmon/scripts/lmon
  17. 16
      mtce/src/lmon/scripts/lmon.logrotate
  18. 16
      mtce/src/lmon/scripts/lmon.pmon.conf
  19. 17
      mtce/src/lmon/scripts/lmon.service
  20. 19
      mtce/src/lmon/scripts/lmond.conf
  21. 2
      mtce/src/rmon/rmonHdlr.cpp

@ -8,6 +8,7 @@ mtce-pmon
mtce-rmon
mtce-hwmon
mtce-hostw
mtce-lmon
# mtce-compute
mtce-compute

@ -27,6 +27,33 @@ static char rest_api_filename[MAX_FILENAME_LEN];
static char rest_api_log_str [MAX_API_LOG_LEN];
static libEvent nullEvent ;
#define HTTP_GET_STR "GET"
#define HTTP_PUT_STR "PUT"
#define HTTP_PATCH_STR "PATCH"
#define HTTP_POST_STR "POST"
#define HTTP_DELETE_STR "DELETE"
#define HTTP_UNKNOWN_STR "UNKNOWN"
/* convert http event type to its string name */
const char * getHttpCmdType_str ( evhttp_cmd_type type )
{
switch (type)
{
case EVHTTP_REQ_GET: return(HTTP_GET_STR);
case EVHTTP_REQ_PUT: return(HTTP_PUT_STR);
case EVHTTP_REQ_PATCH: return(HTTP_PATCH_STR);
case EVHTTP_REQ_POST: return(HTTP_POST_STR);
case EVHTTP_REQ_DELETE: return(HTTP_DELETE_STR);
case EVHTTP_REQ_HEAD:
case EVHTTP_REQ_OPTIONS:
case EVHTTP_REQ_TRACE:
case EVHTTP_REQ_CONNECT:
default:
break ;
}
return(HTTP_UNKNOWN_STR);
}
/* ***********************************************************************
*
* Name : httpUtil_event_init
@ -1057,3 +1084,132 @@ void httpUtil_log_event ( libEvent * event_ptr )
send_log_message ( mtclogd_ptr, event_ptr->hostname.data(), &rest_api_filename[0], &rest_api_log_str[0] );
}
/*****************************************************************
*
* Name : httpUtil_bind
*
* Description : Setup the HTTP server socket
*
*****************************************************************/
int httpUtil_bind ( libEvent & event )
{
int one = 1;
event.fd = socket(AF_INET, SOCK_STREAM, 0);
if (event.fd < 0)
{
elog ("failed to create http server socket (%d:%m)\n", errno );
return FAIL_SOCKET_CREATE ;
}
/* make socket reusable */
if ( 0 > setsockopt(event.fd, SOL_SOCKET, SO_REUSEADDR, (char *)&one, sizeof(int)))
{
elog ("failed to set http server socket to reusable (%d:%m)\n", errno );
return FAIL_SOCKET_OPTION ;
}
memset(&event.addr, 0, sizeof(struct sockaddr_in));
event.addr.sin_family = AF_INET;
/* ERIK: INADDR_ANY; TODO: Refine this if we can */
event.addr.sin_addr.s_addr = inet_addr(LOOPBACK_IP);
// event.addr.sin_addr.s_addr = INADDR_ANY;
event.addr.sin_port = htons(event.port);
/* bind port */
if ( 0 > bind ( event.fd, (struct sockaddr*)&event.addr, sizeof(struct sockaddr_in)))
{
elog ("failed to bind to http server port %d (%d:%m)\n", event.port, errno );
return FAIL_SOCKET_BIND ;
}
/* Listen for events */
if ( 0 > listen(event.fd, 10 ))
{
elog ("failed to listen to http server socket (%d:%m)\n", errno );
return FAIL_SOCKET_LISTEN;
}
/* make non-blocking */
int flags = fcntl ( event.fd, F_GETFL, 0) ;
if ( flags < 0 || fcntl(event.fd, F_SETFL, flags | O_NONBLOCK) < 0)
{
elog ("failed to set http server socket to non-blocking (%d:%m)\n", errno );
return FAIL_SOCKET_OPTION;
}
return PASS;
}
/* Setup the http server */
int httpUtil_setup ( libEvent & event,
int supported_methods,
void(*hdlr)(struct evhttp_request *, void *) )
{
int rc = PASS ;
if ( ( rc = httpUtil_bind ( event )) != PASS )
{
return rc ;
}
else if (event.fd < 0)
{
wlog ("failed to get http server socket file descriptor\n");
return RETRY ;
}
event.base = event_base_new();
if (event.base == NULL)
{
elog ("failed to get http server event base\n");
return -1;
}
event.httpd = evhttp_new(event.base);
if (event.httpd == NULL)
{
elog ("failed to get httpd server handle\n");
return -1;
}
/* api is a void return */
evhttp_set_allowed_methods (event.httpd, supported_methods );
rc = evhttp_accept_socket(event.httpd, event.fd);
if ( rc == -1)
{
elog ("failed to accept on http server socket\n");
return -1;
}
/* api is a void return */
evhttp_set_gencb(event.httpd, hdlr, NULL);
ilog ("Listening On: 'http server' socket %s:%d\n",
inet_ntoa(event.addr.sin_addr), event.port );
return PASS ;
}
void httpUtil_fini ( libEvent & event )
{
if ( event.fd )
{
if ( event.base )
{
event_base_free( event.base);
}
close ( event.fd );
event.fd = 0 ;
}
}
void httpUtil_look ( libEvent & event )
{
/* Look for Events */
if ( event.base )
{
// rc = event_base_loopexit( mtce_event.base, NULL ) ; // EVLOOP_NONBLOCK );
event_base_loop(event.base, EVLOOP_NONBLOCK );
}
}

@ -12,6 +12,7 @@
#include <evhttp.h> /* for ... http libevent client */
#include <time.h>
#include <list>
#include <fcntl.h> /* for ... F_GETFL */
using namespace std;
@ -22,6 +23,7 @@ using namespace std;
#define MTC_HTTP_BAD_REQUEST 400
#define MTC_HTTP_UNAUTHORIZED 401
#define MTC_HTTP_FORBIDDEN 403
#define MTC_HTTP_METHOD_NOT_ALLOWED 405
#define MTC_HTTP_CONFLICT 409
#define MTC_HTTP_LENGTH_REQUIRED 411
#define MTC_HTTP_NORESPONSE 444
@ -194,6 +196,10 @@ struct libEvent
struct evbuffer *buf ; /**< HTTP output buffer ptr */
struct evbuffer_ptr evp ; /**< HTTP output buffer ptr */
int fd ;
struct sockaddr_in addr ;
struct evhttp *httpd ;
string log_prefix ; /**< log prefix for this event */
/** Service Specific Request Info */
@ -339,5 +345,14 @@ void httpUtil_event_info ( libEvent & event );
const char * getHttpCmdType_str ( evhttp_cmd_type type );
/* HTTP Server setup utilities */
int httpUtil_bind ( libEvent & event );
int httpUtil_setup ( libEvent & event,
int supported_methods,
void(*hdlr)(struct evhttp_request *, void *));
/* Cleanup */
void httpUtil_fini ( libEvent & event );
void httpUtil_look ( libEvent & event );
#endif /* __INCLUDE_HTTPUTIL_H__ */

@ -55,6 +55,7 @@ typedef struct
int mtc_agent_port ; /**< mtcAgent receive port (from Client) */
int mtc_client_port ; /**< mtcClient receive port (from Agent) */
char* uri_path ; /**< /mtce/lmon ... for link monitor */
int keystone_port ; /**< Keystone REST API port number */
char* keystone_prefix_path ; /**< Keystone REST API prefix path */
char* keystone_auth_host ; /**< =auth_host=192.168.204.2 */
@ -67,7 +68,6 @@ typedef struct
char* keystone_user_domain; /**< = Default */
char* keystone_project_domain; /**< = Default */
char* keyring_directory ; /**< =/opt/platform/.keyring/<release> */
char* sysinv_mtc_inv_label ; /**< =/v1/hosts/ */
int sysinv_api_port ; /**< =6385 */
char* sysinv_api_bind_ip ; /**< =<local floating IP> */
@ -114,8 +114,9 @@ typedef struct
int event_port ; /**< daemon specific event tx port */
int cmd_port ; /**< daemon specific command rx port */
int sensor_port ; /**< sensor read value port */
int sm_server_port ; /**< port mtce uses to receive data from SM */
int sm_client_port ; /**< port mtce uses to send SM data */
int sm_server_port ; /**< port mtce uses to receive data from SM */
int sm_client_port ; /**< port mtce uses to send SM data */
int lmon_query_port ;
int start_delay ; /**< startup delay, added for pmon */
int api_retries ; /**< api retries before failure */
int hostwd_failure_threshold ; /**< allowed # of missed pmon/hostwd messages */

@ -1489,40 +1489,24 @@ string get_event_str ( int event_code )
}
}
#define HTTP_GET_STR "GET"
#define HTTP_PUT_STR "PUT"
#define HTTP_PATCH_STR "PATCH"
#define HTTP_POST_STR "POST"
#define HTTP_DELETE_STR "DELETE"
#define HTTP_UNKNOWN_STR "UNKNOWN"
/* Private: convert http event type to its string name */
const char * getHttpCmdType_str ( evhttp_cmd_type type )
#define MAX_NUM_LEN 64
string itos ( int val )
{
switch (type)
{
case EVHTTP_REQ_GET: return(HTTP_GET_STR);
case EVHTTP_REQ_PUT: return(HTTP_PUT_STR);
case EVHTTP_REQ_PATCH: return(HTTP_PATCH_STR);
case EVHTTP_REQ_POST: return(HTTP_POST_STR);
case EVHTTP_REQ_DELETE: return(HTTP_DELETE_STR);
case EVHTTP_REQ_HEAD:
case EVHTTP_REQ_OPTIONS:
case EVHTTP_REQ_TRACE:
case EVHTTP_REQ_CONNECT:
default:
break ;
}
return(HTTP_UNKNOWN_STR);
char int_str[MAX_NUM_LEN] ;
string temp ;
memset ( &int_str[0], 0, MAX_NUM_LEN );
snprintf ( &int_str[0], MAX_NUM_LEN, "%d" , val );
temp = int_str ;
return (temp);
}
#define MAX_NUM_LEN 64
string itos ( int val )
string lltos (long long unsigned int val )
{
char int_str[MAX_NUM_LEN] ;
string temp ;
memset ( &int_str[0], 0, MAX_NUM_LEN );
snprintf ( &int_str[0], MAX_NUM_LEN, "%d" , val );
snprintf ( &int_str[0], MAX_NUM_LEN, "%llu" , val );
temp = int_str ;
return (temp);
}

@ -99,9 +99,9 @@ int get_link_state ( int ioctl_socket , const char * iface_ptr, bool * run
int open_ioctl_socket ( void );
string get_event_str ( int event_code );
const char * getHttpCmdType_str ( evhttp_cmd_type type );
string itos ( int val );
string lltos (long long unsigned int val );
string ftos ( float val, int resolution );
unsigned short checksum(void *b, int len);

@ -34,6 +34,7 @@ void daemon_config_default ( daemon_config_type* config_ptr )
config_ptr->mon_process_5 = strdup("none");
config_ptr->mon_process_6 = strdup("none");
config_ptr->mon_process_7 = strdup("none");
config_ptr->uri_path = strdup("");
config_ptr->keystone_prefix_path = strdup("");
config_ptr->keystone_identity_uri = strdup("");
config_ptr->keystone_auth_uri = strdup("");
@ -295,6 +296,7 @@ void daemon_dump_cfg ( void )
/* mtcAgent & hwmond */
if ( ptr->sysinv_api_port ) { ilog ("sysinv_api_port = %d\n", ptr->sysinv_api_port );}
if ( ptr->uri_path ) { ilog ("uri_path = %s\n", ptr->uri_path );}
if ( ptr->keystone_prefix_path ) { ilog ("keystone_prefix_path = %s\n", ptr->keystone_prefix_path );}
if ( ptr->keystone_auth_host ) { ilog ("keystone_auth_host = %s\n", ptr->keystone_auth_host );}
if ( ptr->keystone_identity_uri ) { ilog ("keystone_identity_uri = %s\n", ptr->keystone_identity_uri );}

@ -1,3 +1,3 @@
SRC_DIR="src"
TIS_PATCH_VER=145
TIS_PATCH_VER=146
BUILD_IS_SLOW=5

@ -178,7 +178,7 @@ Provides: librmonapi.so.1()(64bit)
Titanium Cloud Host Maintenance Resource Monitor Service (rmond) adds
threshold based monitoring with predictive severity level alarming for
out of tolerance utilization of critical resourses such as memory, cpu
file system, interface state, etc.
file system, etc.
%package -n mtce-hwmon
Summary: Titanuim Server Maintenance Hardware Monitor Package
@ -266,6 +266,39 @@ of spec operating conditions that can reduce outage time through automated
notification and recovery thereby improving overall platform availability
for the customer.
%package -n mtce-lmon
Summary: Titanuim Server Maintenance Link Monitor Package
Group: base
BuildRequires: cppcheck
Requires: util-linux
Requires: /bin/bash
Requires: /bin/systemctl
Requires: dpkg
Requires: time
Requires: libstdc++.so.6(CXXABI_1.3)(64bit)
Requires: libfmcommon.so.1()(64bit)
Requires: libc.so.6(GLIBC_2.7)(64bit)
Requires: libc.so.6(GLIBC_2.2.5)(64bit)
Requires: libstdc++.so.6(GLIBCXX_3.4.11)(64bit)
Requires: /bin/sh
Requires: libc.so.6(GLIBC_2.3)(64bit)
Requires: libc.so.6(GLIBC_2.14)(64bit)
Requires: librt.so.1(GLIBC_2.3.3)(64bit)
Requires: libgcc_s.so.1(GCC_3.0)(64bit)
Requires: librt.so.1(GLIBC_2.2.5)(64bit)
Requires: libm.so.6()(64bit)
Requires: rtld(GNU_HASH)
Requires: libstdc++.so.6()(64bit)
Requires: libc.so.6(GLIBC_2.4)(64bit)
Requires: libc.so.6()(64bit)
Requires: libgcc_s.so.1()(64bit)
Requires: libstdc++.so.6(GLIBCXX_3.4)(64bit)
Requires: libstdc++.so.6(GLIBCXX_3.4.15)(64bit)
%description -n mtce-lmon
Titanium Cloud Maintenance Link Monitor service (lmond) provides
netlink monitoring for provisioned oam, mgmt and infra interfaces.
%define local_dir /usr/local
%define local_bindir %{local_dir}/bin
%define local_sbindir %{local_dir}/sbin
@ -321,6 +354,7 @@ install -m 644 -p -D %{_buildsubdir}/scripts/mtc.conf %{buildroot}%{_sysconfdir}
install -m 644 -p -D %{_buildsubdir}/fsmon/scripts/fsmond.conf %{buildroot}%{_sysconfdir}/mtc/fsmond.conf
install -m 644 -p -D %{_buildsubdir}/hwmon/scripts/hwmond.conf %{buildroot}%{_sysconfdir}/mtc/hwmond.conf
install -m 644 -p -D %{_buildsubdir}/pmon/scripts/pmond.conf %{buildroot}%{_sysconfdir}/mtc/pmond.conf
install -m 644 -p -D %{_buildsubdir}/lmon/scripts/lmond.conf %{buildroot}%{_sysconfdir}/mtc/lmond.conf
install -m 644 -p -D %{_buildsubdir}/rmon/scripts/rmond.conf %{buildroot}%{_sysconfdir}/mtc/rmond.conf
install -m 644 -p -D %{_buildsubdir}/hostw/scripts/hostwd.conf %{buildroot}%{_sysconfdir}/mtc/hostwd.conf
@ -335,6 +369,7 @@ install -m 755 -p -D %{_buildsubdir}/maintenance/mtcClient %{buildroot}/%{local_
install -m 755 -p -D %{_buildsubdir}/heartbeat/hbsAgent %{buildroot}/%{local_bindir}/hbsAgent
install -m 755 -p -D %{_buildsubdir}/heartbeat/hbsClient %{buildroot}/%{local_bindir}/hbsClient
install -m 755 -p -D %{_buildsubdir}/pmon/pmond %{buildroot}/%{local_bindir}/pmond
install -m 755 -p -D %{_buildsubdir}/lmon/lmond %{buildroot}/%{local_bindir}/lmond
install -m 755 -p -D %{_buildsubdir}/hostw/hostwd %{buildroot}/%{local_bindir}/hostwd
install -m 755 -p -D %{_buildsubdir}/rmon/rmond %{buildroot}/%{local_bindir}/rmond
install -m 755 -p -D %{_buildsubdir}/fsmon/fsmond %{buildroot}/%{local_bindir}/fsmond
@ -355,6 +390,7 @@ install -m 755 -p -D %{_buildsubdir}/hwmon/scripts/lsb/hwmon %{buildroot}%{_sysc
install -m 755 -p -D %{_buildsubdir}/fsmon/scripts/fsmon %{buildroot}%{_sysconfdir}/init.d/fsmon
install -m 755 -p -D %{_buildsubdir}/scripts/mtclog %{buildroot}%{_sysconfdir}/init.d/mtclog
install -m 755 -p -D %{_buildsubdir}/pmon/scripts/pmon %{buildroot}%{_sysconfdir}/init.d/pmon
install -m 755 -p -D %{_buildsubdir}/lmon/scripts/lmon %{buildroot}%{_sysconfdir}/init.d/lmon
install -m 755 -p -D %{_buildsubdir}/rmon/scripts/rmon %{buildroot}%{_sysconfdir}/init.d/rmon
install -m 755 -p -D %{_buildsubdir}/hostw/scripts/hostw %{buildroot}%{_sysconfdir}/init.d/hostw
install -m 755 -p -D %{_buildsubdir}/alarm/scripts/mtcalarm.init %{buildroot}%{_sysconfdir}/init.d/mtcalarm
@ -377,6 +413,7 @@ install -m 644 -p -D %{_buildsubdir}/scripts/mtclog.service %{buildroot}%{_unitd
install -m 644 -p -D %{_buildsubdir}/scripts/goenabled.service %{buildroot}%{_unitdir}/goenabled.service
install -m 644 -p -D %{_buildsubdir}/scripts/runservices.service %{buildroot}%{_unitdir}/runservices.service
install -m 644 -p -D %{_buildsubdir}/alarm/scripts/mtcalarm.service %{buildroot}%{_unitdir}/mtcalarm.service
install -m 644 -p -D %{_buildsubdir}/lmon/scripts/lmon.service %{buildroot}%{_unitdir}/lmon.service
# go enabled stuff
install -m 755 -d %{buildroot}%{local_etc_goenabledd}
@ -407,18 +444,15 @@ install -m 644 -p -D %{_buildsubdir}/rmon/scripts/rmon.conf %{buildroot}%{local_
install -m 644 -p -D %{_buildsubdir}/fsmon/scripts/fsmon.conf %{buildroot}%{local_etc_pmond}/fsmon.conf
install -m 644 -p -D %{_buildsubdir}/scripts/mtclogd.conf %{buildroot}%{local_etc_pmond}/mtclogd.conf
install -m 644 -p -D %{_buildsubdir}/alarm/scripts/mtcalarm.pmon.conf %{buildroot}%{local_etc_pmond}/mtcalarm.conf
install -m 644 -p -D %{_buildsubdir}/lmon/scripts/lmon.pmon.conf %{buildroot}%{local_etc_pmond}/lmon.conf
# resource monitor config files
install -m 755 -d %{buildroot}%{local_etc_rmond}
install -m 755 -d %{buildroot}%{_sysconfdir}/rmonapi.d
install -m 755 -d %{buildroot}%{_sysconfdir}/rmonfiles.d
install -m 755 -d %{buildroot}%{_sysconfdir}/rmon_interfaces.d
install -m 644 -p -D %{_buildsubdir}/rmon/scripts/remotelogging_resource.conf %{buildroot}%{local_etc_rmond}/remotelogging_resource.conf
install -m 644 -p -D %{_buildsubdir}/rmon/scripts/cinder_virtual_resource.conf %{buildroot}%{local_etc_rmond}/cinder_virtual_resource.conf
install -m 644 -p -D %{_buildsubdir}/rmon/scripts/nova_virtual_resource.conf %{buildroot}%{local_etc_rmond}/nova_virtual_resource.conf
install -m 644 -p -D %{_buildsubdir}/rmon/scripts/oam_resource.conf %{buildroot}%{_sysconfdir}/rmon_interfaces.d/oam_resource.conf
install -m 644 -p -D %{_buildsubdir}/rmon/scripts/management_resource.conf %{buildroot}%{_sysconfdir}/rmon_interfaces.d/management_resource.conf
install -m 644 -p -D %{_buildsubdir}/rmon/scripts/infrastructure_resource.conf %{buildroot}%{_sysconfdir}/rmon_interfaces.d/infrastructure_resource.conf
install -m 755 -p -D %{_buildsubdir}/rmon/scripts/rmon_reload_on_cpe.sh %{buildroot}%{local_etc_goenabledd}/rmon_reload_on_cpe.sh
# log rotation
@ -426,6 +460,7 @@ install -m 755 -d %{buildroot}%{_sysconfdir}/logrotate.d
install -m 644 -p -D %{_buildsubdir}/scripts/mtce.logrotate %{buildroot}%{local_etc_logrotated}/mtce.logrotate
install -m 644 -p -D %{_buildsubdir}/hostw/scripts/hostw.logrotate %{buildroot}%{local_etc_logrotated}/hostw.logrotate
install -m 644 -p -D %{_buildsubdir}/pmon/scripts/pmon.logrotate %{buildroot}%{local_etc_logrotated}/pmon.logrotate
install -m 644 -p -D %{_buildsubdir}/lmon/scripts/lmon.logrotate %{buildroot}%{local_etc_logrotated}/lmon.logrotate
install -m 644 -p -D %{_buildsubdir}/rmon/scripts/rmon.logrotate %{buildroot}%{local_etc_logrotated}/rmon.logrotate
install -m 644 -p -D %{_buildsubdir}/fsmon/scripts/fsmon.logrotate %{buildroot}%{local_etc_logrotated}/fsmon.logrotate
install -m 644 -p -D %{_buildsubdir}/hwmon/scripts/hwmon.logrotate %{buildroot}%{local_etc_logrotated}/hwmon.logrotate
@ -466,6 +501,9 @@ install -m 755 -d %{buildroot}/var/run
%post -n mtce-rmon
/bin/systemctl enable rmon.service
%post -n mtce-lmon
/bin/systemctl enable lmon.service
###############################
# Maintenance RPM Files
###############################
@ -583,10 +621,6 @@ install -m 755 -d %{buildroot}/var/run
%{local_etc_rmond}/cinder_virtual_resource.conf
%{local_etc_rmond}/nova_virtual_resource.conf
%{_sysconfdir}/rmon_interfaces.d/management_resource.conf
%{_sysconfdir}/rmon_interfaces.d/oam_resource.conf
%{_sysconfdir}/rmon_interfaces.d/infrastructure_resource.conf
%{_libdir}/librmonapi.so.1.0
%{_libdir}/librmonapi.so.1
%{_libdir}/librmonapi.so
@ -628,6 +662,21 @@ install -m 755 -d %{buildroot}/var/run
%{_sysconfdir}/init.d/hostw
%{local_bindir}/hostwd
###############################
# Link Monitor RPM Files
###############################
%files -n mtce-lmon
%defattr(-,root,root,-)
# Config files - Non-Modifiable
%{_sysconfdir}/mtc/lmond.conf
%{_unitdir}/lmon.service
%{local_etc_logrotated}/lmon.logrotate
%{local_etc_pmond}/lmon.conf
%{local_bindir}/lmond
%{_sysconfdir}/init.d/lmon
###############################
# Maintenance Software Development RPM
###############################

@ -16,6 +16,7 @@ build:
(cd maintenance ; make build VER=$(VER) VER_MJR=$(VER_MJR))
(cd hwmon ; make build VER=$(VER) VER_MJR=$(VER_MJR))
(cd mtclog ; make build VER=$(VER) VER_MJR=$(VER_MJR))
(cd lmon ; make build VER=$(VER) VER_MJR=$(VER_MJR))
(cd pmon ; make build VER=$(VER) VER_MJR=$(VER_MJR))
(cd fsmon ; make build VER=$(VER) VER_MJR=$(VER_MJR))
(cd rmon ; make build VER=$(VER) VER_MJR=$(VER_MJR))
@ -30,6 +31,7 @@ clean:
@( cd alarm ; make clean )
@( cd mtclog ; make clean )
@( cd hwmon ; make clean )
@( cd lmon ; make clean )
@( cd pmon ; make clean )
@( cd fsmon ; make clean )
@( cd heartbeat ; make clean )

@ -0,0 +1,35 @@
#
# Copyright (c) 2019 Wind River Systems, Inc.
#
# SPDX-License-Identifier: Apache-2.0
#
SHELL = /bin/bash
SRCS = lmonInit.cpp lmonUtil.cpp lmonHdlr.cpp
OBJS = $(SRCS:.cpp=.o)
LDLIBS = -lstdc++ -ldaemon -lcommon -ljson-c -lcrypto -lrt -levent
LDPATH = -L../../../mtce-common/src/daemon -L../../../mtce-common/src/common
INCLUDES = -I. -I/usr/include/mtce-daemon -I/usr/include/mtce-common
CCFLAGS = -g -O2 -Wall -Wextra -Werror
STATIC_ANALYSIS_TOOL = cppcheck
STATIC_ANALYSIS_TOOL_EXISTS = $(shell [[ -e `which $(STATIC_ANALYSIS_TOOL)` ]] && echo 1 || echo 0)
all: clean static_analysis build
.cpp.o:
$(CXX) $(INCLUDES) $(CCFLAGS) $(EXTRACCFLAGS) -c $< -o $@
static_analysis:
ifeq ($(STATIC_ANALYSIS_TOOL_EXISTS), 1)
$(STATIC_ANALYSIS_TOOL) --language=c++ --enable=warning -U__AREA__ *.cpp *.h
else
echo "Warning: '$(STATIC_ANALYSIS_TOOL)' static analysis tool not installed ; bypassing ..."
endif
build: clean static_analysis $(OBJS)
$(CXX) $(CCFLAGS) $(OBJS) $(LDPATH) $(LDLIBS) -o lmond
clean:
@rm -v -f $(OBJ) lmond *.o *.a

@ -0,0 +1,119 @@
/*
* Copyright (c) 2019 Wind River Systems, Inc.
*
* SPDX-License-Identifier: Apache-2.0
*
*/
#include <net/if.h> /* for ... IF_NAMESIZE */
using namespace std;
#include "daemon_ini.h" /* for ... ini_parse */
#include "daemon_common.h" /* for ... daemon common definitions and types */
#include "nodeBase.h" /* for ... maintenance base definitions */
#include "nodeTimers.h" /* for ... mtcTimer_init/start/stop utilities */
#include "nodeUtil.h" /* for ... common utils like open_ioctl_socket */
#include "httpUtil.h" /* for ... httputil_setup */
#include "nlEvent.h" /* for ... open_netlink_socket */
#include "fmAPI.h" /* for ... FMTimeT */
#ifdef __AREA__
#undef __AREA__
#endif
#define __AREA__ "mon"
#define INTERFACES_DIR ((const char *)"/sys/class/net/")
#define PLATFORM_DIR ((const char *)"/etc/platform/platform.conf")
#define INTERFACES_MAX (3) /* maximum number of interfaces to monitor */
enum interface_type { ethernet = 0, vlan = 1, bond = 2 };
string iface_type ( interface_type type_enum );
/* daemon only supports the GET request */
#define HTTP_SUPPORTED_METHODS (EVHTTP_REQ_GET)
typedef struct
{
int ioctl_socket ;
int netlink_socket ;
libEvent http_event ;
msgSock_type mtclogd ;
int dos_log_throttle ;
struct mtc_timer audit_timer ;
char my_hostname[MAX_HOST_NAME_SIZE+1];
char my_address [MAX_CHARS_IN_IP_ADDR+1];
} lmon_ctrl_type ;
typedef struct
{
const char * name ; /* pointer to well known primary interface name */
/* primary interface names */
#define MGMT_INTERFACE_NAME ((const char *)"mgmt")
#define INFRA_INTERFACE_NAME ((const char *)"infra")
#define OAM_INTERFACE_NAME ((const char *)"oam")
/* name labels used in platform.conf */
#define MGMT_INTERFACE_FULLNAME ((const char *)"management_interface")
#define INFRA_INTERFACE_FULLNAME ((const char *)"infrastructure_interface")
#define OAM_INTERFACE_FULLNAME ((const char *)"oam_interface")
/* true if the interface is configured.
* i.e. the name label shown above is found in platform.conf */
bool used ;
interface_type type_enum ;
/* true if the link is up ; false otherwise */
bool interface_one_link_up ;
bool interface_two_link_up ;
FMTimeT interface_one_event_time ;
FMTimeT interface_two_event_time ;
/* Config Items */
const char * severity ; /* MINOR, MAJOR or CRITICAL for each resource */
unsigned int debounce ; /* Period to wait before clearing alarms */
unsigned int num_tries ; /* Number of times a resource has to be in
failed or cleared state before sending alarm */
/* Dynamic Data */
char interface_one[IF_NAMESIZE] ; /* primary interface */
char interface_two[IF_NAMESIZE] ; /* second interface if lagged */
char bond[IF_NAMESIZE] ; /* bonded interface name */
bool lagged ; /* Lagged interface=true or not=false */
// unsigned int debounce_cnt ; /* running monitor debounce count */
// unsigned int minorlog_cnt ; /* track minor log count for thresholding */
// unsigned int count ; /* track the number of times the condition has been occured */
// bool failed ; /* track if the resource needs to be serviced by the resource handler */
// int resource_value ; /* 1 if the interface is up and 0 if it is down */
// int resource_value_lagged ; /* 1 if the interface is up and 0 if it is down for lagged interfaces */
// int sev ; /* The severity of the failed resource */
// rmonStage_enum stage ; /* The stage the resource is in within the resource handler fsm */
// char alarm_id[FM_MAX_BUFFER_LENGTH] ; /* Used by FM API, type of alarm being raised */
// char alarm_id_port[FM_MAX_BUFFER_LENGTH] ; /* Used by FM API, type of alarm being raised for the ports */
// char errorMsg[ERR_SIZE];
// rmon_api_socket_type msg;
// bool link_up_and_running; /* whether the interface is up or down initially */
// bool alarm_raised;
// int failed_send; /* The number of times the rmon api failed to send a message */
} interface_ctrl_type ;
/* lmonHdlr.cpp */
void daemon_exit ( void );
void lmon_learn_interfaces ( int ioctl_sock );
/* lmonUtils.cpp */
FMTimeT lmon_fm_timestamp ( void );
int lmon_interfaces_init ( interface_ctrl_type * ptr );
int lmon_get_link_state ( int ioctl_socket,
char iface[IF_NAMESIZE],
bool & link_up );

@ -0,0 +1,769 @@
/*
* Copyright (c) 2019 Wind River Systems, Inc.
*
* SPDX-License-Identifier: Apache-2.0
*
*/
/**
* @file
* Starling-X Maintenance Link Monitor Service Header
*/
#include "lmon.h"
#include <linux/rtnetlink.h> /* for ... RTMGRP_LINK */
#include "nodeMacro.h" /* for ... CREATE_REUSABLE_INET_UDP_TX_SOCKET */
#define HTTP_SERVER_NAME ((const char *)"link status query")
static lmon_ctrl_type lmon_ctrl ;
static interface_ctrl_type interfaces[INTERFACES_MAX];
static const char * iface_list[INTERFACES_MAX] = { MGMT_INTERFACE_NAME,
INFRA_INTERFACE_NAME,
OAM_INTERFACE_NAME };
/* httpUtil needs a mtclog socket pointer */
msgSock_type * get_mtclogd_sockPtr ( void )
{
return (&lmon_ctrl.mtclogd);
}
/* dump state before exiting */
void daemon_exit ( void )
{
daemon_files_fini ();
daemon_dump_info ();
exit (0);
}
/* daemon timer handler */
void lmonTimer_handler ( int sig, siginfo_t *si, void *uc)
{
UNUSED(sig); UNUSED(uc);
timer_t * tid_ptr = (void**)si->si_value.sival_ptr ;
if ( !(*tid_ptr) )
return ;
else if (( *tid_ptr == lmon_ctrl.audit_timer.tid ) )
lmon_ctrl.audit_timer.ring = true ;
else
mtcTimer_stop_tid_int_safe ( tid_ptr );
}
/*****************************************************************************
*
* Name : lmonHdlr_http_handler
*
* Description: Handle HTTP Link Status Query requests.
*
* Method : GET
*
******************************************************************************/
#define DOS_LOG_THROTTLE_THLD (10000)
void lmonHdlr_http_handler (struct evhttp_request *req, void *arg)
{
int http_status_code = HTTP_NOTFOUND ;
UNUSED(arg);
if ( ! req )
return;
/* Get sender must be localhost */
const char * host_ptr = evhttp_request_get_host (req);
if (( host_ptr == NULL ) ||
(( strncmp ( host_ptr , "localhost" , 10 ) != 0 ) &&
( strncmp ( host_ptr , LOOPBACK_IP , 10 ) != 0 )))
{
wlog_throttled ( lmon_ctrl.dos_log_throttle,
DOS_LOG_THROTTLE_THLD,
"Message received from unknown host (%s)\n",
host_ptr?host_ptr:"(null)" );
return ;
}
const char * uri_ptr = evhttp_request_get_uri (req);
if ( uri_ptr == NULL )
{
wlog_throttled ( lmon_ctrl.dos_log_throttle,
DOS_LOG_THROTTLE_THLD,
"null uri");
return ;
}
string uri_path = daemon_get_cfg_ptr()->uri_path ;
if (strncmp(uri_ptr, uri_path.data(), uri_path.length()))
{
wlog_throttled ( lmon_ctrl.dos_log_throttle,
DOS_LOG_THROTTLE_THLD,
"http request not for this service: %s",
uri_ptr);
return ;
}
/* Extract the operation */
evhttp_cmd_type http_cmd = evhttp_request_get_command (req);
jlog ("'%s' %s\n", uri_ptr, getHttpCmdType_str(http_cmd));
switch ( http_cmd )
{
case EVHTTP_REQ_GET:
{
http_status_code = HTTP_OK ;
break ;
}
default:
{
ilog_throttled ( lmon_ctrl.dos_log_throttle,
DOS_LOG_THROTTLE_THLD,
"unsupported %s request (%d)",
getHttpCmdType_str(http_cmd),
http_cmd);
http_status_code = MTC_HTTP_METHOD_NOT_ALLOWED ;
}
}
/*
* Link status query response format - success path
*
* Lagged case has an array of 2 links
*
{ "status" : "pass",
"link_info": [
{ "network":"mgmt",
"type":"vlan",
"links": [
{ "name":"enp0s8.1", "state":"Up/Down", "time":5674323454567 },
{ "name":"enp0s8.2", "state":"Up/Down", "time":5674323454567 }]
},
{ "network":"infra",
"type":"bond",
"bond":"bond0",
"links": [
{ "name":"enp0s9f1", "state":"Up/Down", "time":5674323454567 },
{ "name":"enp0s9f0", "state":"Up/Down", "time":5674323454567 }]
},
{ "network":"oam",
"type":"ethernet",
"links": [
{ "name":"enp0s3", "state":"Up/Down", "time":5674323454567 }]
}]
}
*
*lmonHdlr.cpp
*
*/
// #define WANT_TYPE_STR
// #define WANT_BOND_STR
if (( http_status_code == HTTP_OK ) || ( http_status_code == MTC_HTTP_ACCEPTED ))
{
/* build response string */
string response = "{ \"status\":\"pass\",\"link_info\":[" ;
/* loop over the interfaces and build a response string for each
* of those that are used */
for ( int i = 0 ; i < INTERFACES_MAX ; i++ )
{
if ((interfaces[i].used == true) && (interfaces[i].name[0] != '\0'))
{
if ( i > 0 )
response.append (",");
response.append ("{\"network\":\"");
response.append (interfaces[i].name);
response.append ("\"");
#ifdef WANT_TYPE_STR
string type_str = "ethernet" ;
if ( interfaces[i].type_enum == bond )
type_str = "bond" ;
else if ( interfaces[i].type_enum == vlan )
type_str = "vlan" ;
response.append (",\"type\":\"" + type_str + "\"");
#endif
#ifdef WANT_BOND_STR
if ( interfaces[i].type_enum == bond )
{
response.append (",\"bond\":\"");
response.append (interfaces[i].bond);
response.append ("\"");
}
#endif
response.append (",\"links\":[");
{
response.append ("{\"name\":\"");
response.append (interfaces[i].interface_one);
response.append ("\",\"state\":\"");
response.append (interfaces[i].interface_one_link_up?"Up":"Down");
response.append ("\",\"time\":\"" + lltos(interfaces[i].interface_one_event_time) + "\"}");
}
if (( interfaces[i].lagged ) &&
( interfaces[i].interface_two[0] != '\0'))
{
response.append (",{\"name\":\"");
response.append (interfaces[i].interface_two);
response.append ("\",\"state\":\"");
response.append (interfaces[i].interface_two_link_up?"Up":"Down");
response.append ("\",\"time\":\"" + lltos(interfaces[i].interface_two_event_time) + "\"}");
}
response.append ("]}");
}
}
response.append ("]}");
struct evbuffer * resp_buf = evbuffer_new();
jlog ("Resp: %s\n", response.c_str());
evbuffer_add_printf (resp_buf, "%s\n", response.data());
evhttp_send_reply (req, http_status_code, "OK", resp_buf );
evbuffer_free ( resp_buf );
}
else if ( http_status_code == MTC_HTTP_METHOD_NOT_ALLOWED )
{
/* build response string */
string response = "{" ;
response.append (" \"status\" : \"fail ; method not allowed\"");
response.append ("}");
struct evbuffer * resp_buf = evbuffer_new();
jlog ("Event Response: %s\n", response.c_str());
evbuffer_add_printf (resp_buf, "%s\n", response.data());
/* Add the 'Allow' header */
int rc = evhttp_add_header( req->output_headers, "Allow", "GET" );
if ( rc ) { ilog ("failed to add 'Allow' header (%d %d:%m", rc, errno);}
evhttp_send_reply (req, http_status_code, "NOT ALLOWED", resp_buf );
evbuffer_free ( resp_buf );
}
else
{
/* build response string */
string response = "{" ;
response.append (" \"status\" : \"fail ; bad request\"");
response.append ("}");
elog ("HTTP Event error:%d ; cmd:%s uri:%s response:%s\n",
http_status_code,
getHttpCmdType_str(http_cmd),
uri_ptr,
response.c_str());
evhttp_send_error (req, http_status_code, response.data() );
}
}
/*****************************************************************************
*
* Name : lmon_socket_init
*
* Purpose : Initialize all the sockets for this process.
*
* Sockets include ...
*
* 1. local kernel ioctl socket ; link attribute query
*
*****************************************************************************/
int lmon_socket_init ( lmon_ctrl_type * ctrl_ptr )
{
int rc = PASS ;
if ( ctrl_ptr )
{
httpUtil_event_init ( &lmon_ctrl.http_event,
&lmon_ctrl.my_hostname[0],
HTTP_SERVER_NAME,
lmon_ctrl.my_address,
daemon_get_cfg_ptr()->lmon_query_port );
if (( ctrl_ptr->ioctl_socket = open_ioctl_socket()) <= 0 )
{
/* errno/strerror logged by open utility if failure is detected */
elog ("failed to create ioctl socket\n");
rc = FAIL_SOCKET_CREATE ;
}
/* Note that address changes should not generate netlink events.
* Therefore these options are not set
* RTMGRP_IPV4_IFADDR
* RTMGRP_IPV6_IFADDR
*/
else if (( ctrl_ptr->netlink_socket = open_netlink_socket ( RTMGRP_LINK )) <= 0 )
{
/* errno/strerr logged by open utility if failure is detected */
elog ("failed to create netlink listener socket\n");
rc = FAIL_SOCKET_CREATE ;
}
else if ( httpUtil_setup ( ctrl_ptr->http_event,
HTTP_SUPPORTED_METHODS,
&lmonHdlr_http_handler ) != PASS )
{
/* errno/strerr logged by open utility if failure is detected */
elog ("failed to setup http server\n");
rc = FAIL_SOCKET_CREATE ;
}
else
{
ctrl_ptr->mtclogd.port = daemon_get_cfg_ptr()->daemon_log_port ;
CREATE_REUSABLE_INET_UDP_TX_SOCKET ( LOOPBACK_IP,
ctrl_ptr->mtclogd.port,
ctrl_ptr->mtclogd.sock,
ctrl_ptr->mtclogd.addr,
ctrl_ptr->mtclogd.port,
ctrl_ptr->mtclogd.len,
"mtc logger message",
rc );
if ( rc )
{
elog ("failed to setup mtce logger port %d\n", ctrl_ptr->mtclogd.port );
rc = PASS ;
}
}
}
else
{
rc = FAIL_NULL_POINTER ;
}
return (rc);
}
/*****************************************************************************
*
* Name : lmon_learn_interfaces
*
* Purpose : realize the interfaces to monitor in terms of
*
* - interface type ; ethernet, bonded or vlan
* - initial up/down state
*
*****************************************************************************/
void lmon_learn_interfaces ( int ioctl_socket )
{
/* initialize interface monitoring */
for ( int iface = 0 ; iface < INTERFACES_MAX ; iface++ )
{
interfaces[iface].name = iface_list[iface];
lmon_interfaces_init ( &interfaces[iface] );
if ( interfaces[iface].used == false )
continue ;
/* set the link state for all the primary physical interfaces */
if ( lmon_get_link_state ( ioctl_socket,
interfaces[iface].interface_one,
interfaces[iface].interface_one_link_up ) )
{
interfaces[iface].interface_one_event_time = lmon_fm_timestamp();
interfaces[iface].interface_one_link_up = false ;
wlog ("%s interface state query failed ; defaulting to Down\n",
interfaces[iface].interface_one) ;
}
else
{
interfaces[iface].interface_one_event_time = lmon_fm_timestamp();
ilog ("%s is %s\n",
interfaces[iface].interface_one,
interfaces[iface].interface_one_link_up ?
"Up" : "Down" );
if ( interfaces[iface].lagged == true )
{
/* set the link state for all the lagged physical interfaces */
if ( lmon_get_link_state ( ioctl_socket,
interfaces[iface].interface_two,
interfaces[iface].interface_two_link_up ) )
{
interfaces[iface].interface_two_event_time = lmon_fm_timestamp();
interfaces[iface].interface_two_link_up = false ;
wlog ("%s lag interface state query failed ; defaulting to Down\n",
interfaces[iface].interface_two) ;
}
else
{
interfaces[iface].interface_two_event_time = lmon_fm_timestamp();
ilog ("%s is %s (lag)\n",
interfaces[iface].interface_two,
interfaces[iface].interface_two_link_up ?
"Up" : "Down" );
}
}
}
}
}
/*****************************************************************************
*
* Name : service_interface_events
*
* Purpose : Service state changes for monitored link
*
* Description: netlink event driven state change handler.
*
*****************************************************************************/
int service_interface_events ( void )
{
list<string> links_gone_down ;
list<string> links_gone_up ;
list<string>::iterator iter_ptr ;
links_gone_down.clear();
links_gone_up.clear();
int events = get_netlink_events ( lmon_ctrl.netlink_socket,
links_gone_down,
links_gone_up );
if ( events <= 0 )
{
dlog1 ("called but get_netlink_events reported no events");
return RETRY ;
}
for ( int i = 0 ; i < INTERFACES_MAX ; i++ )
{
if ( interfaces[i].used == true )
{
bool running = false ;
/* handle links that went down */
if ( ! links_gone_down.empty() )
{
bool found = false ;
dlog ("netlink Down events: %ld", links_gone_down.size());
/* Look at the down list */
for ( iter_ptr = links_gone_down.begin();
iter_ptr != links_gone_down.end() ;
iter_ptr++ )
{
if ( strcmp ( interfaces[i].interface_one, iter_ptr->c_str()) == 0 )
{
found = true ;
interfaces[i].interface_one_event_time = lmon_fm_timestamp();
dlog ("%s is Down ; netlink event\n",
interfaces[i].interface_one );
if ( get_link_state ( lmon_ctrl.ioctl_socket,
iter_ptr->c_str(),
&running ) == PASS )
{
if ( interfaces[i].interface_one_link_up == true )
{
wlog ("%s is Down ; (%s)\n",
iter_ptr->c_str(),
running ? "Up" : "Down" );
}
else
{
dlog ("%s is Down ; (%s)\n",
iter_ptr->c_str(),
running ? "Up" : "Down" );
}
interfaces[i].interface_one_link_up = running ? true:false;
}
else
{
wlog ("%s is Down ; oper query failed\n",
iter_ptr->c_str());
interfaces[i].interface_one_link_up = false ;
}
}
else if (interfaces[i].lagged == true)
{
if ( strcmp ( interfaces[i].interface_two, iter_ptr->c_str()) == 0 )
{
found = true ;
interfaces[i].interface_two_event_time = lmon_fm_timestamp();
dlog ("%s is Down\n", interfaces[i].interface_two);
if ( get_link_state ( lmon_ctrl.ioctl_socket,
iter_ptr->c_str(),
&running ) == PASS )
{
if ( interfaces[i].interface_two_link_up == true )
{
wlog ("%s is Down (%s)\n",
iter_ptr->c_str(),
running ? "Up" : "Down" );
}
else
{
dlog ("%s is Down (%s)\n",
iter_ptr->c_str(),
running ? "Up" : "Down" );
}
interfaces[i].interface_two_link_up = running ? true:false;
}
else
{
wlog ("%s is Down ; oper query failed\n",
iter_ptr->c_str() );
interfaces[i].interface_two_link_up = false ;
}
}
if ( strcmp ( interfaces[i].bond, iter_ptr->c_str()) == 0 )
{
found = true ;
wlog ("%s is Down (bond)\n", interfaces[i].bond);
}
}
}
if ( ! found )
{
dlog ("netlink Down event on unmonitored link:%s", iter_ptr->c_str());
}
}
/* handle links that came up */
if ( !links_gone_up.empty() )
{
bool found = false ;
dlog ("netlink Up events: %ld", links_gone_up.size());
/* Look at the down list */
for ( iter_ptr = links_gone_up.begin();
iter_ptr != links_gone_up.end() ;
iter_ptr++ )
{
if ( strcmp ( interfaces[i].interface_one, iter_ptr->c_str()) == 0 )
{
found = true ;
interfaces[i].interface_one_event_time = lmon_fm_timestamp();
dlog ("%s is Up\n", interfaces[i].interface_one );
if ( get_link_state ( lmon_ctrl.ioctl_socket,
iter_ptr->c_str(),
&running ) == PASS )
{
if ( interfaces[i].interface_one_link_up == false )
{
ilog ("%s is Up (%s)\n",
iter_ptr->c_str(),
running ? "Up" : "Down" );
}
else
{
dlog ("%s is Up (%s)\n",
iter_ptr->c_str(),
running ? "Up" : "Down" );
}
interfaces[i].interface_one_link_up = running ? true:false;
}
else
{
wlog ("%s is Down ; oper query failed\n", iter_ptr->c_str() );
interfaces[i].interface_one_link_up = false ;
}
}
else if (interfaces[i].lagged == true)
{
if ( strcmp ( interfaces[i].interface_two, iter_ptr->c_str()) == 0 )
{
found = true ;
interfaces[i].interface_two_event_time = lmon_fm_timestamp();
dlog ("%s is Up\n", interfaces[i].interface_two );
if ( get_link_state ( lmon_ctrl.ioctl_socket,
iter_ptr->c_str(),
&running ) == PASS )
{
if ( interfaces[i].interface_two_link_up == false )
{
ilog ("%s is Up (%s)\n",
iter_ptr->c_str(),
running ? "Up" : "Down" );
}
else
{
dlog ("%s is Up (%s)\n",
iter_ptr->c_str(),
running ? "Up" : "Down" );
}
interfaces[i].interface_two_link_up = running ? true:false;
}
else
{
wlog ("%s is Down ; oper query failed\n", iter_ptr->c_str() );
interfaces[i].interface_two_link_up = false ;
}
}
if ( strcmp ( interfaces[i].bond, iter_ptr->c_str()) == 0 )
{
found = true ;
wlog ("%s is Up (bond)\n", interfaces[i].bond);
}
}
}
if ( ! found )
{
dlog ("netlink Up event on unmonitored link:%s", iter_ptr->c_str());
}
}
}
}
return (PASS);
}
/**************************************************************************
*
* Name : lmon_query_all_links
*
* Purpose : self correct for netlink event misses by running this
* as a periodic audit at a 1 minute cadence.
*
**************************************************************************/
void lmon_query_all_links( void )
{
dlog1 ("audit timer fired");
for ( int i = 0 ; i < INTERFACES_MAX ; i++ )
{
if ( interfaces[i].used )
{
bool link_up = false ;
string log_msg = "link state mismatch detected by audit";
if ( lmon_get_link_state ( lmon_ctrl.ioctl_socket,
interfaces[i].interface_one,
link_up) == PASS )
{
if ( link_up != interfaces[i].interface_one_link_up )
{
wlog ("%s %s ; is:%s was:%s ; corrected",
interfaces[i].interface_one,
log_msg.c_str(),
link_up?"Up":"Down",
interfaces[i].interface_one_link_up?"Up":"Down" );
interfaces[i].interface_one_event_time = lmon_fm_timestamp();
interfaces[i].interface_one_link_up = link_up ;
}
}
if ( interfaces[i].lagged )
{
if ( lmon_get_link_state ( lmon_ctrl.ioctl_socket,
interfaces[i].interface_two,
link_up) == PASS )
{
if ( link_up != interfaces[i].interface_two_link_up )
{
wlog ("%s %s ; is:%s was:%s ; corrected",
interfaces[i].interface_two,
log_msg.c_str(),
link_up?"Up":"Down",
interfaces[i].interface_two_link_up?"Up":"Down" );
interfaces[i].interface_two_event_time = lmon_fm_timestamp();
interfaces[i].interface_two_link_up = link_up ;
}
}
}
}
}
}
/*****************************************************************************
*
* Name : daemon_service_run
*
* Purpose : track interface profile link status.