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

vlan.c (11997B)


      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:        vlan.c
      8  * Purpose:
      9  * Requires:    
     10  */
     11 
     12 
     13 #include <bcm/vlan.h>
     14 
     15 #include <bcm/custom.h>
     16 #include <bcm/error.h>
     17 #include <bcmx/vlan.h>
     18 #include <bcmx/bcmx.h>
     19 
     20 #include <sal/appl/io.h>
     21 
     22 #include <appl/diag/shell.h>
     23 #include <appl/diag/system.h>
     24 #include <appl/diag/parse.h>
     25 
     26 #include "bcmx.h"
     27 #include <appl/diag/diag.h>
     28 
     29 char bcmx_cmd_vlan_usage[] =
     30     "Usages:  \n"
     31     "    vlan {create | destroy} <id>    - Create/destroy a VLAN\n"
     32     "    vlan add <id> <uport-list> [<untagged-uport-list>]\n"
     33     "                                    - Add port(s) to a VLAN\n"
     34     "    vlan remove <id> <uport-list>   - Remove ports from a VLAN\n"
     35     "    vlan show [<id>]                - Display VLAN info\n"
     36     "    vlan clear                      - Destroy all VLANs\n"
     37     "    vlan default [<id>]             - Set/show default VLAN\n";
     38 
     39 typedef enum _vlan_op_e {
     40     _VO_CREATE,
     41     _VO_DESTROY,
     42     _VO_ADD,
     43     _VO_REMOVE,
     44     _VO_CLEAR,
     45     _VO_SHOW,
     46     _VO_CUSTOM_SHOW,
     47     _VO_DEFAULT,
     48     _VO_NONE
     49 } _vlan_op_t;
     50 
     51 /*
     52  * VLAN id represented as bit field in an array
     53  * of 32-bit words
     54  */
     55 #define VID_VEC_WORDS (4096/32)
     56 
     57 _vlan_op_t
     58 get_op(char *subcmd)
     59 {
     60     if (sal_strcasecmp(subcmd, "create") == 0) {
     61         return _VO_CREATE;
     62     }
     63     if (sal_strcasecmp(subcmd, "destroy") == 0) {
     64         return _VO_DESTROY;
     65     }
     66     if (sal_strcasecmp(subcmd, "add") == 0) {
     67         return _VO_ADD;
     68     }
     69     if (sal_strcasecmp(subcmd, "remove") == 0) {
     70         return _VO_REMOVE;
     71     }
     72     if (sal_strcasecmp(subcmd, "clear") == 0) {
     73         return _VO_CLEAR;
     74     }
     75     if (sal_strcasecmp(subcmd, "show") == 0) {
     76         return _VO_SHOW;
     77     }
     78     if (sal_strcasecmp(subcmd, "custom_show") == 0) {
     79         return _VO_CUSTOM_SHOW;
     80     }
     81     if (sal_strcasecmp(subcmd, "default") == 0) {
     82         return _VO_DEFAULT;
     83     }
     84 
     85     return _VO_NONE;
     86 }
     87 
     88 #define _VID_BAD 0xffff
     89 
     90 #define _CLEAN_UP_RETURN(rv) do { \
     91     bcmx_lplist_free(&ports); \
     92    return (rv); \
     93 } while (0)
     94 
     95 #define _IF_BAD_VID_RETURN(vid) if (vid == _VID_BAD) { \
     96     sal_printf("VLAN:  Bad vid or not specified\n"); \
     97     _CLEAN_UP_RETURN(CMD_USAGE); \
     98 }
     99 
    100 #define _IF_BAD_PL_RETURN(pl_given) if (!pl_given) { \
    101     sal_printf("VLAN:  Bad port list or not specified\n"); \
    102     _CLEAN_UP_RETURN(CMD_USAGE); \
    103 }
    104 
    105 int
    106 display_vlan_lplist(int unit, int vec_count, uint32 vid_vec[VID_VEC_WORDS]) 
    107 {
    108     int i, j, vid, vid_count = 0;
    109     int rv = BCM_E_NONE;
    110     int lport, count = 0;
    111     bcmx_lplist_t t_ports, ut_ports;
    112 
    113     if (bcmx_lplist_init(&t_ports, 0, 0) < 0) {
    114         sal_printf("Could not init tagged port list\n");
    115         return rv; 
    116     }
    117 
    118     if (bcmx_lplist_init(&ut_ports, 0, 0) < 0) {
    119         sal_printf("Could not init untagged port list\n");
    120         bcmx_lplist_free(&t_ports);
    121         return rv;
    122     }
    123 
    124     for (i=0; i < VID_VEC_WORDS; i++) {
    125         for (j=0; j<32; j++) {
    126             if (vid_vec[i] & (1 << j)) {
    127                 vid = 32*i + j;
    128                 vid_count++;
    129 
    130                 sal_printf("\nVLAN %d: ", vid);
    131 
    132                 /*
    133                  * Get tagged and untagged lplist
    134                  */
    135                  
    136                 rv = bcmx_vlan_port_get(vid, &t_ports, &ut_ports);
    137                 bcmx_lplist_sort(&t_ports);
    138                 bcmx_lplist_sort(&ut_ports);
    139                 sal_printf("\n\tTagged Uports: ");
    140                 if (!(BCMX_LPLIST_IS_EMPTY(&t_ports))) {  
    141                     count = BCMX_LPLIST_COUNT(&t_ports);
    142                     BCMX_LPLIST_ITER(t_ports, lport, count) {
    143                        sal_printf("%s ", bcmx_lport_to_uport_str(lport));
    144                     }
    145                 } else {
    146                     sal_printf("None");
    147                 }
    148                  
    149                 sal_printf("\n\n\tUntagged Uports: ");
    150                 if (!(BCMX_LPLIST_IS_EMPTY(&ut_ports))) {
    151                     count = BCMX_LPLIST_COUNT(&ut_ports);
    152                     BCMX_LPLIST_ITER(ut_ports, lport, count) {
    153                        sal_printf("%s ", bcmx_lport_to_uport_str(lport));
    154                     }
    155                 } else {
    156                     sal_printf("None");
    157                 }
    158                 sal_printf("\n");
    159                 if (vid_count == vec_count) {
    160                     return rv;
    161                 }
    162             } /* if vlan is valid */
    163         } /* for 32 bits */
    164     } /* for 0..127 */
    165 
    166     if (vid_count != vec_count) {
    167         return -1;
    168     }
    169         
    170     return rv;
    171 }
    172 
    173 cmd_result_t
    174 bcmx_cmd_vlan(int unit, args_t *args)
    175 {
    176     char *subcmd, *ch;
    177     bcmx_lplist_t ports;
    178     int rv = BCM_E_NONE;
    179     cmd_result_t cmd_rv = CMD_OK;
    180     bcm_vlan_t id;
    181     int portlist_given = 1;
    182     int count;
    183     _vlan_op_t op;
    184     uint32 vid_vector[VID_VEC_WORDS];
    185 
    186     if ((subcmd = ARG_GET(args)) == NULL) {
    187         sal_printf("Subcommand required\n");
    188         return CMD_USAGE;
    189     }
    190 
    191     if ((ch = ARG_GET(args)) == NULL) {
    192         id = _VID_BAD;
    193     } else {
    194         id = parse_integer(ch);
    195     }
    196 
    197     if (bcmx_lplist_init(&ports, 0, 0) < 0) {
    198         sal_printf("Could not init port list\n");
    199         return CMD_FAIL;
    200     }
    201 
    202     if ((ch = ARG_GET(args)) == NULL) {
    203         portlist_given = 0;
    204     } else {
    205         if (bcmx_lplist_parse(&ports, ch) < 0) {
    206             sal_printf("%s: Error: could not parse portlist: %s\n",
    207                          ARG_CMD(args), ch);
    208             _CLEAN_UP_RETURN(CMD_FAIL);
    209         }
    210     }
    211 
    212     op = get_op(subcmd);
    213     switch (op) {
    214     case _VO_CREATE:
    215         _IF_BAD_VID_RETURN(id);
    216 
    217         rv = bcmx_vlan_create(id);
    218 
    219         /* Add option to add ports here */
    220         break;
    221 
    222     case _VO_DESTROY:
    223         _IF_BAD_VID_RETURN(id);
    224         rv = bcmx_vlan_destroy(id);
    225         break;
    226 
    227     case _VO_ADD:
    228     {
    229         bcmx_lplist_t ut_ports;
    230 
    231         _IF_BAD_VID_RETURN(id);
    232         _IF_BAD_PL_RETURN(portlist_given);
    233 
    234         if (bcmx_lplist_init(&ut_ports, 0, 0) != BCM_E_NONE) {
    235             sal_printf("VLAN: Could not allocate untagged port list\n");
    236             _CLEAN_UP_RETURN(CMD_FAIL);
    237         }
    238 
    239         if ((ch = ARG_GET(args)) != NULL) {
    240             if (bcmx_lplist_parse(&ut_ports, ch) < 0) {
    241                 sal_printf("%s: Error: could not parse untagged "
    242                              "portlist: %s\n", ARG_CMD(args), ch);
    243                 bcmx_lplist_free(&ut_ports);
    244                 _CLEAN_UP_RETURN(CMD_USAGE);
    245             }
    246         }
    247 
    248         rv = bcmx_vlan_port_add(id, ports, ut_ports);
    249         if (rv != BCM_E_NONE) {
    250             sal_printf("VLAN: Add failed %d: %s\n", rv, bcm_errmsg(rv));
    251             break;
    252         }
    253 
    254         bcmx_lplist_free(&ut_ports);
    255         break;
    256     }
    257 
    258     case _VO_REMOVE:
    259         _IF_BAD_VID_RETURN(id);
    260         rv = bcmx_vlan_port_remove(id, ports);
    261         if (rv != BCM_E_NONE) {
    262             sal_printf("VLAN: Remove failed %d: %s\n", rv, bcm_errmsg(rv));
    263         }
    264         break;
    265 
    266     case _VO_CUSTOM_SHOW:
    267     {
    268         int bcm_unit, i, j, count = 0;
    269         uint32 cu_args[BCM_CUSTOM_ARGS_MAX];
    270         int actual;
    271 
    272         sal_memset(vid_vector, 0, VID_VEC_WORDS *sizeof(uint32));
    273         sal_memset(cu_args, 0, BCM_CUSTOM_ARGS_MAX *sizeof(uint32));
    274 
    275         BCMX_UNIT_ITER(bcm_unit, i) {
    276           rv = bcm_custom_port_get(bcm_unit, -1,
    277                                    CUSTOM_HANDLER_VLAN_GET,
    278                                    BCM_CUSTOM_ARGS_MAX,
    279                                    cu_args, &actual);  
    280           if (rv < 0) {
    281               sal_printf("\nVLAN: vlan vector fetch failed at unit %d", bcm_unit);
    282               continue;
    283           } 
    284           
    285           /*
    286            * Some devices may not have VLANs configured;
    287            * OR them with the existing vlan vector for each unit
    288            */
    289           for (j = 0; j < VID_VEC_WORDS; j++) {
    290               vid_vector[j] |= cu_args[j+1];
    291           }
    292 
    293           if (count < cu_args[0]) {
    294               count =  cu_args[0];
    295           }
    296         }
    297 
    298         rv = display_vlan_lplist(bcm_unit, count, vid_vector);
    299         if (rv < 0) {
    300             sal_printf("\nVLAN: failure in displaying active VLANs\n");
    301             return CMD_FAIL;
    302         }
    303         break;
    304     }
    305 
    306     case _VO_SHOW:
    307     {
    308         bcmx_lplist_t t_ports;
    309         bcmx_lplist_t ut_ports;
    310 
    311         if (bcmx_lplist_init(&t_ports, 0, 0) < 0) {
    312             sal_printf("Could not init tagged port list\n");
    313             _CLEAN_UP_RETURN(CMD_FAIL);
    314         }
    315 
    316         if (bcmx_lplist_init(&ut_ports, 0, 0) < 0) {
    317             sal_printf("Could not init port list\n");
    318             bcmx_lplist_free(&t_ports);
    319             _CLEAN_UP_RETURN(CMD_FAIL);
    320         }
    321 
    322         if (id == _VID_BAD) {
    323             int vid;
    324             int count = 0;
    325 
    326             sal_printf("Current VLANS:  \n");
    327             for (vid = 0; vid < 4096; vid++) {
    328                 rv = bcmx_vlan_port_get(vid, &t_ports, &ut_ports);
    329                 BCM_IF_ERROR_RETURN(rv);
    330                 bcmx_lplist_sort(&t_ports);
    331                 bcmx_lplist_sort(&ut_ports);
    332                 if (!(BCMX_LPLIST_IS_EMPTY(&t_ports))) {
    333                     sal_printf("%d ", vid);
    334                     if ((++count % 12) == 0) {
    335                         sal_printf("\n");
    336                     }
    337                 }
    338             }
    339             sal_printf("\n");
    340             rv = BCM_E_NONE;
    341         } else {
    342             bcmx_lport_t lport;
    343             int out_count_t = 0;
    344             int out_count_ut = 0;
    345 
    346             rv = bcmx_vlan_port_get(id, &t_ports, &ut_ports);
    347             bcmx_lplist_sort(&t_ports);
    348             bcmx_lplist_sort(&ut_ports);
    349 
    350             if (!BCMX_LPLIST_IS_EMPTY(&t_ports)) {
    351                 BCMX_LPLIST_ITER(t_ports, lport, count) {
    352                     if (!out_count_t) {
    353                         sal_printf("Tagged uports for vlan %d:\n", id);
    354                     }
    355                     sal_printf("%s ", bcmx_lport_to_uport_str(lport));
    356                     if (!(++out_count_t % 10)) {
    357                         sal_printf("\n");
    358                     }
    359                 }
    360                 sal_printf("\n");
    361             }
    362 
    363             if (!BCMX_LPLIST_IS_EMPTY(&ut_ports)) {
    364                 BCMX_LPLIST_ITER(ut_ports, lport, count) {
    365                     if (!out_count_ut) {
    366                         sal_printf("Untagged uports for vlan %d:\n",
    367                                    id);
    368                     }
    369                     sal_printf("%s ", bcmx_lport_to_uport_str(lport));
    370                     if (!(++out_count_ut % 10)) {
    371                         sal_printf("\n");
    372                     }
    373                 }
    374                 sal_printf("\n");
    375             }
    376 
    377             if (!out_count_t && !out_count_ut) {
    378                 if (rv < 0) {
    379                     sal_printf("VLAN port get returns error %d: %s\n",
    380                                rv, bcm_errmsg(rv));
    381                     cmd_rv = CMD_FAIL;
    382                     rv = 0;
    383                 } else {
    384                     sal_printf("VLAN %d contains no ports\n", id);
    385                 }
    386             } else if (rv < 0) {
    387                 sal_printf("NOTE: VLAN get failed on some units (%d): %s\n",
    388                            rv, bcm_errmsg(rv));
    389                 rv = 0;
    390             }
    391         }
    392         bcmx_lplist_free(&t_ports);
    393         bcmx_lplist_free(&ut_ports);
    394         break;
    395     }
    396 
    397     case _VO_CLEAR:
    398         rv = bcmx_vlan_destroy_all();
    399         break;
    400 
    401     case _VO_DEFAULT:
    402 	if (id == _VID_BAD) {
    403 	    rv = bcmx_vlan_default_get(&id);
    404 	    if (rv >= 0) {
    405 		sal_printf("VLAN default is %d\n", id);
    406 	    }
    407 	} else {
    408 	    rv = bcmx_vlan_default_set(id);
    409 	}
    410 	break;
    411     case _VO_NONE:
    412     default:
    413         sal_printf("VLAN: Unknown subcommand %s\n", subcmd);
    414         cmd_rv = CMD_FAIL;
    415         break;
    416     }  /* End of sub-operation */
    417 
    418     if (rv < 0) {
    419         sal_printf("Error: Command returned %s\n", bcm_errmsg(rv));
    420         cmd_rv = CMD_FAIL;
    421     }
    422 
    423     bcmx_lplist_free(&ports);
    424     return cmd_rv;
    425 }
    426