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

ftmon.c (16357B)


      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  * Diag CLI IPFIX command
      8  */
      9 
     10 #include <appl/diag/system.h>
     11 #include <appl/diag/parse.h>
     12 #include <shared/bsl.h>
     13 #include <soc/format.h>
     14 
     15 #include <bcm/error.h>
     16 #include <bcm/flowtracker.h>
     17 #include <bcm_int/esw/flowtracker.h>
     18 #include <bcm_int/esw/flowtracker/ft_export.h>
     19 
     20 char cmd_ftmon_usage[] =
     21     "Parameters: [report +/-<values>] [set <values>] [stop|start]\n"
     22 #ifndef COMPILER_STRING_CONST_LIMIT
     23     "\t  start  - Start the FT export fifo deamon\n"
     24     "\t  stop   - Stop the FT export fifo deamon\n"
     25     "\t  report - Configure reporting to the console\n"
     26     "\t      count   - print export entry # only\n"
     27     "\t      decode  - dump decoded export entry\n"
     28     "\t      Prepend + to set, - to clear\n"
     29 #endif
     30 ;
     31 
     32 static int ftmon_report_count[BCM_MAX_NUM_UNITS] = { 0 };
     33 static int ftmon_is_running[BCM_MAX_NUM_UNITS] = { 0 };
     34 static uint32 ftmon_report[BCM_MAX_NUM_UNITS] = { 0 };
     35 
     36 #ifdef BCM_FLOWTRACKER_SUPPORT
     37 extern int bcma_ft_ipfix_print_record(int unit,
     38                                       int set_c,
     39                                       int payload_length,
     40                                       uint8 *payload_data);
     41 #endif /* BCM_FLOWTRACKER_SUPPORT */
     42 
     43 typedef struct ft_cache_s {
     44     int record_count;
     45     bcm_collector_export_record_t record;
     46 } ft_cache_t;
     47 
     48 /* FT record reasons. */
     49 #define FT_RECORD_REASON_ALU16          0x1
     50 #define FT_RECORD_REASON_ALU32          0x2
     51 #define FT_RECORD_REASON_STATE_TRANS    0x4
     52 #define FT_RECORD_REASON_LEARN          0x8
     53 #define FT_RECORD_REASON_AGED           0x10
     54 #define FT_RECORD_REASON_FLUSH          0x20
     55 #define FT_RECORD_REASON_PERIODIC       0x40
     56 
     57 
     58 typedef struct ft_record_info_s {
     59     int ft_group;
     60     int ft_index;
     61     int key_len;
     62     int data_len;
     63     uint32 ft_reason;
     64     uint8 ft_key[64];
     65     uint8 ft_data[64];
     66 } ft_record_info_t;
     67 
     68 ft_cache_t *ft_record_cache[BCM_MAX_NUM_UNITS];
     69 
     70 #define REPORT_COUNT      0x01   /* Report export count */
     71 #define REPORT_DECODE     0x02   /* Report Decoded export data */
     72 #define REPORT_CACHE      0x04   /* Report Start Caching export data */
     73 #define REPORT_DUMP       0x08   /* Report Dump cached record data */
     74 
     75 #define REPORT_CACHE_ENABLED  0x10
     76 
     77 static const parse_pm_t ftmon_report_table[] = {
     78     {"Count",     REPORT_COUNT},
     79     {"Decode",    REPORT_DECODE},
     80     {"Cache",     REPORT_CACHE},
     81     {"Dump",      REPORT_DUMP},
     82     {"@ALL",      ~0},
     83     {"@*",        ~0},
     84     {NULL,        0}
     85 };
     86 
     87 
     88 #ifdef BCM_FLOWTRACKER_SUPPORT
     89 uint8    record_data_record[] = {
     90             0xe1,
     91             0xfe,
     92             0x00,
     93             0x80,
     94             0x01,
     95             0x94,
     96             0x00,
     97             0x19,
     98             0x00,
     99             0x08,
    100             0x00,
    101             0x00,
    102             0x00,
    103             0x00,
    104             0x00,
    105             0x00,
    106             0x00,
    107             0x00,
    108             0x00,
    109             0x00,
    110             0x00,
    111             0x00,
    112             0x00,
    113             0x00,
    114             0x00,
    115             0x00,
    116             0x00,
    117             0x00,
    118             0x00,
    119             0x00,
    120             0x00,
    121             0x00,
    122             0x00,
    123             0x00,
    124             0x00,
    125             0x00,
    126             0x00,
    127             0x00,
    128             0x00,
    129             0x00,
    130             0x00,
    131             0x00,
    132             0x00,
    133             0x00,
    134             0x00,
    135             0x00,
    136             0x00,
    137             0x00,
    138             0x00,
    139             0x00,
    140             0x06,
    141             0x42,
    142             0x72,
    143             0x6f,
    144             0x61,
    145             0x19,
    146             0x32,
    147             0x00,
    148             0x00,
    149             0x1a,
    150             0x32,
    151             0x00,
    152             0x00,
    153             0x02,
    154 
    155             0x00,
    156             0xc9,
    157             0xff,
    158             0xff,
    159             0xde,
    160             0x00,
    161             0x00,
    162             0x00,
    163             0x00,
    164             0x44,
    165             0x00,
    166             0x00,
    167             0x00,
    168             0x01,
    169             0x00,
    170             0x2a,
    171             0x00,
    172             0x00,
    173             0x00,
    174             0x2a,
    175             0xff,
    176             0xff,
    177             0x00,
    178             0x00,
    179             0x00,
    180             0x00,
    181             0x06,
    182             0x00,
    183             0x01,
    184             0x00,
    185             0x00,
    186             0x00,
    187             0x00,
    188             0x00,
    189             0x00,
    190             0x00,
    191             0x00,
    192             0x00,
    193             0x00,
    194             0x00,
    195             0x00,
    196             0x00,
    197             0x00,
    198             0x00,
    199             0x00,
    200             0x00,
    201             0x00,
    202             0x00,
    203             0x00,
    204             0x00,
    205             0x00,
    206             0x00,
    207             0x00,
    208             0x00,
    209             0x00,
    210             0x00,
    211             0x00,
    212             0x00,
    213             0x00,
    214             0x00,
    215             0x00,
    216             0x00,
    217             0x00,
    218             0x00,
    219     };
    220 
    221 
    222 
    223 
    224 STATIC void
    225 bcm_ftmon_export_entry_parse(int unit,
    226                              bcm_collector_export_record_t *record,
    227                              ft_record_info_t *record_info)
    228 {
    229     int ix, rec_words, fld_len;
    230     soc_field_t fld;
    231     soc_format_t fmt;
    232     uint32 fldbuf[32] = {0}, entbuf[32] = {0}, *record_p;
    233 
    234 
    235     rec_words = 128 / 4;
    236 
    237     record_p = (uint32 *)(&(record->data_record[0]));
    238     for (ix = 0; ix < (rec_words); ix++) {
    239 
    240         entbuf[rec_words - ix - 1] = record_p[ix];
    241     }
    242 
    243     fmt = BSC_EX_EXPORT_RECORDfmt;
    244 
    245     sal_memset(fldbuf, 0, 128);
    246     fld = GROUP_IDf;
    247     record_info->ft_group = soc_format_field32_get(unit, fmt, entbuf, fld);
    248 
    249     sal_memset(fldbuf, 0, 128);
    250     fld = FLOW_INDEXf;
    251     record_info->ft_index = soc_format_field32_get(unit, fmt, entbuf, fld);
    252 
    253     sal_memset(fldbuf, 0, 128);
    254     fld = EXPORT_REASONf;
    255     record_info->ft_reason = soc_format_field32_get(unit, fmt, entbuf, fld);
    256 
    257     sal_memset(fldbuf, 0, 128);
    258     fld = FLOW_KEYf;
    259     fld_len = soc_format_field_length(unit, fmt, fld);
    260     soc_format_field_get(unit, fmt, entbuf, fld, fldbuf);
    261     record_info->key_len = (fld_len / 8);
    262     sal_memcpy((record_info->ft_key), fldbuf, (fld_len / 8));
    263 
    264     sal_memset(fldbuf, 0, 128);
    265     fld = FLOW_DATAf;
    266     fld_len = soc_format_field_length(unit, fmt, fld);
    267     soc_format_field_get(unit, fmt, entbuf, fld, fldbuf);
    268     record_info->data_len = (fld_len / 8);
    269     sal_memcpy((record_info->ft_data), fldbuf, (fld_len / 8));
    270 
    271     return;
    272 }
    273 
    274 #define LINE_DEMARC cli_out("**************************************************\n")
    275 
    276 
    277 STATIC void
    278 bcm_ftmon_export_entry_dump(int unit,
    279                             int count,
    280                             bcm_collector_export_record_t *record,
    281                             ft_record_info_t *record_info)
    282 {
    283     int ix;
    284     uint8 *d, n;
    285 
    286     LINE_DEMARC;
    287 
    288     cli_out("FT Export Record: Flow Index:%d", record_info->ft_index);
    289     if (count > 0) {
    290         cli_out(" Num Exports:%d", count);
    291     }
    292     cli_out("\n");
    293 
    294     cli_out("Group Id:%d Flow Reasons:%d", record_info->ft_group, record_info->ft_reason);
    295     cli_out("\n");
    296 
    297     cli_out("Key:\n");
    298     n = record_info->key_len;
    299     d = &(record_info->ft_key[0]);
    300 
    301     for (ix = 0; ix < n; ix++) {
    302 
    303         if (ix == 0)
    304             cli_out("0x");
    305 
    306         cli_out("%02x", d[ix]);
    307 
    308         if (ix == (n - 1))
    309             cli_out("\n");
    310     }
    311 
    312 
    313     cli_out("Data:\n");
    314     n = record_info->data_len;
    315     d = &(record_info->ft_data[0]);
    316 
    317     for (ix = 0; ix < n; ix++) {
    318 
    319         if (ix == 0)
    320             cli_out("0x");
    321 
    322         cli_out("%02x", d[ix]);
    323 
    324         if (ix == (n - 1))
    325             cli_out("\n");
    326     }
    327 
    328 
    329     LINE_DEMARC;
    330 
    331     return;
    332 }
    333 
    334 int
    335 bcm_ftmon_record_parse_test(int unit)
    336 {
    337     bcm_collector_export_record_t record;
    338     ft_record_info_t record_info;
    339 
    340     sal_memcpy(record.data_record,record_data_record, 128);
    341     bcm_ftmon_export_entry_parse(unit, &record, &record_info);
    342 
    343     return 0;
    344 }
    345 
    346 
    347 
    348 bcm_collector_export_record_handle_t
    349 ftmon_callback(int unit,
    350                bcm_collector_t collector_id,
    351                bcm_collector_export_record_t *record,
    352                void *userdata)
    353 {
    354     int handled = 0;
    355     ft_record_info_t record_info;
    356 
    357 
    358     /* Increment the global record count.  */
    359     ftmon_report_count[unit]++;
    360 
    361     /* If Caching is disabled, print count for each record.*/
    362     if ((ftmon_report[unit] & REPORT_COUNT) &&
    363         !(ftmon_report[unit] & REPORT_CACHE_ENABLED)) {
    364         cli_out("Export entry #%d.\n", ftmon_report_count[unit]);
    365         handled = 1;
    366     }
    367 
    368     /* If Caching is enabled, dump each record.*/
    369     if ((ftmon_report[unit] & REPORT_DUMP) &&
    370         !(ftmon_report[unit] & REPORT_CACHE_ENABLED)) {
    371 
    372         sal_memset(&(record_info), 0, sizeof(record_info));
    373         bcm_ftmon_export_entry_parse(unit, record, &record_info);
    374 
    375         bcm_ftmon_export_entry_dump(unit, 0, record, &record_info);
    376         handled = 1;
    377     }
    378 
    379     /* Decode record.*/
    380     if ((ftmon_report[unit] & REPORT_DECODE) &&
    381         !(ftmon_report[unit] & REPORT_CACHE_ENABLED)) {
    382 
    383         if (bcma_ft_ipfix_print_record(unit, 0, record->size, record->data_record)) {
    384             cli_out("ipfix parsing failed\n");
    385         }
    386         handled = 1;
    387     }
    388 
    389 
    390 
    391     /* If cache is enabled, cache the record.*/
    392     if(ftmon_report[unit] & REPORT_CACHE_ENABLED) {
    393         sal_memset(&(record_info), 0, sizeof(record_info));
    394         bcm_ftmon_export_entry_parse(unit, record, &record_info);
    395 
    396         ft_record_cache[unit][record_info.ft_index].record_count += 1;
    397         sal_memcpy(&(ft_record_cache[unit][record_info.ft_index].record),
    398                      record, sizeof(bcm_collector_export_record_t));
    399 
    400         handled = 1;
    401     }
    402 
    403     if (handled == 0) {
    404         return BCM_FLOWTRACKER_EXPORT_RECORD_NOT_HANDLED;
    405     } else {
    406         return BCM_FLOWTRACKER_EXPORT_RECORD_HANDLED_OWNED;
    407     }
    408 }
    409 
    410 
    411 STATIC int
    412 ftmon_cache_alloc(int unit, int enable)
    413 {
    414     int max_flows;
    415 
    416     /* Max flows is size of single wide key table. */
    417     max_flows = soc_mem_index_count(unit, FT_KEY_SINGLEm);
    418 
    419     if (enable) {
    420         ft_record_cache[unit] = sal_alloc((sizeof(ft_cache_t) * max_flows),
    421                                           "FT records Cache");
    422         sal_memset(ft_record_cache[unit], 0, (sizeof(ft_cache_t) * max_flows));
    423         if (ft_record_cache[unit] == NULL) {
    424             return -1;
    425         }
    426     } else {
    427         sal_free(ft_record_cache[unit]);
    428         ft_record_cache[unit] = NULL;
    429     }
    430 
    431     return 0;
    432 }
    433 #endif /* BCM_FLOWTRACKER_SUPPORT */
    434 
    435 
    436 cmd_result_t
    437 cmd_ftmon(int unit, args_t *arg)
    438 {
    439     int rv;
    440     char *subcmd;
    441 #ifdef BCM_FLOWTRACKER_SUPPORT
    442     bcm_collector_t collector_id;
    443     bcm_collector_callback_options_t callback_options;
    444 #endif /* BCM_FLOWTRACKER_SUPPORT */
    445 
    446     if (!soc_feature(unit, soc_feature_bscan_ft_fifodma_support)) {
    447         return (CMD_NFND);
    448     }
    449 
    450     if (!ARG_CNT(arg)) {                  /* Nothing passed */
    451         cli_out("IPFIX Deamon Status: %s.\n",
    452                 (ftmon_is_running[unit]) ? "Running" : "Not Running");
    453 
    454         cli_out("Reporting is enabled for: ");
    455         parse_mask_format(80, ftmon_report_table, ftmon_report[unit]);
    456         cli_out("Reporting is disabled for: ");
    457         parse_mask_format(80, ftmon_report_table, ftmon_report[unit] ^ ~0);
    458 
    459         cli_out("Number of records received: %d\n", ftmon_report_count[unit]);
    460         return(CMD_OK);
    461     }
    462 
    463     subcmd = ARG_GET(arg);
    464     if (subcmd == NULL) {
    465         return CMD_USAGE;
    466     }
    467 
    468     rv = BCM_E_NONE;
    469 
    470 #ifdef BCM_FLOWTRACKER_SUPPORT
    471     callback_options.callback_prio = 0;
    472     if (!sal_strcasecmp(subcmd, "start")) {
    473         if (ftmon_is_running[unit]) {
    474             cli_out("%s: FTMON thread already running.\n", ARG_CMD(arg));
    475             return CMD_OK;
    476         }
    477         ftmon_report_count[unit] = 0;
    478         ftmon_is_running[unit] = 1;
    479         rv = bcma_ft_export_fifo_control(unit, 1000000);
    480         if (rv < 0) {
    481             cli_out("%s: ERROR: %s\n", ARG_CMD(arg), bcm_errmsg(rv));
    482             return CMD_FAIL;
    483         }
    484 
    485         rv = bcma_ft_export_dma_collector_get(unit, &collector_id);
    486         if (BCM_FAILURE(rv)) {
    487             return CMD_FAIL;
    488         }
    489 
    490         rv = bcm_collector_export_record_register(unit, collector_id,
    491                                                     callback_options,
    492                                                     ftmon_callback, NULL);
    493     } else if (!sal_strcasecmp(subcmd, "stop")) {
    494         if (!ftmon_is_running[unit]) {
    495             cli_out("%s: ERROR: FTMON thread already stopped.\n", ARG_CMD(arg));
    496             return CMD_FAIL;
    497         }
    498         rv = bcma_ft_export_fifo_control(unit, 0);
    499         if (rv < 0) {
    500             cli_out("%s: ERROR: %s\n", ARG_CMD(arg), bcm_errmsg(rv));
    501             return CMD_FAIL;
    502         }
    503         ftmon_is_running[unit] = 0;
    504 
    505         rv = bcma_ft_export_dma_collector_get(unit, &collector_id);
    506         if (BCM_FAILURE(rv)) {
    507             return CMD_FAIL;
    508         }
    509 
    510         rv = bcm_collector_export_record_unregister(unit, collector_id,
    511                                                       callback_options,
    512                                                       ftmon_callback);
    513 
    514     } else if (!sal_strcasecmp(subcmd, "report")) {
    515         if (ARG_CNT(arg)) {
    516             while ((subcmd = ARG_CUR(arg)) != NULL &&
    517                    !parse_mask(subcmd, ftmon_report_table, &ftmon_report[unit])) {
    518                 ARG_NEXT(arg);        /* Bump arg if matched report */
    519             }
    520 
    521             /* Enable caching. */
    522             if ((ftmon_report[unit] & REPORT_CACHE) &&
    523                 !(ftmon_report[unit] & REPORT_CACHE_ENABLED)) {
    524                 if (ftmon_cache_alloc(unit, TRUE) != 0) {
    525                     return CMD_FAIL;
    526                 }
    527                 ftmon_report[unit] |= REPORT_CACHE_ENABLED;
    528             }
    529 
    530             /* Disable caching. */
    531             if (!(ftmon_report[unit] & REPORT_CACHE) &&
    532                 (ftmon_report[unit] & REPORT_CACHE_ENABLED)) {
    533                 if (ftmon_cache_alloc(unit, FALSE) != 0) {
    534                     return CMD_FAIL;
    535                 }
    536                 ftmon_report[unit] &= ~REPORT_CACHE_ENABLED;
    537             }
    538 
    539             /* Dump cached entries. */
    540             if ((ftmon_report[unit] & REPORT_DUMP) &&
    541                 (ftmon_report[unit] & REPORT_CACHE_ENABLED)) {
    542                 int ix;
    543                 int max_flows;
    544                 ft_record_info_t record_info;
    545 
    546                 /* Max flows is size of single wide key table. */
    547                 max_flows = soc_mem_index_count(unit, FT_KEY_SINGLEm);
    548 
    549                 for (ix = 0; ix < max_flows; ix++) {
    550                     if ((ft_record_cache[unit][ix].record_count) > 0) {
    551                         bcm_ftmon_export_entry_parse(unit, &(ft_record_cache[unit][ix].record), &record_info);
    552                         bcm_ftmon_export_entry_dump(unit, ft_record_cache[unit][ix].record_count, &(ft_record_cache[unit][ix].record), &record_info);
    553                     }
    554                 }
    555             }
    556 
    557         } else {                    /* Print values */
    558             cli_out("FTMON Reporting on for: ");
    559             parse_mask_format(50, ftmon_report_table, ftmon_report[unit]);
    560             cli_out("FTMON Reporting off for: ");
    561             parse_mask_format(50, ftmon_report_table, ~ftmon_report[unit]);
    562         }
    563     } else if (!sal_strcasecmp(subcmd, "dump")) {
    564             /* Dump cached entries. */
    565             if ((ftmon_report[unit] & REPORT_CACHE_ENABLED)) {
    566                 int ix;
    567                 int max_flows;
    568                 ft_record_info_t record_info;
    569 
    570                 /* Max flows is size of single wide key table. */
    571                 max_flows = soc_mem_index_count(unit, FT_KEY_SINGLEm);
    572 
    573                 for (ix = 0; ix < max_flows; ix++) {
    574                     if ((ft_record_cache[unit][ix].record_count) > 0) {
    575                         bcm_ftmon_export_entry_parse(unit, &(ft_record_cache[unit][ix].record), &record_info);
    576                         bcm_ftmon_export_entry_dump(unit, ft_record_cache[unit][ix].record_count, &(ft_record_cache[unit][ix].record), &record_info);
    577                     }
    578                 }
    579             }
    580 
    581 
    582     } else {
    583         return CMD_USAGE;
    584     }
    585 #endif /* BCM_FLOWTRACKER_SUPPORT */
    586 
    587     if (rv < 0) {
    588         cli_out("%s: ERROR: %s\n", ARG_CMD(arg), bcm_errmsg(rv));
    589         return CMD_FAIL;
    590     }
    591 
    592     return CMD_OK;
    593 }