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

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 }