ipmc.c (19490B)
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: ipmc.c 8 * Purpose: 9 * Requires: 10 */ 11 12 #include <bcm/types.h> 13 #include <bcm/error.h> 14 #include <shared/bsl.h> 15 #include <bcm/l3.h> 16 #include <bcmx/ipmc.h> 17 18 #include <appl/diag/parse.h> 19 #include <appl/diag/shell.h> 20 #include <appl/diag/system.h> 21 22 #include "bcmx.h" 23 24 #ifdef INCLUDE_L3 25 26 char bcmx_cmd_ipmc_usage[] = 27 "Usages:\n" 28 #ifdef COMPILER_STRING_CONST_LIMIT 29 " ipmc init | add | lookup\n" 30 " ipmc test add\n" 31 #else 32 " ipmc init\n" 33 " - Initialize BMCX mcast stuff\n" 34 " ipmc add [L2Ports=<user-port-list>] [UntagPorts=<user-port-list>]\n" 35 " [L3Ports=<user-port-list>] [SrcIP=<IP>] [McIP=<IP>]\n" 36 " [CosDst=<COS Value>] [Trunk=<True|False>] [PortTgid=<user-port>]\n" 37 " [Vlanid=<id>] [TTL=<ttl>] [CPUDrop=<True|False>]\n" 38 " [Replace=<True|False>]\n" 39 " - Add IP Multicast address & associated with port(s)\n" 40 " ipmc lookup [SrcIP=<IP>] [McIP=<IP>] [Vlanid=<id>]\n" 41 " - Lookup an IP Mcast Address entry\n" 42 " ipmc test add Ports=<Max. number of ports in the system>\n" 43 " - add -> Adds 256 ipmc incremental addresses\n" 44 " ipmc egr set [Port=<user-port>] [Mac=<macaddr>] [Vlan=<id>] \n" 45 " [Untag=<True|False>] [Ttl_thresh=<ttl_threshold>]\n" 46 " - Set egress IP Multicast configuration regs for a port\n" 47 " ipmc v6 add [SrcIP=<IP>] [McIP=<IP>] [L2Ports=<user-port-list>]\n" 48 " [UntagPorts=<user-port-list>] [L3Ports=<user-port-list>]\n" 49 " [CosDst=<COS Value>] [Trunk=<True|False>] [PortTgid=<user-port>]\n" 50 " [Vlanid=<id>] [TTL=<ttl>] [CPUDrop=<True|False>]\n" 51 " - Add an IPv6 MCAST entry into ipmc table\n" 52 " ipmc v6 del [SrcIP=<IP>] [McIP=<IP>] [Vlanid=<id>]\n" 53 " - Delete IPv6 MCAST entry from ipmc table\n" 54 #endif 55 ; 56 57 cmd_result_t 58 bcmx_cmd_ipmc(int unit, args_t *args) 59 { 60 char *subcmd = NULL; 61 static int initted = 0; 62 static sal_mac_addr_t arg_macaddr; 63 static int arg_cos_dst = 0, 64 arg_vlan = VLAN_ID_DEFAULT; 65 int arg_trunk = 0; 66 int replace = 0; 67 int arg_ttl = 0; 68 uint32 arg_src_ip = 0; 69 uint32 arg_mc_ip = 0; 70 int rv = CMD_OK; 71 int i, u_port_num; 72 int arg_max_ports; 73 parse_table_t pt; 74 char *port_str = NULL; 75 char *l2_plist_str = NULL; 76 char *l3_plist_str = NULL; 77 char *puntag_list_str = NULL; 78 bcmx_ipmc_addr_t ipmcxaddr; 79 char port_list[256]; 80 bcmx_lplist_t l2_port_list; /* L2 Port logical port list*/ 81 bcmx_lplist_t l3_port_list; /* L3 logical port list */ 82 bcmx_lplist_t l2_untag_list; 83 bcmx_uport_t uport; 84 bcmx_lport_t lport; 85 int count; 86 87 /* 88 * Initialize MAC address field for the user to the first real 89 * address which does not conflict 90 */ 91 if (! initted) { 92 arg_macaddr[0] = 0; 93 arg_macaddr[1] = 0; 94 arg_macaddr[2] = 0; 95 arg_macaddr[3] = 0; 96 arg_macaddr[4] = 0; 97 arg_macaddr[5] = 0; 98 bcmx_lplist_init(&l2_port_list, 0, 0); 99 bcmx_lplist_init(&l3_port_list, 0, 0); 100 bcmx_lplist_init(&l2_untag_list, 0, 0); 101 } 102 103 if ((subcmd = ARG_GET(args)) == NULL) { 104 return CMD_USAGE; 105 } 106 107 if (! sal_strcasecmp(subcmd, "init")) { 108 rv = bcmx_ipmc_init(); 109 110 if (rv < 0) { 111 cli_out("ERROR: %s\n", bcm_errmsg(rv)); 112 return CMD_FAIL; 113 } 114 115 return CMD_OK; 116 } 117 else if (! sal_strcasecmp(subcmd, "add")) { 118 parse_table_init(unit, &pt); 119 parse_table_add(&pt, "L2Ports", PQ_STRING, 120 0, &l2_plist_str, NULL); 121 parse_table_add(&pt, "UntagPorts", PQ_STRING, 122 0, &puntag_list_str, NULL); 123 parse_table_add(&pt, "L3Ports", PQ_STRING, 124 0, &l3_plist_str, NULL); 125 parse_table_add(&pt, "SrcIP", PQ_DFL|PQ_IP, 126 0, &arg_src_ip,NULL); 127 parse_table_add(&pt, "McIP", PQ_DFL|PQ_IP, 128 0, &arg_mc_ip,NULL); 129 parse_table_add(&pt, "Vlanid", PQ_DFL|PQ_INT, 130 0, &arg_vlan, NULL); 131 parse_table_add(&pt, "CosDst", PQ_DFL|PQ_INT, 132 0, &arg_cos_dst, NULL); 133 parse_table_add(&pt, "Trunk", PQ_DFL|PQ_BOOL, 134 0, &arg_trunk,NULL); 135 parse_table_add(&pt, "PortTgid", PQ_DFL|PQ_STRING, 136 0, &port_str, NULL); 137 parse_table_add(&pt, "Replace", PQ_DFL|PQ_BOOL, 138 0, &replace,NULL); 139 140 if (parse_arg_eq(args, &pt) < 0) { 141 cli_out("%s ERROR: parsing arguments\n", ARG_CMD(args)); 142 parse_arg_eq_done(&pt); 143 return CMD_FAIL; 144 } 145 146 bcmx_ipmc_addr_t_init(&ipmcxaddr); 147 ipmcxaddr.s_ip_addr = arg_src_ip; 148 ipmcxaddr.mc_ip_addr = arg_mc_ip; 149 ipmcxaddr.vid = arg_vlan; 150 bcmx_lplist_clear(&ipmcxaddr.l2_ports); 151 if (bcmx_lplist_parse(&ipmcxaddr.l2_ports, l2_plist_str) < 0) { 152 sal_printf("%s: Error: could not parse l2 portlist: %s\n", 153 ARG_CMD(args), l2_plist_str); 154 bcmx_ipmc_addr_t_free(&ipmcxaddr); 155 parse_arg_eq_done(&pt); 156 return CMD_FAIL; 157 } 158 bcmx_lplist_clear(&ipmcxaddr.l2_untag_ports); 159 if (bcmx_lplist_parse(&ipmcxaddr.l2_untag_ports, puntag_list_str) < 0) { 160 sal_printf("%s: Error: could not parse untag portlist: %s\n", 161 ARG_CMD(args), puntag_list_str); 162 bcmx_ipmc_addr_t_free(&ipmcxaddr); 163 parse_arg_eq_done(&pt); 164 return CMD_FAIL; 165 } 166 bcmx_lplist_clear(&ipmcxaddr.l3_ports); 167 if (bcmx_lplist_parse(&ipmcxaddr.l3_ports, l3_plist_str) < 0) { 168 sal_printf("%s: Error: could not parse l3 portlist: %s\n", 169 ARG_CMD(args), l3_plist_str); 170 bcmx_ipmc_addr_t_free(&ipmcxaddr); 171 parse_arg_eq_done(&pt); 172 return CMD_FAIL; 173 } 174 ipmcxaddr.ts = arg_trunk; 175 176 if (arg_trunk == 0) { /* non trunk port */ 177 /* convert user port to logical port */ 178 if (port_str == NULL) { 179 sal_printf("%s: Error: port is required if not a trunk port\n", 180 ARG_CMD(args)); 181 bcmx_ipmc_addr_t_free(&ipmcxaddr); 182 parse_arg_eq_done(&pt); 183 return CMD_FAIL; 184 } 185 uport = bcmx_uport_parse(port_str, NULL); 186 lport = bcmx_uport_to_lport(uport); 187 if (lport == BCMX_NO_SUCH_LPORT) { 188 sal_printf("%s: Error: could not parse port: %s\n", 189 ARG_CMD(args), port_str); 190 bcmx_ipmc_addr_t_free(&ipmcxaddr); 191 parse_arg_eq_done(&pt); 192 return CMD_FAIL; 193 } 194 ipmcxaddr.port_tgid = lport; 195 } 196 parse_arg_eq_done(&pt); 197 198 ipmcxaddr.cos = arg_cos_dst; 199 if (replace) { 200 ipmcxaddr.flags |= BCM_IPMC_REPLACE; 201 } 202 rv = bcmx_ipmc_add(&ipmcxaddr); 203 if (rv < 0) { 204 cli_out("ERROR: %s\n", bcm_errmsg(rv)); 205 bcmx_ipmc_addr_t_free(&ipmcxaddr); 206 return CMD_FAIL; 207 } 208 bcmx_ipmc_addr_t_free(&ipmcxaddr); 209 return CMD_OK; 210 } 211 else if (! sal_strcasecmp(subcmd, "lookup") || ! sal_strcasecmp(subcmd, "lkup")) { 212 213 /* 214 * Lookup an arl entry 215 */ 216 parse_table_init(unit, &pt); 217 parse_table_add(&pt, "SrcIP", PQ_DFL|PQ_IP, 218 0, &arg_src_ip,NULL); 219 parse_table_add(&pt, "McIP", PQ_DFL|PQ_IP, 220 0, &arg_mc_ip,NULL); 221 parse_table_add(&pt, "Vlanid", PQ_DFL|PQ_HEX, 222 0, &arg_vlan, NULL); 223 224 if (parse_arg_eq(args, &pt) < 0) { 225 cli_out("%s ERROR: parsing arguments\n", ARG_CMD(args)); 226 parse_arg_eq_done(&pt); 227 return CMD_FAIL; 228 } 229 parse_arg_eq_done(&pt); 230 231 bcmx_ipmc_addr_t_init(&ipmcxaddr); 232 rv = bcmx_ipmc_find(&ipmcxaddr); 233 234 if (rv < 0) { 235 cli_out("ERROR: %s\n", bcm_errmsg(rv)); 236 bcmx_ipmc_addr_t_free(&ipmcxaddr); 237 return CMD_FAIL; 238 } else { /* Found it. Display. */ 239 cli_out("SourceIP 0x%x MCastIP 0x%x Vlan %d COS %d\n", 240 ipmcxaddr.s_ip_addr, ipmcxaddr.mc_ip_addr, 241 ipmcxaddr.vid, ipmcxaddr.cos); 242 cli_out("l2 uports:"); 243 BCMX_LPLIST_ITER(ipmcxaddr.l2_ports, lport, count) { 244 cli_out(" %s", bcmx_lport_to_uport_str(lport)); 245 } 246 cli_out("\n"); 247 cli_out("l2 untag uports:"); 248 BCMX_LPLIST_ITER(ipmcxaddr.l2_untag_ports, lport, count) { 249 cli_out(" %s", bcmx_lport_to_uport_str(lport)); 250 } 251 cli_out("\n"); 252 cli_out("l3 uports:"); 253 BCMX_LPLIST_ITER(ipmcxaddr.l3_ports, lport, count) { 254 cli_out(" %s", bcmx_lport_to_uport_str(lport)); 255 } 256 cli_out("\n"); 257 bcmx_ipmc_addr_t_free(&ipmcxaddr); 258 return CMD_OK; 259 } 260 } 261 else if (! sal_strcasecmp(subcmd, "test")) { 262 263 if ((subcmd = ARG_GET(args)) == NULL) { 264 return CMD_USAGE; 265 } 266 if (! sal_strcasecmp(subcmd, "add")) { 267 parse_table_init(unit, &pt); 268 parse_table_add(&pt, "Ports", PQ_DFL|PQ_INT, 269 0, &arg_max_ports,NULL); 270 271 if (parse_arg_eq(args, &pt) < 0) { 272 cli_out("%s ERROR: parsing arguments\n", ARG_CMD(args)); 273 parse_arg_eq_done(&pt); 274 return CMD_FAIL; 275 } 276 parse_arg_eq_done(&pt); 277 arg_mc_ip = 0xe1010100; 278 arg_src_ip = 0xa010100; 279 280 for (i=0; i<256; i++) { 281 282 arg_vlan = 2; 283 bcmx_ipmc_addr_t_init(&ipmcxaddr); 284 ipmcxaddr.s_ip_addr = arg_src_ip; 285 ipmcxaddr.mc_ip_addr = arg_mc_ip; 286 ipmcxaddr.vid = arg_vlan; 287 u_port_num = i % arg_max_ports; 288 sal_sprintf(port_list,"%d,%d,%d,%d",(u_port_num%arg_max_ports)+1, 289 ((u_port_num+1)%arg_max_ports)+1, 290 ((u_port_num+2)%arg_max_ports)+1, 291 ((u_port_num+3)%arg_max_ports)+1); 292 bcmx_lplist_clear(&ipmcxaddr.l2_ports); 293 if (bcmx_lplist_parse(&ipmcxaddr.l2_ports, 294 port_list) < 0) { 295 sal_printf("%s: Error: could not parse portlist: %s\n", 296 ARG_CMD(args), port_list); 297 bcmx_ipmc_addr_t_free(&ipmcxaddr); 298 return CMD_FAIL; 299 } 300 301 u_port_num = (i+10) % arg_max_ports; 302 sal_sprintf(port_list,"%d,%d,%d,%d",(u_port_num%arg_max_ports)+1, 303 ((u_port_num+1)%arg_max_ports)+1, 304 ((u_port_num+2)%arg_max_ports)+1, 305 ((u_port_num+3)%arg_max_ports)+1); 306 bcmx_lplist_clear(&ipmcxaddr.l3_ports); 307 if (bcmx_lplist_parse(&ipmcxaddr.l3_ports, 308 port_list) < 0) { 309 sal_printf("%s: Error: could not parse portlist: %s\n", 310 ARG_CMD(args), port_list); 311 bcmx_ipmc_addr_t_free(&ipmcxaddr); 312 return CMD_FAIL; 313 } 314 315 bcmx_lplist_clear(&ipmcxaddr.l2_untag_ports); 316 317 ipmcxaddr.ts = 0; 318 ipmcxaddr.port_tgid = (i % arg_max_ports)+1; 319 ipmcxaddr.cos = arg_cos_dst; 320 321 rv = bcmx_ipmc_add(&ipmcxaddr); 322 if (rv < 0) { 323 cli_out("ERROR: %s\n", bcm_errmsg(rv)); 324 bcmx_ipmc_addr_t_free(&ipmcxaddr); 325 return CMD_FAIL; 326 } 327 bcmx_ipmc_addr_t_free(&ipmcxaddr); 328 arg_src_ip += 1; 329 arg_mc_ip += 1; 330 } 331 } 332 return CMD_OK; 333 } else if (sal_strcasecmp(subcmd, "egr") == 0) { 334 int arg_untag; 335 336 if ((subcmd = ARG_GET(args)) == NULL) { 337 return CMD_FAIL; 338 } 339 340 if (sal_strcasecmp(subcmd, "set")) { 341 return CMD_FAIL; 342 } 343 344 parse_table_init(unit, &pt); 345 parse_table_add(&pt, "Port", PQ_STRING, 0, &port_str, NULL); 346 parse_table_add(&pt, "Mac", PQ_DFL | PQ_MAC, 0, &arg_macaddr, NULL); 347 parse_table_add(&pt, "Vlan", PQ_DFL | PQ_INT, 0, &arg_vlan, 0); 348 parse_table_add(&pt, "Untag", PQ_DFL | PQ_INT, 349 0, &arg_untag, NULL); 350 parse_table_add(&pt, "Ttl_thresh", PQ_DFL | PQ_INT, 0, 351 &arg_ttl, NULL); 352 if (!parse_arg_eq(args, &pt)) { 353 sal_printf("%s: Unknown options: %s\n", 354 ARG_CMD(args), ARG_CUR(args)); 355 parse_arg_eq_done(&pt); 356 return(CMD_FAIL); 357 } 358 359 uport = bcmx_uport_parse(port_str, NULL); 360 lport = BCMX_UPORT_TO_LPORT(uport); 361 if (lport == BCMX_NO_SUCH_LPORT) { 362 sal_printf("%s: bad port given: %s\n", ARG_CMD(args), port_str); 363 parse_arg_eq_done(&pt); 364 return CMD_FAIL; 365 } 366 parse_arg_eq_done(&pt); 367 rv = bcmx_ipmc_egress_port_set(lport, arg_macaddr, arg_untag, 368 arg_vlan, arg_ttl); 369 if (rv < 0) { 370 cli_out("\nERROR %s\n", bcm_errmsg(rv)); 371 return CMD_FAIL; 372 } 373 return CMD_OK; 374 } 375 #if defined(BCM_XGS3_SWITCH_SUPPORT) 376 else if (sal_strcasecmp(subcmd, "v6") == 0) { 377 bcm_ip6_t ip6_addr, sip6_addr; 378 379 if ((subcmd = ARG_GET(args)) == NULL) { 380 return CMD_FAIL; 381 } 382 383 if (sal_strcasecmp(subcmd, "add") == 0) { 384 385 parse_table_init(unit, &pt); 386 parse_table_add(&pt, "SrcIP", PQ_DFL|PQ_IP6, 0, 387 (void *)&sip6_addr, NULL); 388 parse_table_add(&pt, "McIP", PQ_DFL|PQ_IP6, 0, 389 (void *)&ip6_addr, NULL); 390 parse_table_add(&pt, "L3Ports", PQ_STRING, 0, &l3_plist_str, NULL); 391 parse_table_add(&pt, "L2Ports", PQ_STRING, 0, &l2_plist_str, NULL); 392 parse_table_add(&pt, "UntagPorts", PQ_STRING, 393 0, &puntag_list_str, NULL); 394 parse_table_add(&pt, "Vlanid", PQ_DFL|PQ_INT, 395 0, &arg_vlan, NULL); 396 parse_table_add(&pt, "CosDst", PQ_DFL|PQ_INT, 397 0, &arg_cos_dst, NULL); 398 parse_table_add(&pt, "Trunk", PQ_DFL|PQ_BOOL, 399 0, &arg_trunk,NULL); 400 parse_table_add(&pt, "PortTgid", PQ_INT, 0, &u_port_num, 0); 401 402 if (parse_arg_eq(args, &pt) < 0) { 403 cli_out("%s ERROR: parsing arguments\n", ARG_CMD(args)); 404 parse_arg_eq_done(&pt); 405 return CMD_FAIL; 406 } 407 bcmx_ipmc_addr_t_init(&ipmcxaddr); 408 409 sal_memcpy(ipmcxaddr.s_ip6_addr, sip6_addr, BCM_IP6_ADDRLEN); 410 sal_memcpy(ipmcxaddr.mc_ip6_addr, ip6_addr, BCM_IP6_ADDRLEN); 411 ipmcxaddr.vid = arg_vlan; 412 413 bcmx_lplist_clear(&ipmcxaddr.l2_ports); 414 if (bcmx_lplist_parse(&ipmcxaddr.l2_ports, l2_plist_str) < 0) { 415 sal_printf("%s: Error: could not parse l2 portlist: %s\n", 416 ARG_CMD(args), l2_plist_str); 417 bcmx_ipmc_addr_t_free(&ipmcxaddr); 418 parse_arg_eq_done(&pt); 419 return CMD_FAIL; 420 } 421 bcmx_lplist_clear(&ipmcxaddr.l2_untag_ports); 422 if (bcmx_lplist_parse(&ipmcxaddr.l2_untag_ports, 423 puntag_list_str) < 0) { 424 sal_printf("%s: Error: could not parse untag portlist: %s\n", 425 ARG_CMD(args), puntag_list_str); 426 bcmx_ipmc_addr_t_free(&ipmcxaddr); 427 parse_arg_eq_done(&pt); 428 return CMD_FAIL; 429 } 430 bcmx_lplist_clear(&ipmcxaddr.l3_ports); 431 if (bcmx_lplist_parse(&ipmcxaddr.l3_ports, l3_plist_str) < 0) { 432 sal_printf("%s: Error: could not parse l3 portlist: %s\n", 433 ARG_CMD(args), l3_plist_str); 434 bcmx_ipmc_addr_t_free(&ipmcxaddr); 435 parse_arg_eq_done(&pt); 436 return CMD_FAIL; 437 } 438 ipmcxaddr.ts = arg_trunk; 439 440 if (arg_trunk == 0) { /* non trunk port */ 441 ipmcxaddr.port_tgid = u_port_num; 442 } 443 parse_arg_eq_done(&pt); 444 445 ipmcxaddr.cos = arg_cos_dst; 446 ipmcxaddr.flags |= BCM_IPMC_IP6; 447 rv = bcmx_ipmc_add(&ipmcxaddr); 448 if (rv < 0) { 449 cli_out("ERROR: %s\n", bcm_errmsg(rv)); 450 bcmx_ipmc_addr_t_free(&ipmcxaddr); 451 return CMD_FAIL; 452 } 453 bcmx_ipmc_addr_t_free(&ipmcxaddr); 454 return CMD_OK; 455 } else if (sal_strcasecmp(subcmd, "del") == 0) { 456 457 parse_table_init(unit, &pt); 458 parse_table_add(&pt, "SrcIP", PQ_DFL|PQ_IP6, 0, 459 (void *)&sip6_addr, NULL); 460 parse_table_add(&pt, "McIP", PQ_DFL|PQ_IP6, 0, 461 (void *)&ip6_addr, NULL); 462 parse_table_add(&pt, "Vlanid", PQ_DFL|PQ_INT, 463 0, &arg_vlan, NULL); 464 465 if (parse_arg_eq(args, &pt) < 0) { 466 cli_out("%s ERROR: parsing arguments\n", ARG_CMD(args)); 467 parse_arg_eq_done(&pt); 468 return CMD_FAIL; 469 } 470 parse_arg_eq_done(&pt); 471 472 bcmx_ipmc_addr_t_init(&ipmcxaddr); 473 474 sal_memcpy(ipmcxaddr.s_ip6_addr, sip6_addr, BCM_IP6_ADDRLEN); 475 sal_memcpy(ipmcxaddr.mc_ip6_addr, ip6_addr, BCM_IP6_ADDRLEN); 476 ipmcxaddr.vid = arg_vlan; 477 ipmcxaddr.flags |= BCM_IPMC_IP6; 478 rv = bcmx_ipmc_remove(&ipmcxaddr); 479 if (rv < 0) { 480 cli_out("ERROR: %s\n", bcm_errmsg(rv)); 481 bcmx_ipmc_addr_t_free(&ipmcxaddr); 482 return CMD_FAIL; 483 } 484 bcmx_ipmc_addr_t_free(&ipmcxaddr); 485 return CMD_OK; 486 } 487 } 488 #endif /* BCM_XGS3_SWITCH_SUPPORT */ 489 490 else { 491 return CMD_USAGE; 492 } 493 return CMD_FAIL; 494 } 495 496 #endif /* INCLUDE_L3 */