Browse Source

Merge "Add new Link Monitor (lmond) daemon to Mtce"

Zuul 2 months ago
parent
commit
6e7bbf6e35

+ 1
- 0
centos_iso_image.inc View File

@@ -8,6 +8,7 @@ mtce-pmon
8 8
 mtce-rmon
9 9
 mtce-hwmon
10 10
 mtce-hostw
11
+mtce-lmon
11 12
 
12 13
 # mtce-compute
13 14
 mtce-compute

+ 156
- 0
mtce-common/src/common/httpUtil.cpp View File

@@ -27,6 +27,33 @@ static char rest_api_filename[MAX_FILENAME_LEN];
27 27
 static char rest_api_log_str [MAX_API_LOG_LEN];
28 28
 static libEvent nullEvent ;
29 29
 
30
+#define HTTP_GET_STR "GET"
31
+#define HTTP_PUT_STR "PUT"
32
+#define HTTP_PATCH_STR "PATCH"
33
+#define HTTP_POST_STR "POST"
34
+#define HTTP_DELETE_STR "DELETE"
35
+#define HTTP_UNKNOWN_STR "UNKNOWN"
36
+
37
+/* convert http event type to its string name */
38
+const char * getHttpCmdType_str ( evhttp_cmd_type type )
39
+{
40
+    switch (type)
41
+    {
42
+        case EVHTTP_REQ_GET:    return(HTTP_GET_STR);
43
+        case EVHTTP_REQ_PUT:    return(HTTP_PUT_STR);
44
+        case EVHTTP_REQ_PATCH:  return(HTTP_PATCH_STR);
45
+        case EVHTTP_REQ_POST:   return(HTTP_POST_STR);
46
+        case EVHTTP_REQ_DELETE: return(HTTP_DELETE_STR);
47
+        case EVHTTP_REQ_HEAD:
48
+        case EVHTTP_REQ_OPTIONS:
49
+        case EVHTTP_REQ_TRACE:
50
+        case EVHTTP_REQ_CONNECT:
51
+        default:
52
+            break ;
53
+    }
54
+    return(HTTP_UNKNOWN_STR);
55
+}
56
+
30 57
 /* ***********************************************************************
31 58
  *
32 59
  * Name       : httpUtil_event_init
@@ -1057,3 +1084,132 @@ void httpUtil_log_event ( libEvent * event_ptr )
1057 1084
 
1058 1085
     send_log_message ( mtclogd_ptr, event_ptr->hostname.data(), &rest_api_filename[0], &rest_api_log_str[0] );
1059 1086
 }
1087
+
1088
+/*****************************************************************
1089
+ *
1090
+ * Name        : httpUtil_bind
1091
+ *
1092
+ * Description : Setup the HTTP server socket
1093
+ *
1094
+ *****************************************************************/
1095
+int httpUtil_bind ( libEvent & event )
1096
+{
1097
+   int one = 1;
1098
+
1099
+   event.fd = socket(AF_INET, SOCK_STREAM, 0);
1100
+   if (event.fd < 0)
1101
+   {
1102
+       elog ("failed to create http server socket (%d:%m)\n", errno );
1103
+       return FAIL_SOCKET_CREATE ;
1104
+   }
1105
+
1106
+   /* make socket reusable */
1107
+   if ( 0 > setsockopt(event.fd, SOL_SOCKET, SO_REUSEADDR, (char *)&one, sizeof(int)))
1108
+   {
1109
+       elog ("failed to set http server socket to reusable (%d:%m)\n", errno );
1110
+       return FAIL_SOCKET_OPTION ;
1111
+   }
1112
+
1113
+   memset(&event.addr, 0, sizeof(struct sockaddr_in));
1114
+   event.addr.sin_family = AF_INET;
1115
+
1116
+   /* ERIK: INADDR_ANY; TODO: Refine this if we can */
1117
+   event.addr.sin_addr.s_addr = inet_addr(LOOPBACK_IP);
1118
+   // event.addr.sin_addr.s_addr = INADDR_ANY;
1119
+   event.addr.sin_port = htons(event.port);
1120
+
1121
+   /* bind port */
1122
+   if ( 0 > bind ( event.fd, (struct sockaddr*)&event.addr, sizeof(struct sockaddr_in)))
1123
+   {
1124
+       elog ("failed to bind to http server port %d (%d:%m)\n", event.port, errno );
1125
+       return FAIL_SOCKET_BIND ;
1126
+   }
1127
+
1128
+   /* Listen for events */
1129
+   if ( 0 > listen(event.fd, 10 ))
1130
+   {
1131
+       elog ("failed to listen to http server socket (%d:%m)\n", errno );
1132
+       return FAIL_SOCKET_LISTEN;
1133
+   }
1134
+
1135
+   /* make non-blocking */
1136
+   int flags = fcntl ( event.fd, F_GETFL, 0) ;
1137
+   if ( flags < 0 || fcntl(event.fd, F_SETFL, flags | O_NONBLOCK) < 0)
1138
+   {
1139
+       elog ("failed to set http server socket to non-blocking (%d:%m)\n", errno );
1140
+       return FAIL_SOCKET_OPTION;
1141
+   }
1142
+
1143
+   return PASS;
1144
+}
1145
+
1146
+/* Setup the http server */
1147
+int httpUtil_setup ( libEvent & event,
1148
+                     int          supported_methods,
1149
+                     void(*hdlr)(struct evhttp_request *, void *) )
1150
+{
1151
+   int rc = PASS ;
1152
+   if ( ( rc = httpUtil_bind ( event )) != PASS )
1153
+   {
1154
+       return rc ;
1155
+   }
1156
+   else if (event.fd < 0)
1157
+   {
1158
+       wlog ("failed to get http server socket file descriptor\n");
1159
+       return RETRY ;
1160
+   }
1161
+
1162
+   event.base = event_base_new();
1163
+   if (event.base == NULL)
1164
+   {
1165
+       elog ("failed to get http server event base\n");
1166
+       return -1;
1167
+   }
1168
+   event.httpd = evhttp_new(event.base);
1169
+   if (event.httpd == NULL)
1170
+   {
1171
+       elog ("failed to get httpd server handle\n");
1172
+       return -1;
1173
+   }
1174
+
1175
+   /* api is a void return */
1176
+   evhttp_set_allowed_methods (event.httpd, supported_methods );
1177
+
1178
+   rc = evhttp_accept_socket(event.httpd, event.fd);
1179
+   if ( rc == -1)
1180
+   {
1181
+       elog ("failed to accept on http server socket\n");
1182
+       return -1;
1183
+   }
1184
+
1185
+   /* api is a void return */
1186
+   evhttp_set_gencb(event.httpd, hdlr, NULL);
1187
+
1188
+   ilog ("Listening On: 'http server' socket %s:%d\n",
1189
+          inet_ntoa(event.addr.sin_addr), event.port );
1190
+   return PASS ;
1191
+}
1192
+
1193
+void httpUtil_fini ( libEvent & event )
1194
+{
1195
+    if ( event.fd )
1196
+    {
1197
+        if ( event.base )
1198
+        {
1199
+            event_base_free( event.base);
1200
+        }
1201
+        close ( event.fd );
1202
+        event.fd = 0 ;
1203
+    }
1204
+}
1205
+
1206
+void httpUtil_look ( libEvent & event )
1207
+{
1208
+    /* Look for Events */
1209
+    if ( event.base )
1210
+    {
1211
+        // rc = event_base_loopexit( mtce_event.base, NULL ) ; // EVLOOP_NONBLOCK );
1212
+        event_base_loop(event.base, EVLOOP_NONBLOCK );
1213
+    }
1214
+}
1215
+

+ 15
- 0
mtce-common/src/common/httpUtil.h View File

@@ -12,6 +12,7 @@
12 12
 #include <evhttp.h>         /* for ... http libevent client */
13 13
 #include <time.h>
14 14
 #include <list>
15
+#include <fcntl.h>          /* for ... F_GETFL              */
15 16
 
16 17
 using namespace std;
17 18
 
@@ -22,6 +23,7 @@ using namespace std;
22 23
 #define MTC_HTTP_BAD_REQUEST          400
23 24
 #define MTC_HTTP_UNAUTHORIZED         401
24 25
 #define MTC_HTTP_FORBIDDEN            403
26
+#define MTC_HTTP_METHOD_NOT_ALLOWED   405
25 27
 #define MTC_HTTP_CONFLICT             409
26 28
 #define MTC_HTTP_LENGTH_REQUIRED      411
27 29
 #define MTC_HTTP_NORESPONSE           444
@@ -194,6 +196,10 @@ struct libEvent
194 196
     struct evbuffer          *buf ; /**< HTTP output buffer ptr      */
195 197
     struct evbuffer_ptr       evp ; /**< HTTP output buffer ptr      */
196 198
 
199
+    int                        fd ;
200
+    struct sockaddr_in       addr ;
201
+    struct evhttp          *httpd ;
202
+
197 203
     string log_prefix             ; /**< log prefix for this event   */
198 204
 
199 205
     /** Service Specific Request Info */
@@ -339,5 +345,14 @@ void httpUtil_event_info ( libEvent & event );
339 345
 
340 346
 const char * getHttpCmdType_str ( evhttp_cmd_type type );
341 347
 
348
+/* HTTP Server setup utilities */
349
+int httpUtil_bind  ( libEvent & event );
350
+
351
+int httpUtil_setup ( libEvent & event,
352
+                     int        supported_methods,
353
+                     void(*hdlr)(struct evhttp_request *, void *));
354
+/* Cleanup */
355
+void httpUtil_fini ( libEvent & event );
356
+void httpUtil_look ( libEvent & event );
342 357
 
343 358
 #endif /* __INCLUDE_HTTPUTIL_H__ */

+ 4
- 3
mtce-common/src/common/logMacros.h View File

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

+ 10
- 26
mtce-common/src/common/nodeUtil.cpp View File

@@ -1489,40 +1489,24 @@ string get_event_str ( int event_code )
1489 1489
     }
1490 1490
 }
1491 1491
 
1492
-#define HTTP_GET_STR "GET"
1493
-#define HTTP_PUT_STR "PUT"
1494
-#define HTTP_PATCH_STR "PATCH"
1495
-#define HTTP_POST_STR "POST"
1496
-#define HTTP_DELETE_STR "DELETE"
1497
-#define HTTP_UNKNOWN_STR "UNKNOWN"
1498
-
1499
-/* Private: convert http event type to its string name */
1500
-const char * getHttpCmdType_str ( evhttp_cmd_type type )
1492
+#define MAX_NUM_LEN 64
1493
+string itos ( int val )
1501 1494
 {
1502
-    switch (type)
1503
-    {
1504
-        case EVHTTP_REQ_GET:    return(HTTP_GET_STR);
1505
-        case EVHTTP_REQ_PUT:    return(HTTP_PUT_STR);
1506
-        case EVHTTP_REQ_PATCH:  return(HTTP_PATCH_STR);
1507
-        case EVHTTP_REQ_POST:   return(HTTP_POST_STR);
1508
-        case EVHTTP_REQ_DELETE: return(HTTP_DELETE_STR);
1509
-        case EVHTTP_REQ_HEAD:
1510
-        case EVHTTP_REQ_OPTIONS:
1511
-        case EVHTTP_REQ_TRACE:
1512
-        case EVHTTP_REQ_CONNECT:
1513
-        default:
1514
-            break ;
1515
-    }
1516
-    return(HTTP_UNKNOWN_STR);    
1495
+    char int_str[MAX_NUM_LEN] ;
1496
+    string temp ;
1497
+    memset  ( &int_str[0], 0, MAX_NUM_LEN );
1498
+    snprintf ( &int_str[0], MAX_NUM_LEN, "%d" , val );
1499
+    temp = int_str ;
1500
+    return (temp);
1517 1501
 }
