1 /*************************************************************************//**
3 * Copyright © 2019 AT&T Intellectual Property. All rights reserved.
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
16 ****************************************************************************/
30 #define MAX_BUFFER_SIZE 4096
31 #define MAX_TOKENS 1000
32 #define MAX_INTERFACES 40
34 void *MeasThread(void *threadarg);
36 typedef struct dummy_vpp_metrics_struct {
47 typedef struct linkstat {
56 vpp_metrics_struct meas_intfstat[MAX_INTERFACES];
57 LINKSTAT meas_linkstat[MAX_INTERFACES];
59 unsigned long long epoch_start = 0;
61 int format_val_params(KEYVALRESULT * keyValArray, int numElements, const char *replace, const char *search)
69 for (i=0; i<numElements; i++)
71 if ((sp = strstr(keyValArray[i].valStr, search)) == NULL) {
72 printf("\n String not found\n");
73 return 1; //Error search string not found
76 search_len = strlen(search);
77 replace_len = strlen(replace);
78 tail_len = strlen(sp+search_len);
79 memmove(sp+replace_len,sp+search_len,tail_len+1);
80 memcpy(sp, replace, replace_len);
81 // printf("\n Changed value for i=%d is %s", i, keyValArray[i].valStr);
83 return 0; //search and replace is successful
86 void runCommands(KEYVALRESULT * commandArray, int numCommands)
89 char buf[BUFSIZE]; /* buffer used to store VPP metrics */
90 FILE *fp; /* file descriptor to pipe cmd to shell */
93 for(i = 0; i < numCommands; i++)
95 memset(buf, 0, BUFSIZE);
97 // Open a pipe and read VPP values
98 if ((fp = popen(commandArray[i].valStr, "r")) == NULL) {
99 printf("Error opening pipe!\n");
103 while (fgets(buf, BUFSIZE, fp) != NULL);
104 strcpy(commandArray[i].resultStr, buf);
107 printf("Command not found or exited with error status\n");
111 //for(i = 0; i < numCommands; i++)
112 // printf("-%d-valstr and resultStr is- %s - %s\n", i, commandArray[i].valStr, commandArray[i].resultStr);
113 printf("%d - %d - %d - %d\n", atoi(commandArray[0].resultStr), atoi(commandArray[1].resultStr), atoi(commandArray[2].resultStr), atoi(commandArray[3].resultStr));
117 void copy_vpp_metic_data(vpp_metrics_struct *intfstats, KEYVALRESULT * cmdArray, int numCmds, int linkNum)
121 // Store the current metric in the last metric
122 intfstats[linkNum].last_bytes_in = intfstats[linkNum].curr_bytes_in;
123 intfstats[linkNum].last_bytes_out = intfstats[linkNum].curr_bytes_out;
124 intfstats[linkNum].last_packets_in = intfstats[linkNum].curr_packets_in;
125 intfstats[linkNum].last_packets_out = intfstats[linkNum].curr_packets_out;
127 // Store metrics read from the vNIC in the current
128 for(i=0; i<numCmds; i++)
130 if((strcmp(cmdArray[i].keyStr, "tmp_t0BytesIn") == 0) ||
131 (strcmp(cmdArray[i].keyStr, "tmp_t1BytesIn") == 0))
132 intfstats[linkNum].curr_bytes_in = atoi(cmdArray[i].resultStr);
134 if((strcmp(cmdArray[i].keyStr, "tmp_t0BytesOut") == 0) ||
135 (strcmp(cmdArray[i].keyStr, "tmp_t1BytesOut") == 0))
136 intfstats[linkNum].curr_bytes_out = atoi(cmdArray[i].resultStr);
138 if((strcmp(cmdArray[i].keyStr, "tmp_t0PacketsIn") == 0) ||
139 (strcmp(cmdArray[i].keyStr, "tmp_t1PacketsIn") == 0))
140 intfstats[linkNum].curr_packets_in = atoi(cmdArray[i].resultStr);
142 if((strcmp(cmdArray[i].keyStr, "tmp_t0PacketsOut") == 0) ||
143 (strcmp(cmdArray[i].keyStr, "tmp_t1PacketsOut") == 0))
144 intfstats[linkNum].curr_packets_out = atoi(cmdArray[i].resultStr);
146 // printf("intfstats[%d].curr_bytes_in = %d\n", linkNum, intfstats[linkNum].curr_bytes_in);
147 // printf("intfstats[%d].curr_bytes_out = %d\n", linkNum, intfstats[linkNum].curr_bytes_out);
148 // printf("intfstats[%d].curr_packets_in = %d\n", linkNum, intfstats[linkNum].curr_packets_in);
149 // printf("intfstats[%d].curr_packets_out = %d\n", linkNum, intfstats[linkNum].curr_packets_out);
152 int get_priority(char * inStr)
156 if(strcmp(inStr, "High") == 0)
157 result = EVEL_PRIORITY_HIGH;
158 else if(strcmp(inStr, "Medium") == 0)
159 result = EVEL_PRIORITY_MEDIUM;
160 else if(strcmp(inStr, "Normal") == 0)
161 result = EVEL_PRIORITY_NORMAL;
162 else if(strcmp(inStr, "Low") == 0)
163 result = EVEL_PRIORITY_LOW;
168 /**************************************************************************//**
170 *****************************************************************************/
171 void evel_get_cpu_stats(EVENT_MEASUREMENT * measurement)
184 MEASUREMENT_CPU_USE *cpu_use = NULL;
186 /* Open the command for reading. */
187 //fp = popen("/bin/ls /etc/", "r");
188 fp = popen("/usr/bin/top -bn 2 -d 0.01 | grep '^%Cpu' | tail -n 1 ", "r");
190 printf("Failed to run command\n" );
194 /* Read the output a line at a time - output it. */
195 while (fgets(path, sizeof(path)-1, fp) != NULL) {
196 printf("%s", path+10);
197 sscanf(path+10," %lf us, %lf sy, %lf ni, %lf id, %lf wa, %lf hi, %lf si, %lf st",
198 &user,&sys,&nice,&idle,&wait,&intrpt,&softirq,&steal);
204 cpu_use = evel_measurement_new_cpu_use_add(measurement, "cpu1", usage);
205 if( cpu_use != NULL ){
207 evel_measurement_cpu_use_idle_set(cpu_use,idle);
208 //evel_measurement_cpu_use_interrupt_set(cpu_use,intrpt);
209 //evel_measurement_cpu_use_nice_set(cpu_use,nice);
210 //evel_measurement_cpu_use_softirq_set(cpu_use,softirq);
211 //evel_measurement_cpu_use_steal_set(cpu_use,steal);
212 evel_measurement_cpu_use_system_set(cpu_use,sys);
213 evel_measurement_cpu_use_usageuser_set(cpu_use,user);
214 //evel_measurement_cpu_use_wait_set(cpu_use,wait);
215 //evel_measurement_cpu_use_add(measurement, "cpu2", usage,idle,intrpt,nice,softirq,steal,sys,user,wait);
219 int measure_traffic()
226 struct tm * timeinfo;
233 printf("Checking app traffic\n");
235 timeinfo = localtime (&rawtime);
236 strftime(period,21,"%d/%b/%Y:%H:%M:",timeinfo);
237 strftime(secs,3,"%S",timeinfo);
239 if (sec == 0) sec = 59;
240 sprintf(secs, "%02d", sec);
241 strncat(period, secs, 21);
242 // ....x....1....x....2.
243 // 15/Oct/2016:17:51:19
244 strcpy(cmd, "sudo docker logs vHello | grep -c ");
245 strncat(cmd, period, 100);
246 fp = popen(cmd, "r");
248 EVEL_ERROR("popen failed to execute command");
251 if (fgets(count, 10, fp) != NULL) {
252 request_rate = atoi(count);
253 printf("Reporting request rate for second: %s as %d\n", period, request_rate);
257 EVEL_ERROR("New Measurement failed");
259 printf("Processed measurement\n");
263 EVEL_ERROR("pclose returned an error");
270 int main(int argc, char** argv)
272 char* fqdn = argv[1];
273 int port = atoi(argv[2]);
277 pthread_t meas_thread;
284 port2 = atoi(argv[4]);
287 if (!((argc == 3) || (argc == 5)))
289 fprintf(stderr, "Usage: %s <FQDN>|<IP address> <port> <FQDN>|<IP address> <port> \n", argv[0]);
290 fprintf(stderr, "OR\n");
291 fprintf(stderr, "Usage: %s <FQDN>|<IP address> <port> \n", argv[0]);
295 /**************************************************************************/
297 /**************************************************************************/
298 if(evel_initialize(fqdn, /* FQDN */
300 fqdn2, /* Backup FQDN */
301 port2, /* Backup port */
302 NULL, /* optional path */
303 NULL, /* optional topic */
304 100, /* Ring Buffer size */
306 NULL, /* cert file */
312 "sample1", /* Username */
313 "sample1", /* Password */
314 "sample1", /* Username2 */
315 "sample1", /* Password2 */
316 NULL, /* Source ip */
317 NULL, /* Source ip2 */
318 EVEL_SOURCE_VIRTUAL_MACHINE, /* Source type */
319 "vFirewall", /* Role */
322 fprintf(stderr, "\nFailed to initialize the EVEL library!!!\n");
327 printf("\nInitialization completed\n");
330 /* Initialize and set thread detached attribute */
331 pthread_attr_init(&attr);
332 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
334 printf("Main:Creating thread \n");
335 rc = pthread_create(&meas_thread, NULL, MeasThread, &i);
338 printf("ERROR; return code from pthread_create() is %d\n", rc);
341 printf("Main:Created Meas thread \n");
343 pthread_join(meas_thread, NULL);
346 printf("Terminated\n");
350 void *MeasThread(void *mainMeas)
352 EVEL_ERR_CODES evel_rc = EVEL_SUCCESS;
353 EVENT_MEASUREMENT * vpp_m = NULL;
354 MEASUREMENT_CPU_USE *cpu_use = NULL;
355 EVENT_HEADER* vpp_m_header = NULL;
360 unsigned long long epoch_now;
361 int request_rate = 0;
363 struct timeval time_val;
364 MEASUREMENT_VNIC_PERFORMANCE * vnic_performance = NULL;
365 char event_id1[10] = "mvfs";
366 char event_id2[15] = {0};
367 char event_id[BUFSIZE] = {0};
368 int meas_event_id = 0;
371 jsmntok_t tokens[MAX_TOKENS];
372 char js[MAX_BUFFER_SIZE];
379 char nfcCode[BUFSIZE];
380 char nfCode[BUFSIZE];
382 char reportEId[BUFSIZE];
383 char reportEName[BUFSIZE];
385 char srcName[BUFSIZE];
390 char hostname[BUFSIZE];
393 ARRAYVAL intfArray[MAX_INTERFACES];
394 KEYVALRESULT keyValResultArray[32];
395 KEYVALRESULT keyValResultArray2[32];
396 KEYVALRESULT vnicCommandArray[32];
397 KEYVALRESULT cpuUsageCommandArray[32];
398 int numInitCommands = 0;
399 int numVnicCommands = 0;
400 int numCpuUsageCommands = 0;
404 double cpuSystem=0.0;
414 memset(hostname, 0, BUFSIZE);
415 gethostname(hostname, BUFSIZE);
416 printf("MeasThread::The hostname is %s\n", hostname);
419 printf("MeasThread::Running Meas thread \n");
422 memset(&intfArray[0],0,(sizeof(ARRAYVAL) * MAX_INTERFACES));
423 memset(&keyValResultArray[0],0,(sizeof(KEYVALRESULT) * 32));
425 memset(js, 0, MAX_BUFFER_SIZE);
426 memset(ch, 0, BUFSIZE);
427 memset(&meas_intfstat[0],0,(sizeof(vpp_metrics_struct)* MAX_INTERFACES));
428 memset(&meas_linkstat[0],0,(sizeof(LINKSTAT) * MAX_INTERFACES));
430 FILE * file = fopen("meas_config.json", "r");
432 while((fgets(ch, (BUFSIZE-1), file)) !=NULL)
435 memset(ch, 0, BUFSIZE);
437 // printf("MeasThread::the file content is \n %s \n", js);
440 numToken = jsmn_parse(&p, js, strlen(js), tokens, MAX_TOKENS);
441 printf("MeasThread::count-%d\n", numToken);
443 // printToken(js,tokens, numToken);
446 ret = getIntToken(js, tokens, numToken, "measurementInterval", "tmp_directParameters", &meas_interval);
449 printf("MeasThread::The parameter measurementInterval is not defined, defaulted to 60 seconds\n");
453 ret = getArrayTokens(js, tokens, numToken, "tmp_device", "tmp_directParameters", intfArray, &linkCount);
455 printf("MeasThread::Array link count is %d\n", linkCount);
457 /* Copy the link information */
458 for(i=0;i<linkCount;i++)
460 strcpy(meas_linkstat[i].linkname, &intfArray[i]);
461 // printf("MeasThread::Link name %s\n", meas_linkstat[i].linkname);
465 read_keyVal_params(js, tokens, numToken, "tmp_init", "tmp_indirectParameters", keyValResultArray, &numInitCommands);
467 for(i=0;i<linkCount;i++)
469 memset(&vnicCommandArray[0],0,(sizeof(KEYVALRESULT) * 32));
470 memcpy(vnicCommandArray, keyValResultArray, (sizeof(KEYVALRESULT) * 32));
471 format_val_params(vnicCommandArray, numInitCommands, meas_linkstat[i].linkname, "$tmp_device");
472 runCommands(vnicCommandArray, numInitCommands);
473 copy_vpp_metic_data(meas_intfstat, vnicCommandArray, numInitCommands, i);
476 gettimeofday(&time_val, NULL);
478 sleep(meas_interval);
480 /***************************************************************************/
481 /* Collect metrics from the VNIC */
482 /***************************************************************************/
486 ret = getIntToken(js, tokens, numToken, "measurementInterval", "tmp_directParameters", &meas_interval);
492 ret = getStringToken(js, tokens, numToken, "eventName", "tmp_directParameters", eName, BUFSIZE);
495 printf("MeasThread::Missing mandatory parameters - eventName is not there in tmp_directParameters. Exiting...\n");
499 ret = getStringToken(js, tokens, numToken, "eventType", "tmp_directParameters", eType, BUFSIZE);
500 ret = getStringToken(js, tokens, numToken, "nfcNamingCode", "tmp_directParameters", nfcCode, BUFSIZE);
501 ret = getStringToken(js, tokens, numToken, "nfNamingCode", "tmp_directParameters", nfCode, BUFSIZE);
502 ret = getStringToken(js, tokens, numToken, "reportingEntityId", "tmp_directParameters", reportEId, BUFSIZE);
503 ret = getStringToken(js, tokens, numToken, "sourceId", "tmp_directParameters", srcId, BUFSIZE);
504 ret = getStringToken(js, tokens, numToken, "reportingEntityName", "tmp_directParameters", reportEName, BUFSIZE);
507 printf("MeasThread::Missing mandatory parameters - reportingEntityName is not there in tmp_directParameters\n");
508 printf("MeasThread::Defaulting reportingEntityName to hostname\n");
509 strcpy(reportEName, hostname);
511 ret = getStringToken(js, tokens, numToken, "sourceName", "tmp_directParameters", srcName, BUFSIZE);
514 printf("MeasThread::Missing mandatory parameters - sourceName is not there in tmp_directParameters\n");
515 printf("MeasThread::Defaulting sourceName to hostname\n");
516 strcpy(srcName, hostname);
519 ret = getStringToken(js, tokens, numToken, "priority", "tmp_directParameters", prio, BUFSIZE);
522 printf("MeasThread::Missing mandatory parameters - priority is not there in tmp_directParameters\nDefaulting priority to Low\n");
523 strcpy(prio, "Medium");
525 priority = get_priority(prio);
528 printf("MeasThread::Meas priority value is not matching, prioirty-%s \n", prio);
532 read_keyVal_params(js, tokens, numToken, "tmp_vnic_command", "vNicPerformance", keyValResultArray, &numVnicCommands);
534 for(i=0;i<linkCount;i++)
536 memset(&vnicCommandArray[0],0,(sizeof(KEYVALRESULT) * 32));
537 memcpy(vnicCommandArray, keyValResultArray, (sizeof(KEYVALRESULT) * 32));
538 format_val_params(vnicCommandArray, numVnicCommands, meas_linkstat[i].linkname, "$tmp_device");
539 runCommands(vnicCommandArray, numVnicCommands);
540 copy_vpp_metic_data(meas_intfstat, vnicCommandArray, numVnicCommands, i);
543 memset(event_id, 0, BUFSIZE);
544 meas_event_id = meas_event_id+1;
545 sprintf(event_id2, "%09d", meas_event_id);
546 strcat(event_id, event_id1);
547 strcat(event_id, event_id2);
549 vpp_m = evel_new_measurement(meas_interval, eName,event_id);
553 printf("New measurement report created...\n");
555 for (int i = 0; i < linkCount; i++)
557 if(meas_intfstat[i].curr_bytes_in - meas_intfstat[i].last_bytes_in > 0) {
558 bytes_in = meas_intfstat[i].curr_bytes_in - meas_intfstat[i].last_bytes_in;
563 if(meas_intfstat[i].curr_bytes_out - meas_intfstat[i].last_bytes_out > 0) {
564 bytes_out = meas_intfstat[i].curr_bytes_out - meas_intfstat[i].last_bytes_out;
569 if(meas_intfstat[i].curr_packets_in - meas_intfstat[i].last_packets_in > 0) {
570 packets_in = meas_intfstat[i].curr_packets_in - meas_intfstat[i].last_packets_in;
575 if(meas_intfstat[i].curr_packets_out - meas_intfstat[i].last_packets_out > 0) {
576 packets_out = meas_intfstat[i].curr_packets_out - meas_intfstat[i].last_packets_out;
581 vnic_performance = (MEASUREMENT_VNIC_PERFORMANCE *)evel_measurement_new_vnic_performance(meas_linkstat[i].linkname, "true");
582 evel_meas_vnic_performance_add(vpp_m, vnic_performance);
583 evel_vnic_performance_rx_total_pkt_delta_set(vnic_performance, packets_in);
584 evel_vnic_performance_tx_total_pkt_delta_set(vnic_performance, packets_out);
586 evel_vnic_performance_rx_octets_delta_set(vnic_performance, bytes_in);
587 evel_vnic_performance_tx_octets_delta_set(vnic_performance, bytes_out);
589 if (strcmp(meas_linkstat[i].linkname, "docker") == 0)
591 request_rate = measure_traffic();
595 evel_measurement_request_rate_set(vpp_m, request_rate);
597 //evel_get_cpu_stats(vpp_m);
598 memset(&keyValResultArray2[0],0,(sizeof(KEYVALRESULT) * 32));
599 memset(&cpuUsageCommandArray[0],0,(sizeof(KEYVALRESULT) * 32));
601 ret = getStringToken(js, tokens, numToken, "cpuIdentifier", "cpuUsage", cpuId, BUFSIZE);
604 printf("MeasThread::Missing parameters - cpuIdentifier is not there in cpuUsage, default to Cpu1\n");
605 strcpy(cpuId, "Cpu1");
607 read_keyVal_params(js, tokens, numToken, "tmp_cpuuse_command", "cpuUsage", keyValResultArray2, &numCpuUsageCommands);
608 memcpy(cpuUsageCommandArray, keyValResultArray2, (sizeof(KEYVALRESULT) * 32));
609 runCommands(cpuUsageCommandArray, numCpuUsageCommands);
611 cpu_use = evel_measurement_new_cpu_use_add(vpp_m, cpuId, usage);
612 if( cpu_use != NULL )
614 /****************************
615 for(i=0; i<numCpuUsageCommands; i++)
617 if(strcmp(cpuUsageCommandArray[i].keyStr, "tmp_cpuIdle") == 0)
619 cpuIdle = atof(cpuUsageCommandArray[i].resultStr);
621 if(strcmp(cpuUsageCommandArray[i].keyStr, "tmp_cpuUsageSystem") == 0)
623 cpuSystem = atof(cpuUsageCommandArray[i].resultStr);
625 if(strcmp(cpuUsageCommandArray[i].keyStr, "tmp_cpuUsageUser") == 0)
627 cpuUser = atof(cpuUsageCommandArray[i].resultStr);
629 } **********************/
630 printf("%s", cpuUsageCommandArray[0].resultStr);
631 sscanf(cpuUsageCommandArray[0].resultStr, " %lf us, %lf sy, %lf ni, %lf id, %lf wa, %lf hi, %lf si, %lf st", &cpuUser,&cpuSystem,&nice,&cpuIdle,&wait,&intrpt,&softirq,&steal);
632 printf("user - %f, system - %f, idle - %f\n", cpuUser, cpuSystem, cpuIdle);
634 evel_measurement_cpu_use_idle_set(cpu_use, cpuIdle);
635 evel_measurement_cpu_use_system_set(cpu_use, cpuSystem);
636 evel_measurement_cpu_use_usageuser_set(cpu_use, cpuUser);
639 struct timeval tv_now;
640 gettimeofday(&tv_now, NULL);
641 epoch_now = tv_now.tv_usec + 1000000 * tv_now.tv_sec;
643 vpp_m_header = (EVENT_HEADER *)vpp_m;
647 evel_measurement_type_set(vpp_m, eType);
649 evel_start_epoch_set(&vpp_m->header, epoch_start);
650 evel_last_epoch_set(&vpp_m->header, epoch_now);
651 epoch_start= epoch_now;
654 evel_nfcnamingcode_set(&vpp_m->header, nfcCode);
656 evel_nfnamingcode_set(&vpp_m->header, nfCode);
657 evel_reporting_entity_name_set(&vpp_m->header, reportEName);
658 if(reportEId != NULL)
659 evel_reporting_entity_id_set(&vpp_m->header, reportEId);
661 evel_source_id_set(&vpp_m->header, srcId);
663 evel_source_name_set(&vpp_m->header, srcName);
665 evel_rc = evel_post_event(vpp_m_header);
667 if(evel_rc == EVEL_SUCCESS)
668 printf("MeasThread::Meas event is correctly sent to the collector!\n");
670 printf("MeasThread::Post failed %d (%s)\n", evel_rc, evel_error_string());
674 printf("MeasThread::Measurement event creation failed (%s)\n", evel_error_string());
677 sleep(meas_interval);
680 /***************************************************************************/
682 /***************************************************************************/