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