1518 1502
 
1519 1503
 #define MAX_NUM_LEN 64
1520
-string itos ( int val )
1504
+string lltos (long long unsigned int val )
1521 1505
 {
1522 1506
     char int_str[MAX_NUM_LEN] ;
1523 1507
     string temp ;
1524 1508
     memset  ( &int_str[0], 0, MAX_NUM_LEN );
1525
-    snprintf ( &int_str[0], MAX_NUM_LEN, "%d" , val );
1509
+    snprintf ( &int_str[0], MAX_NUM_LEN, "%llu" , val );
1526 1510
     temp = int_str ;
1527 1511
     return (temp);
1528 1512
 }

+ 1
- 1
mtce-common/src/common/nodeUtil.h View File

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

+ 2
- 0
mtce-common/src/daemon/daemon_config.cpp View File

@@ -34,6 +34,7 @@ void daemon_config_default ( daemon_config_type* config_ptr )
34 34
     config_ptr->mon_process_5         = strdup("none");
35 35
     config_ptr->mon_process_6         = strdup("none");
36 36
     config_ptr->mon_process_7         = strdup("none");
37
+    config_ptr->uri_path              = strdup("");
37 38
     config_ptr->keystone_prefix_path  = strdup("");
38 39
     config_ptr->keystone_identity_uri = strdup("");
39 40
     config_ptr->keystone_auth_uri     = strdup("");
@@ -295,6 +296,7 @@ void daemon_dump_cfg ( void )
295 296
 
296 297
     /* mtcAgent & hwmond */
297 298
     if ( ptr->sysinv_api_port       ) { ilog ("sysinv_api_port       = %d\n", ptr->sysinv_api_port       );}
299
+    if ( ptr->uri_path  )             { ilog ("uri_path              = %s\n", ptr->uri_path              );}
298 300
     if ( ptr->keystone_prefix_path  ) { ilog ("keystone_prefix_path  = %s\n", ptr->keystone_prefix_path  );}
299 301
     if ( ptr->keystone_auth_host    ) { ilog ("keystone_auth_host    = %s\n", ptr->keystone_auth_host    );}
300 302
     if ( ptr->keystone_identity_uri ) { ilog ("keystone_identity_uri = %s\n", ptr->keystone_identity_uri );}

+ 1
- 1
mtce/centos/build_srpm.data View File

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

+ 58
- 9
mtce/centos/mtce.spec View File

@@ -178,7 +178,7 @@ Provides: librmonapi.so.1()(64bit)
178 178
 Titanium Cloud Host Maintenance Resource Monitor Service (rmond) adds
179 179
 threshold based monitoring with predictive severity level alarming for
180 180
 out of tolerance utilization of critical resourses such as memory, cpu
181
-file system, interface state, etc.
181
+file system, etc.
182 182
 
183 183
 %package -n mtce-hwmon
184 184
 Summary: Titanuim Server Maintenance Hardware Monitor Package
@@ -266,6 +266,39 @@ of spec operating conditions that can reduce outage time through automated
266 266
 notification and recovery thereby improving overall platform availability
267 267
 for the customer.
268 268
 
269
+%package -n mtce-lmon
270
+Summary: Titanuim Server Maintenance Link Monitor Package
271
+Group: base
272
+BuildRequires: cppcheck
273
+Requires: util-linux
274
+Requires: /bin/bash
275
+Requires: /bin/systemctl
276
+Requires: dpkg
277
+Requires: time
278
+Requires: libstdc++.so.6(CXXABI_1.3)(64bit)
279
+Requires: libfmcommon.so.1()(64bit)
280
+Requires: libc.so.6(GLIBC_2.7)(64bit)
281
+Requires: libc.so.6(GLIBC_2.2.5)(64bit)
282
+Requires: libstdc++.so.6(GLIBCXX_3.4.11)(64bit)
283
+Requires: /bin/sh
284
+Requires: libc.so.6(GLIBC_2.3)(64bit)
285
+Requires: libc.so.6(GLIBC_2.14)(64bit)
286
+Requires: librt.so.1(GLIBC_2.3.3)(64bit)
287
+Requires: libgcc_s.so.1(GCC_3.0)(64bit)
288
+Requires: librt.so.1(GLIBC_2.2.5)(64bit)
289
+Requires: libm.so.6()(64bit)
290
+Requires: rtld(GNU_HASH)
291
+Requires: libstdc++.so.6()(64bit)
292
+Requires: libc.so.6(GLIBC_2.4)(64bit)
293
+Requires: libc.so.6()(64bit)
294
+Requires: libgcc_s.so.1()(64bit)
295
+Requires: libstdc++.so.6(GLIBCXX_3.4)(64bit)
296
+Requires: libstdc++.so.6(GLIBCXX_3.4.15)(64bit)
297
+
298
+%description -n mtce-lmon
299
+Titanium Cloud Maintenance Link Monitor service (lmond) provides
300
+netlink monitoring for provisioned oam, mgmt and infra interfaces.
301
+
269 302
 %define local_dir /usr/local
270 303
 %define local_bindir %{local_dir}/bin
271 304
 %define local_sbindir %{local_dir}/sbin
@@ -321,6 +354,7 @@ install -m 644 -p -D %{_buildsubdir}/scripts/mtc.conf %{buildroot}%{_sysconfdir}
321 354
 install -m 644 -p -D %{_buildsubdir}/fsmon/scripts/fsmond.conf %{buildroot}%{_sysconfdir}/mtc/fsmond.conf
322 355
 install -m 644 -p -D %{_buildsubdir}/hwmon/scripts/hwmond.conf %{buildroot}%{_sysconfdir}/mtc/hwmond.conf
323 356
 install -m 644 -p -D %{_buildsubdir}/pmon/scripts/pmond.conf %{buildroot}%{_sysconfdir}/mtc/pmond.conf
357
+install -m 644 -p -D %{_buildsubdir}/lmon/scripts/lmond.conf %{buildroot}%{_sysconfdir}/mtc/lmond.conf
324 358
 install -m 644 -p -D %{_buildsubdir}/rmon/scripts/rmond.conf %{buildroot}%{_sysconfdir}/mtc/rmond.conf
325 359
 install -m 644 -p -D %{_buildsubdir}/hostw/scripts/hostwd.conf %{buildroot}%{_sysconfdir}/mtc/hostwd.conf
326 360
 
