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

rxmon.c (12818B)


      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  * File:        rxmon.c
      8  * Purpose:     Implementation of rxmon command
      9  * Requires:    
     10  */
     11 
     12 #include <shared/bsl.h>
     13 
     14 #include <sal/core/thread.h>
     15 #include <soc/types.h>
     16 #include <soc/higig.h>
     17 #include <soc/dma.h>
     18 #include <soc/dcb.h>
     19 #include <soc/drv.h>
     20 
     21 #ifdef __KERNEL__
     22 #include <linux/kernel.h>
     23 #include <linux/net.h>
     24 #include <linux/in.h>
     25 #else
     26 #include <stdlib.h>
     27 #include <sys/types.h>
     28 #include <sys/socket.h>
     29 #include <netinet/in.h>
     30 #endif
     31 
     32 #include <bcm/pkt.h>
     33 #include <bcm/rx.h>
     34 #include <bcm/error.h>
     35 
     36 #include <appl/diag/system.h>
     37 
     38 /* Default data for configuring RX system */
     39 static bcm_rx_cfg_t rx_cfg = {
     40     8 * 1024, /* packet alloc size */
     41     4,        /* Packets per chain */
     42     1000,     /* Default pkt rate, global (all COS for this device) */
     43     100,      /* Burst doesn't matter */
     44     {  /* Just configure channel 1 */
     45         {0},  /* Channel 0 is usually TX */
     46         {    /* Channel 1, default RX */
     47             4,                     /* DV count (number of chains) */
     48             1000,                  /* Default pkt rate */
     49             0,                     /* No flags */
     50             0xff                   /* All COS to this channel */
     51         }
     52     },
     53     NULL,     /* Used default RX alloc and free routines */
     54     NULL,
     55     0        /* flags */
     56 };
     57 
     58 static bcm_rx_chan_cfg_t rx_chan_cfg = {
     59     4,                     /* DV count (number of chains) */
     60     1000,                  /* Default pkt rate */
     61     0,                     /* No flags */
     62     0xff                   /* All COS to this channel */
     63 };
     64 
     65 static int rx_cb_count;
     66 
     67 /* Packet free queue; use first word of data buffer as next ptr */
     68 static sal_mutex_t pkt_queue_lock[BCM_MAX_NUM_UNITS];
     69 static sal_sem_t pkts_are_ready[BCM_MAX_NUM_UNITS];
     70 static volatile uint32 *pkt_free_queue[BCM_MAX_NUM_UNITS];
     71 static volatile int enqueue_pkts[BCM_MAX_NUM_UNITS];
     72 static volatile int rx_pkt_count[BCM_MAX_NUM_UNITS];
     73 
     74 STATIC bcm_rx_t
     75 rx_cb_handler(int unit, bcm_pkt_t *info, void *cookie)
     76 {
     77     int		count;
     78 
     79     COMPILER_REFERENCE(cookie);
     80 
     81     count = ++rx_cb_count;
     82 
     83     LOG_INFO(BSL_LS_APPL_RX,
     84              (BSL_META_U(unit,
     85                          "RX packet %d: unit=%d len=%d rx_port=%d reason=%d cos=%d\n"),
     86               count, unit, info->tot_len, info->rx_port, info->rx_reason,
     87               info->cos));
     88 
     89 #ifdef	BCM_XGS_SUPPORT
     90     if (SOC_IS_XGS12_FABRIC(unit)) {
     91         if (LOG_CHECK(BSL_LS_APPL_RX | BSL_INFO)) {
     92             soc_higig_dump(unit, "HG HEADER: ",
     93                            (soc_higig_hdr_t *)BCM_PKT_HG_HDR(info));
     94         }
     95     }
     96 #endif	/* BCM_XGS_SUPPORT */
     97 
     98     LOG_INFO(BSL_LS_APPL_RX,
     99              (BSL_META_U(unit,
    100                          "Parsed packet info:\n")));
    101     LOG_INFO(BSL_LS_APPL_RX,
    102              (BSL_META_U(unit,
    103                          "    src mod=%d. src port=%d. op=%d.\n"),
    104               info->src_mod, info->src_port, info->opcode));
    105     LOG_INFO(BSL_LS_APPL_RX,
    106              (BSL_META_U(unit,
    107                          "    dest mod=%d. dest port=%d. chan=%d.\n"),
    108               info->dest_mod, info->dest_port, info->dma_channel));
    109 
    110     if (LOG_CHECK(BSL_LS_APPL_RX | BSL_INFO)) {
    111         soc_dma_dump_pkt(unit, "Data: ", BCM_PKT_DMAC(info),
    112 			 info->tot_len, TRUE);
    113     }
    114 
    115     if (enqueue_pkts[unit] > 0) {
    116         sal_mutex_take(pkt_queue_lock[unit], sal_mutex_FOREVER);
    117         *(uint32 **)(info->alloc_ptr) = (uint32 *)pkt_free_queue[unit];
    118         pkt_free_queue[unit] = info->alloc_ptr;
    119         rx_pkt_count[unit]++;
    120         if (rx_pkt_count[unit] >= enqueue_pkts[unit]) {
    121             sal_sem_give(pkts_are_ready[unit]);
    122         }
    123         sal_mutex_give(pkt_queue_lock[unit]);
    124 #if defined(BCM_RXP_DEBUG)
    125         bcm_rx_pool_own(info->alloc_ptr, "rxmon");
    126 #endif
    127         return BCM_RX_HANDLED_OWNED;
    128     }
    129 
    130     return BCM_RX_HANDLED;
    131 }
    132 
    133 STATIC void
    134 rx_free_pkts(void *cookie)
    135 {
    136     uint32 *to_free;
    137     uint32 *next;
    138     int unit = PTR_TO_INT(cookie);
    139 
    140     while (TRUE) {
    141         sal_sem_take(pkts_are_ready[unit], sal_sem_FOREVER);
    142         sal_mutex_take(pkt_queue_lock[unit], sal_mutex_FOREVER);
    143         to_free = (uint32 *)pkt_free_queue[unit];
    144         pkt_free_queue[unit] = NULL;
    145         rx_pkt_count[unit] = 0;
    146         sal_mutex_give(pkt_queue_lock[unit]);
    147         while (to_free != NULL) {
    148             next = *(uint32 **)to_free;
    149             bcm_rx_free(unit, to_free);
    150             to_free = next;
    151         }
    152     }
    153 }
    154 
    155 #define BASIC_PRIO 100
    156 
    157 STATIC int
    158 _init_rx_api(int unit)
    159 {
    160     int r;
    161 
    162     if (bcm_rx_active(unit)) {
    163         cli_out("RX is already running\n");
    164         return -1;
    165     }
    166 
    167     if (pw_running(unit)) {
    168         cli_out("rxmon: Error: Cannot start RX with packetwatcher running\n");
    169         return -1;
    170     }
    171 
    172     if ((r = bcm_rx_start(unit, &rx_cfg)) < 0) {
    173         cli_out("rxmon: Error: Cannot start RX: %s.\n", bcm_errmsg(r));
    174         return -1;
    175     }
    176 
    177     return 0;
    178 }
    179 
    180 cmd_result_t
    181 cmd_esw_rx_mon(int unit, args_t *args)
    182 /*
    183  * Function:    rx
    184  * Purpose:     Perform simple RX test
    185  * Parameters:  unit - unit number
    186  *              args - arguments
    187  * Returns:     CMD_XX
    188  */
    189 {
    190     char                *c;
    191     uint32              active;
    192     int                 r;
    193     int rv = CMD_OK;
    194 
    195     if (!sh_check_attached(ARG_CMD(args), unit)) {
    196         return(CMD_FAIL);
    197     }
    198 
    199     bcm_rx_channels_running(unit, &active);
    200 
    201     c = ARG_GET(args);
    202     if (c == NULL) {
    203         cli_out("Active bitmap for RX is %x.\n", active);
    204         return CMD_OK;
    205     }
    206 
    207     if (sal_strcasecmp(c, "init") == 0) {
    208         if (_init_rx_api(unit) < 0) {
    209             return CMD_FAIL;
    210         } else {
    211             return CMD_OK;
    212         }
    213     } else if (sal_strcasecmp(c, "enqueue") == 0) {
    214         if (pkt_queue_lock[unit] == NULL) { /* Init free pkt stuff */
    215             pkt_queue_lock[unit] = sal_mutex_create("rxmon");
    216             pkts_are_ready[unit] = sal_sem_create("rxmon", sal_sem_BINARY, 0);
    217             if (sal_thread_create("rxmon", SAL_THREAD_STKSZ, 80, rx_free_pkts,
    218                                   INT_TO_PTR(unit)) == SAL_THREAD_ERROR) {
    219                 cli_out("FAILED to start rxmon packet free thread\n");
    220                 sal_mutex_destroy(pkt_queue_lock[unit]);
    221                 pkt_queue_lock[unit] = NULL;
    222                 sal_sem_destroy(pkts_are_ready[unit]);
    223                 pkts_are_ready[unit] = NULL;
    224                 return CMD_FAIL;
    225             }
    226         }
    227         enqueue_pkts[unit] = 1;
    228         if ((c = ARG_GET(args)) != NULL) {
    229             enqueue_pkts[unit] = strtoul(c, NULL, 0);
    230         }
    231     } else if (sal_strcasecmp(c, "-enqueue") == 0) {
    232         enqueue_pkts[unit] = 0;
    233     } else if (sal_strcasecmp(c, "start") == 0) {
    234         rx_cb_count = 0;
    235 
    236         if (!bcm_rx_active(unit)) { /* Try to initialize */
    237             if (_init_rx_api(unit) < 0) {
    238                 cli_out("Warning:  init failed.  Will attempt register\n");
    239             }
    240         }
    241 
    242         /* Register to accept all cos */
    243         if ((r = bcm_rx_register(unit, "RX CMD", rx_cb_handler,
    244                     BASIC_PRIO, NULL, BCM_RCO_F_ALL_COS)) < 0) {
    245             cli_out("%s: bcm_rx_register failed: %s\n",
    246                     ARG_CMD(args), bcm_errmsg(r));
    247             return CMD_FAIL;
    248         }
    249 
    250         cli_out("NOTE:  'debugmod diag rx' required for rxmon output\n");
    251 
    252     } else if (sal_strcasecmp(c, "stop") == 0) {
    253         if ((r = bcm_rx_stop(unit, &rx_cfg)) < 0) {
    254             cli_out("%s: Error: Cannot stop RX: %s.  Is it running?\n",
    255                     ARG_CMD(args), bcm_errmsg(r));
    256             return CMD_FAIL;
    257         }
    258         /* Unregister handler */
    259         if ((r = bcm_rx_unregister(unit, rx_cb_handler, BASIC_PRIO)) < 0) {
    260             cli_out("%s: bcm_rx_unregister failed: %s\n",
    261                     ARG_CMD(args), bcm_errmsg(r));
    262             return CMD_FAIL;
    263         }
    264 
    265     } else if (sal_strcasecmp(c, "show") == 0) {
    266 #ifdef	BROADCOM_DEBUG
    267         bcm_rx_show(unit);
    268 #else
    269 	cli_out("%s: ERROR: cannot show in non-BROADCOM_DEBUG compilation\n",
    270                 ARG_CMD(args));
    271 	return CMD_FAIL;
    272 #endif	/* BROADCOM_DEBUG */
    273     } else {
    274         return CMD_USAGE;
    275     }
    276 
    277     return rv;
    278 }
    279 
    280 static int free_buffers;
    281 
    282 cmd_result_t
    283 cmd_esw_rx_cfg(int unit, args_t *args)
    284 /*
    285  * Function:    rx
    286  * Purpose:     Perform simple RX test
    287  * Parameters:  unit - unit number
    288  *              args - arguments
    289  * Returns:     CMD_XX
    290  */
    291 {
    292     int chan;
    293     parse_table_t	pt;
    294     bcm_cos_queue_t queue_max;
    295     /* This isn't configurable per unit yet. */
    296     int cos_pps[BCM_RX_COS];
    297     char cospps_str[BCM_RX_COS][20];
    298     uint8 cos_pps_init = 0;
    299     int rv = BCM_E_NONE;
    300     int i;
    301     int system_pps = 0;
    302 
    303     if (!cos_pps_init) {
    304         for (i = 0; i < BCM_RX_COS; i++) {
    305             cos_pps[i] = 100;
    306         }
    307         cos_pps_init = 1;
    308     }
    309 
    310     if (!sh_check_attached(ARG_CMD(args), unit)) {
    311         return(CMD_FAIL);
    312     }
    313 
    314     if (BCM_FAILURE(bcm_rx_queue_max_get(unit, &queue_max))) {
    315         return (CMD_FAIL);
    316     }
    317 
    318     if (!ARG_CUR(args)) {
    319         int spps;
    320 
    321         /* Display current configuration */
    322         cli_out("Current RX configuration:\n");
    323         cli_out("    Pkt Size %d. Pkts/chain %d. All COS PPS %d. Burst %d\n",
    324                 rx_cfg.pkt_size, rx_cfg.pkts_per_chain,
    325                 rx_cfg.global_pps, rx_cfg.max_burst);
    326         for (chan = 0; chan < BCM_RX_CHANNELS; chan++) {
    327             cli_out("    Channel %d:  Chains %d. PPS %d. COSBMP 0x%x.\n",
    328                     chan, rx_cfg.chan_cfg[chan].chains,
    329                     rx_cfg.chan_cfg[chan].rate_pps,
    330                     rx_cfg.chan_cfg[chan].cos_bmp);
    331         }
    332         if ((rv = bcm_rx_cpu_rate_get(unit, &spps)) < 0) {
    333             cli_out("ERROR getting system rate limit:  %s\n",
    334                     bcm_errmsg(rv));
    335         } else {
    336             cli_out("    System wide rate limit:  %d\n", spps);
    337         }
    338         return CMD_OK;
    339     }
    340 
    341     if (isint(ARG_CUR(args))) {
    342         chan = parse_integer(ARG_GET(args));
    343         if (chan < 0 || chan >= BCM_RX_CHANNELS) {
    344             cli_out("Error: Bad channel %d\n", chan);
    345             return CMD_FAIL;
    346         }
    347     } else {
    348         chan = -1;
    349     }
    350 
    351     parse_table_init(unit, &pt);
    352 
    353     /* SPPS must be first, or else adjust pt_entries index below */
    354     parse_table_add(&pt, "SPPS", PQ_DFL|PQ_INT, 0,
    355                     &system_pps, NULL);
    356     parse_table_add(&pt, "GPPS", PQ_DFL|PQ_INT, 0,
    357                     &rx_cfg.global_pps, NULL);
    358     parse_table_add(&pt, "PKTSIZE", PQ_DFL|PQ_INT, 0,
    359                     &rx_cfg.pkt_size, NULL);
    360     parse_table_add(&pt, "PPC", PQ_DFL|PQ_INT, 0,
    361                     &rx_cfg.pkts_per_chain, NULL);
    362     parse_table_add(&pt, "BURST", PQ_DFL|PQ_INT, 0,
    363                     &rx_cfg.max_burst, NULL);
    364     parse_table_add(&pt, "FREE", PQ_DFL|PQ_BOOL, 0,
    365                     &free_buffers, NULL);
    366     
    367     if (queue_max >= BCM_RX_COS) {
    368         cli_out("Error: Too many queues %d > %d\n", queue_max, BCM_RX_COS);
    369         parse_arg_eq_done(&pt);
    370         return CMD_FAIL;
    371     }
    372     for (i = 0; i < queue_max; i++) {
    373         sal_sprintf(cospps_str[i], "COSPPS%d", i);
    374         parse_table_add(&pt, cospps_str[i], PQ_DFL|PQ_INT, 0,
    375                         &cos_pps[i], NULL);
    376     }
    377 
    378     if (chan >= 0) {
    379         parse_table_add(&pt, "CHAINS", PQ_DFL|PQ_INT, 0,
    380                         &rx_chan_cfg.chains, NULL);
    381         parse_table_add(&pt, "PPS", PQ_DFL|PQ_INT, 0,
    382                         &rx_chan_cfg.rate_pps, NULL);
    383         parse_table_add(&pt, "COSBMP", PQ_DFL|PQ_HEX, 0,
    384                         &rx_chan_cfg.cos_bmp, NULL);
    385     }
    386 
    387     /* Parse remaining arguments */
    388     if (0 > parse_arg_eq(args, &pt)) {
    389 	cli_out("%s: Error: Invalid option or malformed expression: %s\n",
    390                 ARG_CMD(args), ARG_CUR(args));
    391 	parse_arg_eq_done(&pt);
    392 	return(CMD_FAIL);
    393     }
    394 
    395     /* Check if SPPS was entered; if so do only that */
    396     if (pt.pt_entries[0].pq_type & PQ_PARSED) {
    397         rv = bcm_rx_cpu_rate_set(unit, system_pps);
    398         parse_arg_eq_done(&pt);
    399         if (rv < 0) {
    400             cli_out("Warning:  system rate set (to %d) returned %s\n",
    401                     system_pps, bcm_errmsg(rv));
    402             return CMD_FAIL;
    403         }
    404         return CMD_OK;
    405     }
    406 
    407     parse_arg_eq_done(&pt);
    408 
    409     for (i = 0; i < queue_max; i++) {
    410         rv = bcm_rx_cos_rate_set(unit, i, cos_pps[i]);
    411         if (rv < 0) {
    412             cli_out("Warning:  cos rate set(%d to %d) returned %s\n", i,
    413                     cos_pps[i], bcm_errmsg(rv));
    414         }
    415     }
    416 
    417     if (chan >=0 ) { /* Copy external chan cfg to right place */
    418         sal_memcpy(&rx_cfg.chan_cfg[chan], &rx_chan_cfg,
    419                    sizeof(bcm_rx_chan_cfg_t));
    420     }
    421     return CMD_OK;
    422 }
    423