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

pfc.c (7870B)


      1 /* Feature Name   : PFC(Priority Flow control) Receive & Trasmit
      2  *
      3  * Usage          : BCM.0>cint pfc.c
      4  *
      5  * Config         : pfc_config.bcm
      6  *
      7  * Log file       : pfc_log.txt
      8  *
      9  * Test Topology  :
     10  *  
     11  * DMAC=0x1            +------------+         DMAC=0x1
     12  * SMAC=0x2   +-------->   56980    +-------> SMAC=0x2
     13  * VLAN=2,Pri=2  cd0(1)|            |cd1(2)   VLAN=2,Pri=2
     14  *                     | l2:mac=0x1 |
     15  *                     |    vlan=2  |
     16  *      <-------+      |    port=2  |     <-------+
     17  *   TX PFC FRAMES     |            |  RX PFC FRAMES
     18  *                     +------------+ 
     19  *
     20  *  Summary:
     21  *  ========
     22  *  This cint example demonstrates PFC feature on TH3
     23  *
     24  *    Detailed steps done in the CINT script:
     25  *    =======================================
     26  *    1) Step1 - Test Setup (Done in test_setup())
     27  *    ============================================
     28  *      a) Select one ingress and one egress port
     29  *    2) Step2 - Configuration (Done in pfc_config())
     30  *    ===============================================
     31  *      a) Sets up required data path for traffic and enables PFC Tx and Rx on
     32  *         ports
     33  *    3) Step3 - Verification (Done in verify())
     34  *    ==========================================
     35  *      a) send at linerate to cd0 L2 learnt packets (vlan=1 prio=2 dmac=0x1 smac=0x2)
     36  *      b) Along with a), send at linerate to cd1 PFC frames with pause-control class 2 enabled
     37  *      c) Expected Result:
     38  *         ================
     39  *         For test case mentioned in a)
     40  *         On cd0 (Port-1): verify that PFC frames should be transmitted at regular intervals as
     41  *         egress port is congested.
     42  *         In 'show c' output, PFC frame Tx should be seen on cd0 (port-1)
     43  *
     44  *         On cd1 (Port-2): packets should egress at configured rate
     45  *
     46  *         For test case mentioned in b)
     47  *         Port cd1 should not egress any packets as pfc pasue frames are being
     48  *         received. In 'show c' output, there should not be any Tx on on cd1 (port-2)
     49  */
     50  
     51 cint_reset();
     52 int rv = 0;
     53 int unit = 0;
     54 bcm_port_t ing_port; /*Ingress port */
     55 bcm_port_t egr_port; /*Egress port */
     56 
     57 /* This function is written so that hardcoding of port
     58    numbers in Cint scripts is removed. This function gives
     59    required number of ports
     60 */
     61 
     62 bcm_error_t portNumbersGet(int unit, int *port_list, int num_ports)
     63 {
     64 
     65   int i=0,port=0,rv=0;
     66   bcm_port_config_t configP;
     67   bcm_pbmp_t ports_pbmp;
     68 
     69   rv = bcm_port_config_get(unit,&configP);
     70   if(BCM_FAILURE(rv)) {
     71      printf("\nError in retrieving port configuration: %s.\n",bcm_errmsg(rv));
     72      return rv;
     73   }
     74 
     75   ports_pbmp = configP.e;
     76   for (i= 1; i < BCM_PBMP_PORT_MAX; i++) {
     77     if (BCM_PBMP_MEMBER(&ports_pbmp,i)&& (port < num_ports)) {
     78         port_list[port]=i;
     79         port++;
     80     }
     81   }
     82 
     83   if (( port == 0 ) || ( port != num_ports )) {
     84        printf("portNumbersGet() failed \n");
     85        return -1;
     86   }
     87 
     88   return BCM_E_NONE;
     89 
     90 }
     91 
     92 bcm_error_t test_setup(int unit)
     93 {
     94   int port_list[2], i;
     95   if (BCM_E_NONE != portNumbersGet(unit, port_list, 2)) {
     96       printf("portNumbersGet() failed\n");
     97       return -1;
     98   }
     99 
    100   ing_port = port_list[0];
    101   egr_port = port_list[1];
    102 
    103   return BCM_E_NONE;
    104 }
    105 
    106 bcm_error_t common_data_path_init(int unit)
    107 {
    108   bcm_vlan_t vid = 2;
    109   bcm_mac_t dest_mac = "00:00:00:00:00:01"; /*Destination MAC */
    110   bcm_pbmp_t pbmp,upbmp;
    111   bcm_l2_addr_t l2addr;
    112 
    113   rv = bcm_vlan_create(unit, vid);
    114   if (rv != BCM_E_NONE) {
    115       printf("[bcm_vlan_create] returned '%s'\n",bcm_errmsg(rv));
    116       return rv;
    117   }
    118 
    119   BCM_PBMP_CLEAR(pbmp);
    120   BCM_PBMP_CLEAR(upbmp);
    121   BCM_PBMP_PORT_ADD(pbmp, ing_port);
    122   BCM_PBMP_PORT_ADD(pbmp, egr_port);
    123   rv = bcm_vlan_port_add(unit, vid, pbmp, upbmp);
    124   if (rv != BCM_E_NONE) {
    125       printf("bcm_vlan_port_add returned :%s.\n", bcm_errmsg(rv));
    126       return rv;
    127   }
    128 
    129   bcm_l2_addr_t_init(l2addr, dest_mac, vid);
    130   l2addr.port = egr_port;
    131   l2addr.flags |= BCM_L2_STATIC;
    132   rv = bcm_l2_addr_add(unit, &l2addr);
    133   if (rv != BCM_E_NONE) {
    134       printf("bcm_l2_addr_add returned :'%s'\n",bcm_errmsg(rv));
    135       return rv;
    136   }
    137   return BCM_E_NONE;
    138 }
    139 
    140 bcm_error_t pfc_setup(int unit, bcm_port_t ing_port, bcm_port_t egr_port)
    141 {
    142  uint32 limit_kbits_sec = 100000; /*Bandwidth limit on egress queue - 100 Mbps*/
    143  int enable = 1;
    144  int disable = 0;
    145  bcm_mac_t pause_smac = "00:11:22:33:44:55"; /*Source MAC on all PFC frames transmitted from a port */
    146  int num_cos = 8; /* Number of COS levels */
    147  int cos = 2; /*Priority of incoming packet on which testing is done */
    148  int pri; /* Used for iterations */
    149 
    150  /* pfc tx priotiry to pg mapping array */
    151  int pri_to_pg_array[8] = {0, 1, 2, 3, 4, 5, 6, 7}; 
    152  int profile_id = 1;
    153   
    154 /* Configure num of COS levels in the system */
    155   rv = bcm_cosq_config_set(unit, num_cos);
    156   if (rv != BCM_E_NONE) {
    157       printf("bcm_cosq_config_set returned '%s'\n",bcm_errmsg(rv)); 
    158       return rv;
    159   }
    160 
    161 /**** Egress queue rate limit settings *****
    162  **** Set the bandwidth limit on particular queue of egr port 
    163 */
    164   rv = bcm_cosq_gport_bandwidth_set(unit, egr_port, cos, limit_kbits_sec, limit_kbits_sec, 0);
    165   if (rv != BCM_E_NONE) {
    166       printf("bcm_cosq_gport_bandwidth_set returned '%s'\n",bcm_errmsg(rv));
    167       return rv;
    168   }
    169 
    170 /**** Pause Settings ****/
    171   /* Set the source MAC for PFC Transmit frames */
    172   rv = bcm_port_pause_addr_set(unit, ing_port, pause_smac);
    173   if (rv != BCM_E_NONE) { 
    174       printf("bcm_port_pause_addr_set returned '%s'\n",bcm_errmsg(rv));
    175       return rv;
    176   }
    177 
    178   /* Disable normal pause on ingress port */
    179   rv = bcm_port_pause_set(unit, ing_port, disable, disable);
    180   if (rv != BCM_E_NONE) {
    181       printf("bcm_port_pause_set~ingress returned '%s'\n",bcm_errmsg(rv));
    182       return rv;
    183   }
    184 
    185   /* Disable normal pause on egress port */
    186   rv = bcm_port_pause_set(unit, egr_port, disable, disable);
    187   if (rv != BCM_E_NONE) {
    188       printf("bcm_port_pause_set~egress returned '%s'\n",bcm_errmsg(rv));
    189       return rv;
    190   }
    191 
    192 
    193   /* set PFC-tx priority to PG mapping 1:1 mapping*/
    194   rv = bcm_cosq_priority_group_pfc_priority_mapping_profile_set(0, profile_id, 8, pri_to_pg_array);
    195   if (rv != BCM_E_NONE) {
    196      printf("bcm_cosq_priority_group_pfc_priority_mapping_profile_set returned '%s'\n",bcm_errmsg(rv));
    197      return rv;
    198   }
    199  
    200   /* Enable PFC Tx on ingress port and RX on egress port */
    201   rv = bcm_port_control_set(unit,ing_port, bcmPortControlPFCTransmit, 1);
    202   if (rv != BCM_E_NONE) {
    203       printf("bcm_port_control_set~Tx returned '%s'\n",bcm_errmsg(rv));
    204       return rv;
    205   }
    206   rv = bcm_port_control_set(unit,egr_port, bcmPortControlPFCReceive, 1);
    207   if (rv != BCM_E_NONE) {
    208       printf("bcm_port_control_set~Rx returned '%s'\n",bcm_errmsg(rv));
    209       return rv;
    210   }
    211   return BCM_E_NONE;
    212 }
    213 
    214 bcm_error_t pfc_config(int unit, bcm_port_t ing_port, bcm_port_t egr_port)
    215 {
    216   /* common data path setup */
    217   if (BCM_FAILURE((rv = common_data_path_init(unit)))) {
    218       printf("common_data_path_init() failed.: %s.\n", bcm_errmsg(rv));
    219       return rv;
    220   }
    221 
    222   /* pfc config */
    223   if (BCM_FAILURE((rv = pfc_setup(unit, ing_port, egr_port)))) {
    224       printf("pfc_setup() failed. : %s. \n", bcm_errmsg(rv)); 
    225       return rv;
    226   }
    227   return BCM_E_NONE;
    228 }
    229 
    230 /* ing_port should send PFC frame towards Ixia
    231    egr_port should not egress anything as it receives PFC pause frames from Ixia.
    232  */
    233 void verify(int unit)
    234 {
    235   bshell(unit, "show c");
    236 }
    237 
    238 bcm_error_t execute()
    239 {
    240   bcm_error_t rv;
    241   int unit = 0;
    242 
    243   bshell(unit, "config show; a ; version");
    244 
    245   /* select port */
    246   if (BCM_FAILURE((rv = test_setup(unit)))) {
    247       printf("test_setup() failed.\n");
    248       return -1;
    249   }
    250 
    251   /* pfc setup */
    252   if (BCM_FAILURE((rv = pfc_config(unit, ing_port, egr_port)))) {
    253       printf("pfc_config() failed.\n");
    254       return -1;
    255   }
    256 
    257   /* verify the result */
    258   verify(unit);
    259   return BCM_E_NONE;
    260 }
    261 
    262 const char *auto_execute = (ARGC == 1) ? ARGV[0] : "YES";
    263 if (!sal_strcmp(auto_execute, "YES")) {
    264   print execute();
    265 }
    266