@@ -335,6 +369,7 @@ install -m 755 -p -D %{_buildsubdir}/maintenance/mtcClient %{buildroot}/%{local_
335 369
 install -m 755 -p -D %{_buildsubdir}/heartbeat/hbsAgent %{buildroot}/%{local_bindir}/hbsAgent
336 370
 install -m 755 -p -D %{_buildsubdir}/heartbeat/hbsClient %{buildroot}/%{local_bindir}/hbsClient
337 371
 install -m 755 -p -D %{_buildsubdir}/pmon/pmond %{buildroot}/%{local_bindir}/pmond
372
+install -m 755 -p -D %{_buildsubdir}/lmon/lmond %{buildroot}/%{local_bindir}/lmond
338 373
 install -m 755 -p -D %{_buildsubdir}/hostw/hostwd %{buildroot}/%{local_bindir}/hostwd
339 374
 install -m 755 -p -D %{_buildsubdir}/rmon/rmond %{buildroot}/%{local_bindir}/rmond
340 375
 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
355 390
 install -m 755 -p -D %{_buildsubdir}/fsmon/scripts/fsmon %{buildroot}%{_sysconfdir}/init.d/fsmon
356 391
 install -m 755 -p -D %{_buildsubdir}/scripts/mtclog %{buildroot}%{_sysconfdir}/init.d/mtclog
357 392
 install -m 755 -p -D %{_buildsubdir}/pmon/scripts/pmon %{buildroot}%{_sysconfdir}/init.d/pmon
393
+install -m 755 -p -D %{_buildsubdir}/lmon/scripts/lmon %{buildroot}%{_sysconfdir}/init.d/lmon
358 394
 install -m 755 -p -D %{_buildsubdir}/rmon/scripts/rmon %{buildroot}%{_sysconfdir}/init.d/rmon
359 395
 install -m 755 -p -D %{_buildsubdir}/hostw/scripts/hostw %{buildroot}%{_sysconfdir}/init.d/hostw
360 396
 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
377 413
 install -m 644 -p -D %{_buildsubdir}/scripts/goenabled.service %{buildroot}%{_unitdir}/goenabled.service
378 414
 install -m 644 -p -D %{_buildsubdir}/scripts/runservices.service %{buildroot}%{_unitdir}/runservices.service
379 415
 install -m 644 -p -D %{_buildsubdir}/alarm/scripts/mtcalarm.service %{buildroot}%{_unitdir}/mtcalarm.service
416
+install -m 644 -p -D %{_buildsubdir}/lmon/scripts/lmon.service %{buildroot}%{_unitdir}/lmon.service
380 417
 
381 418
 # go enabled stuff
382 419
 install -m 755 -d %{buildroot}%{local_etc_goenabledd}
@@ -407,18 +444,15 @@ install -m 644 -p -D %{_buildsubdir}/rmon/scripts/rmon.conf %{buildroot}%{local_
407 444
 install -m 644 -p -D %{_buildsubdir}/fsmon/scripts/fsmon.conf %{buildroot}%{local_etc_pmond}/fsmon.conf
408 445
 install -m 644 -p -D %{_buildsubdir}/scripts/mtclogd.conf %{buildroot}%{local_etc_pmond}/mtclogd.conf
409 446
 install -m 644 -p -D %{_buildsubdir}/alarm/scripts/mtcalarm.pmon.conf %{buildroot}%{local_etc_pmond}/mtcalarm.conf
447
+install -m 644 -p -D %{_buildsubdir}/lmon/scripts/lmon.pmon.conf %{buildroot}%{local_etc_pmond}/lmon.conf
410 448
 
411 449
 # resource monitor config files
412 450
 install -m 755 -d %{buildroot}%{local_etc_rmond}
413 451
 install -m 755 -d %{buildroot}%{_sysconfdir}/rmonapi.d
414 452
 install -m 755 -d %{buildroot}%{_sysconfdir}/rmonfiles.d
415
-install -m 755 -d %{buildroot}%{_sysconfdir}/rmon_interfaces.d
416 453
 install -m 644 -p -D %{_buildsubdir}/rmon/scripts/remotelogging_resource.conf %{buildroot}%{local_etc_rmond}/remotelogging_resource.conf
417 454
 install -m 644 -p -D %{_buildsubdir}/rmon/scripts/cinder_virtual_resource.conf %{buildroot}%{local_etc_rmond}/cinder_virtual_resource.conf
418 455
 install -m 644 -p -D %{_buildsubdir}/rmon/scripts/nova_virtual_resource.conf %{buildroot}%{local_etc_rmond}/nova_virtual_resource.conf
419
-install -m 644 -p -D %{_buildsubdir}/rmon/scripts/oam_resource.conf %{buildroot}%{_sysconfdir}/rmon_interfaces.d/oam_resource.conf
420
-install -m 644 -p -D %{_buildsubdir}/rmon/scripts/management_resource.conf %{buildroot}%{_sysconfdir}/rmon_interfaces.d/management_resource.conf
421
-install -m 644 -p -D %{_buildsubdir}/rmon/scripts/infrastructure_resource.conf %{buildroot}%{_sysconfdir}/rmon_interfaces.d/infrastructure_resource.conf
422 456
 install -m 755 -p -D %{_buildsubdir}/rmon/scripts/rmon_reload_on_cpe.sh %{buildroot}%{local_etc_goenabledd}/rmon_reload_on_cpe.sh
423 457
 
424 458
 # log rotation
@@ -426,6 +460,7 @@ install -m 755 -d %{buildroot}%{_sysconfdir}/logrotate.d
426 460
 install -m 644 -p -D %{_buildsubdir}/scripts/mtce.logrotate %{buildroot}%{local_etc_logrotated}/mtce.logrotate
427 461
 install -m 644 -p -D %{_buildsubdir}/hostw/scripts/hostw.logrotate %{buildroot}%{local_etc_logrotated}/hostw.logrotate
428 462
 install -m 644 -p -D %{_buildsubdir}/pmon/scripts/pmon.logrotate %{buildroot}%{local_etc_logrotated}/pmon.logrotate
463
+install -m 644 -p -D %{_buildsubdir}/lmon/scripts/lmon.logrotate %{buildroot}%{local_etc_logrotated}/lmon.logrotate
429 464
 install -m 644 -p -D %{_buildsubdir}/rmon/scripts/rmon.logrotate %{buildroot}%{local_etc_logrotated}/rmon.logrotate
430 465
 install -m 644 -p -D %{_buildsubdir}/fsmon/scripts/fsmon.logrotate %{buildroot}%{local_etc_logrotated}/fsmon.logrotate
431 466
 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
466 501
 %post -n mtce-rmon
467 502
 /bin/systemctl enable rmon.service
468 503
 
504
+%post -n mtce-lmon
505
+/bin/systemctl enable lmon.service
506
+
469 507
 ###############################
470 508
 # Maintenance RPM Files
471 509
 ###############################
@@ -583,10 +621,6 @@ install -m 755 -d %{buildroot}/var/run
583 621
 %{local_etc_rmond}/cinder_virtual_resource.conf
584 622
 %{local_etc_rmond}/nova_virtual_resource.conf
585 623
 
586
-%{_sysconfdir}/rmon_interfaces.d/management_resource.conf
587
-%{_sysconfdir}/rmon_interfaces.d/oam_resource.conf
588
-%{_sysconfdir}/rmon_interfaces.d/infrastructure_resource.conf
589
-
590 624
 %{_libdir}/librmonapi.so.1.0
591 625
 %{_libdir}/librmonapi.so.1
592 626
 %{_libdir}/librmonapi.so
@@ -628,6 +662,21 @@ install -m 755 -d %{buildroot}/var/run
628 662
 %{_sysconfdir}/init.d/hostw
629 663
 %{local_bindir}/hostwd
630 664
 
665
+###############################
666
+# Link Monitor RPM Files
667
+###############################
668
+%files -n mtce-lmon
669
+%defattr(-,root,root,-)
670
+
671
+# Config files - Non-Modifiable
672
+%{_sysconfdir}/mtc/lmond.conf
673
+
674
+%{_unitdir}/lmon.service
675
+%{local_etc_logrotated}/lmon.logrotate
676
+%{local_etc_pmond}/lmon.conf
677
+%{local_bindir}/lmond
678
+%{_sysconfdir}/init.d/lmon
679
+
631 680
 ###############################
632 681
 # Maintenance Software Development RPM
633 682
 ###############################

+ 2
- 0
mtce/src/Makefile View File

@@ -16,6 +16,7 @@ build:
16 16
 	(cd maintenance ; make build VER=$(VER) VER_MJR=$(VER_MJR))
17 17
 	(cd hwmon  ; make build VER=$(VER) VER_MJR=$(VER_MJR))
18 18
 	(cd mtclog ; make build VER=$(VER) VER_MJR=$(VER_MJR))
19
+	(cd lmon   ; make build VER=$(VER) VER_MJR=$(VER_MJR))
19 20
 	(cd pmon   ; make build VER=$(VER) VER_MJR=$(VER_MJR))
20 21
 	(cd fsmon  ; make build VER=$(VER) VER_MJR=$(VER_MJR))
21 22
 	(cd rmon   ; make build VER=$(VER) VER_MJR=$(VER_MJR))
@@ -30,6 +31,7 @@ clean:
30 31
 	@( cd alarm  ; make clean )
31 32
 	@( cd mtclog ; make clean )
32 33
 	@( cd hwmon  ; make clean )
34
+	@( cd lmon   ; make clean )
33 35
 	@( cd pmon   ; make clean )
34 36
 	@( cd fsmon  ; make clean )
35 37
 	@( cd heartbeat ; make clean )

+ 35
- 0
mtce/src/lmon/Makefile View File

@@ -0,0 +1,35 @@
1
+#
2
+# Copyright (c) 2019 Wind River Systems, Inc.
3
+#
4
+# SPDX-License-Identifier: Apache-2.0
5
+#
6
+
7
+SHELL = /bin/bash
8
+
9
+SRCS = lmonInit.cpp lmonUtil.cpp lmonHdlr.cpp
10
+OBJS = $(SRCS:.cpp=.o)
11
+LDLIBS = -lstdc++ -ldaemon -lcommon -ljson-c -lcrypto -lrt -levent
12
+LDPATH = -L../../../mtce-common/src/daemon -L../../../mtce-common/src/common
13
+INCLUDES = -I. -I/usr/include/mtce-daemon -I/usr/include/mtce-common
14
+CCFLAGS = -g -O2 -Wall -Wextra -Werror
15
+
16
+STATIC_ANALYSIS_TOOL = cppcheck
17
+STATIC_ANALYSIS_TOOL_EXISTS = $(shell [[ -e `which $(STATIC_ANALYSIS_TOOL)` ]] && echo 1 || echo 0)
18
+
19
+all: clean static_analysis build
20
+
21
+.cpp.o:
22
+	$(CXX) $(INCLUDES) $(CCFLAGS) $(EXTRACCFLAGS) -c $< -o $@
23
+
24
+static_analysis:
25
+ifeq ($(STATIC_ANALYSIS_TOOL_EXISTS), 1)
26
+	$(STATIC_ANALYSIS_TOOL) --language=c++ --enable=warning -U__AREA__ *.cpp *.h
27
+else
28
+	echo "Warning: '$(STATIC_ANALYSIS_TOOL)' static analysis tool not installed ; bypassing ..."
29
+endif
30
+
31
+build: clean static_analysis $(OBJS)
32
+	$(CXX) $(CCFLAGS) $(OBJS) $(LDPATH) $(LDLIBS) -o lmond
33
+
34
+clean:
35
+	@rm -v -f $(OBJ) lmond *.o *.a

+ 119
- 0
mtce/src/lmon/lmon.h View File

@@ -0,0 +1,119 @@
1
+/*
2
+ * Copyright (c) 2019 Wind River Systems, Inc.
3
+ *
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ *
6
+ */
7
+
8
+#include <net/if.h>          /* for ... IF_NAMESIZE                         */
9
+
10
+using namespace std;
11
+
12
+#include "daemon_ini.h"      /* for ... ini_parse                           */
13
+#include "daemon_common.h"   /* for ... daemon common definitions and types */
14
+#include "nodeBase.h"        /* for ... maintenance base definitions        */
15
+#include "nodeTimers.h"      /* for ... mtcTimer_init/start/stop utilities  */
16
+#include "nodeUtil.h"        /* for ... common utils like open_ioctl_socket */
17
+#include "httpUtil.h"        /* for ... httputil_setup                      */
18
+#include "nlEvent.h"         /* for ... open_netlink_socket                 */
19
+#include "fmAPI.h"           /* for ... FMTimeT                             */
20
+
21
+#ifdef __AREA__
22
+#undef __AREA__
23
+#endif
24
+#define __AREA__ "mon"
25
+
26
+#define INTERFACES_DIR ((const char *)"/sys/class/net/")
27
+#define PLATFORM_DIR   ((const char *)"/etc/platform/platform.conf")
28
+
29
+#define INTERFACES_MAX (3) /* maximum number of interfaces to monitor */
30
+
31
+enum interface_type { ethernet = 0, vlan = 1, bond = 2 };
32
+string iface_type ( interface_type type_enum );
33
+
34
+/* daemon only supports the GET request */
35
+#define HTTP_SUPPORTED_METHODS  (EVHTTP_REQ_GET)
36
+
37
+typedef struct
38
+{
39
+    int              ioctl_socket     ;
40
+    int              netlink_socket   ;
41
+    libEvent         http_event       ;
42
+    msgSock_type     mtclogd          ;
43
+    int              dos_log_throttle ;
44
+    struct mtc_timer audit_timer      ;
45
+
46
+    char my_hostname[MAX_HOST_NAME_SIZE+1];
47
+    char my_address [MAX_CHARS_IN_IP_ADDR+1];
48
+
49
+} lmon_ctrl_type ;
50
+
51
+typedef struct
52
+{
53
+    const char * name ;  /* pointer to well known primary interface name */
54
+
55
+    /* primary interface names */
56
+    #define MGMT_INTERFACE_NAME  ((const char *)"mgmt")
57
+    #define INFRA_INTERFACE_NAME ((const char *)"infra")
58
+    #define OAM_INTERFACE_NAME   ((const char *)"oam")
59
+
60
+    /* name labels used in platform.conf */
61
+    #define MGMT_INTERFACE_FULLNAME  ((const char *)"management_interface")
62
+    #define INFRA_INTERFACE_FULLNAME ((const char *)"infrastructure_interface")
63
+    #define OAM_INTERFACE_FULLNAME   ((const char *)"oam_interface")
64
+
65
+    /* true if the interface is configured.
66
+     * i.e. the name label shown above is found in platform.conf */
67
+    bool used ;
68
+    interface_type type_enum ;
69
+
70
+    /* true if the link is up ; false otherwise */
71
+    bool interface_one_link_up ;
72
+    bool interface_two_link_up ;
73
+
74
+    FMTimeT interface_one_event_time ;
75
+    FMTimeT interface_two_event_time ;
76
+
77
+    /* Config Items */
78
+    const char * severity  ;              /* MINOR, MAJOR or CRITICAL for each resource */
79
+    unsigned int debounce  ;              /* Period to wait before clearing alarms  */
80
+    unsigned int num_tries ;              /* Number of times a resource has to be in
81
+                                             failed or cleared state before sending alarm */
82
+
83
+    /* Dynamic Data */
84
+    char          interface_one[IF_NAMESIZE] ; /* primary interface */
85
+    char          interface_two[IF_NAMESIZE] ; /* second interface if lagged  */
86
+    char          bond[IF_NAMESIZE]          ; /* bonded interface name */
87
+    bool          lagged                     ; /* Lagged interface=true or not=false     */
88
+
89
+//    unsigned int     debounce_cnt   ; /* running monitor debounce count         */
90
+//    unsigned int     minorlog_cnt   ; /* track minor log count for thresholding */
91
+//    unsigned int     count          ; /* track the number of times the condition has been occured */
92
+//    bool             failed         ; /* track if the resource needs to be serviced by the resource handler */
93
+//    int              resource_value ; /* 1 if the interface is up and 0 if it is down   */
94
+//    int     resource_value_lagged   ; /* 1 if the interface is up and 0 if it is down for lagged interfaces  */
95
+//    int              sev            ; /* The severity of the failed resource */
96
+//  rmonStage_enum   stage          ; /* The stage the resource is in within the resource handler fsm */
97
+//    char alarm_id[FM_MAX_BUFFER_LENGTH] ; /* Used by FM API, type of alarm being raised */
98
+//    char alarm_id_port[FM_MAX_BUFFER_LENGTH] ; /* Used by FM API, type of alarm being raised for the ports */
99
+//    char errorMsg[ERR_SIZE];
100
+//    rmon_api_socket_type msg;
101
+//    bool link_up_and_running; /* whether the interface is up or down initially */
102
+
103
+//    bool alarm_raised;
104
+//    int failed_send; /* The number of times the rmon api failed to send a message */
105
+
106
+
107
+} interface_ctrl_type ;
108
+
109
+
110
+/* lmonHdlr.cpp */
111
+void daemon_exit ( void );
112
+void lmon_learn_interfaces ( int ioctl_sock );
113
+
114
+/* lmonUtils.cpp */
115
+FMTimeT lmon_fm_timestamp     ( void );
116
+int     lmon_interfaces_init  ( interface_ctrl_type * ptr );
117
+int     lmon_get_link_state   ( int    ioctl_socket,
118
+                                char   iface[IF_NAMESIZE],
119
+                                bool & link_up );

+ 769
- 0
mtce/src/lmon/lmonHdlr.cpp View File

@@ -0,0 +1,769 @@
1
+/*
2
+ * Copyright (c) 2019 Wind River Systems, Inc.
3
+*
4
+* SPDX-License-Identifier: Apache-2.0
5
+*
6
+ */
7
+
8
+ /**
9
+  * @file
10
+  * Starling-X Maintenance Link Monitor Service Header
11
+  */
12
+
13
+#include "lmon.h"
14
+#include <linux/rtnetlink.h> /* for ... RTMGRP_LINK                         */
15
+#include "nodeMacro.h"       /* for ... CREATE_REUSABLE_INET_UDP_TX_SOCKET  */
16
+
17
+#define HTTP_SERVER_NAME ((const char *)"link status query")
18
+
19
+
20
+static lmon_ctrl_type lmon_ctrl ;
21
+
22
+static interface_ctrl_type interfaces[INTERFACES_MAX];
23
+
24
+static const char * iface_list[INTERFACES_MAX] = { MGMT_INTERFACE_NAME,
25
+                                                   INFRA_INTERFACE_NAME,
26
+                                                   OAM_INTERFACE_NAME };
27
+
28
+/* httpUtil needs a mtclog socket pointer */
29
+msgSock_type * get_mtclogd_sockPtr ( void )
30
+{
31
+    return (&lmon_ctrl.mtclogd);
32
+}
33
+
34
+/* dump state before exiting */
35
+void daemon_exit ( void )
36
+{
37
+    daemon_files_fini ();
38
+    daemon_dump_info  ();
39
+    exit (0);
40
+}
41
+
42
+/* daemon timer handler */
43
+void lmonTimer_handler ( int sig, siginfo_t *si, void *uc)
44
+{
45
+    UNUSED(sig); UNUSED(uc);
46
+    timer_t * tid_ptr = (void**)si->si_value.sival_ptr ;
47
+    if ( !(*tid_ptr) )
48
+        return ;
49
+    else if (( *tid_ptr == lmon_ctrl.audit_timer.tid ) )
50
+        lmon_ctrl.audit_timer.ring = true ;
51
+    else
52
+        mtcTimer_stop_tid_int_safe ( tid_ptr );
53
+}
54
+
55
+/*****************************************************************************
56
+ *
57
+ * Name       : lmonHdlr_http_handler
58
+ *
59
+ * Description: Handle HTTP Link Status Query requests.
60
+ *
61
+ * Method     : GET
62
+ *
63
+ ******************************************************************************/
64
+
65
+#define DOS_LOG_THROTTLE_THLD (10000)
66
+void lmonHdlr_http_handler (struct evhttp_request *req, void *arg)
67
+{
68
+    int http_status_code = HTTP_NOTFOUND ;
69
+
70
+    UNUSED(arg);
71
+
72
+    if ( ! req )
73
+        return;
74
+
75
+    /* Get sender must be localhost */
76
+    const char * host_ptr = evhttp_request_get_host (req);
77
+    if (( host_ptr == NULL ) ||
78
+        (( strncmp ( host_ptr , "localhost" , 10 ) != 0 ) &&
79
+         ( strncmp ( host_ptr , LOOPBACK_IP , 10 ) != 0 )))
80
+    {
81
+        wlog_throttled ( lmon_ctrl.dos_log_throttle,
82
+                         DOS_LOG_THROTTLE_THLD,
83
+                         "Message received from unknown host (%s)\n",
84
+                         host_ptr?host_ptr:"(null)" );
85
+        return ;
86
+    }
87
+
88
+    const char * uri_ptr = evhttp_request_get_uri (req);
89
+    if ( uri_ptr == NULL )
90
+    {
91
+        wlog_throttled ( lmon_ctrl.dos_log_throttle,
92
+                         DOS_LOG_THROTTLE_THLD,
93
+                         "null uri");
94
+        return ;
95
+    }
96
+
97
+    string uri_path = daemon_get_cfg_ptr()->uri_path ;
98
+    if (strncmp(uri_ptr, uri_path.data(), uri_path.length()))
99
+    {
100
+        wlog_throttled ( lmon_ctrl.dos_log_throttle,
101
+                         DOS_LOG_THROTTLE_THLD,
102
+                         "http request not for this service: %s",
103
+                         uri_ptr);
104
+        return ;
105
+    }
106
+
107
+    /* Extract the operation */
108
+    evhttp_cmd_type http_cmd = evhttp_request_get_command (req);
109
+    jlog ("'%s' %s\n", uri_ptr, getHttpCmdType_str(http_cmd));
110
+    switch ( http_cmd )
111
+    {
112
+        case EVHTTP_REQ_GET:
113
+        {
114
+            http_status_code = HTTP_OK ;
115
+            break ;
116
+        }
117
+        default:
118
+        {
119
+            ilog_throttled ( lmon_ctrl.dos_log_throttle,
120
+                             DOS_LOG_THROTTLE_THLD,
121
+                             "unsupported %s request (%d)",
122
+                             getHttpCmdType_str(http_cmd),
123
+                             http_cmd);
124
+
125
+            http_status_code = MTC_HTTP_METHOD_NOT_ALLOWED ;
126
+        }
127
+    }
128
+
129
+    /*
130
+     * Link status query response format - success path
131
+     *
132
+     * Lagged case has an array of 2 links
133
+     *
134
+
135
+{ "status" : "pass",
136
+   "link_info": [
137
+      { "network":"mgmt",
138
+        "type":"vlan",
139
+        "links": [
140
+              { "name":"enp0s8.1", "state":"Up/Down", "time":5674323454567 },
141
+              { "name":"enp0s8.2", "state":"Up/Down", "time":5674323454567 }]
142
+      },
143
+      { "network":"infra",
144
+        "type":"bond",
145
+        "bond":"bond0",
146
+        "links": [
147
+              { "name":"enp0s9f1", "state":"Up/Down", "time":5674323454567 },
148
+              { "name":"enp0s9f0", "state":"Up/Down", "time":5674323454567 }]
149
+      },
150
+      { "network":"oam",
151
+        "type":"ethernet",
152
+        "links": [
153
+              { "name":"enp0s3", "state":"Up/Down", "time":5674323454567 }]
154
+      }]
155
+}
156
+     *
157
+     *lmonHdlr.cpp
158
+     *
159
+     */
160
+
161
+// #define WANT_TYPE_STR
162
+// #define WANT_BOND_STR
163
+
164
+    if (( http_status_code == HTTP_OK ) || ( http_status_code == MTC_HTTP_ACCEPTED ))
165
+    {
166
+        /* build response string */
167
+        string response = "{ \"status\":\"pass\",\"link_info\":[" ;
168
+
169
+        /* loop over the interfaces and build a response string for each
170
+         * of those that are used */
171
+        for ( int i = 0 ; i < INTERFACES_MAX ; i++ )
172
+        {
173
+            if ((interfaces[i].used == true) && (interfaces[i].name[0] != '\0'))
174
+            {
175
+                if ( i > 0 )
176
+                    response.append (",");
177
+
178
+                response.append ("{\"network\":\"");
179
+                response.append (interfaces[i].name);
180
+                response.append ("\"");
181
+
182
+#ifdef WANT_TYPE_STR
183
+                string type_str = "ethernet" ;
184
+                if ( interfaces[i].type_enum == bond )
185
+                    type_str = "bond" ;
186
+                else if ( interfaces[i].type_enum == vlan )
187
+                    type_str = "vlan" ;
188
+                response.append (",\"type\":\"" + type_str + "\"");
189
+#endif
190
+
191
+#ifdef WANT_BOND_STR
192
+                if ( interfaces[i].type_enum == bond )
193
+                {
194
+                    response.append (",\"bond\":\"");
195
+                    response.append (interfaces[i].bond);
196
+                    response.append ("\"");
197
+                }
198
+#endif
199
+
200
+                response.append (",\"links\":[");
201
+                {
202
+                    response.append ("{\"name\":\"");
203
+                    response.append (interfaces[i].interface_one);
204
+                    response.append ("\",\"state\":\"");
205
+                    response.append (interfaces[i].interface_one_link_up?"Up":"Down");
206
+                    response.append ("\",\"time\":\"" + lltos(interfaces[i].interface_one_event_time) + "\"}");
207
+                }
208
+                if (( interfaces[i].lagged ) &&
209
+                    ( interfaces[i].interface_two[0] != '\0'))
210
+                {
211
+                    response.append (",{\"name\":\"");
212
+                    response.append (interfaces[i].interface_two);
213
+                    response.append ("\",\"state\":\"");
214
+                    response.append (interfaces[i].interface_two_link_up?"Up":"Down");
215
+                    response.append ("\",\"time\":\"" + lltos(interfaces[i].interface_two_event_time) + "\"}");
216
+                }
217
+                response.append ("]}");
218
+            }
219
+        }
220
+        response.append ("]}");
221
+
222
+        struct evbuffer * resp_buf = evbuffer_new();
223
+        jlog ("Resp: %s\n", response.c_str());
224
+        evbuffer_add_printf (resp_buf, "%s\n", response.data());
225
+        evhttp_send_reply (req, http_status_code, "OK", resp_buf );
226
+        evbuffer_free ( resp_buf );
227
+    }
228
+    else if ( http_status_code == MTC_HTTP_METHOD_NOT_ALLOWED )
229
+    {
230
+        /* build response string */
231
+        string response = "{" ;
232
+        response.append (" \"status\" : \"fail ; method not allowed\"");
233
+        response.append ("}");
234
+
235
+        struct evbuffer * resp_buf = evbuffer_new();
236
+        jlog ("Event Response: %s\n", response.c_str());
237
+        evbuffer_add_printf (resp_buf, "%s\n", response.data());
238
+
239
+        /* Add the 'Allow' header */
240
+        int rc = evhttp_add_header( req->output_headers, "Allow", "GET" );
241
+        if ( rc ) { ilog ("failed to add 'Allow' header (%d %d:%m", rc, errno);}
242
+        evhttp_send_reply (req, http_status_code, "NOT ALLOWED", resp_buf );
243
+        evbuffer_free ( resp_buf );
244
+    }
245
+    else
246
+    {
247
+        /* build response string */
248
+        string response = "{" ;
249
+        response.append (" \"status\" : \"fail ; bad request\"");
250
+        response.append ("}");
251
+        elog ("HTTP Event error:%d ; cmd:%s uri:%s response:%s\n",
252
+               http_status_code,
253
+               getHttpCmdType_str(http_cmd),
254
+               uri_ptr,
255
+               response.c_str());
256
+        evhttp_send_error (req, http_status_code, response.data() );
257
+    }
258
+}
259
+
260
+/*****************************************************************************
261
+ *
262
+ * Name    : lmon_socket_init
263
+ *
264
+ * Purpose : Initialize all the sockets for this process.
265
+ *
266
+ *           Sockets include ...
267
+ *
268
+ *           1. local kernel ioctl socket ; link attribute query
269
+ *
270
+ *****************************************************************************/
271
+
272
+int lmon_socket_init ( lmon_ctrl_type * ctrl_ptr )
273
+{
274
+    int rc = PASS ;
275
+    if ( ctrl_ptr )
276
+    {
277
+        httpUtil_event_init ( &lmon_ctrl.http_event,
278
+                               &lmon_ctrl.my_hostname[0],
279
+                               HTTP_SERVER_NAME,
280
+                               lmon_ctrl.my_address,
281
+                               daemon_get_cfg_ptr()->lmon_query_port );
282
+
283
+        if (( ctrl_ptr->ioctl_socket = open_ioctl_socket()) <= 0 )
284
+        {
285
+            /* errno/strerror logged by open utility if failure is detected */
286
+            elog ("failed to create ioctl socket\n");
287
+            rc = FAIL_SOCKET_CREATE ;
288
+        }
289
+
290
+        /* Note that address changes should not generate netlink events.
291
+         * Therefore these options are not set
292
+         *     RTMGRP_IPV4_IFADDR
293
+         *     RTMGRP_IPV6_IFADDR
294
+         */
295
+        else if (( ctrl_ptr->netlink_socket = open_netlink_socket ( RTMGRP_LINK )) <= 0 )
296
+        {
297
+            /* errno/strerr logged by open utility if failure is detected */
298
+            elog ("failed to create netlink listener socket\n");
299
+            rc = FAIL_SOCKET_CREATE ;
300
+        }
301
+        else if ( httpUtil_setup ( ctrl_ptr->http_event,
302
+                                    HTTP_SUPPORTED_METHODS,
303
+                                   &lmonHdlr_http_handler ) != PASS )
304
+        {
305
+            /* errno/strerr logged by open utility if failure is detected */
306
+            elog ("failed to setup http server\n");
307
+            rc = FAIL_SOCKET_CREATE ;
308
+        }
309
+        else
310
+        {
311
+            ctrl_ptr->mtclogd.port = daemon_get_cfg_ptr()->daemon_log_port ;
312
+            CREATE_REUSABLE_INET_UDP_TX_SOCKET ( LOOPBACK_IP,
313
+                                             ctrl_ptr->mtclogd.port,
314
+                                             ctrl_ptr->mtclogd.sock,
315
+                                             ctrl_ptr->mtclogd.addr,
316
+                                             ctrl_ptr->mtclogd.port,
317
+                                             ctrl_ptr->mtclogd.len,
318
+                                             "mtc logger message",
319
+                                             rc );
320
+            if ( rc )
321
+            {
322
+                elog ("failed to setup mtce logger port %d\n", ctrl_ptr->mtclogd.port );
323
+                rc = PASS ;
324
+            }
325
+        }
326
+    }
327
+    else
328
+    {
329
+        rc = FAIL_NULL_POINTER ;
330
+    }
331
+    return (rc);
332
+}
333
+
334
+/*****************************************************************************
335
+ *
336
+ * Name    : lmon_learn_interfaces
337
+ *
338
+ * Purpose : realize the interfaces to monitor in terms of
339
+ *
340
+ *           - interface type ; ethernet, bonded or vlan
341
+ *           - initial up/down state
342
+ *
343
+ *****************************************************************************/
344
+
345
+void lmon_learn_interfaces ( int ioctl_socket )
346
+{
347
+    /* initialize interface monitoring */
348
+    for ( int iface = 0 ; iface < INTERFACES_MAX ; iface++ )
349
+    {
350
+        interfaces[iface].name = iface_list[iface];
351
+        lmon_interfaces_init ( &interfaces[iface] );
352
+
353
+        if ( interfaces[iface].used == false )
354
+            continue ;
355
+
356
+        /* set the link state for all the primary physical interfaces */
357
+        if ( lmon_get_link_state ( ioctl_socket,
358
+                                   interfaces[iface].interface_one,
359
+                                   interfaces[iface].interface_one_link_up ) )
360
+        {
361
+            interfaces[iface].interface_one_event_time = lmon_fm_timestamp();
362
+            interfaces[iface].interface_one_link_up = false ;
363
+            wlog ("%s interface state query failed ; defaulting to Down\n",
364
+                      interfaces[iface].interface_one) ;
365
+        }
366
+        else
367
+        {
368
+            interfaces[iface].interface_one_event_time = lmon_fm_timestamp();
369
+            ilog ("%s is %s\n",
370
+                      interfaces[iface].interface_one,
371
+                      interfaces[iface].interface_one_link_up ?
372
+                      "Up" : "Down" );
373
+
374
+            if ( interfaces[iface].lagged == true )
375
+            {
376
+                /* set the link state for all the lagged physical interfaces */
377
+                if ( lmon_get_link_state ( ioctl_socket,
378
+                                           interfaces[iface].interface_two,
379
+                                           interfaces[iface].interface_two_link_up ) )
380
+                {
381
+                    interfaces[iface].interface_two_event_time = lmon_fm_timestamp();
382
+                    interfaces[iface].interface_two_link_up = false ;
383
+                    wlog ("%s lag interface state query failed ; defaulting to Down\n",
384
+                              interfaces[iface].interface_two) ;
385
+                }
386
+                else
387
+                {
388
+                    interfaces[iface].interface_two_event_time = lmon_fm_timestamp();
389
+                    ilog ("%s is %s (lag)\n",
390
+                              interfaces[iface].interface_two,
391
+                              interfaces[iface].interface_two_link_up ?
392
+                              "Up" : "Down" );
393
+                }
394
+            }
395
+        }
396
+    }
397
+}
398
+
399
+/*****************************************************************************
400
+ *
401
+ * Name       : service_interface_events
402
+ *
403
+ * Purpose    : Service state changes for monitored link
404
+ *
405
+ * Description: netlink event driven state change handler.
406
+ *
407
+ *****************************************************************************/
408
+int service_interface_events ( void )
409
+{
410
+    list<string> links_gone_down ;
411
+    list<string> links_gone_up   ;
412
+    list<string>::iterator iter_ptr ;
413
+
414
+    links_gone_down.clear();
415
+    links_gone_up.clear();
416
+
417
+    int events = get_netlink_events ( lmon_ctrl.netlink_socket,
418
+                                  links_gone_down,
419
+                                  links_gone_up );
420
+    if ( events <= 0 )
421
+    {
422
+        dlog1 ("called but get_netlink_events reported no events");
423
+        return RETRY ;
424
+    }
425
+
426
+    for ( int i = 0 ; i < INTERFACES_MAX ; i++ )
427
+    {
428
+        if ( interfaces[i].used == true )
429
+        {
430
+            bool running = false ;
431
+
432
+            /* handle links that went down */
433
+            if ( ! links_gone_down.empty() )
434
+            {
435
+                bool found = false ;
436
+                dlog ("netlink Down events: %ld", links_gone_down.size());
437
+                /* Look at the down list */
438
+                for ( iter_ptr  = links_gone_down.begin();
439
+                      iter_ptr != links_gone_down.end() ;
440
+                      iter_ptr++ )
441
+                {
442
+                    if ( strcmp ( interfaces[i].interface_one, iter_ptr->c_str()) == 0 )
443
+                    {
444
+                        found = true ;
445
+                        interfaces[i].interface_one_event_time = lmon_fm_timestamp();
446
+
447
+                        dlog ("%s is Down ; netlink event\n",
448
+                                  interfaces[i].interface_one );
449
+
450
+                        if ( get_link_state ( lmon_ctrl.ioctl_socket,
451
+                                              iter_ptr->c_str(),
452
+                                              &running ) == PASS )
453
+                        {
454
+                            if ( interfaces[i].interface_one_link_up == true )
455
+                            {
456
+                                wlog ("%s is Down ; (%s)\n",
457
+                                        iter_ptr->c_str(),
458
+                                        running ? "Up" : "Down" );
459
+                            }
460
+                            else
461
+                            {
462
+                                dlog ("%s is Down ; (%s)\n",
463
+                                        iter_ptr->c_str(),
464
+                                        running ? "Up" : "Down" );
465
+                            }
466
+                            interfaces[i].interface_one_link_up = running ? true:false;
467
+                        }
468
+                        else
469
+                        {
470
+                            wlog ("%s is Down ; oper query failed\n",
471
+                                      iter_ptr->c_str());
472
+                            interfaces[i].interface_one_link_up = false ;
473
+                        }
474
+                    }
475
+
476
+                    else if (interfaces[i].lagged == true)
477
+                    {
478
+                        if ( strcmp ( interfaces[i].interface_two, iter_ptr->c_str()) == 0 )
479
+                        {
480
+                            found = true ;
481
+                            interfaces[i].interface_two_event_time = lmon_fm_timestamp();
482
+
483
+                            dlog ("%s is Down\n", interfaces[i].interface_two);
484
+
485
+                            if ( get_link_state ( lmon_ctrl.ioctl_socket,
486
+                                                  iter_ptr->c_str(),
487
+                                                  &running ) == PASS )
488
+                            {
489
+                                if ( interfaces[i].interface_two_link_up == true )
490
+                                {
491
+                                    wlog ("%s is Down (%s)\n",
492
+                                            iter_ptr->c_str(),
493
+                                            running ? "Up" : "Down" );
494
+                                }
495
+                                else
496
+                                {
497
+                                    dlog ("%s is Down (%s)\n",
498
+                                            iter_ptr->c_str(),
499
+                                            running ? "Up" : "Down" );
500
+                                }
501
+                                interfaces[i].interface_two_link_up = running ? true:false;
502
+                            }
503
+                            else
504
+                            {
505
+                                wlog ("%s is Down ; oper query failed\n",
506
+                                          iter_ptr->c_str() );
507
+                                interfaces[i].interface_two_link_up = false ;
508
+                            }
509
+                        }
510
+                        if ( strcmp ( interfaces[i].bond, iter_ptr->c_str()) == 0 )
511
+                        {
512
+                            found = true ;
513
+                            wlog ("%s is Down (bond)\n", interfaces[i].bond);
514
+                        }
515
+                    }
516
+                }
517
+                if ( ! found )
518
+                {
519
+                    dlog ("netlink Down event on unmonitored link:%s", iter_ptr->c_str());
520
+                }
521
+            }
522
+            /* handle links that came up */
523
+            if ( !links_gone_up.empty() )
524
+            {
525
+                bool found = false ;
526
+                dlog ("netlink Up events: %ld", links_gone_up.size());
527
+                /* Look at the down list */
528
+                for ( iter_ptr  = links_gone_up.begin();
529
+                      iter_ptr != links_gone_up.end() ;
530
+                      iter_ptr++ )
531
+                {
532
+                    if ( strcmp ( interfaces[i].interface_one, iter_ptr->c_str()) == 0 )
533
+                    {
534
+                        found = true ;
535
+                        interfaces[i].interface_one_event_time = lmon_fm_timestamp();
536
+
537
+                        dlog ("%s is Up\n", interfaces[i].interface_one );
538
+
539
+                        if ( get_link_state ( lmon_ctrl.ioctl_socket,
540
+                                              iter_ptr->c_str(),
541
+                                              &running ) == PASS )
542
+                        {
543
+                            if ( interfaces[i].interface_one_link_up == false )
544
+                            {
545
+                                ilog ("%s is Up   (%s)\n",
546
+                                          iter_ptr->c_str(),
547
+                                          running ? "Up" : "Down" );
548
+                            }
549
+                            else
550
+                            {
551
+                                dlog ("%s is Up   (%s)\n",
552
+                                          iter_ptr->c_str(),
553
+                                          running ? "Up" : "Down" );
554
+                            }
555
+                            interfaces[i].interface_one_link_up = running ? true:false;
556
+                        }
557
+                        else
558
+                        {
559
+                            wlog ("%s is Down ; oper query failed\n", iter_ptr->c_str() );
560
+                            interfaces[i].interface_one_link_up = false ;
561
+                        }
562
+                    }
563
+                    else if (interfaces[i].lagged == true)
564
+                    {
565
+                        if ( strcmp ( interfaces[i].interface_two, iter_ptr->c_str()) == 0 )
566
+                        {
567
+                            found = true ;
568
+                            interfaces[i].interface_two_event_time = lmon_fm_timestamp();
569
+                            dlog ("%s is Up\n", interfaces[i].interface_two );
570
+
571
+                            if ( get_link_state ( lmon_ctrl.ioctl_socket,
572
+                                                  iter_ptr->c_str(),
573
+                                                  &running ) == PASS )
574
+                            {
575
+                                if ( interfaces[i].interface_two_link_up == false )
576
+                                {
577
+                                    ilog ("%s is Up   (%s)\n",
578
+                                              iter_ptr->c_str(),
579
+                                              running ? "Up" : "Down" );
580
+                                }
581
+                                else
582
+                                {
583
+                                    dlog ("%s is Up   (%s)\n",
584
+                                              iter_ptr->c_str(),
585
+                                              running ? "Up" : "Down" );
586
+                                }
587
+                                interfaces[i].interface_two_link_up = running ? true:false;
588
+                            }
589
+                            else
590
+                            {
591
+                                wlog ("%s is Down ; oper query failed\n", iter_ptr->c_str() );
592
+                                interfaces[i].interface_two_link_up = false ;
593
+                            }
594
+                        }
595
+                        if ( strcmp ( interfaces[i].bond, iter_ptr->c_str()) == 0 )
596
+                        {
597
+                            found = true ;
598
+                            wlog ("%s is Up   (bond)\n", interfaces[i].bond);
599
+                        }
600
+                    }
601
+                }
602
+                if ( ! found )
603
+                {
604
+                    dlog ("netlink Up event on unmonitored link:%s", iter_ptr->c_str());
605
+                }
606
+            }
607
+        }
608
+    }
609
+    return (PASS);
610
+}
611
+
612
+
613
+/**************************************************************************
614
+ *
615
+ * Name     : lmon_query_all_links
616
+ *
617
+ * Purpose  : self correct for netlink event misses by running this
618
+ *            as a periodic audit at a 1 minute cadence.
619
+ *
620
+ **************************************************************************/
621
+void lmon_query_all_links( void )
622
+{
623
+    dlog1 ("audit timer fired");
624
+
625
+    for ( int i = 0 ; i < INTERFACES_MAX ; i++ )
626
+    {
627
+        if ( interfaces[i].used )
628
+        {
629
+            bool link_up = false ;
630
+            string log_msg = "link state mismatch detected by audit";
631
+            if ( lmon_get_link_state ( lmon_ctrl.ioctl_socket,
632
+                                       interfaces[i].interface_one,
633
+                                       link_up) == PASS )
634
+            {
635
+                if ( link_up != interfaces[i].interface_one_link_up )
636
+                {
637
+                    wlog ("%s %s ; is:%s was:%s ; corrected",
638
+                              interfaces[i].interface_one,
639
+                              log_msg.c_str(),
640
+                              link_up?"Up":"Down",
641
+                              interfaces[i].interface_one_link_up?"Up":"Down" );
642
+
643
+                    interfaces[i].interface_one_event_time = lmon_fm_timestamp();
644
+                    interfaces[i].interface_one_link_up = link_up ;
645
+                }
646
+            }
647
+            if ( interfaces[i].lagged )
648
+            {
649
+                if ( lmon_get_link_state ( lmon_ctrl.ioctl_socket,
650
+                                           interfaces[i].interface_two,
651
+                                           link_up) == PASS )
652
+                {
653
+                    if ( link_up != interfaces[i].interface_two_link_up )
654
+                    {
655
+                        wlog ("%s %s ; is:%s was:%s ; corrected",
656
+                                  interfaces[i].interface_two,
657
+                                  log_msg.c_str(),
658
+                                  link_up?"Up":"Down",
659
+                                  interfaces[i].interface_two_link_up?"Up":"Down" );
660
+
661
+                        interfaces[i].interface_two_event_time = lmon_fm_timestamp();
662
+                        interfaces[i].interface_two_link_up = link_up ;
663
+                    }
664
+                }
665
+            }
666
+        }
667
+    }
668
+}
669
+
670
+/*****************************************************************************
671
+ *
672
+ * Name    : daemon_service_run
673
+ *
674
+ * Purpose : track interface profile link status.
675
+ *
676
+ * Assumptions: Event driven with self-correcting audit.
677
+ *
678
+ * General Behavior:
679
+ *
680
+ *   Init:
681
+ *
682
+ *   1. learn interface/port model
683
+ *   2. setup http server
684
+ *
685
+ *   Select:
686
+ *
687
+ *   3. load initial link status for learned links
688
+ *   4. listen for link status change events
689
+ *   5. provide link status info to http GET Query requests.
690
+ *
691
+ *   Audit:
692
+ *
693
+ *   6. run 1 minute periodic self correcting audit.
694
+ *
695
+ */
696
+
697
+void daemon_service_run ( void )
698
+{
699
+    fd_set readfds;
700
+    struct timeval waitd;
701
+    std::list<int> socks;
702
+
703
+    lmon_ctrl.ioctl_socket = 0 ;
704
+    lmon_ctrl.netlink_socket = 0 ;
705
+    memset (&lmon_ctrl.mtclogd, 0, sizeof(lmon_ctrl.mtclogd));
706
+    memset (&interfaces, 0, sizeof(interface_ctrl_type));
707
+
708
+    get_hostname (&lmon_ctrl.my_hostname[0], MAX_HOST_NAME_SIZE );
709
+    mtcTimer_init ( lmon_ctrl.audit_timer, lmon_ctrl.my_hostname, "audit");
710
+
711
+    string my_address = lmon_ctrl.my_address ;
712
+    get_iface_address ( daemon_mgmnt_iface().data(), my_address, true );
713
+
714
+    /* Setup the messaging sockets */
715
+    if (( lmon_socket_init ( &lmon_ctrl )) != PASS )
716
+    {
717
+        elog ("socket initialization failed ; exiting ...\n");
718
+        daemon_exit ();
719
+    }
720
+    else if ( 0 >= lmon_ctrl.netlink_socket )
721
+    {
722
+        elog ("failed to get ioctl socket descriptor (%d) ; exiting ...\n",
723
+               lmon_ctrl.netlink_socket );
724
+        daemon_exit ();
725
+    }
726
+
727
+    lmon_learn_interfaces ( lmon_ctrl.ioctl_socket );
728
+
729
+    int audit_secs = daemon_get_cfg_ptr()->audit_period ;
730
+    ilog ("started %d second link state self correcting audit", audit_secs );
731
+    mtcTimer_start ( lmon_ctrl.audit_timer, lmonTimer_handler, audit_secs );
732
+
733
+    socks.clear();
734
+    socks.push_front (lmon_ctrl.netlink_socket);
735
+    socks.sort();
736
+
737
+    ilog ("waiting on netlink events ...");
738
+
739
+    for (;;)
740
+    {
741
+        /* Accomodate for hup reconfig */
742
+        FD_ZERO(&readfds);
743
+        FD_SET(lmon_ctrl.netlink_socket, &readfds);
744
+        waitd.tv_sec  = 0;
745
+        waitd.tv_usec = SOCKET_WAIT ;
746
+
747
+        /* This is used as a delay up to select timeout ; SOCKET_WAIT */
748
+        select( socks.back()+1, &readfds, NULL, NULL, &waitd);
749
+        if (FD_ISSET(lmon_ctrl.netlink_socket, &readfds))
750
+        {
751
+            dlog ("netlink socket fired\n");
752
+            service_interface_events ();
753
+        }
754
+
755
+        if ( lmon_ctrl.audit_timer.ring == true )
756
+        {
757
+            lmon_ctrl.audit_timer.ring = false ;
758
+            lmon_query_all_links();
759
+        }
760
+
761
+        httpUtil_look ( lmon_ctrl.http_event );
762
+        daemon_signal_hdlr();
763
+    }
764
+    daemon_exit();
765
+}
766
+
767
+
768
+
769
+

+ 145
- 0
mtce/src/lmon/lmonInit.cpp View File

@@ -0,0 +1,145 @@
1
+/*
2
+ * Copyright (c) 2019 Wind River Systems, Inc.
3
+*
4
+* SPDX-License-Identifier: Apache-2.0
5
+*
6
+ */
7
+
8
+ /**
9
+  * @file
10
+  * Starling-X Maintenance Link Monitor Initialization
11
+  */
12
+
13
+#include "lmon.h"
14
+
15
+/** Daemon Configuration Structure - Allocation and get pointer
16
+ * @see daemon_common.h for daemon_config_type struct format. */
17
+static daemon_config_type lmon_config ;
18
+daemon_config_type * daemon_get_cfg_ptr () { return &lmon_config ; }
19
+
20
+/* read config label values */
21
+static int lmon_config_handler ( void * user,
22
+                           const char * section,
23
+                           const char * name,
24
+                           const char * value)
25
+{
26
+    daemon_config_type* config_ptr = (daemon_config_type*)user;
27
+
28
+    if (MATCH("client", "audit_period"))
29
+    {
30
+        config_ptr->audit_period = atoi(value);
31
+        ilog ("Audit Period: %d (secs)", config_ptr->audit_period );
32
+    }
33
+    else if (MATCH("client", "lmon_query_port"))
34
+    {
35
+        config_ptr->lmon_query_port = atoi(value);
36
+        ilog ("Status Query: %d (port)", config_ptr->lmon_query_port );
37
+    }
38
+    else if (MATCH("client", "daemon_log_port"))
39
+    {
40
+        config_ptr->daemon_log_port = atoi(value);
41
+        ilog ("Daemon Log  : %d (port)", config_ptr->daemon_log_port );
42
+    }
43
+    else if (MATCH("client", "uri_path"))
44
+    {
45
+        config_ptr->uri_path = strdup(value);
46
+    }
47
+
48
+    return (PASS);
49
+}
50
+
51
+/*****************************************************************************
52
+ *
53
+ * Name    : daemon_configure
54
+ *
55
+ * Purpose : Read process config file settings into the daemon configuration
56
+ *
57
+ * Configuration File */
58
+
59
+#define CONFIG_FILE   ((const char *)"/etc/mtc/lmond.conf")
60
+
61
+/*****************************************************************************/
62
+
63
+int daemon_configure ( void )
64
+{
65
+    int rc = PASS ;
66
+
67
+    /* read config out of /etc/mtc/lmond.conf */
68
+    if (ini_parse( CONFIG_FILE, lmon_config_handler, &lmon_config) < 0)
69
+    {
70
+        elog("Can't load '%s'\n", CONFIG_FILE );
71
+        rc = FAIL_INI_CONFIG ;
72
+    }
73
+    else
74
+    {
75
+        get_debug_options ( CONFIG_FILE, &lmon_config );
76
+    }
77
+    return (rc);
78
+}
79
+
80
+/*****************************************************************************
81
+ *
82
+ * Name    : daemon_init
83
+ *
84
+ * Purpose : Daemon Initialization
85
+ *
86
+ *****************************************************************************/
87
+
88
+int daemon_init ( string iface, string nodetype_str )
89
+{
90
+    int rc = PASS ;
91
+
92
+    UNUSED(iface);
93
+    UNUSED(nodetype_str);
94
+
95
+    if ( daemon_files_init ( ) != PASS )
96
+    {
97
+        elog ("Pid, log or other files could not be opened\n");
98
+        return ( FAIL_FILES_INIT ) ;
99
+    }
100
+
101
+    /* Bind signal handlers */
102
+    if ( daemon_signal_init () != PASS )
103
+    {
104
+        elog ("daemon_signal_init failed\n");
105
+        return ( FAIL_SIGNAL_INIT );
106
+    }
107
+
108
+    daemon_wait_for_file ( CONFIG_COMPLETE_FILE, 0);
109
+    daemon_wait_for_file ( PLATFORM_DIR, 0);
110
+    daemon_wait_for_file ( GOENABLED_MAIN_READY, 0);
111
+
112
+    /* Configure the daemon */
113
+    if ( (rc = daemon_configure ( )) != PASS )
114
+    {
115
+        elog ("Daemon service configuration failed (rc:%i)\n", rc );
116
+        rc = FAIL_DAEMON_CONFIG ;
117
+    }
118
+
119
+    return (rc);
120
+}
121
+
122
+
123
+void daemon_dump_info ( void )
124
+{
125
+
126
+
127
+}
128
+
129
+void daemon_sigchld_hdlr ( void )
130
+{
131
+    ; /* dlog("Received SIGCHLD ... no action\n"); */
132
+}
133
+
134
+const char MY_DATA [100] = { "eieio\n" } ;
135
+const char * daemon_stream_info ( void )
136
+{
137
+    return (&MY_DATA[0]);
138
+}
139
+
140
+/** Teat Head Entry */
141
+int daemon_run_testhead ( void )
142
+{
143
+    // ilog ("Empty test head.\n");
144
+    return (PASS);
145
+}

+ 415
- 0
mtce/src/lmon/lmonUtil.cpp View File

@@ -0,0 +1,415 @@
1
+/*
2
+ * Copyright (c) 2019 Wind River Systems, Inc.
3
+*
4
+* SPDX-License-Identifier: Apache-2.0
5
+*
6
+ */
7
+
8
+ /**
9
+  * @file
10
+  * Starling-X Maintenance Link Monitor Utility
11
+  */
12
+
13
+#include "lmon.h"
14
+#include <fstream>           /* for ... ifstream                            */
15
+#include <sstream>           /* for ... stringstream                        */
16
+#include <net/if.h>          /* for ... if_indextoname , IF_NAMESIZE        */
17
+#include <sys/ioctl.h>       /* for ... SIOCGIFFLAGS                        */
18
+#include "nlEvent.h"         /* for ... get_netlink_events                  */
19
+
20
+#ifdef  __AREA__
21
+#undef  __AREA__
22
+#endif
23
+#define __AREA__ "mon"
24
+
25
+/*****************************************************************************
26
+ *
27
+ * Name    : iface_type
28
+ *
29
+ * Purpose : convert interface type enum to representative string.
30
+ *
31
+ * Returns : 0:ethernet returns "ethernet"
32
+ *           1:vlan     returns "vlan"
33
+ *           2:bond     returns "bond"
34
+ *           ?          returns "unknown"   ... error case
35
+ *
36
+ ****************************************************************************/
37
+
38
+string iface_type ( interface_type type_enum )
39
+{
40
+    switch(type_enum)
41
+    {
42
+        case ethernet: return "ethernet";
43
+        case vlan:     return "vlan"    ;
44
+        case bond:     return "bond"    ;
45
+        default:       return "unknown" ;
46
+    }
47
+}
48
+
49
+/*****************************************************************************
50
+ *
51
+ * Name    : get_iflink_interface
52
+ *
53
+ * Purpose : Gets the ifname of the linked parent interface
54
+ *
55
+ * Returns : Returns a string containing the ifname.
56
+ *
57
+ ****************************************************************************/
58
+
59
+string get_iflink_interface (string & ifname )
60
+{
61
+    string ret = "";
62
+
63
+    /* build the full file path */
64
+    string iflink_file = INTERFACES_DIR + ifname + "/iflink";
65
+
66
+    /* declare a file stream based on the full file path */
67
+    ifstream iflink_file_stream ( iflink_file.c_str() );
68
+
69
+    /* open the file stream */
70
+    if (iflink_file_stream.is_open())
71
+    {
72
+        int iflink = -1;
73
+        string iflink_line;
74
+        char * dummy_ptr  ;
75
+        char iface_buffer [IF_NAMESIZE] = "";
76
+        memset (&iface_buffer[0], 0, IF_NAMESIZE);
77
+        while ( getline (iflink_file_stream, iflink_line) )
78
+        {
79
+            iflink = strtol(iflink_line.c_str(), &dummy_ptr, 10);
80
+        }
81
+        iflink_file_stream.close();
82
+
83
+        /*
84
+         * load iface_buffer with the name of the network interface
85
+         * corresponding to iflink.
86
+         */
87
+        if_indextoname (iflink, iface_buffer);
88
+
89
+        if (iface_buffer[0] != '\0')
90
+        {
91
+            ret = iface_buffer;
92
+        }
93
+        else
94
+        {
95
+            slog ("no ifname from linked parent interface\n");
96
+        }
97
+    }
98
+    return ret;
99
+}
100
+
101
+/*****************************************************************************
102
+ *
103
+ * Name       : lmon_fm_timestamp
104
+ *
105
+ * Purpose    : Get a microsecond timestamp of the current time.
106
+ *
107
+ * Description: Used to record the time of link state changes.
108
+ *
109
+ *              The value is included in link state query responses.
110
+ *
111
+ * Uses       : FMTimeT from fmAPI.h
112
+ *
113
+ ****************************************************************************/
114
+
115
+FMTimeT lmon_fm_timestamp ( void )
116
+{
117
+    struct timespec ts;
118
+    clock_gettime(CLOCK_REALTIME, &ts);
119
+    return ( ts.tv_sec*1000000 + ts.tv_nsec/1000 );
120
+}
121
+
122
+/*****************************************************************************
123
+ *
124
+ * Name    : lmon_get_link_state
125
+ *
126
+ * Purpose : Query the link up/down state of the specified interface.
127
+ *
128
+ * Updates : Sets the callers boolean pointer to ...
129
+ *
130
+ *            true  if interface is up
131
+ *            false if interface is doewn
132
+ *
133
+ * Returns : PASS           on query success.
134
+ *           FAIL_OPERATION if the query was not successful.
135
+ *
136
+ ****************************************************************************/
137
+
138
+static int get_link_state_throttle = 0 ;
139
+#define GET_LINK_STATE__LOG_THROTTLE (100)
140
+
141
+int lmon_get_link_state ( int    ioctl_socket,
142
+                          char   iface[IF_NAMESIZE],
143
+                          bool & link_up )
144
+{
145
+    int rc = FAIL_OPERATION ;
146
+
147
+    link_up = false ; /* default to link down */
148
+
149
+    if (iface[0] == '\0')
150
+    {
151
+        slog ("supplied interface name is invalid ; null\n");
152
+        return ( rc ) ;
153
+    }
154
+
155
+    /* Declare and load interface data for ioctl query */
156
+    struct ifreq if_data;
157
+    memset( &if_data, 0, sizeof(if_data) );
158
+    snprintf( if_data.ifr_name, IF_NAMESIZE, "%s", iface );
159
+
160
+    /* read the interface up/down state */
161
+    if( 0 <= ioctl( ioctl_socket, SIOCGIFFLAGS, &if_data ) )
162
+    {
163
+        if( if_data.ifr_flags & IFF_RUNNING )
164
+            link_up = true;
165
+
166
+        /* reset log flood gate counter */
167
+        get_link_state_throttle = 0 ;
168
+
169
+        rc = PASS ;
170
+    }
171
+    else
172
+    {
173
+        wlog_throttled (get_link_state_throttle,
174
+                        GET_LINK_STATE__LOG_THROTTLE,
175
+                        "failed to get %s (%s) interface state (%d:%s)\n",
176
+                        iface,
177
+                        if_data.ifr_name,
178
+                        errno,
179
+                        strerror(errno));
180
+    }
181
+    return ( rc );
182
+}
183
+
184
+
185
+/*****************************************************************************
186
+ *
187
+ * Name    : lmon_interfaces_init
188
+ *
189
+ * Purpose : Map an interface (mgmt, oam or infra) to a physical port.
190
+ *           See interface_type enum in lmon.h
191
+ *
192
+ *****************************************************************************/
193
+
194
+int lmon_interfaces_init ( interface_ctrl_type * ptr )
195
+{
196
+    FILE * file_ptr;
197
+    char line_buf[MAX_CHARS_ON_LINE];
198
+    string str;
199
+    string physical_interface = "";
200
+
201
+    /* iface enum to pltform.conf iface name */
202
+    if ( strcmp(ptr->name, MGMT_INTERFACE_NAME) == 0 )
203
+        str = MGMT_INTERFACE_FULLNAME;
204
+    else if ( strcmp(ptr->name, INFRA_INTERFACE_NAME) == 0 )
205
+        str = INFRA_INTERFACE_FULLNAME;
206
+    else if ( strcmp(ptr->name, OAM_INTERFACE_NAME) == 0 )
207
+        str = OAM_INTERFACE_FULLNAME;
208
+    else
209
+    {
210
+        slog ("%s is an unsupported iface\n", ptr->name );
211
+        return (FAIL_BAD_PARM);
212
+    }
213
+
214
+    /* open platform.conf and find the line containing this interface name. */
215
+    file_ptr = fopen (PLATFORM_DIR , "r");
216
+    if (file_ptr)
217
+    {
218
+        ifstream fin( PLATFORM_DIR );
219
+        string line;
220
+
221
+        while ( getline( fin, line ))
222
+        {
223
+            /* does this line contain it ? */
224
+            if ( line.find(str) != string::npos )
225
+            {
226
+                stringstream ss( line );
227
+                getline( ss, physical_interface, '=' ); // string before
228
+                getline( ss, physical_interface, '=' ); // string after
229
+
230
+                plog ("%s is the %s primary network interface",
231
+                          physical_interface.c_str(),
232
+                          ptr->name);
233
+
234
+                /* determine the interface type */
235
+                string uevent_interface_file =
236
+                       INTERFACES_DIR + physical_interface + "/uevent";
237
+                ifstream finUevent( uevent_interface_file.data() );
238
+
239
+                if (!finUevent)
240
+                {
241
+                    elog ("Cannot find '%s' ; unable to monitor '%s' interface\n",
242
+                          uevent_interface_file.c_str(), ptr->name );
243
+
244
+                    ptr->used = false;
245
+                    fclose(file_ptr);
246
+                    return FAIL_OPERATION ;
247
+                }
248
+                else
249
+                {
250
+                    string line;
251
+                    ptr->type_enum = ethernet;
252
+                    while( getline( finUevent, line ) )
253
+                    {
254
+                        if ( line.find ("DEVTYPE") == 0 )
255
+                        {
256
+                            if ( line.find ("=vlan") != string::npos )
257
+                                ptr->type_enum = vlan;
258
+                            else if ( line.find ("=bond") != string::npos )
259
+                                ptr->type_enum = bond;
260
+                            break;
261
+                        }
262
+                    }
263
+                }
264
+
265
+                switch (ptr->type_enum)
266
+                {
267
+                    case ethernet:
268
+                    {
269
+                        memcpy(ptr->interface_one,
270
+                               physical_interface.c_str(),
271
+                               physical_interface.size());
272
+
273
+                        ilog("%s is a %s ethernet interface\n",
274
+                             ptr->interface_one, ptr->name );
275
+
276
+                        break;
277
+                    }
278
+                    case bond:
279
+                    {
280
+                        memcpy(ptr->bond,
281
+                               physical_interface.c_str(),
282
+                               physical_interface.size());
283
+
284
+                        ilog("%s is a bonded %s network interface\n",
285
+                             ptr->bond, ptr->name);
286
+
287
+                        break;
288
+                    }
289
+                    case vlan:
290
+                    {
291
+                        /****************************************************
292
+                         *
293
+                         * If it is a VLAN interface, we need to determine its
294
+                         * parent interface, which may be a single ethernet
295
+                         * link or a bonded interface.
296
+                         *
297
+                         ****************************************************/
298
+
299
+                        string parent = get_iflink_interface(physical_interface);
300
+                        if (!parent.empty())
301
+                        {
302
+                            string physical_interface_save = physical_interface ;
303
+                            physical_interface = parent;
304
+
305
+                            string uevent_parent_file =
306
+                                   INTERFACES_DIR + parent + "/uevent";
307
+
308
+                            ifstream finUevent2( uevent_parent_file.c_str() );
309
+
310
+                            string line;
311
+                            bool bond_configured = false;
312
+                            while( getline( finUevent2, line ) )
313
+                            {
314
+                                // if this uevent does not have a DEVTYPE
315
+                                // then its a ethernet interface. If this
316
+                                // does have a DEVTYPE then check explicity
317
+                                // for bond. Since we don't allow vlan over
318
+                                // vlan, for all other DEVTYPEs, assume
319
+                                // this is a ethernet interface.
320
+                                if ( (line.find ("DEVTYPE") == 0) &&
321
+                                     (line.find ("=bond") != string::npos) ) {
322
+
323
+                                     ilog("%s is a vlan off the %s network whose parent is %s\n",
324
+                                              physical_interface_save.c_str(),
325
+                                              ptr->name,
326
+                                              parent.c_str());
327
+                                    bond_configured = true;
328
+                                    break;
329
+                                }
330
+                            }
331
+
332
+                            if (!bond_configured)
333
+                            {
334
+                                ilog("%s is a vlan off the %s network whose parent is %s\n",
335
+                                     physical_interface.c_str(),
336
+                                     ptr->name,
337
+                                     parent.c_str());
338
+
339
+                                memcpy(ptr->interface_one,
340
+                                       parent.c_str(),
341
+                                       parent.size());
342
+                            }
343
+                        }
344
+                        else
345
+                        {
346
+                            ilog("%s is a vlan %s network\n",
347
+                                     physical_interface.c_str(), ptr->name);
348
+                        }
349
+                        break;
350
+                    }
351
+                } // end of switch
352
+                break;
353
+            }
354
+        }
355
+        fclose(file_ptr);
356
+    }
357
+
358
+    /* Lagged interface */
359
+    if ((ptr->interface_one[0] == '\0') && (!physical_interface.empty()))
360
+    {
361
+        string lagged_interface_file =
362
+               INTERFACES_DIR + physical_interface + "/bonding/slaves";
363
+
364
+        ifstream finTwo( lagged_interface_file.c_str() );
365
+        if (!finTwo)
366
+        {
367
+            elog ("Cannot find bond interface file (%s) to "
368
+                  "resolve slave interfaces\n", lagged_interface_file.c_str());
369
+            ptr->used = false ;
370
+            return (FAIL_OPERATION);
371
+        }
372
+        else
373
+        {
374
+            string line;
375
+            while ( getline( finTwo, line ) )
376
+            {
377
+                strncpy(line_buf, line.c_str(), MAX_CHARS_ON_LINE);
378
+
379
+                // the slave interfaces are listed as enXYYY enXYYY...
380
+                // starting with the primary. Read all other slaves
381
+                // as interface_two
382
+                sscanf(line_buf, "%19s %19s", ptr->interface_one, ptr->interface_two);
383
+
384
+                ilog("%s and %s are %s network aggregated interfaces\n",
385
+                         ptr->interface_one,
386
+                         ptr->interface_two,
387
+                         ptr->name);
388
+                break;
389
+            }
390
+        }
391
+    }
392
+
393
+    if ( ptr->interface_one[0] == '\0' )
394
+    {
395
+        ptr->used = false;
396
+    }
397
+    else
398
+    {
399
+        ptr->used = true;
400
+        if ( ptr->interface_two[0] == '\0' )
401
+        {
402
+            /* this is not a lagged interface */
403
+            ptr->lagged = false;
404
+        }
405
+        else
406
+        {
407
+            /* this is a lagged interface */
408
+            ptr->lagged = true;
409
+        }
410
+    }
411
+    return (PASS);
412
+}
413
+
414
+
415
+

+ 83
- 0
mtce/src/lmon/scripts/lmon View File

@@ -0,0 +1,83 @@
1
+#! /bin/sh
2
+#
3
+# Copyright (c) 2019 Wind River Systems, Inc.
4
+#
5
+# SPDX-License-Identifier: Apache-2.0
6
+#
7
+
8
+#
9
+# chkconfig: 2345 95 95
10
+#
11
+### BEGIN INIT INFO
12
+# Provides:          lmon
13
+# Default-Start:     3 5
14
+# Default-Stop:      0 1 2 6
15
+# Short-Description: Link Monitor daemon
16
+### END INIT INFO
17
+
18
+. /etc/init.d/functions
19
+
20
+DAEMON_NAME="lmond"
21
+DAEMON="/usr/local/bin/${DAEMON_NAME}"
22
+IFACE=""
23
+
24
+if [ ! -e "$DAEMON" ] ; then
25
+    logger "$DAEMON is missing"
26
+    exit 1
27
+fi
28
+
29
+RETVAL=0
30
+
31
+PATH=/sbin:/usr/sbin:/bin:/usr/bin:/usr/local/bin
32
+export PATH
33
+
34
+case "$1" in
35
+    start)
36
+        echo -n "Starting $DAEMON_NAME: "
37
+        # Prevent multiple starts
38
+        if [ -n "`pidof ${DAEMON_NAME}`" ] ; then
39
+            echo "OK"
40
+            exit $RETVAL
41
+        fi
42
+        start-stop-daemon --start -b -x ${DAEMON} --
43
+        RETVAL=$?
44
+        if [ $RETVAL -eq 0 ] ; then
45
+            echo "OK"
46
+        else
47
+            echo "FAIL"
48
+        fi
49
+        ;;
50
+
51
+    stop)
52
+        echo -n "Stopping ${DAEMON_NAME}: "
53
+        if [ -n "`pidof ${DAEMON_NAME}`" ] ; then
54
+            killproc ${DAEMON_NAME}
55
+        fi
56
+        echo "OK"
57
+        ;;
58
+
59
+    restart)
60
+        $0 stop
61
+        $0 start
62
+        ;;
63
+
64
+    status)
65
+        pid=`pidof ${DAEMON_NAME}`
66
+        RETVAL=$?
67
+        if [ ${RETVAL} -eq 0 ] ; then
68
+            echo "${DAEMON_NAME} is running"
69
+        else
70
+            echo "${DAEMON_NAME} is NOT running"
71
+        fi
72
+        ;;
73
+
74
+    condrestart)
75
+        [ -f /var/lock/subsys/${DAEMON_NAME} ] && $0 restart
76
+        ;;
77
+
78
+    *)
79
+        echo "usage: $0 { start | stop | status | restart | condrestart | status }"
80
+        ;;
81
+esac
82
+
83
+exit $RETVAL

