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