ac816b2fe20449b42adb4a79d8e339fa200bb1b0
[demo.git] / vnfs / VES5.0 / evel / evel-library / code / VESreporting_vAFX / afx_linkmon.c
1  /*****************************************************************************//***
2  * Copyright(c) <2017>, AT&T Intellectual Property.  All other rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are met:
6  *
7  * 1. Redistributions of source code must retain the above copyright notice,
8  *    this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright notice,
10  *    this list of conditions and the following disclaimer in the documentation
11  *    and/or other materials provided with the distribution.
12  * 3. All advertising materials mentioning features or use of this software
13  *    must display the following acknowledgement:  This product includes
14  *    software developed by the AT&T.
15  * 4. Neither the name of AT&T nor the names of its contributors may be used to
16  *    endorse or promote products derived from this software without specific
17  *    prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY AT&T INTELLECTUAL PROPERTY ''AS IS'' AND ANY
20  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22  * DISCLAIMED. IN NO EVENT SHALL AT&T INTELLECTUAL PROPERTY BE LIABLE FOR ANY
23  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
26  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
28  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  *****************************************************************************/
30
31 #include <pthread.h>
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <ctype.h>
35 #include <string.h>
36 #include <stdint.h>
37 #include <unistd.h>
38 #include <sys/stat.h>
39 #include <sys/time.h>
40 #include <sys/types.h>
41
42 #include "evel.h"
43 #include "afx_ves_reporter.h"
44
45
46 /**************************************************************************//**
47  * Thread function to Monitor Ethernet links
48  * Checks status of afx inout and afx output service every service monitor
49  * interval. It reports fault event at startup and whenever status changes
50  *
51  * @param threadarg  Thread arguments for startup message
52  *
53  * @retvalue  int   Success 1 service running 0 service inactive
54  *****************************************************************************/
55 void *LinkMonitorAfxThread(void *threadarg)
56 {
57    int taskid, sum;
58    char *hello_msg;
59    struct thread_data *my_data;
60     FILE *fp;
61     char const* const fileName = AFX_INTERFACE_FILE;
62     char line[256];
63     char cmd[256];
64     char intf[256];
65     char descr[256];
66     char linkdata[256];
67     int linkcount = 0;
68     char *search = ":";
69     char *token;
70     char *pch;
71     time_t filetime = 0;
72     int newrun = 1;
73     int n_spaces = 0, i;
74     char ** res  = NULL;
75     char *pos;
76     int tlinkstat;
77     LINKSTAT intfstats[MAX_INTERFACES];
78     char vesevid[128];
79     int status = 1; /** VFS Status is Active **/
80
81
82    sleep(1);
83    my_data = (struct thread_data *) threadarg;
84    taskid = my_data->thread_id;
85    sum = my_data->sum;
86    hello_msg = my_data->message;
87    EVEL_INFO("AFX: Linkmon Thread %d: %s  Sum=%d\n", taskid, hello_msg, sum);
88
89 while(1)
90 {
91     /*Check if file is modified recently */
92     if( file_is_modified(fileName, &filetime) )  newrun = 1;
93
94     FILE* file = fopen(fileName, "r"); /* should check the result */
95     if( file == NULL ){
96       EVEL_ERROR("AFX: Linkmon Interface config file unavailable\n");
97       pthread_exit(NULL);
98     }
99
100     while ( file != NULL && fgets(line, sizeof(line), file)) {
101         /* note that fgets don't strip the terminating \n, checking its
102            presence would allow to handle lines longer that sizeof(line) */
103         sscanf(line,"%s %s",intf,descr);
104         //remove_spaces(line);
105         if ((pos=strchr(line, '\n')) != NULL)
106            *pos = '\0';
107         //printf("%s", line);
108         sprintf(cmd,"/sbin/ethtool %s\n", intf);
109         //printf("%s", cmd);
110         if( newrun ){
111                 strcpy(intfstats[linkcount].linkname,intf);
112                 strcpy(intfstats[linkcount].linkdescr,line);
113         }
114
115   /* Open the ethtool interface command for reading. */
116   fp = popen(cmd, "r");
117   if (fp == NULL) {
118     EVEL_DEBUG("AFX Linkmon: Failed to run command\n" );
119     //pthread_exit(NULL);
120     sleep(LINK_MONITOR_INTERVAL);
121     continue;
122   }
123
124   while( !feof(fp) ) {
125   /* Read the output a line at a time - output it. */
126   while (fgets(linkdata, sizeof(linkdata)-1, fp) != NULL) {
127     //EVEL_INFO("AFX: LinkMon :%s:",linkdata);
128     if ((pos=strchr(linkdata, '\n')) != NULL)
129            *pos = '\0';
130     if( strstr(linkdata,"Supported link modes"))
131     {
132           pch = strstr(linkdata, search);
133           while( pch != NULL &&( *pch == ':' || *pch == ' ')) pch++;
134           if(pch!=NULL){
135             //printf("Link mode %s\n",pch);
136             strcpy(intfstats[linkcount].linkmode,pch);
137           }
138     }
139     else if( strstr(linkdata,"Speed"))
140     {
141           token = strtok(linkdata, search);
142           token = strtok(NULL, search);
143           intfstats[linkcount].speedmbps = atoi(token);
144             //printf("Link speed %d\n",intfstats[linkcount].speedmbps);
145     }
146     else if( strstr(linkdata,"Link detected:"))
147     {
148           /* parse link data for connectivity */
149           token = strtok(linkdata, search);
150           token = strtok(NULL, search);
151           while( *token == ' ') token++;
152           if( !strcmp(token,"yes")){
153             tlinkstat = 1;
154           } else {
155             tlinkstat = 0;
156           }
157           if( newrun || tlinkstat !=  intfstats[linkcount].linkstat)
158           {
159             EVEL_DEBUG("AFX LinkMon Status changed report fault\n");
160             if( tlinkstat == 1 ){
161                sprintf(vesevid,"Fault_vAfx_LinkState_%s",oam_intfaddr);
162                report_fault("Fault_vAfx_Link_Status",vesevid,EVEL_SEVERITY_NORMAL,"link",intfstats[linkcount].linkdescr,"link up trap_alarm","physical or logical connection to a remote router is up","remrouter","rname",NULL, status);
163             } else {
164                sprintf(vesevid,"Fault_vAfx_LinkState_%s",oam_intfaddr);
165                report_fault("Fault_vAfx_Link_Status",vesevid,EVEL_SEVERITY_CRITICAL,"link",intfstats[linkcount].linkdescr,"link down trap_alarm","physical or logical connection to a remote router is down","remrouter","rname",NULL, status);
166             }
167           }
168           intfstats[linkcount].linkstat = tlinkstat;
169     }
170     else if( strstr(linkdata,"Cannot get link status:"))
171     {
172          sprintf(vesevid,"Fault_vAfx_LinkState_%s",oam_intfaddr);
173          report_fault("Fault_vAfx_Link_Status",vesevid,EVEL_SEVERITY_CRITICAL,"link",intfstats[linkcount].linkname,"link down trap_alarm","physical or logical connection to a remote router is down","remrouter","rname",NULL, status);
174     }
175    }
176   }
177
178   /* close */
179   pclose(fp);
180   linkcount++;
181   }
182
183   newrun = linkcount = 0;
184   if(file)fclose(file);
185
186     sleep(LINK_MONITOR_INTERVAL);
187   }
188
189    pthread_exit(NULL);
190 }
191