+ 16
- 0
mtce/src/lmon/scripts/lmon.logrotate View File

@@ -0,0 +1,16 @@
1
+#daily
2
+nodateext
3
+
4
+/var/log/lmond.log
5
+{
6
+    nodateext
7
+    size 10M
8
+    start 1
9
+    missingok
10
+    rotate 20
11
+    compress
12
+    sharedscripts
13
+    postrotate
14
+        systemctl reload syslog-ng > /dev/null 2>&1 || true
15
+    endscript
16
+}

+ 16
- 0
mtce/src/lmon/scripts/lmon.pmon.conf View File

@@ -0,0 +1,16 @@
1
+[process]
2
+process  = lmond
3
+service  = lmon
4
+pidfile  = /var/run/lmond.pid
5
+style    = lsb            ; ocf or lsb
6
+severity = major          ; minor, major, critical
7
+restarts = 3              ; restart retries before error assertion
8
+interval = 5              ; number of seconds to wait between restarts
9
+debounce = 20             ; number of seconds that a process needs to remain
10
+                          ;   running before degrade is removed and retry count
11
+                          ;   is cleared.
12
+startuptime  = 5          ; Seconds to wait after process start before starting the debounce monitor
13
+mode  = passive           ; Monitoring mode: passive (default) or active
14
+                          ; passive: process death monitoring (default: always)
15
+                          ; active : heartbeat monitoring, i.e. request / response messaging 
16
+                          ; ignore : do not monitor or stop monitoring

