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

txrx.c (10719B)


      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:        txrx.c
      8  * Purpose:
      9  * Requires:    
     10  */
     11 
     12 #include <bcm/error.h>
     13 #include <bcm/pkt.h>
     14 #include <bcm/topo.h>
     15 #include <shared/bsl.h>
     16 #ifdef BCM_RPC_SUPPORT
     17 #include <bcm_int/rpc/rlink.h>
     18 #endif
     19 #include <bcm_int/control.h>
     20 
     21 #include <bcmx/tx.h>
     22 #include <bcmx/rx.h>
     23 
     24 #include <appl/diag/system.h>
     25 #include <appl/diag/decode.h>
     26 
     27 #include <appl/cputrans/ct_tun.h>
     28 
     29 #include "bcmx.h"
     30 
     31 static volatile int dump;
     32 
     33 static volatile int pkt_count;
     34 static volatile int rmt_count;
     35 static volatile int tx_async_count;
     36 
     37 char bcmx_cmd_rx_usage[] =
     38     "    [+|- dump] [source | start | stop | reg | unreg]\n"
     39     "    Test the bcmx rx subsystem.  \n"
     40 #ifndef COMPILER_STRING_CONST_LIMIT
     41     "        start   - Make tunnel connect requests and register handler\n"
     42     "        stop    - Make tunnel disconnect requests\n"
     43     "        reg     - Register local BCMX handler (dump)\n"
     44     "        unreg   - Unregister local BCMX handler (dump)\n"
     45     "        dump    - Set/clear/toggle whether pkts are dumped\n"
     46     "        rlclear - Call rlink_clear function\n"
     47     "        txtunnel- Setup tx tunnel registration\n"
     48     "        notxtun - Tear down tx tunnel\n"
     49 #endif
     50     ;
     51 
     52 STATIC bcm_rx_t _bcmx_rx_handler(int unit,
     53                                  bcm_pkt_t *pkt,
     54                                  void *cookie);
     55 
     56 cmd_result_t
     57 bcmx_cmd_rx(int unit, args_t *args)
     58 {
     59     int rv = CMD_OK;
     60     char *ch;
     61 
     62     if ((ch = ARG_GET(args)) == NULL) {
     63         cli_out("BCMX RX is %srunning; seen %d packet%s (%d remote); "
     64                 "pkt dump is %s\n",
     65                 bcmx_rx_running() ? "" : "not ", 
     66                 pkt_count, pkt_count == 1 ? "" : "s",
     67                 rmt_count,
     68                 dump ? "on" : "off");
     69         return CMD_OK;
     70     }
     71 
     72     while (ch) {
     73         if (!strcmp("start", ch)) {
     74             rv = bcmx_rx_start();
     75             pkt_count = 0;
     76             cli_out("BCMX RX start returns %s\n", bcm_errmsg(rv));
     77         } else if (!strcmp("rlclear", ch)) {
     78 #ifdef	BCM_RPC_SUPPORT
     79             bcm_rlink_clear();
     80 #else
     81             cli_out("Function rlink_clear unavailable\n");
     82 	    return CMD_FAIL;
     83 #endif	/* BCM_RPC_SUPPORT */
     84         } else if (!strcmp("stop", ch)) {
     85             rv = bcmx_rx_stop();
     86             cli_out("BCMX RX stop returns %s\n", bcm_errmsg(rv));
     87         } else if (!strcmp("reg", ch)) {
     88             rv = bcmx_rx_register(
     89                 "bcmx_diag",
     90                 _bcmx_rx_handler,
     91                 100,
     92                 NULL,
     93                 BCM_RCO_F_ALL_COS);
     94             cli_out("BCMX RX register returns %s\n", bcm_errmsg(rv));
     95         } else if (!strcmp("unreg", ch)) {
     96             rv = bcmx_rx_unregister(_bcmx_rx_handler, 100);
     97             cli_out("BCMX RX unregister returns %s\n", bcm_errmsg(rv));
     98         } else if (!strcmp("-dump", ch)) {
     99             dump = FALSE;
    100         } else if (!strcmp("dump", ch)) {
    101             dump = !dump;
    102         } else if (!strcmp("+dump", ch)) {
    103             dump = TRUE;
    104         } else if (!strcmp("txtunnel", ch)) {
    105 #ifdef	BCM_RPC_SUPPORT
    106             rv = ct_tx_tunnel_setup();
    107             pkt_count = 0;
    108             cli_out("BCM TX Tunnel Setup returns %s\n", bcm_errmsg(rv));
    109 #else
    110             cli_out("BCM TX Tunnel Setup unavailable\n");
    111 	    return CMD_FAIL;
    112 #endif	/* BCM_RPC_SUPPORT */
    113         } else if (!strcmp("notxtun", ch)) {
    114 #ifdef	BCM_RPC_SUPPORT
    115             rv = ct_tx_tunnel_stop();
    116             pkt_count = 0;
    117             cli_out("BCM TX Tunnel Stop returns %s\n", bcm_errmsg(rv));
    118 #else
    119             cli_out("BCM TX Tunnel Stop unavailable\n");
    120 	    return CMD_FAIL;
    121 #endif	/* BCM_RPC_SUPPORT */
    122         } else {
    123             return CMD_USAGE;
    124         }
    125         ch = ARG_GET(args);
    126     }
    127 
    128     return rv < 0 ? CMD_FAIL : CMD_OK;
    129 }
    130 
    131 
    132 STATIC bcm_rx_t
    133 _bcmx_rx_handler(int unit, bcm_pkt_t *pkt, void *cookie)
    134 {
    135 
    136     pkt_count++;
    137     if (dump) {
    138         cli_out("BCMX RX %d: %p from: (%d, %d), len %d.\n", unit,
    139                 (void *)pkt, pkt->src_mod, pkt->src_port, pkt->pkt_len);
    140 #ifdef	BROADCOM_DEBUG
    141         bcm_pkt_dump(-1, pkt, dump);
    142 #endif	/* BROADCOM_DEBUG */
    143     }
    144 
    145     if (BCM_IS_REMOTE(unit)) {
    146         rmt_count++;
    147     }
    148     /* Don't want to interfere with other stuff that's going on */
    149     return BCM_RX_NOT_HANDLED;
    150 }
    151 
    152 #define TX_UNIT 0
    153 
    154 STATIC void _bcmx_tx_handler(int unit, bcm_pkt_t *pkt, void *cookie)
    155 {
    156     COMPILER_REFERENCE(unit);
    157     COMPILER_REFERENCE(pkt);
    158     COMPILER_REFERENCE(cookie);
    159     tx_async_count++;
    160 }
    161 
    162 char bcmx_cmd_tx_usage[] =
    163     "    tx <user-port-list> [<opts>]\n"
    164 #ifndef COMPILER_STRING_CONST_LIMIT
    165     "    Options include:\n"
    166     "        Length=<n>       Of packet in bytes\n"
    167     "        Count=<n>        Number of packets to send\n"
    168     "        Delay=<n>        Delay between packets (us)\n"
    169     "        VLantag=<n>      VLAN ID to use\n"
    170     "        VlanPrio=<n>     VLAN priority to use\n"
    171     "        L2Lookup=(T|F)   Should L2 lookup be done\n"
    172     "        DestMac=<mac>    Destination MAC address\n"
    173     "        SrcMac=<mac>     Source MAC address\n"
    174     "        SrcMod=<n>       Source module ID\n"
    175     "        SrcPort=<n>      Source port\n"
    176     "        COSqueue=<n>     COS queue on which to send\n"
    177     "        Pattern=<n>      Packet data pattern\n"
    178     "        PatternInc=<n>   Increment for packet data pattern\n"
    179     "        UnTagged=(T|F)   All pkts to be sent untagged\n"
    180     "        BestEffort=(T|F) If tunnelled, use best effort\n"
    181     "        Reliable=(T|F)   If tunnelled, use reliable transport\n"
    182     "        Flood=(T|F)      Flood the packet\n"
    183 #endif
    184     "    Send out a packet to the indicated user ports\n"
    185     "    If L2 Lookup is true, user-port-list is ignored.\n";
    186 
    187 cmd_result_t
    188 bcmx_cmd_tx(int unit, args_t *args)
    189 {
    190     char *ch;
    191     static int len = 68;
    192     bcm_pkt_t *pkt = NULL;
    193     int rv;
    194     int xfer;
    195     bcmx_lplist_t ports;
    196     static int src_port = 0, src_mod = 0;
    197     static int vlan_id = 1;
    198     static int vlan_prio = 0;
    199     static int l2_lookup = FALSE;
    200     static int cos = 0;
    201     static uint32 pattern = 0x12345678;
    202     static uint32 pat_inc = 0;
    203     static bcm_mac_t src_mac, dest_mac;
    204     static int count = 1;
    205     static int delay = 0;
    206     uint16 vtag;
    207     parse_table_t pt;
    208     int i;
    209     int untagged = FALSE;
    210     int best_effort = FALSE;
    211     int reliable = FALSE;
    212     int flood = FALSE;
    213     int async = FALSE;
    214     int bcmx_flags = 0;
    215 
    216     ch = ARG_GET(args);
    217     if (ch == NULL) {
    218         cli_out("BCMX TX async count=%d\n",tx_async_count);
    219         return CMD_OK;
    220     }
    221 
    222     bcmx_lplist_init(&ports, 0, 0);
    223     if (bcmx_lplist_parse(&ports, ch) < 0) {
    224         cli_out("%s: Error: could not parse portlist: %s\n",
    225                 ARG_CMD(args), ch);
    226         rv = CMD_FAIL;
    227         goto done;
    228     }
    229 
    230     if (ports.lp_last < 0) {
    231         cli_out("No ports specified.\n");
    232         rv = CMD_FAIL;
    233         goto done;
    234     }
    235 
    236     parse_table_init(unit, &pt);
    237 
    238     parse_table_add(&pt, "Length", 	PQ_DFL|PQ_INT, 	0,
    239 		    &len,    NULL);
    240     parse_table_add(&pt, "DeLay", 	PQ_DFL|PQ_INT, 	0,
    241 		    &delay, NULL);
    242     parse_table_add(&pt, "Count", 	PQ_DFL|PQ_INT, 	0,
    243 		    &count, NULL);
    244     parse_table_add(&pt, "VLantag", 	PQ_DFL|PQ_HEX, 	0,
    245 		    &vlan_id,	    NULL);
    246     parse_table_add(&pt, "VlanPrio", 	PQ_DFL|PQ_INT, 	0,
    247 		    &vlan_prio,	    NULL);
    248     parse_table_add(&pt, "L2Lookup", 	PQ_DFL|PQ_BOOL,	0,
    249 		    &l2_lookup, NULL);
    250     parse_table_add(&pt, "DestMac", 	PQ_DFL|PQ_MAC, 	0,
    251 		    &dest_mac,    NULL);
    252     parse_table_add(&pt, "SrcMac", 	PQ_DFL|PQ_MAC, 	0,
    253 		    &src_mac,    NULL);
    254     parse_table_add(&pt, "SrcMod", 	PQ_DFL|PQ_INT, 	0,
    255 		    &src_mod, NULL);
    256     parse_table_add(&pt, "SrcPort", 	PQ_DFL|PQ_INT, 	0,
    257 		    &src_port, NULL);
    258     parse_table_add(&pt, "COSqueue", 	PQ_DFL|PQ_INT, 	0,
    259 		    &cos, NULL);
    260     parse_table_add(&pt, "Pattern", 	PQ_DFL|PQ_HEX,	0,
    261 		    &pattern,	    NULL);
    262     parse_table_add(&pt, "PatternInc", 	PQ_DFL|PQ_INT,	0,
    263 		    &pat_inc,    NULL);
    264     parse_table_add(&pt, "UnTagged", 	PQ_DFL|PQ_BOOL,	0,
    265 		    &untagged, NULL);
    266     parse_table_add(&pt, "BestEffort", 	PQ_DFL|PQ_BOOL,	0,
    267 		    &best_effort, NULL);
    268     parse_table_add(&pt, "Reliable", 	PQ_DFL|PQ_BOOL,	0,
    269 		    &reliable, NULL);
    270     parse_table_add(&pt, "Flood", 	PQ_DFL|PQ_BOOL,	0,
    271 		    &flood, NULL);
    272     parse_table_add(&pt, "Async", 	PQ_DFL|PQ_BOOL,	0,
    273 		    &async, NULL);
    274 
    275     /* Parse remaining arguments */
    276     if (0 > parse_arg_eq(args, &pt)) {
    277 	cli_out("%s: Error: Invalid option or malformed expression: %s\n",
    278                 ARG_CMD(args), ARG_CUR(args));
    279 	parse_arg_eq_done(&pt);
    280 	rv = CMD_FAIL;
    281         goto done;
    282     }
    283     parse_arg_eq_done(&pt);
    284 
    285     if (BCM_FAILURE(bcm_pkt_alloc(TX_UNIT, len, BCM_TX_CRC_APPEND, &pkt))) {
    286 	rv = CMD_FAIL;
    287         goto done;
    288     }
    289 
    290     for (i = 0; i < len/4; i++) {
    291         sal_memcpy(&pkt->_pkt_data.data[i * 4], &pattern, 4);
    292         pattern += pat_inc;
    293     }
    294     sal_memcpy(pkt->_pkt_data.data, dest_mac, sizeof(bcm_mac_t));
    295     sal_memcpy(&pkt->_pkt_data.data[6], src_mac, sizeof(bcm_mac_t));
    296 
    297     vtag = (vlan_prio << 13) | vlan_id;
    298     pkt->_pkt_data.data[12] = 0x81; /* vlan 1 */
    299     pkt->_pkt_data.data[13] = 0;
    300     pkt->_pkt_data.data[14] = vtag >> 8;
    301     pkt->_pkt_data.data[15] = vtag & 0xff;
    302 
    303     /* Packet flags indicate tunnel mode */
    304     if (best_effort) {
    305         pkt->flags |= BCM_TX_BEST_EFFORT;
    306         bcmx_flags |= BCMX_TX_F_CPU_TUNNEL;
    307     }
    308     if (reliable) {
    309         pkt->flags |= BCM_TX_RELIABLE;
    310         bcmx_flags |= BCMX_TX_F_CPU_TUNNEL;
    311     }
    312 
    313     if (async) {
    314         pkt->call_back = _bcmx_tx_handler;
    315     }
    316 
    317     for ( xfer = 0; xfer < count; xfer++ ) {
    318         if (l2_lookup) { /* Don't need to look for dest port */
    319             rv = bcmx_tx(pkt, BCMX_TX_F_L2_LOOKUP|bcmx_flags);
    320         } else if (flood) {
    321             rv = bcmx_tx_flood(pkt, bcmx_flags);
    322         } else if (BCMX_LPLIST_COUNT(&ports) == 1
    323                    && !untagged) {  /* Single port (tagged) transmit */
    324             rv = bcmx_tx_uc(pkt, bcmx_lplist_first(&ports), bcmx_flags);
    325         } else {
    326             if (untagged) {
    327                 rv = bcmx_tx_lplist(pkt, NULL, &ports, bcmx_flags); 
    328             } else {
    329                 rv = bcmx_tx_lplist(pkt, &ports, NULL, bcmx_flags); 
    330             }
    331         }
    332         if (rv < 0) {
    333             cli_out("BCMX TX ERROR:  return value is %d (%s)\n",
    334                     rv, bcm_errmsg(rv));
    335             break;
    336         }
    337         sal_usleep(delay);
    338     }
    339 
    340 done:
    341     if (pkt != NULL) {
    342         bcm_pkt_free(TX_UNIT, pkt);
    343     }
    344     bcmx_lplist_free(&ports);
    345 
    346     return CMD_OK;
    347 }