l2_mc.c (16579B)
1 /* Feature : L2 Multicast 2 * 3 * Usage : BCM.0> cint l2_mc.c 4 * 5 * config : l2_config.bcm 6 * 7 * Log file : l2_mc_log.txt 8 * 9 * Test Topology : 10 * 11 * +------------------------------+ egress_port1 12 * | +-----------------+ 13 * | | 14 * | | 15 * ingress_port | | egress_port2 16 * +----------------+ SWITCH +-----------------+ 17 * | | 18 * | | 19 * | | egress_port3 20 * | +-----------------+ 21 * | | 22 * +------------------------------+ 23 * 24 * 25 * Summary: 26 * ======== 27 * This CINT configures L2 multicast using BCM APIs. 28 * This example shows the steps to set up L2 multicast along with Port 29 * Filtering Mode(PFM) on a per Vlan basis. The PFM controls the forwarding of 30 * known and unknown multicast packets. 31 * 32 * PFM 33 * === 34 * 0 - All multicast packets are flooded to the entire Vlan 35 * 1 - Known multicast packets are forwarded only to the ports in the 36 * multicast group. Unknown multicast packets are flooded to the Vlan. 37 * 2 - Known multicast packets are forwarded only to the ports in the 38 * multicast group. Unknown multicast packets are dropped. 39 * 40 * Detailed steps done in the CINT script: 41 * ======================================= 42 * 1) Step1 - Test Setup (Done in test_setup()): 43 * ============================================= 44 * a) Select one ingress and three egress ports and configure them in 45 * Loopback mode. Install a rule to copy incoming packets to CPU and 46 * additional action to drop the packets when it loops back on egress 47 * ports. Start packet watcher. 48 * 49 * 2) Step2 - Configuration (Done in configure_l2_mc()) 50 * ==================================================== 51 * a) Create a VLAN(2) and add egress_port1, egress_port2 and egress_port3 52 * as members. 53 * b) Create a L2 multicast group and add egress_port1, egress_port2 and egress_port3 to 54 * this L2 multicast group. 55 * c) Configure the PFM mode as BCM_VLAN_MCAST_FLOOD_NONE(mode 2) for VLAN(2). 56 * d) Add ingress_port as member of vlan(2) and add an entry into L2 table 57 * specifying the L2 multicast group as destination for the multicast MAC 58 * address. 59 * 60 * 3) Step3 - Verification (Done in verify()): 61 * =========================================== 62 * a) Transmit the below known multicast packet on ingress_port. 63 * Packet: 64 * ====== 65 * Ethernet II, Src: Xerox_00:00:00 (00:00:04:00:00:00), Dst: Xerox_00:01:00 (01:00:04:00:01:00) 66 * 802.1Q Virtual LAN, PRI: 0, CFI: 0, ID: 2 67 * 68 * 0100 0400 0100 0000 0400 0000 8100 0002 69 * 0800 0001 0203 0405 0607 0809 0a0b 0c0d 70 * 0e0f 1011 1213 1415 1617 1819 1a1b 1c1d 71 * 1e1f 2021 2223 2425 2627 2829 2a2b 2c2d 72 * 8e0b ec9e 1cdf 4421 73 * 74 * b) Transmit the below unknown multicast packet on ingress_port and verify that the 75 * packet is dropped as PFM for VLAN(2) is set to 2. 76 * 77 * Packet: 78 * ====== 79 * Ethernet II, Src: Xerox_00:00:00 (00:00:04:00:00:00), Dst: Xerox_00:01:00 (01:00:03:00:01:00) 80 * 802.1Q Virtual LAN, PRI: 0, CFI: 0, ID: 2 81 * 82 * 0100 0300 0100 0000 0400 0000 8100 0002 83 * 0800 0001 0203 0405 0607 0809 0a0b 0c0d 84 * 0e0f 1011 1213 1415 1617 1819 1a1b 1c1d 85 * 1e1f 2021 2223 2425 2627 2829 2a2b 2c2d 86 * 5ca6 4d2a 1cdf 4421 87 * 88 * c) Expected Result: 89 * =================== 90 * After Step 3.a, the packet egresses out of egress_port1, egress_port2 and egress_port3. 91 * This can be observed using "show counters" and/or packet watcher dump on console. 92 * 93 * After step 3.b, it can be observed that packet is dropped as PFM for VLAN(2) is set to 94 * BCM_VLAN_MCAST_FLOOD_NONE(mode 2) 95 */ 96 cint_reset(); 97 98 bcm_port_t ingress_port; 99 bcm_port_t egress_port1, egress_port2, egress_port3; 100 101 /* This function is written so that hardcoding of port 102 numbers in Cint scripts is removed. This function gives 103 required number of ports 104 */ 105 bcm_error_t portNumbersGet(int unit, int *port_list, int num_ports) 106 { 107 108 int i=0,port=0,rv=0; 109 bcm_port_config_t configP; 110 bcm_pbmp_t ports_pbmp; 111 112 rv = bcm_port_config_get(unit,&configP); 113 if(BCM_FAILURE(rv)) { 114 printf("\nError in retrieving port configuration: %s.\n",bcm_errmsg(rv)); 115 return rv; 116 } 117 118 ports_pbmp = configP.e; 119 for (i= 1; i < BCM_PBMP_PORT_MAX; i++) { 120 if (BCM_PBMP_MEMBER(&ports_pbmp,i)&& (port < num_ports)) { 121 port_list[port]=i; 122 port++; 123 } 124 } 125 126 if (( port == 0 ) || ( port != num_ports )) { 127 printf("portNumbersGet() failed \n"); 128 return -1; 129 } 130 131 return BCM_E_NONE; 132 133 } 134 135 /* 136 * Configures the port in loopback mode and installs 137 * an IFP rule. This IFP rule copies the packets ingressing 138 * on the specified port to CPU. 139 */ 140 bcm_error_t ingress_port_setup(int unit, bcm_port_t port) 141 { 142 bcm_field_qset_t qset; 143 bcm_field_group_t group; 144 bcm_field_entry_t entry; 145 146 BCM_IF_ERROR_RETURN(bcm_port_loopback_set(unit, port, BCM_PORT_LOOPBACK_PHY)); 147 148 BCM_FIELD_QSET_INIT(qset); 149 BCM_FIELD_QSET_ADD(qset, bcmFieldQualifyInPort); 150 151 BCM_IF_ERROR_RETURN(bcm_field_group_create(unit, qset, BCM_FIELD_GROUP_PRIO_ANY, &group)); 152 153 BCM_IF_ERROR_RETURN(bcm_field_entry_create(unit, group, &entry)); 154 155 BCM_IF_ERROR_RETURN(bcm_field_qualify_InPort(unit, entry, port, BCM_FIELD_EXACT_MATCH_MASK)); 156 BCM_IF_ERROR_RETURN(bcm_field_action_add(unit, entry, bcmFieldActionCopyToCpu, 0, 0)); 157 158 BCM_IF_ERROR_RETURN(bcm_field_entry_install(unit, entry)); 159 return BCM_E_NONE; 160 } 161 162 /* 163 * Configures the port in loopback mode and installs 164 * an IFP rule. This IFP rule copies the packets ingressing 165 * on the specified port to CPU and drop the packets. This is 166 * to avoid continuous loopback of the packet. 167 */ 168 bcm_error_t egress_port_setup(int unit, bcm_port_t port) 169 { 170 bcm_field_qset_t qset; 171 bcm_field_group_t group; 172 bcm_field_entry_t entry; 173 174 BCM_IF_ERROR_RETURN(bcm_port_loopback_set(unit, port, BCM_PORT_LOOPBACK_PHY)); 175 BCM_IF_ERROR_RETURN(bcm_port_discard_set(unit, port, BCM_PORT_DISCARD_ALL)); 176 177 BCM_FIELD_QSET_INIT(qset); 178 BCM_FIELD_QSET_ADD(qset, bcmFieldQualifyInPort); 179 180 BCM_IF_ERROR_RETURN(bcm_field_group_create(unit, qset, BCM_FIELD_GROUP_PRIO_ANY, &group)); 181 182 BCM_IF_ERROR_RETURN(bcm_field_entry_create(unit, group, &entry)); 183 184 BCM_IF_ERROR_RETURN(bcm_field_qualify_InPort(unit, entry, port, BCM_FIELD_EXACT_MATCH_MASK)); 185 BCM_IF_ERROR_RETURN(bcm_field_action_add(unit, entry, bcmFieldActionCopyToCpu, 0, 0)); 186 BCM_IF_ERROR_RETURN(bcm_field_action_add(unit, entry, bcmFieldActionDrop, 0, 0)); 187 188 BCM_IF_ERROR_RETURN(bcm_field_entry_install(unit, entry)); 189 190 return BCM_E_NONE; 191 } 192 /* Select one ingress and three egress ports and configure them in 193 * Loopback mode. Install a rule to copy incoming packets to CPU and 194 * additional action to drop the packets when it loops back on egress 195 * ports. Start packet watcher. Ingress port setup is done in 196 * ingress_port_setup(). egress port setup is done in egress_port_setup(). 197 */ 198 bcm_error_t test_setup(int unit) 199 { 200 int port_list[4], i; 201 202 if (BCM_E_NONE != portNumbersGet(unit, port_list, 4)) { 203 printf("portNumbersGet() failed\n"); 204 return -1; 205 } 206 207 ingress_port = port_list[0]; 208 egress_port1 = port_list[1]; 209 egress_port2 = port_list[2]; 210 egress_port3 = port_list[3]; 211 212 if (BCM_E_NONE != ingress_port_setup(unit, ingress_port)) { 213 printf("ingress_port_setup() failed for port %d\n", ingress_port); 214 return -1; 215 } 216 217 for (i = 1; i <= 3; i++) { 218 if (BCM_E_NONE != egress_port_setup(unit, port_list[i])) { 219 printf("egress_port_setup() failed for port %d\n", port_list[i]); 220 return -1; 221 } 222 } 223 224 bshell(unit, "pw start report +raw +decode"); 225 return BCM_E_NONE; 226 } 227 228 /* This function does the following. 229 * Transmit the below known multicast packet on ingress_port and verify 230 * that the packet egresses out of egress_port1, egress_port2 and egress_port3 using 231 * "show counters" and/or packet watcher dump on console. 232 * Packet: 233 * ====== 234 * Ethernet II, Src: Xerox_00:00:00 (00:00:04:00:00:00), Dst: Xerox_00:01:00 (01:00:04:00:01:00) 235 * 802.1Q Virtual LAN, PRI: 0, CFI: 0, ID: 2 236 * 237 * 0100 0400 0100 0000 0400 0000 8100 0002 238 * 0800 0001 0203 0405 0607 0809 0a0b 0c0d 239 * 0e0f 1011 1213 1415 1617 1819 1a1b 1c1d 240 * 1e1f 2021 2223 2425 2627 2829 2a2b 2c2d 241 * 8e0b ec9e 1cdf 4421 242 * 243 * Transmit the below unknown multicast packet on ingress_port and verify that the 244 * packet is dropped as PFM for VLAN(2) is set to 2. 245 * 246 * Packet: 247 * ====== 248 * Ethernet II, Src: Xerox_00:00:00 (00:00:04:00:00:00), Dst: Xerox_00:01:00 (01:00:03:00:01:00) 249 * 802.1Q Virtual LAN, PRI: 0, CFI: 0, ID: 2 250 * 251 * 0100 0300 0100 0000 0400 0000 8100 0002 252 * 0800 0001 0203 0405 0607 0809 0a0b 0c0d 253 * 0e0f 1011 1213 1415 1617 1819 1a1b 1c1d 254 * 1e1f 2021 2223 2425 2627 2829 2a2b 2c2d 255 * 5ca6 4d2a 1cdf 4421 256 */ 257 void verify(int unit) 258 { 259 char str[512]; 260 bshell(unit, "hm ieee"); 261 printf("Transmiting known multicast packet on ingress_port:%d\n", ingress_port); 262 snprintf(str, 512, "tx 1 pbm=%d data=0x010004000100000004000000810000020800000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D8E0BEC9E; sleep 1", ingress_port); 263 bshell(unit, str); 264 printf("Executing 'show c'\n"); 265 bshell(unit, "show c"); 266 bshell(unit, "clear c"); 267 268 269 printf("Transmiting unknown multicast packet on ingress_port:%d\n", ingress_port); 270 snprintf(str, 512, "tx 1 pbm=%d data=0x010003000100000004000000810000020800000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D5CA64D2A; sleep 1", ingress_port); 271 bshell(unit, str); 272 printf("Executing 'show c'\n"); 273 bshell(unit, "show c"); 274 bshell(unit, "clear c"); 275 276 } 277 278 /* Create vlan and add port to vlan */ 279 int 280 create_vlan_add_port(int unit, bcm_vlan_t vlan, bcm_port_t port) 281 { 282 bcm_error_t rv; 283 bcm_pbmp_t pbmp, ubmp; 284 285 BCM_PBMP_CLEAR(ubmp); 286 BCM_PBMP_CLEAR(pbmp); 287 BCM_PBMP_PORT_ADD(pbmp, port); 288 289 rv = bcm_vlan_create(unit, vlan); 290 if ((BCM_FAILURE(rv)) & (rv != BCM_E_EXISTS)) { 291 printf("Error in configuring vlan : %s.\n", bcm_errmsg(rv)); 292 return rv; 293 } 294 rv = bcm_vlan_port_add(unit, vlan, pbmp, ubmp); 295 if (BCM_FAILURE(rv)) { 296 printf("Error executing bcm_vlan_port_add(): %s.\n", bcm_errmsg(rv)); 297 return rv; 298 } 299 return BCM_E_NONE; 300 } 301 302 /* Adding egress ports to multicast group */ 303 int 304 multicast_egress_add(int unit, bcm_multicast_t l2mc_group, bcm_port_t port, 305 bcm_vlan_t vlan) 306 { 307 bcm_error_t rv; 308 bcm_gport_t gport; 309 bcm_if_t encap; 310 311 rv = bcm_port_gport_get(unit, port, &gport); 312 if (BCM_FAILURE(rv)) { 313 printf("Error in gport get : %s.\n", bcm_errmsg(rv)); 314 return rv; 315 } 316 317 /* Getting encap for L2 multicast */ 318 rv = bcm_multicast_l2_encap_get(unit, l2mc_group, gport, vlan, &encap); 319 if (BCM_FAILURE(rv)) { 320 printf("Error in encap get : %s.\n", bcm_errmsg(rv)); 321 return rv; 322 } 323 324 /* Adding port to multicast index */ 325 rv = bcm_multicast_egress_add(unit, l2mc_group, gport, encap); 326 if (BCM_FAILURE(rv)) { 327 printf("Error in egress add : %s.\n", bcm_errmsg(rv)); 328 return rv; 329 } 330 331 return BCM_E_NONE; 332 } 333 334 /* Configuring L2 Multicast */ 335 int 336 configure_multicast(int unit, bcm_vlan_t egr_vlan, bcm_multicast_t* l2mc_group) 337 { 338 bcm_error_t rv; 339 int num_ports = 3; 340 bcm_port_t egr_port[num_ports] = {egress_port1, egress_port2, egress_port3}; 341 int i; 342 343 /* Create multicast group */ 344 rv = bcm_multicast_create(unit, BCM_MULTICAST_TYPE_L2, l2mc_group); 345 if (BCM_FAILURE(rv)) { 346 printf("Error in creating multicast group : %s.\n", bcm_errmsg(rv)); 347 return rv; 348 } 349 350 for(i = 0; i < num_ports; i++) { 351 rv = create_vlan_add_port(unit, egr_vlan, egr_port[i]); 352 if (BCM_FAILURE(rv)) { 353 printf("Error in configuring vlan : %s.\n", bcm_errmsg(rv)); 354 return rv; 355 } 356 rv = multicast_egress_add(unit, *l2mc_group, egr_port[i], egr_vlan); 357 if (BCM_FAILURE(rv)) { 358 printf("Error in multicast egress add : %s.\n", bcm_errmsg(rv)); 359 return rv; 360 } 361 } 362 363 return BCM_E_NONE; 364 } 365 366 /* Configuring Port Filtering Mode */ 367 int 368 configure_pfm(int unit, bcm_vlan_mcast_flood_t mode, bcm_vlan_t vlan, 369 bcm_multicast_t l2mc_group) 370 { 371 bcm_error_t rv; 372 bcm_vlan_control_vlan_t vlan_ctrl; 373 int valid_field = BCM_VLAN_CONTROL_VLAN_L2_MCAST_FLOOD_MODE_MASK; 374 375 bcm_vlan_control_vlan_t_init(&vlan_ctrl); 376 vlan_ctrl.l2_mcast_flood_mode = mode; 377 378 rv = bcm_vlan_control_vlan_selective_set(unit, vlan, valid_field, &vlan_ctrl); 379 if(BCM_FAILURE(rv)) { 380 printf("\nError in configuring vlan control: %s.\n",bcm_errmsg(rv)); 381 return rv; 382 } 383 384 return BCM_E_NONE; 385 } 386 387 /* Adding multicast mac in L2 entry */ 388 int 389 add_multicast_mac(int unit, bcm_mac_t mc_mac, bcm_vlan_t ing_vlan, 390 bcm_port_t ing_port, bcm_multicast_t l2mc_group) 391 { 392 bcm_error_t rv; 393 bcm_l2_addr_t l2_addr; 394 395 rv = create_vlan_add_port(unit, ing_vlan, ing_port); 396 if (BCM_FAILURE(rv)) { 397 printf("Error in adding ingress port to vlan : %s.\n", bcm_errmsg(rv)); 398 return rv; 399 } 400 401 bcm_l2_addr_t_init(l2_addr, mc_mac, ing_vlan); 402 403 l2_addr.flags = BCM_L2_MCAST; 404 l2_addr.l2mc_group = l2mc_group; 405 406 rv = bcm_l2_addr_add(unit, &l2_addr); 407 if (BCM_FAILURE(rv)) { 408 printf("Error executing bcm_l2_addr_add() : %s.\n", bcm_errmsg(rv)); 409 return rv; 410 } 411 412 return BCM_E_NONE; 413 } 414 /* 1)Create a VLAN(2) and add egress_port1, egress_port2 and egress_port3 415 * as members. 416 * 2)Create a L2 multicast group and add the L2 multicast encap IDs to 417 * this L2 multicast group. 418 * 3)Configure the PFM mode as BCM_VLAN_MCAST_FLOOD_NONE(mode 2). 419 * 4)Add ingress_port as member of vlan(2) and add an entry into L2 table 420 * specifying the L2 multicast group as destination for the multicast MAC 421 * address. 422 */ 423 424 bcm_error_t configure_l2_mc(int unit) 425 { 426 bcm_error_t rv; 427 bcm_vlan_mcast_flood_t mode = BCM_VLAN_MCAST_FLOOD_NONE; /* Mode 2 */ 428 bcm_mac_t l2mc_mac = {0x01, 0x00, 0x04, 0x00, 0x01, 0x00}; 429 bcm_vlan_t vlan = 2; 430 bcm_port_t ing_port = ingress_port; 431 bcm_multicast_t mc_group; 432 433 rv = configure_multicast(unit, vlan, &mc_group); 434 if(BCM_FAILURE(rv)) { 435 printf("\nError in configuring L2 multicast: %s.\n",bcm_errmsg(rv)); 436 return rv; 437 } 438 439 /* Configuring Port Filtering Mode */ 440 441 /* 442 * Mode 0 - BCM_VLAN_MCAST_FLOOD_ALL 443 * Mode 1 - BCM_VLAN_MCAST_FLOOD_UNKNOWN 444 * Mode 2 - BCM_VLAN_MCAST_FLOOD_NONE 445 */ 446 447 rv = configure_pfm(unit, mode, vlan, mc_group); 448 if(BCM_FAILURE(rv)) { 449 printf("\nError in configuring PFM for L2 multicast: %s.\n", 450 bcm_errmsg(rv)); 451 return rv; 452 } 453 454 rv = add_multicast_mac(unit, l2mc_mac, vlan, ing_port, mc_group); 455 if(BCM_FAILURE(rv)) { 456 printf("\nError in adding multicast mac: %s.\n",bcm_errmsg(rv)); 457 return rv; 458 } 459 460 return BCM_E_NONE; 461 } 462 /* 463 * This functions does the following 464 * a)test setup 465 * b)actual configuration (Done in configure_l2_mc()) 466 * c)demonstrates the functionality(done in verify()). 467 */ 468 bcm_error_t execute() 469 { 470 bcm_error_t rv; 471 int unit =0; 472 473 bshell(unit, "config show; a ; version"); 474 475 if (BCM_FAILURE((rv = test_setup(unit)))) { 476 printf("test_setup() failed.\n"); 477 return -1; 478 } 479 printf("Completed test setup successfully.\n"); 480 481 if (BCM_FAILURE((rv = configure_l2_mc(unit)))) { 482 printf("configure_l2_mc() failed.\n"); 483 return -1; 484 } 485 printf("Completed configuration(i.e executing configure_l2_mc()) successfully.\n"); 486 487 verify(unit); 488 return BCM_E_NONE; 489 } 490 491 const char *auto_execute = (ARGC == 1) ? ARGV[0] : "YES"; 492 if (!sal_strcmp(auto_execute, "YES")) { 493 print execute(); 494 }