+ 17
- 0
mtce/src/lmon/scripts/lmon.service View File

@@ -0,0 +1,17 @@
1
+[Unit]
2
+Description=Starling-X Maintenance Link Monitor
3
+
4
+After=config.service
5
+After=syslog-ng.service
6
+Before=pmon.service
7
+
8
+[Service]
9
+Type=forking
10
+ExecStart=/etc/rc.d/init.d/lmon start
11
+ExecStop=/etc/rc.d/init.d/lmon stop
12
+ExecReload=/etc/rc.d/init.d/lmon reload
13
+PIDFile=/var/run/lmond.pid
14
+KillMode=process
15
+
16
+[Install]
17
+WantedBy=multi-user.target

+ 19
- 0
mtce/src/lmon/scripts/lmond.conf View File

@@ -0,0 +1,19 @@
1
+; Link Monitor Configuration File
2
+[client]                   ; Client configuration
3
+audit_period = 60          ; seconds between process audits
4
+lmon_query_port = 2122     ; port that responds to link query requests
5
+daemon_log_port = 2121     ; daemon logger port
6
+uri_path = /mtce/lmon      ; maintenance service path http://<ip>:<port><uri_path>
7
+
8
+[defaults]
9
+
10
+[timeouts]
11
+
12
+[features]
13
+
14
+[debug]                    ; SIGHUP to reload
15
+debug_timer = 0            ; enable(1) or disable(0) timer logs (tlog)
16
+debug_json = 0             ; enable(1) or disable(0) message logs (jlog)
17
+debug_state = 0            ; enable(1) or disable(0) state change logs (clog)
18
+debug_level = 0            ; decimal mask 0..15 (8,4,2,1)
19
+debug_all = 0              ; set all debug labels to the specified value

+ 1
- 1
mtce/src/rmon/rmonHdlr.cpp View File

@@ -663,7 +663,7 @@ int rmon_hdlr_init ( rmon_ctrl_type * ctrl_ptr )
663 663
 
664 664
     _thinmeta_config_load();
665 665
     _config_files_load ();
666
-    _inter_config_load ();
666
+    // _inter_config_load ();
667 667
 
668 668
     /* init Thin Metadata Monitoring after config reload - including timers */
669 669
     thinmeta_init(thinmeta_resource_config, thinmetatimer, ctrl_ptr->thinmeta_resources);

Loading…
Cancel
Save