* INTC Contribution to the O-RAN F Release for O-DU Low
[o-du/phy.git] / fhi_lib / app / src / aux_cline.c
1 /******************************************************************************
2 *
3 *   Copyright (c) 2020 Intel.
4 *
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 *
9 *       http://www.apache.org/licenses/LICENSE-2.0
10 *
11 *   Unless required by applicable law or agreed to in writing, software
12 *   distributed under the License is distributed on an "AS IS" BASIS,
13 *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 *   See the License for the specific language governing permissions and
15 *   limitations under the License.
16 *
17 *******************************************************************************/
18
19 /**
20  * @brief This file has utilities to parse the parameters passed in through the command
21  *        line and configure the application based on these parameters
22  * @file aux_cline.c
23  * @ingroup xran
24  * @author Intel Corporation
25  **/
26
27
28 #include "aux_cline.h"
29
30 #include <stdio.h>
31 #include <string.h>
32 #include <stdlib.h>
33 #include <errno.h>
34 #include <limits.h>
35 #include <pthread.h>
36
37
38 typedef struct _CLINE_KEY_TABLE_
39 {
40     char *name;
41     char *value;
42 } CLINE_KEY_TABLE;
43
44
45 #define CLINE_MAXKEYS               (256)
46 #define CLINE_MAX_STRING_LENGTH     (128)
47 #define CLINE_MAXKEYSIZE            (2048)
48
49 static CLINE_KEY_TABLE PhyAppKeys[CLINE_MAXKEYS];
50 static uint32_t pPhyCfgNumEntries = 0;
51
52
53
54 //-------------------------------------------------------------------------------------------
55 /** @ingroup group_source_auxlib_cline
56  *
57  *  @param   void
58  *
59  *  @return  0 if AUX_SUCCESS
60  *
61  *  @description
62  *  Initialize Cline Interface
63  *
64 **/
65 //-------------------------------------------------------------------------------------------
66 int cline_init(void)
67 {
68     uint32_t i;
69     pPhyCfgNumEntries = 0;
70     for (i = 0; i < CLINE_MAXKEYS; i++)
71     {
72        PhyAppKeys[i].name = NULL;
73        PhyAppKeys[i].value = NULL;
74     }
75
76     return AUX_SUCCESS;
77 }
78
79
80
81 //-------------------------------------------------------------------------------------------
82 /** @ingroup group_source_auxlib_cline
83  *
84  *  @param[in]   *name String to search for
85  *  @param[out]  *value Pointer to location where number needs to be stored
86  *  @param[in]   deflt Default value to put into the value field if string is not found
87  *
88  *  @return  0 if AUX_SUCCESS
89  *
90  *  @description
91  *  This funtion searchs for a string from the phycfg.xml file and returns the number that
92  *  was associated in file
93  *
94 **/
95 //-------------------------------------------------------------------------------------------
96 uint32_t cline_set_int(const char *name, int *value, int deflt)
97 {
98     uint32_t i;
99
100     for (i = 0; i < pPhyCfgNumEntries; i++)
101     {
102         if (PhyAppKeys[i].name)
103         {
104             if (strcasecmp(name, PhyAppKeys[i].name) == 0)
105             {
106                 char *p1 = PhyAppKeys[i].value;
107                 if (strstr(p1, "0x") || strstr(p1, "0X"))
108                 {
109                     uint64_t core;
110                     if (cline_covert_hex_2_dec(p1, &core) != AUX_SUCCESS)
111                     {
112                         printf("cline_set_int Failed (%s)\n", p1);
113                         return AUX_FAILURE;
114                     }
115                     *value = (int)core;
116                 }
117                 else
118                 {
119                     *value = (int)strtol(PhyAppKeys[i].value, NULL, 0);
120                     if ((*value == 0 && errno == EINVAL) || (*value == INT_MAX && errno == ERANGE))
121                     {
122                         *value = deflt;
123                         return AUX_FAILURE;
124                     }
125                 }
126                 break;
127             }
128         }
129         else
130         {
131             // End of list reached
132             *value = deflt;
133             printf("incomming setting in XML: param \"%s\" is not found!\n", name);
134             return AUX_FAILURE;
135         }
136     }
137
138     return AUX_SUCCESS;
139 }
140
141
142
143
144
145 //-------------------------------------------------------------------------------------------
146 /** @ingroup group_source_auxlib_cline
147  *
148  *  @param[in]   *name String to search for
149  *  @param[out]  *value Pointer to location where number needs to be stored
150  *  @param[in]   deflt Default value to put into the value field if string is not found
151  *
152  *  @return  0 if AUX_SUCCESS
153  *
154  *  @description
155  *  This funtion searchs for a string from the phycfg.xml file and returns the number that
156  *  was associated in file
157  *
158 **/
159 //-------------------------------------------------------------------------------------------
160 uint32_t cline_set_uint64(const char *name, uint64_t *value, uint64_t deflt)
161 {
162     uint32_t i;
163
164     for (i = 0; i < pPhyCfgNumEntries; i++)
165     {
166         if (PhyAppKeys[i].name)
167         {
168             if (strcasecmp(name, PhyAppKeys[i].name) == 0)
169             {
170                 if (strstr(PhyAppKeys[i].value, "0x") || strstr(PhyAppKeys[i].value, "0X"))
171                 {
172                     if (cline_covert_hex_2_dec(PhyAppKeys[i].value, value) != AUX_SUCCESS)
173                     {
174                         printf("cline_covert_hex_2_dec Failed (%s)\n", PhyAppKeys[i].value);
175                         return AUX_FAILURE;
176                     }
177                 }
178                 else
179                 {
180                     *value = strtoull(PhyAppKeys[i].value, NULL, 0);
181                 }
182                 if ((*value == 0 && errno == EINVAL) || (*value == LONG_MAX && errno == ERANGE))
183                 {
184                     *value = deflt;
185                     return AUX_FAILURE;
186                 }
187                 break;
188             }
189         }
190         else
191         {
192             // End of list reached
193             *value = deflt;
194             printf("incomming setting in XML: param \"%s\" is not found!\n", name);
195             return AUX_FAILURE;
196         }
197     }
198
199     return AUX_SUCCESS;
200 }
201
202
203 //-------------------------------------------------------------------------------------------
204 /** @ingroup group_source_auxlib_cline
205  *
206  *  @param[in]   *pStr String to search for
207  *  @param[out]  *pDst Pointer to location where number needs to be stored
208  *
209  *  @return  0 if AUX_SUCCESS
210  *
211  *  @description
212  *  This funtion takes a char string as input and converts it to a unit61_t
213  *
214 **/
215 //-------------------------------------------------------------------------------------------
216 uint32_t cline_covert_hex_2_dec(char *pStr, uint64_t *pDst)
217 {
218     char nibble;
219     int32_t i;
220     uint32_t len;
221     uint64_t value = 0, mult = 1, nibble_val = 0;
222
223     // Skip over "0x"
224     pStr += 2;
225
226     len = strlen(pStr);
227     if (len > 16)
228     {
229         printf("String Length is invalid: %p [%d]\n", pStr, len);
230     }
231
232     for (i = len - 1; i >= 0; i--)
233     {
234         nibble = pStr[i];
235         if ((nibble >= '0') && (nibble <= '9'))
236         {
237             nibble_val = nibble - '0';
238         }
239         else if ((nibble >= 'A') && (nibble <= 'F'))
240         {
241             nibble_val = nibble - 'A' + 10;
242         }
243         else if ((nibble >= 'a') && (nibble <= 'f'))
244         {
245             nibble_val = nibble - 'a' + 10;
246         }
247         else
248         {
249             printf("String is invalid: %p[%d] %c\n", pStr, i, nibble);
250             return AUX_FAILURE;
251         }
252
253         value += (nibble_val * mult);
254
255         mult = mult * 16;
256     }
257
258     *pDst = value;
259
260     return AUX_SUCCESS;
261 }
262
263
264 //-------------------------------------------------------------------------------------------
265 /** @ingroup group_source_auxlib_cline
266  *
267  *  @param[in]   *name String to search for
268  *  @param[out]  *core Pointer to location where core id needs to be stored
269  *  @param[out]  *priority Pointer to location where priority needs to be stored
270  *  @param[out]  *policy Pointer to location where policy needs to be stored
271  *
272  *  @return  0 if AUX_SUCCESS
273  *
274  *  @description
275  *  This funtion searchs for a string from the phycfg.xml file stores all thread related info into
276  *  output locations
277  *
278 **/
279 //-------------------------------------------------------------------------------------------
280 uint32_t cline_set_thread_info(const char *name, uint64_t *core, int *priority, int *policy)
281 {
282 #ifndef TEST_APP
283     uint32_t i;
284     int sched;
285     char *p1, *p2, *p3;
286
287     for (i = 0; i < pPhyCfgNumEntries; i++)
288     {
289         if (PhyAppKeys[i].name)
290         {
291             if (strcasecmp(name, PhyAppKeys[i].name) == 0)
292             {
293                 p1 = (char*)PhyAppKeys[i].value;
294                 p2 = strstr(p1, ",");
295                 if (p2)
296                 {
297                     *p2 = '\0';
298                     p2++;
299                     p3 = strstr(p2, ",");
300                     if (p3)
301                     {
302                         *p3 = '\0';
303                         p3++;
304
305                         if (strstr(p1, "0x") || strstr(p1, "0X"))
306                         {
307                             if (cline_covert_hex_2_dec(p1, core) != AUX_SUCCESS)
308                             {
309                                 printf("cline_covert_hex_2_dec Failed (%s)\n", p1);
310                                 return AUX_FAILURE;
311                             }
312                         }
313                         else
314                         {
315                             *core = strtoull(p1, NULL, 0);
316                         }
317                         *priority = strtol(p2, NULL, 0);
318                         sched = strtol(p3, NULL, 0);
319
320                         *policy = (sched ? SCHED_RR : SCHED_FIFO);
321
322                         //print_info_log("%s %ld %d %d\n", name, *core, *priority, *policy);
323
324                         return AUX_SUCCESS;
325                     }
326                     else
327                     {
328                         printf("p3 is null %s\n", p2);
329                     }
330                 }
331                 else
332                 {
333                     printf("p2 is null %s\n", p1);
334                 }
335
336                 printf("%s FAIL1\n", name);
337                 return AUX_FAILURE;
338             }
339         }
340         else
341         {
342             // End of list reached
343             printf("incomming setting in XML: param \"%s\" is not found!\n", name);
344
345             printf("cline_set_thread_info: %s FAIL2\n", name);
346             return AUX_FAILURE;
347         }
348     }
349
350     printf("cline_set_thread_info: %s FAIL3\n", name);
351     return AUX_FAILURE;
352 #else
353     return AUX_SUCCESS;
354 #endif
355 }
356
357 //-------------------------------------------------------------------------------------------
358 /** @ingroup group_source_auxlib_cline
359  *
360  *  @param[in]   *name String to search for
361  *  @param[in]   maxLen Max lenth of output array
362  *  @param[out]  *dataOut Pointer to the data array filled by each int element of the input string
363  *  @param[out]  *outLen Filled length of the array
364  *
365  *  @return  0 if AUX_SUCCESS
366  *
367  *  @description
368  *  This funtion searchs for a string from the phycfg.xml file stores all int value to output array
369  *
370 **/
371 //-------------------------------------------------------------------------------------------
372 uint32_t cline_set_int_array(const char *name, int maxLen, int *dataOut, int *outLen)
373 {
374     uint32_t i;
375     char *p1, *p2;
376     *outLen = 0;
377
378     for (i = 0; i < pPhyCfgNumEntries; i++)
379     {
380         if (PhyAppKeys[i].name)
381         {
382             if (strcasecmp(name, PhyAppKeys[i].name) == 0)
383             {
384                 p1 = (char*)PhyAppKeys[i].value;
385                 while(*outLen < maxLen)
386                 {
387                     p2 = strstr(p1, ",");
388                     if(p2)
389                     {
390                         *p2 = '\0';
391                         p2 ++;
392                         dataOut[*outLen] = strtol(p1, NULL, 0);
393                         //printf("\ngranularity %d in idx %d",dataOut[*outLen],*outLen);
394                         p1 = p2;
395                         *outLen += 1;
396                     }
397                     else
398                     {
399                         dataOut[*outLen] = strtol(p1, NULL, 0);
400                         //printf("\ngranularity %d in idx %d",dataOut[*outLen],*outLen);
401                         *outLen += 1;
402                         break;
403                     }
404                 }
405                 return AUX_SUCCESS;
406             }
407         }
408     }
409
410     //printf("cline_set_int_array: Could not find %s\n", name);
411
412     return AUX_SUCCESS;
413 }
414
415
416
417 //-------------------------------------------------------------------------------------------
418 /** @ingroup group_source_auxlib_cline
419  *
420  *  @param[in]   *name String to search for
421  *  @param[out]  *value Pointer to location where string needs to be stored
422  *  @param[in]   deflt Default value to put into the value field if string is not found
423  *
424  *  @return  0 if AUX_SUCCESS
425  *
426  *  @description
427  *  This funtion searchs for a string from the phycfg.xml file and returns the string that
428  *  was associated in file
429  *
430 **/
431 //-------------------------------------------------------------------------------------------
432 uint32_t cline_set_str(const char *name, char *value, const char *deflt)
433 {
434     uint32_t i;
435
436     for (i = 0; i < CLINE_MAXKEYS; i++)
437     {
438         if (PhyAppKeys[i].name)
439         {
440             if (strcasecmp(name, PhyAppKeys[i].name) == 0)
441             {
442                 strcpy(value, PhyAppKeys[i].value);
443                 break;
444             }
445         }
446         else
447         {
448             // End of list reached
449             strcpy(value, deflt);
450             return AUX_FAILURE;
451         }
452     }
453
454     return AUX_SUCCESS;
455 }
456
457
458
459
460 //-------------------------------------------------------------------------------------------
461 /** @ingroup group_source_auxlib_cline
462  *
463  *  @param[in]   *pString Pointer to string that needs to be parsed
464  *
465  *  @return  0 if AUX_SUCCESS
466  *
467  *  @description
468  *  This function takes a line from phycfg.xml and parses it and if valid fields are found,
469  *  stores the xml tag and the value associated with the tag into a global structure.
470  *
471 **/
472 //-------------------------------------------------------------------------------------------
473 int cline_parse_line(char *pString)
474 {
475     char *stringLocal, *ptr1, *ptr2, *ptr3;
476 //    char stringName[CLINE_MAX_STRING_LENGTH] = "", stringValue[CLINE_MAX_STRING_LENGTH] = "";
477     char *stringName, *stringValue;
478
479     stringLocal = NULL;
480     stringName = NULL;
481     stringValue = NULL;
482     ptr1 = ptr2 = ptr3 = NULL;
483     uint32_t strLen = strlen(pString);
484     if (strLen)
485     {
486         stringLocal = (char *)malloc(strLen + 1);
487         if (stringLocal == NULL)
488         {
489             printf("Cannot allocate stringLocal of size %d\n", (strLen + 1));
490             return AUX_FAILURE;
491         }
492     }
493
494     // Dont Destroy Original String
495     if (stringLocal)
496         strcpy(stringLocal, pString);
497
498     if (stringLocal)
499     {
500         if (strlen(stringLocal) <= 2)           // Probably line feed
501         {
502             if (stringLocal)
503                 free(stringLocal);
504             return AUX_SUCCESS;
505         }
506     }
507     ptr1 = stringLocal;
508
509     // Locate Starting
510     if (ptr1)
511         ptr2 = strstr(ptr1, "<");
512     if (ptr2 == NULL)
513     {
514         if (stringLocal)
515             free(stringLocal);
516         printf("no begin at parameters string");
517         return AUX_FAILURE;
518     }
519
520     // See if this is a comment
521     if (ptr2)
522         ptr3 = strstr(ptr2, "!--");
523     if (ptr3 != NULL)
524     {
525         if (stringLocal)
526             free(stringLocal);
527         return AUX_SUCCESS;
528     }
529
530     // Locate Ending
531     if (ptr2)
532         ptr3 = strstr(ptr2, ">");
533     if (ptr3 == NULL)
534     {
535         if (stringLocal)
536             free(stringLocal);
537         printf("no ending at parameters string");
538         return AUX_FAILURE;
539     }
540
541     // Copy string
542     if (ptr3)
543         *ptr3 = '\0';
544     if (ptr2)
545         strLen = strlen(ptr2 + 1);
546     if (strLen)
547     {
548         stringName = (char *)malloc(strLen + 1);
549         if (stringName == NULL)
550         {
551             if (stringLocal)
552                 free(stringLocal);
553             printf("Cannot allocate stringName of size %d\n", (strLen + 1));
554             return AUX_FAILURE;
555         }
556         else
557         {
558             if (ptr2)
559                 strcpy(stringName, ptr2 + 1);
560         }
561     }
562
563     ptr1 = ptr3+1;
564
565     // Locate Starting
566     if (ptr1)
567         ptr2 = strstr(ptr1, "<");
568     if (ptr2 != NULL)
569     {
570         // Locate Ending
571         if (ptr2)
572             ptr3 = strstr(ptr2, ">");
573         if (ptr3 == NULL)
574         {
575             if (stringName)
576                 free(stringName);
577             if (stringLocal)
578                 free(stringLocal);
579             printf("no ending at parameters string");
580             return AUX_FAILURE;
581         }
582
583         // Copy string
584         strLen = 0;
585         if (ptr2)
586             *ptr2 = '\0';
587         if (ptr1)
588             strLen = strlen(ptr1);
589         if (strLen)
590         {
591             stringValue = (char *)malloc(strLen + 1);
592             if (stringValue == NULL)
593             {
594                 if (stringName)
595                     free(stringName);
596                 if (stringLocal)
597                     free(stringLocal);
598                 printf("Cannot allocate stringValue of size %d\n", (strLen + 1));
599                 return AUX_FAILURE;
600             }
601             if (ptr1)
602                 strcpy(stringValue, ptr1);
603         }
604
605 #ifdef WIN32
606         printf("Found String: %s with Value: %s\n", stringName, stringValue);
607 #endif
608         {
609             uint32_t len = 0;
610
611             if (stringName)
612             {
613                 len = strlen(stringName);
614                 if (len)
615                 {
616                     PhyAppKeys[pPhyCfgNumEntries].name = (char *) malloc(len+1);
617                     if (PhyAppKeys[pPhyCfgNumEntries].name == NULL)
618                     {
619                         if (stringName)
620                             free(stringName);
621                         if (stringLocal)
622                             free(stringLocal);
623                         if (stringValue)
624                             free(stringValue);
625                         printf("Cannot allocate PhyAppKeys[pPhyCfgNumEntries].name of size %d\n", (strLen + 1));
626                         return AUX_FAILURE;
627                     }
628                     if (stringName)
629                         strcpy(PhyAppKeys[pPhyCfgNumEntries].name, stringName);
630                 }
631             }
632
633             len = 0;
634             if (stringValue)
635             {
636                 len = strlen(stringValue);
637                 if (len)
638                 {
639                     PhyAppKeys[pPhyCfgNumEntries].value = (char *)malloc(len + 1);
640                     if (PhyAppKeys[pPhyCfgNumEntries].value == NULL)
641                     {
642                         if (stringName)
643                             free(stringName);
644                         if (stringLocal)
645                             free(stringLocal);
646                         if (stringValue)
647                             free(stringValue);
648                         printf("Cannot allocate PhyAppKeys[pPhyCfgNumEntries].value of size %d\n", (strLen + 1));
649                         return AUX_FAILURE;
650                     }
651                     if (stringValue)
652                         strcpy(PhyAppKeys[pPhyCfgNumEntries].value, stringValue);
653                 }
654             }
655         }
656         pPhyCfgNumEntries++;
657     }
658
659     if(stringLocal)
660         free(stringLocal);
661     if (stringName)
662         free(stringName);
663     if (stringValue)
664         free(stringValue);
665
666     return AUX_SUCCESS;
667 }
668
669
670
671 //-------------------------------------------------------------------------------------------
672 /** @ingroup group_source_auxlib_cline
673  *
674  *  @param   void
675  *
676  *  @return  void
677  *
678  *  @description
679  *  This function prints all the tags and values found in the phycfg.xml file after parsing
680  *
681 **/
682 //-------------------------------------------------------------------------------------------
683 void cline_print_info(void)
684 {
685 #ifndef TEST_APP
686     uint32_t i;
687
688     for (i = 0; i < pPhyCfgNumEntries; i++)
689     {
690         if (PhyAppKeys[i].name)
691         {
692             printf(" --%s=%s\n", PhyAppKeys[i].name, PhyAppKeys[i].value);
693         }
694     }
695     printf("\n");
696 #endif
697     return;
698 }
699
700
701
702 //-------------------------------------------------------------------------------------------
703 /** @ingroup group_source_auxlib_cline
704  *
705  *  @param[in]   argc Number of command line params
706  *  @param[in]   *argv[] Array of command line params
707  *  @param[in]   pString String to search for
708  *  @param[out]   *pDest Location where to store the payload
709  *
710  *  @return  0 if AUX_SUCCESS
711  *
712  *  @description
713  *  This function looks for a string passed in from the command line and returns the immediate
714  *  next parameter passed after this.
715  *
716 **/
717 //-------------------------------------------------------------------------------------------
718 uint32_t cline_get_string(int argc, char *argv[], char* pString, char *pDest)
719 {
720     uint32_t ret = AUX_FAILURE;
721     int i = 1, length = (int)strlen(pString);
722     char *filename = NULL;
723
724     //print_info_log("Searching for string: %s. Length of string: %d\n", pString, length);
725     while (i < argc)
726     {
727         if (strstr(argv[i], pString) != NULL)
728         {
729             filename = strstr(argv[i], pString);
730             filename += (length + 1);
731
732             //print_info_log("Found %s: Val = %s\n", pString, filename);
733             strcpy(pDest, filename);
734
735             ret = AUX_SUCCESS;
736             break;
737         }
738
739         i++;
740     }
741
742     return ret;
743 }