openbcm

Git mirror of https://github.com/Broadcom-Network-Switching-Software/OpenBCM
git clone git://git.finwo.net/mirror/broadcom/openbcm
Log | Files | Refs | README

bslsink.c (9570B)


      1 /*
      2  * 
      3  * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file.
      4  * 
      5  * Copyright 2007-2019 Broadcom Inc. All rights reserved.
      6  *
      7  * Broadcom System Log Sinks
      8  */
      9 
     10 #include <sal/core/libc.h> 
     11 #include <sal/core/time.h>
     12 #include <sal/core/thread.h>
     13 #include <sal/appl/io.h> 
     14 #include <shared/bsl.h>
     15 #include <shared/bslnames.h>
     16 #include <appl/diag/bslenable.h>
     17 #include <appl/diag/bslsink.h>
     18 
     19 /* List of output sinks */
     20 static bslsink_sink_t *bslsink_sinks = NULL;
     21 
     22 /* System start time */
     23 static sal_time_t init_time;
     24 
     25 /* Append string value to prefix */
     26 static int
     27 add_string(char *buf, int max, const char *str)
     28 {
     29     return sal_snprintf(buf, max, "%s", str);
     30 }
     31 
     32 /* Append decimal integer to prefix */
     33 static int
     34 add_dval(char *buf, int max, int dval)
     35 {
     36     return sal_snprintf(buf, max, "%d", dval);
     37 }
     38 
     39 /* Append unsigned decimal integer to prefix */
     40 static int
     41 add_uval(char *buf, int max, uint32 uval)
     42 {
     43     return sal_snprintf(buf, max, "%u", uval);
     44 }
     45 
     46 /* Append minutes/seconds to prefix */
     47 static int
     48 add_msval(char *buf, int max, int msval)
     49 {
     50     return sal_snprintf(buf, max, ":%02d", msval);
     51 }
     52 
     53 /* Append time stamp to prefix */
     54 static int
     55 add_timetamp(char *buf, int max)
     56 {
     57     int len = 0;
     58     sal_time_t now = sal_time() - init_time;
     59     unsigned long hrs, mins, secs;
     60 
     61     secs = now % 60;
     62     now = now / 60;
     63     mins = now % 60;
     64     hrs = now / 60;
     65 
     66     len += add_dval(&buf[len], max-len, hrs);
     67     len += add_msval(&buf[len], max-len, mins);
     68     len += add_msval(&buf[len], max-len, secs);
     69 
     70     return len;
     71 }
     72 
     73 /* Append micro second timestamp to prefix */
     74 static int
     75 add_hi_res_timestamp(char *buf, int max)
     76 {
     77     int len = 0;
     78     unsigned long time = (unsigned long)(sal_time_usecs());
     79 
     80     len += add_uval(buf, max, time);
     81 
     82     return len;
     83 }
     84 
     85 /* Append thread name to prefix */
     86 static int
     87 add_thread_name(char *buf, int max, const char *str)
     88 {
     89     char tname[SAL_THREAD_NAME_MAX_LEN], *name;
     90 
     91     name = sal_thread_name(sal_thread_self(), tname, SAL_THREAD_NAME_MAX_LEN);
     92 
     93     if (name == NULL) {
     94         name = "unknown thread";
     95     }
     96 
     97     return add_string(buf, max, name);
     98 }
     99 
    100 /*
    101  * Prefix formatting function
    102  *
    103  * Formats log prefix string based on meta data contents and
    104  * configuration string.
    105  *
    106  * The configuration string is similar to a printf format string,
    107  * except that is uses a different set of format specifiers.
    108  *
    109  *   %F - function name
    110  *   %f - file name
    111  *   %l - line number
    112  *   %u - unit number
    113  *   %p - port number
    114  *   %x - xtra parameter
    115  *   %L - layer of this log message source
    116  *   %S - source of this log message
    117  *   %s - severity level (string value) of this log message
    118  *   %t - time stamp (based seconds since system start)
    119  *   %T - high resolution timestamp (micro seconds)
    120  *   %P - process or thread name
    121  */
    122 static int
    123 format_prefix(char *buf, int max, const char *prefix_format,
    124               bsl_meta_t *meta, int path_offset)
    125 {
    126     int len = 0;
    127     const char *str = NULL;
    128     const char *cp = prefix_format;
    129 
    130     while (len < max) {
    131         if (*cp != '%') {
    132             buf[len++] = *cp;
    133             if (*cp == 0) {
    134                 return len;
    135             }
    136             cp++;
    137             continue;
    138         }
    139         cp++;
    140         switch (*cp) {
    141         case 'F':
    142             str = meta->func;
    143             if (str == NULL) {
    144                 str = "<nofunc>";
    145             }
    146             len += add_string(&buf[len], max-len, str);
    147             cp++;
    148             break;
    149         case 'f':
    150             str = "<nofile>";
    151             if (meta->file != NULL) {
    152                 str = &meta->file[path_offset];
    153             }
    154             len += add_string(&buf[len], max-len, str);
    155             cp++;
    156             break;
    157         case 'l':
    158             len += add_dval(&buf[len], max-len, meta->line);
    159             cp++;
    160             break;
    161         case 'u':
    162             if (meta->unit < 0) {
    163                 len += add_string(&buf[len], max-len, "<nounit>");
    164             } else {
    165                 len += add_dval(&buf[len], max-len, meta->unit);
    166             }
    167             cp++;
    168             break;
    169         case 'p':
    170             len += add_dval(&buf[len], max-len, meta->port);
    171             cp++;
    172             break;
    173         case 'x':
    174             len += add_dval(&buf[len], max-len, meta->xtra);
    175             cp++;
    176             break;
    177         case 'L':
    178             str = bsl_layer2str(meta->layer);
    179             len += add_string(&buf[len], max-len, str);
    180             cp++;
    181             break;
    182         case 'S':
    183             str = bsl_source2str(meta->source);
    184             len += add_string(&buf[len], max-len, str);
    185             cp++;
    186             break;
    187         case 's':
    188             str = bsl_severity2str(meta->severity);
    189             len += add_string(&buf[len], max-len, str);
    190             cp++;
    191             break;
    192         case 't':
    193             len += add_timetamp(&buf[len], max-len);
    194             cp++;
    195             break;
    196         case 'T':
    197             len += add_hi_res_timestamp(&buf[len], max-len);
    198             cp++;
    199             break;
    200         case 'P':
    201             len += add_thread_name(&buf[len], max-len, str);
    202             cp++;
    203             break;
    204         default:
    205             /* Bad format */
    206             return len;
    207         }
    208     }
    209     return len;
    210 }
    211 
    212 /*
    213  * Check that severity is within a specific range
    214  */
    215 static int
    216 severity_in_range(bslsink_severity_range_t *range, bsl_severity_t val)
    217 {
    218     if (range == NULL) {
    219         return 0;
    220     }
    221     return (val >= range->min && val <= range->max);
    222 }
    223 
    224 /*
    225  * Convenience function for printing prefix string
    226  */
    227 static int
    228 sink_printf(bslsink_sink_t *sink, const char *format, ...)
    229 {
    230     int rv;
    231     va_list args;
    232 
    233     va_start(args, format);  
    234     rv = sink->vfprintf(sink->file, format, args);
    235     va_end(args);
    236 
    237     return rv;
    238 }
    239 
    240 /*
    241  * Additional filtering based on meta data
    242  */
    243 int
    244 bslsink_out(bslsink_sink_t *sink, bsl_meta_t *meta,
    245             const char *format, va_list args)
    246 {
    247     int unit;
    248     bsl_severity_t sev = meta->severity;
    249     char buf[BSLSINK_PREFIX_MAX];
    250 
    251     if (sink->check && sink->check(meta) == 0) {
    252         return 0;
    253     }
    254     if (!severity_in_range(&sink->enable_range, sev)) {
    255         return 0;
    256     }
    257     if (meta->source == bslSourceEcho &&
    258         (sink->options & BSLSINK_OPT_NO_ECHO)) {
    259         return 0;
    260     }
    261     unit = meta->unit;
    262     if (unit == BSL_UNIT_UNKNOWN) {
    263         /* Map to pseudo-unit to allow proper filtering */
    264         unit = BSLSINK_UNIT_UNKNOWN;
    265     }
    266     if (unit >= 0 && unit < BSLSINK_MAX_NUM_UNITS) {
    267         if (SHR_BITGET(sink->units, unit) == 0) {
    268             return 0;
    269         }
    270     }
    271     if (meta->port >= 0 && meta->port < BSLSINK_MAX_NUM_PORTS) {
    272         if (SHR_BITGET(sink->ports, meta->port) == 0) {
    273             return 0;
    274         }
    275     }
    276     if (meta->xtra >= 0 && sink->xtra >= 0) {
    277         if (meta->xtra != sink->xtra) {
    278             return 0;
    279         }
    280     }
    281     if ((meta->source == bslSourceShell || meta->source == bslSourceEcho) &&
    282         (sink->options & BSLSINK_OPT_SHELL_PREFIX) == 0) {
    283         /* Skip prefix for shell output */
    284     } else if (severity_in_range(&sink->prefix_range, sev)) {
    285         if (meta->options & BSL_META_OPT_START) {
    286             format_prefix(buf, sizeof(buf)-1, sink->prefix_format,
    287                           meta, sink->path_offset);
    288             buf[sizeof(buf)-1] = 0;
    289             sink_printf(sink, buf);
    290             if (meta->options & BSL_META_OPT_PFX_NL) {
    291                 sink_printf(sink, "\n");
    292             }
    293         }
    294     }
    295     return sink->vfprintf(sink->file, format, args);
    296 }
    297 
    298 void
    299 bslsink_sink_t_init(bslsink_sink_t *sink)
    300 {
    301     sal_memset(sink, 0, sizeof(*sink));
    302     SHR_BITSET_RANGE(sink->units, 0, BSLSINK_MAX_NUM_UNITS);
    303     SHR_BITSET_RANGE(sink->ports, 0, BSLSINK_MAX_NUM_PORTS);
    304     sink->xtra = -1;
    305 #ifndef BSLSINK_FULL_FILE_PATH
    306     {
    307         char *ptr, *file = BSL_FILE;
    308 
    309         /* Calculate position of SDK root in BSL_FILE (__FILE__) */
    310         ptr = sal_strstr(file, "src/appl/diag/bslsink.c");
    311         if (ptr != NULL) {
    312             sink->path_offset = PTR_TO_UINTPTR(ptr) - PTR_TO_UINTPTR(file);
    313         }
    314     }
    315 #endif
    316 }
    317 
    318 int
    319 bslsink_sink_cleanup(bslsink_sink_t *sink)
    320 {
    321     if (sink->cleanup) {
    322         sink->cleanup(sink);
    323     }
    324     return 0;
    325 }
    326 
    327 int
    328 bslsink_sink_add(bslsink_sink_t *new_sink)
    329 {
    330     bslsink_sink_t *sink;
    331     int sink_id = 0;
    332 
    333     if (bslsink_sinks == NULL) {
    334         /* First sink */
    335         bslsink_sinks = new_sink;
    336         new_sink->sink_id = sink_id;
    337         return sink_id;
    338     }
    339     sink = bslsink_sinks;
    340     sink_id++;
    341     while (sink->next != NULL) {
    342         sink = sink->next;
    343         sink_id++;
    344     }
    345     sink->next = new_sink;
    346     new_sink->sink_id = sink_id;
    347     return sink_id;
    348 }
    349 
    350 bslsink_sink_t *
    351 bslsink_sink_find(const char *name)
    352 {
    353     bslsink_sink_t *sink = bslsink_sinks;
    354 
    355     if (name == NULL) {
    356         return NULL;
    357     }
    358 
    359     while (sink != NULL) {
    360         if (sal_strcmp(name, sink->name) == 0) {
    361             return sink;
    362         }
    363         sink = sink->next;
    364     }
    365     return NULL;
    366 }
    367 
    368 bslsink_sink_t *
    369 bslsink_sink_find_by_id(int sink_id)
    370 {
    371     bslsink_sink_t *sink = bslsink_sinks;
    372 
    373     while (sink != NULL) {
    374         if (sink->sink_id == sink_id) {
    375             return sink;
    376         }
    377         sink = sink->next;
    378     }
    379     return NULL;
    380 }
    381 
    382 int
    383 bslsink_cleanup(void)
    384 {
    385     bslsink_sink_t *sink = bslsink_sinks;
    386 
    387     while (sink != NULL) {
    388         bslsink_sink_cleanup(sink);
    389         sink = sink->next;
    390     }
    391     return 0;
    392 }
    393 
    394 int
    395 bslsink_init(void)
    396 {
    397     bslsink_sinks = NULL;
    398     init_time = sal_time();
    399 
    400     return 0;
    401 }