VES5.4.1 EVEL Library enhancements
[demo.git] / vnfs / VES5.0 / evel / evel-library / code / VESreporting_vAFX / afx_perfmon.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 unsigned long long epoch_start = 0;
46 #define MAX_CHILDREN 100
47
48
49 /**************************************************************************//**
50  * Utility to compare linknames for ordering
51  *****************************************************************************/
52 int cmpfunc (const void * a, const void * b)
53 {
54    VPP_METRICS_STRUCT *aptr = (VPP_METRICS_STRUCT *)a;
55    VPP_METRICS_STRUCT *bptr = (VPP_METRICS_STRUCT *)b;
56    return ( strcmp(aptr->linkname,bptr->linkname) );
57 }
58
59
60
61 /**************************************************************************//**
62  * Gets CPU Load Statistics
63  *
64  * @param measurement Pointer to measurement event
65  *
66  *
67  *****************************************************************************/
68 void evel_get_cpu_stats(EVENT_MEASUREMENT * measurement)
69 {
70   FILE *fp;
71   char path[1024];
72   char ** res  = NULL;
73   int n_spaces = 0, i;
74   char *p;
75   char cpname[256];
76
77   double usage=0.0;
78   double idle;
79   double intrpt;
80   double nice;
81   double softirq;
82   //double steal;
83   double sys;
84   //double user;
85   double usrl;
86   //double wait;
87   MEASUREMENT_CPU_USE *cpu_use = NULL;
88
89   /* Open the command for reading. */
90   fp = popen("/usr/bin/mpstat -P ALL ", "r");
91   if (fp == NULL) {
92     EVEL_ERROR(" AFX: Perf thread Failed to run command\n" );
93     pthread_exit(NULL);
94   }
95
96   /* Read the output a line at a time - output it. */
97   while (fgets(path, sizeof(path)-1, fp) != NULL) {
98     //printf("%s",path);
99
100 n_spaces = 0;
101 p    = strtok (path, " ");
102 /* split string and append tokens to 'res' */
103
104 while (p) {
105   res = realloc (res, sizeof (char*) * ++n_spaces);
106
107   if (res == NULL)
108     exit (-1); /* memory allocation failed */
109
110   res[n_spaces-1] = p;
111
112   p = strtok (NULL, " ");
113 }
114
115 /* realloc one extra element for the last NULL */
116 res = realloc (res, sizeof (char*) * (n_spaces+1));
117 res[n_spaces] = 0;
118
119 /* print the result */
120 if( n_spaces > 2 && (!strcmp(res[2],"all") || isdigit(res[2][0])) )
121 {
122   //for (i = 0; i < (n_spaces+1); ++i)
123   //{
124   //  printf ("res[%d] = %s\n", i, res[i]);
125   //}
126   if(isdigit(res[2][0]))
127   {
128     sprintf (cpname,"cpu%s", res[2]);
129   }
130   else
131     sprintf (cpname,"%s", res[2]);
132
133     usrl = atof(res[3]);
134     nice = atof(res[4]);
135     sys = atof(res[4]);
136     idle = atof(res[12]);
137     usage = 100.0 - idle;
138
139   //allocate CPU stats structure
140   cpu_use = evel_measurement_new_cpu_use_add(measurement, cpname, usage);
141   if( cpu_use != NULL ){
142   evel_measurement_cpu_use_idle_set(cpu_use,idle);
143   //evel_measurement_cpu_use_interrupt_set(cpu_use,intrpt);
144   evel_measurement_cpu_use_nice_set(cpu_use,nice);
145   //evel_measurement_cpu_use_softirq_set(cpu_use,softirq);
146   //evel_measurement_cpu_use_steal_set(cpu_use,steal);
147   evel_measurement_cpu_use_system_set(cpu_use,sys);
148   evel_measurement_cpu_use_usageuser_set(cpu_use,usrl);
149   //evel_measurement_cpu_use_wait_set(cpu_use,wait);
150   }
151 }
152
153   }
154
155 /* free the memory allocated */
156 if(res != NULL) free (res);
157 res = NULL;
158
159   /* close */
160   pclose(fp);
161
162 }
163
164 /**************************************************************************//**
165  * tap live memory stats
166  *****************************************************************************/
167 void evel_get_mem_stats(EVENT_MEASUREMENT * measurement)
168 {
169 char buffer[4096];
170 char line[100];
171 char c;
172 int  bcount=0,lcount=0;
173
174 double membuffsz=0.0;
175 double memcache=0.0;
176 double memconfig=0.0;
177 double memfree=0.0;
178 double slab=0.0;
179 double slabrecl=0.0;
180 double slabunrecl=0.0;
181 double memused=0.0;
182 MEASUREMENT_MEM_USE *mem_use = NULL;
183
184
185 FILE * filp = fopen("/proc/meminfo", "rb");
186 int bytes_read = fread(buffer, sizeof(char), 4096, filp);
187 fclose(filp);
188
189 EVEL_INFO("AFX perfmon meminfo %d\n",bytes_read);
190
191 while ( bcount < bytes_read )
192 {
193   for(lcount=0; buffer[bcount] != '\n';bcount++,lcount++)
194   {
195      line[lcount] = buffer[bcount];
196   }
197   if( lcount > 0 )
198   {
199     line[lcount] = '\0';
200     //printf("%s\n",line);
201     if(!strncmp(line,"Buffers:", strlen("Buffers:")))
202     {
203         sscanf(line+strlen("Buffers:"),"%lf",&membuffsz);
204         //printf("membuff %lf\n",membuffsz);
205     }
206     else if(!strncmp(line,"Cached:", strlen("Cached:")))
207     {
208         sscanf(line+strlen("Cached:"),"%lf",&memcache);
209     }
210     else if(!strncmp(line,"MemTotal:", strlen("MemTotal:")))
211     {
212         sscanf(line+strlen("MemTotal:"),"%lf",&memconfig);
213     }
214     else if(!strncmp(line,"MemFree:", strlen("MemFree:")))
215     {
216         sscanf(line+strlen("MemFree:"),"%lf",&memfree);
217     }
218     else if(!strncmp(line,"Slab:", strlen("Slab:")))
219     {
220         sscanf(line+strlen("Slab:"),"%lf",&slab);
221     }
222     else if(!strncmp(line,"SReclaimable:", strlen("SReclaimable:")))
223     {
224         sscanf(line+strlen("SReclaimable:"),"%lf",&slabrecl);
225     }
226     else if(!strncmp(line,"SUnreclaim:", strlen("SUnreclaim:")))
227     {
228         sscanf(line+strlen("SUnreclaim:"),"%lf",&slabunrecl);
229     }
230   }
231   bcount++;
232 }
233
234 memused = memconfig - memfree - membuffsz - memcache - slab;
235 EVEL_INFO(" AFX perfmon memused %lf\n",memused);
236
237   mem_use = evel_measurement_new_mem_use_add(measurement, "RAM", hostname, membuffsz);
238   evel_measurement_mem_use_memcache_set(mem_use,memcache);
239   evel_measurement_mem_use_memconfig_set(mem_use,memconfig);
240   evel_measurement_mem_use_memfree_set(mem_use,memfree);
241   evel_measurement_mem_use_slab_reclaimed_set(mem_use,slabrecl);
242   evel_measurement_mem_use_slab_unreclaimable_set(mem_use,slabunrecl);
243   evel_measurement_mem_use_usedup_set(mem_use,memused);
244
245 }
246
247 /**
248  *  System command execution output
249  *    @param <char> command - system command to execute
250  *    @returb <char> execution output
251  */
252 char *system_output (const char *command)
253 {
254   FILE *pipe;
255   static char out[512];
256   out[0]= '\0';
257   pipe = popen (command, "r");
258   if( pipe != NULL )
259   {
260    fgets (out, sizeof(out), pipe);
261    pclose (pipe);
262   }
263   return out;
264 }
265
266
267 /**
268  *  Finding all process's children
269  *    @param <Int> - process ID
270  *    @param <Int> - array of childs
271  */
272 void find_children (int pid, int children[])
273 {
274   int child_pid, i = 1;
275   char empty_command[] = "/bin/ps h -o pid --ppid ";
276   char pid_string[5];
277
278   snprintf(pid_string, 5, "%d", pid);
279
280   char *command = (char*) malloc(strlen(empty_command) + strlen(pid_string) + 1);
281   sprintf(command, "%s%s", empty_command, pid_string);
282
283   FILE *fp = popen(command, "r");
284   if( fp != NULL )
285   {
286     while (fscanf(fp, "%i", &child_pid) != EOF)
287     {
288       children[i] = child_pid;
289       i++;
290     }
291   }
292   free(command);
293   pclose(fp);
294 }
295
296
297 /**
298  *  Parsign `ps` command output
299  *    @param <char> out - ps command output
300  *    @return <int> cpu utilization
301  */
302 int parse_cpu_utilization (char *out, float *pcpu, float *pmem)
303 {
304   if( strlen(out) > 0 )
305   {
306    sscanf (out, "%f %f", pcpu, pmem);
307   }
308   return 0;
309 }
310
311
312 void gather_afx_stats(EVENT_MEASUREMENT *vpp_m,char *lkstr)
313 {
314   double totcpu=0.0,totmem=0.0;
315   float tmpcpu=0.0,tmpmem=0.0;
316   FILE *fp;
317   char path[512];
318   char cmd[128];
319   char grp[128];
320   char cpustr[64];
321   char memstr[64];
322   char *p;
323   //unsigned pid = atoi(argv[1]);
324   unsigned pid;
325   // getting array with process children
326   int process_children[MAX_CHILDREN] = { 0 };
327   unsigned i;
328   float common_cpu_usage = 0.0;
329
330   /* Open the command for reading. */
331   sprintf(cmd," pgrep -f \"%s\" | xargs --no-run-if-empty ps --no-headers ", lkstr);
332   fp = popen(cmd, "r");
333   if (fp == NULL) {
334     EVEL_ERROR("AFX meas : Failed to run afx command\n" );
335     pthread_exit(NULL);
336   }
337
338   /* Read the output a line at a time - output it. */
339   while ( !feof(fp) ) {
340   while (fgets(path, sizeof(path)-1, fp) != NULL) {
341     EVEL_DEBUG("AFX meas : %s",path);
342     p = &path[0];
343     while( p!=NULL && isspace(*p))p++;
344     if( strstr(p,"sh -c") == NULL && isdigit(*p))
345     {
346       sscanf(p,"%d ",&pid);
347       //printf(":%d:\n",pid);
348   process_children[0] = pid; // parent PID as first element
349   find_children(pid, process_children);
350
351   // calculating summary processor utilization
352   for (i = 0; i < sizeof(process_children)/sizeof(int); ++i)
353   {
354     if (process_children[i] > 0)
355     {
356       char *command = (char*)malloc(128);
357       EVEL_DEBUG ("AFX meas :/bin/ps -p %i -o 'pcpu,pmem' --no-headers\n", process_children[i]);
358       sprintf (command, "/bin/ps -p %i -o 'pcpu,pmem' --no-headers", process_children[i]);
359       parse_cpu_utilization(system_output(command),&tmpcpu,&tmpmem);
360       totcpu += tmpcpu;
361       totmem += tmpmem;
362     }
363   }
364   sprintf(grp,"%s_%d",lkstr,pid);
365   EVEL_DEBUG("%s %d CPU %f MEM %f\n", grp, totcpu, totmem);
366   sprintf(cpustr,"%f",totcpu);
367   sprintf(memstr,"%f",totmem);
368   evel_measurement_custom_measurement_add(vpp_m,grp,"cpu",cpustr);
369   evel_measurement_custom_measurement_add(vpp_m,grp,"mem",memstr);
370
371     }
372    }
373   }
374   pclose(fp);
375
376
377 }
378
379
380
381 /**************************************************************************//**
382  * tap live afx stats
383  *****************************************************************************/
384 void evel_get_afx_stats(EVENT_MEASUREMENT * measurement)
385 {
386    gather_afx_stats(measurement,"AFXin");
387    gather_afx_stats(measurement,"AFXout");
388 }
389
390 /**************************************************************************//**
391  * Thread function to Monitor AFX Performance parameters
392  * Opens interface list file to get list of interfaces
393  * Opens Device driver file every READ_INTERVAL and calculates
394  *   Delta packets and bytes
395  *
396  * @param threadarg  Thread arguments for startup message
397  *
398  * 
399  *****************************************************************************/
400 void *MeasureAfxThread(void *threadarg)
401 {
402   struct thread_data *my_data;
403    int taskid, sum;
404    char *hello_msg;
405   struct timeval time_val;
406   int i;
407   //time_t start_epoch;
408   //time_t last_epoch;
409   EVEL_ERR_CODES evel_rc = EVEL_SUCCESS;
410   EVENT_MEASUREMENT* vpp_m = NULL;
411   EVENT_HEADER* vpp_m_header = NULL;
412   MEASUREMENT_VNIC_PERFORMANCE * vnic_performance = NULL;
413   //struct timeval tv_start;
414     FILE *fp;
415     char const* const fileName = AFX_INTERFACE_FILE;
416     char line[256];
417     char intf[256];
418     char descr[256];
419     char linkdata[256];
420     int linkcount = 0;
421     time_t filetime = 0;
422     int newrun = 0;
423     int n_spaces = 0, j;
424     char ** res  = NULL;
425     char *pos;
426     char *p;
427     int tlinkstat;
428     VPP_METRICS_STRUCT intfstats[MAX_INTERFACES];
429     VPP_METRICS_STRUCT *ptritem;
430     uint64_t  curr_rx_bytes;
431     uint64_t  curr_rx_packets;
432     uint64_t  curr_rx_mcast;
433     uint64_t  curr_tx_bytes;
434     uint64_t  curr_tx_packets;
435   char vesevid[128];
436
437
438    sleep(1);
439    my_data = (struct thread_data *) threadarg;
440    taskid = my_data->thread_id;
441    sum = my_data->sum;
442    hello_msg = my_data->message;
443    EVEL_INFO("AFX Perf Thread %d: %s  Sum=%d\n", taskid, hello_msg, sum);
444    sprintf(vesevid,"measurementsForVfScaling_vAfx_%s",get_oam_intfaddr());
445
446   gettimeofday(&time_val, NULL);
447   epoch_start = time_val.tv_sec * 1000000 + time_val.tv_usec;
448   sleep(PERF_MONITOR_INTERVAL);
449
450   while(1) {
451
452     if( file_is_modified(fileName, &filetime) )  newrun = 1;
453
454     if( newrun ) {
455
456     linkcount = 0;
457     FILE* file = fopen(fileName, "r"); /* should check the result */
458
459     while ( file != NULL && fgets(line, sizeof(line), file)) {
460         /* note that fgets don't strip the terminating \n, checking its
461            presence would allow to handle lines longer that sizeof(line) */
462         //printf("%s", line);
463         sscanf(line,"%s %s",intf,descr);
464         //remove_spaces(line);
465         if ((pos=strchr(line, '\n')) != NULL)
466            *pos = '\0';
467         if( newrun ){
468                 memset(&intfstats[linkcount],0,sizeof(VPP_METRICS_STRUCT));
469                 strcpy(intfstats[linkcount].linkname,intf);
470                 strcpy(intfstats[linkcount].linkdescr,line);
471         }
472         linkcount++;
473      }
474      fclose(file);
475      if ((pos=strchr(line, '\n')) != NULL)
476            *pos = '\0';
477      qsort(intfstats,linkcount,sizeof(VPP_METRICS_STRUCT),cmpfunc);
478    }
479
480
481   /* Open the command for reading. */
482   fp = popen("cat /proc/net/dev ", "r");
483   if (fp == NULL) {
484     EVEL_DEBUG("Failed to run net command\n" );
485     //exit(1);
486     sleep(PERF_MONITOR_INTERVAL);
487     continue;
488   }
489
490   /* Read the output a line at a time - output it. */
491   while ( !feof(fp) ) {
492   while (fgets(linkdata, sizeof(linkdata)-1, fp) != NULL) {
493     //printf("%s",linkdata);
494
495 n_spaces = 0;
496 p    = strtok (linkdata, " ");
497 /* split string and append tokens to 'res' */
498
499 while (p) {
500   res = realloc (res, sizeof (char*) * ++n_spaces);
501
502   if (res == NULL){
503     EVEL_DEBUG("Memory allocation failed");
504     exit (-1); /* memory allocation failed */
505   }
506
507   res[n_spaces-1] = p;
508
509   p = strtok (NULL, " ");
510 }
511
512 /* realloc one extra element for the last NULL */
513 res = realloc (res, sizeof (char*) * (n_spaces+1));
514 res[n_spaces] = 0;
515
516
517  if( !strstr(res[0],"Inter") && !strstr(res[0],"face") )
518  {
519   /* for (i = 0; i < (n_spaces+1); ++i)
520   {
521     printf ("res[%d] = %s\n", i, res[i]);
522   }*/
523   if ((pos=strchr(res[0], ':')) != NULL)
524            *pos = '\0';
525    /* using bsearch() to find value 32 in the array */
526    ptritem = (VPP_METRICS_STRUCT*) bsearch (res[0], intfstats, linkcount, sizeof(VPP_METRICS_STRUCT), cmpfunc);
527    if( ptritem == NULL  )
528    {
529       EVEL_DEBUG("Item = %s could not be found\n", res[0]);
530    }
531    else if( !strcmp(res[0],ptritem->linkname) )
532    {
533       EVEL_DEBUG( "AFX Perf values Link %d rxb %d rxp %d rxm %d txb %d txp %d\n", linkcount, ptritem->rx_bytes, ptritem->rx_packets, ptritem->rx_mcast, ptritem->tx_bytes, ptritem->tx_packets );
534
535       curr_rx_bytes = strtoull(res[1],NULL,10);
536       curr_rx_packets = strtoull(res[2],NULL,10);
537       curr_rx_mcast = strtoull(res[8],NULL,10);
538       curr_tx_bytes = strtoull(res[9],NULL,10);
539       curr_tx_packets = strtoull(res[10],NULL,10);
540       if( !newrun ){
541          ptritem->delta_rx_bytes = curr_rx_bytes - ptritem->rx_bytes;
542          ptritem->delta_rx_packets = curr_rx_packets - ptritem->rx_packets;
543          ptritem->delta_rx_mcast = curr_rx_mcast - ptritem->rx_mcast;
544          ptritem->delta_tx_bytes = curr_tx_bytes - ptritem->tx_bytes;
545          ptritem->delta_tx_packets = curr_tx_packets - ptritem->tx_packets;
546       }
547       else
548       {
549          ptritem->delta_rx_bytes = 0;
550          ptritem->delta_rx_packets = 0;
551          ptritem->delta_rx_mcast = 0;
552          ptritem->delta_tx_bytes = 0;
553          ptritem->delta_tx_packets =  0;
554       }
555       ptritem->rx_bytes = curr_rx_bytes;
556       ptritem->rx_packets = curr_rx_packets;
557       ptritem->rx_mcast = curr_rx_mcast;
558       ptritem->tx_bytes = curr_tx_bytes;
559       ptritem->tx_packets = curr_tx_packets;
560
561      //printf( "Acc %s %d %d %d %d %d\n", ptritem->linkname, curr_rx_bytes, curr_rx_packets, curr_rx_mcast, curr_tx_bytes,  curr_tx_packets );
562      //printf( "Delta %d %d %d %d %d\n", ptritem->delta_rx_bytes, ptritem->delta_rx_packets, ptritem->delta_rx_mcast, ptritem->delta_tx_bytes, ptritem->delta_tx_packets );
563
564    }
565   }
566   }
567  }
568  pclose(fp);
569  newrun = 0;
570  if(res != NULL) free (res);
571  res = NULL;
572
573   /***************************************************************************/
574   /* Collect metrics from the VNIC                                           */
575   /***************************************************************************/
576     vpp_m = evel_new_measurement(PERF_MONITOR_INTERVAL,"measurementsForVfScaling_vAfx",vesevid);
577
578     if(vpp_m != NULL) {
579     evel_header_type_set((EVENT_HEADER *)vpp_m, "applicationVnf");
580     evel_nfcnamingcode_set((EVENT_HEADER *)vpp_m, "AFX");
581     evel_nfnamingcode_set((EVENT_HEADER *)vpp_m, "AFX");
582       EVEL_DEBUG("New measurement report created...\n");
583
584     for( i=0; i<linkcount;i++)
585     {
586       ptritem = &intfstats[i];
587       vnic_performance = (MEASUREMENT_VNIC_PERFORMANCE *)evel_measurement_new_vnic_performance
588                                 (ptritem->linkdescr, "true");
589
590       evel_meas_vnic_performance_add(vpp_m, vnic_performance);
591
592      //printf( "Acc %s %d %d %d %d %d\n", ptritem->linkname, curr_rx_bytes, curr_rx_packets, curr_rx_mcast, curr_tx_bytes,  curr_tx_packets );
593      //printf( "Delta %d %d %d %d %d\n", delta_rx_bytes, delta_rx_packets, delta_rx_mcast, delta_tx_bytes, delta_tx_packets );
594       evel_vnic_performance_rx_octets_acc_set(vnic_performance, ptritem->rx_bytes);
595       evel_vnic_performance_rx_octets_delta_set(vnic_performance, ptritem->delta_rx_bytes);
596       evel_vnic_performance_tx_octets_acc_set(vnic_performance, ptritem->tx_bytes);
597       evel_vnic_performance_tx_octets_delta_set(vnic_performance, ptritem->delta_tx_bytes);
598
599       evel_vnic_performance_rx_mcast_pkt_acc_set(vnic_performance, ptritem->rx_mcast);
600       evel_vnic_performance_rx_mcast_pkt_delta_set(vnic_performance, ptritem->delta_rx_mcast);
601
602       evel_vnic_performance_rx_total_pkt_acc_set(vnic_performance, ptritem->rx_packets);
603       evel_vnic_performance_rx_total_pkt_delta_set(vnic_performance, ptritem->delta_rx_packets);
604       evel_vnic_performance_tx_total_pkt_acc_set(vnic_performance, ptritem->tx_packets);
605       evel_vnic_performance_tx_total_pkt_delta_set(vnic_performance, ptritem->delta_tx_packets);
606
607     }
608
609       evel_get_cpu_stats(vpp_m);
610       evel_get_mem_stats(vpp_m);
611       evel_get_afx_stats(vpp_m);
612       /***************************************************************************/
613       /* Set parameters in the MEASUREMENT header packet                         */
614       /***************************************************************************/
615       struct timeval tv_now;
616       gettimeofday(&tv_now, NULL);
617       unsigned long long epoch_now = tv_now.tv_usec + 1000000 * tv_now.tv_sec;
618
619       //last_epoch = start_epoch + PERF_MONITOR_INTERVAL * 1000000;
620       vpp_m_header = (EVENT_HEADER *)vpp_m;
621       evel_start_epoch_set(&vpp_m->header, epoch_start);
622       evel_last_epoch_set(&vpp_m->header, epoch_now);
623       epoch_start = epoch_now;
624
625       evel_reporting_entity_name_set(&vpp_m->header, "AFXM");
626       evel_reporting_entity_id_set(&vpp_m->header, hostname);
627       evel_rc = evel_post_event(vpp_m_header);
628
629       if(evel_rc == EVEL_SUCCESS) {
630         EVEL_DEBUG("Measurement report correctly sent to the collector!\n");
631       }
632       else {
633         EVEL_DEBUG("Post failed %d (%s)\n", evel_rc, evel_error_string());
634       }
635     }
636     else {
637       EVEL_DEBUG("New measurement report failed (%s)\n", evel_error_string());
638     }
639   
640     sleep(PERF_MONITOR_INTERVAL);
641   }
642
643   /***************************************************************************/
644   /* Terminate                                                               */
645   /***************************************************************************/
646   sleep(1);
647
648   return 0;
649 }
650