l2_qos.c (14728B)
1 /* Feature : L2 QoS 2 * 3 * Usage : BCM.0> cint l2_qos.c 4 * 5 * config : vlan_config.bcm 6 * 7 * Log file : l2_qos_log.txt 8 * 9 * Test Topology : 10 * 11 * +------------------------------+ 12 * | | 13 * | | 14 * | | 15 * ingress_port | | egress_port 16 * +----------------+ SWITCH +-----------------+ 17 * | | 18 * | | 19 * | | 20 * | | 21 * | | 22 * +------------------------------+ 23 * Summary: 24 * ======== 25 * This cint example configures mapping between {L2 packet Priority + CFI bit} and 26 * {internal priority and CNG} using BCM APIs. It also shows how internal priority 27 * and CNG can be used to remark out going packet's priority and CFI fields. 28 * 29 * Detailed steps done in the CINT script: 30 * ======================================= 31 * 1) Step1 - Test Setup (Done in test_setup()): 32 * ============================================= 33 * a) Selects one ingress port and one egress port and configure them in Loopback mode. 34 * Install a rule to copy incoming packets to CPU and start packet watcher. 35 * 36 * 2) Step2 - Configuration (Done in l2_qos()): 37 * ============================================ 38 * a) Creates a VLAN(20) and add ingress port and egress port as members. 39 * 40 * b) Configure ingress port's default VLAN as 20, default packet priority as 4 and CFI as 1. 41 * 42 * c) Configure ingress QoS mapping as below and attach it to ingress_port. 43 * {packet priority(4) + CFI(1)} is mapped to {internal_priority(10) + CNG(Yellow)}. 44 * 45 * d) Configure egress QoS mapping as below and attach it to egress_port. 46 * {{internal_priority(10) + CNG(Yellow)} is mapped {packet priority(2) + CFI(0)}. 47 * 48 * 3) Step3 - Verification (Done in verify()): 49 * =========================================== 50 * a) Send the below untagged packet on ingress port. 51 * 52 * Packet: 53 * ======= 54 * Ethernet header: DA=00:00:00:00:00:02, SA=00:00:00:00:00:01 55 * 56 * 0000 0000 0002 0000 0000 0001 0001 0203 57 * 0405 0607 0809 0A0B 0C0D 0E0F 1011 1213 58 * 1415 1617 1819 1A1B 1C1D 1E1F 2021 2223 59 * 2425 2627 2829 2A2B 2C2D 2E2F DF52 E538 60 * 61 * b) Expected Result: 62 * =================== 63 * The packet going out of egress_port has packet priority as "2" and CFI as "0". 64 * Below is the packet that egresses out of egress_port. 65 * 66 * Packet: 67 * ======= 68 * Ethernet II, Src: 00:00:00_00:00:01 (00:00:00:00:00:01), Dst: 00:00:00_00:00:02 (00:00:00:00:00:02) 69 * 802.1Q Virtual LAN, PRI: 2, CFI: 0, ID: 20 70 * 010. .... .... .... = Priority: Spare (2) 71 * ...0 .... .... .... = CFI: Canonical (0) 72 * .... 0000 0001 0100 = ID: 20 73 * 74 * 0000 0000 0002 0000 0000 0001 8100 4014 75 * 0001 0203 0405 0607 0809 0a0b 0c0d 0e0f 76 * 1011 1213 1415 1617 1819 1a1b 1c1d 1e1f 77 * 2021 2223 2425 2627 2829 2a2b 2c2d 2e2f 78 * df52 e538 79 */ 80 /* Reset c interpreter*/ 81 cint_reset(); 82 bcm_port_t ingress_port, egress_port; 83 84 /* This function is written so that hardcoding of port 85 numbers in Cint scripts is removed. This function gives 86 required number of ports 87 */ 88 bcm_error_t portNumbersGet(int unit, int *port_list, int num_ports) 89 { 90 91 int i=0,port=0,rv=0; 92 bcm_port_config_t configP; 93 bcm_pbmp_t ports_pbmp; 94 95 rv = bcm_port_config_get(unit,&configP); 96 if(BCM_FAILURE(rv)) { 97 printf("\nError in retrieving port configuration: %s.\n",bcm_errmsg(rv)); 98 return rv; 99 } 100 101 ports_pbmp = configP.e; 102 for (i= 1; i < BCM_PBMP_PORT_MAX; i++) { 103 if (BCM_PBMP_MEMBER(&ports_pbmp,i)&& (port < num_ports)) { 104 port_list[port]=i; 105 port++; 106 } 107 } 108 109 if (( port == 0 ) || ( port != num_ports )) { 110 printf("portNumbersGet() failed \n"); 111 return -1; 112 } 113 114 return BCM_E_NONE; 115 116 } 117 118 /* 119 * Configures the port in loopback mode and installs 120 * an IFP rule. This IFP rule copies the packets ingressing 121 * on the specified port to CPU. 122 */ 123 bcm_error_t ingress_port_setup(int unit, bcm_port_t port) 124 { 125 bcm_field_qset_t qset; 126 bcm_field_group_t group; 127 bcm_field_entry_t entry; 128 129 BCM_IF_ERROR_RETURN(bcm_port_loopback_set(unit, port, BCM_PORT_LOOPBACK_MAC)); 130 131 BCM_FIELD_QSET_INIT(qset); 132 BCM_FIELD_QSET_ADD(qset, bcmFieldQualifyInPort); 133 134 BCM_IF_ERROR_RETURN(bcm_field_group_create(unit, qset, BCM_FIELD_GROUP_PRIO_ANY, &group)); 135 136 BCM_IF_ERROR_RETURN(bcm_field_entry_create(unit, group, &entry)); 137 138 BCM_IF_ERROR_RETURN(bcm_field_qualify_InPort(unit, entry, port, BCM_FIELD_EXACT_MATCH_MASK)); 139 BCM_IF_ERROR_RETURN(bcm_field_action_add(unit, entry, bcmFieldActionCopyToCpu, 0, 0)); 140 141 BCM_IF_ERROR_RETURN(bcm_field_entry_install(unit, entry)); 142 return BCM_E_NONE; 143 } 144 145 /* 146 * Configures the port in loopback mode and installs 147 * an IFP rule. This IFP rule copies the packets ingressing 148 * on the specified port to CPU and drop the packets. This is 149 * to avoid continuous loopback of the packet. 150 */ 151 bcm_error_t egress_port_setup(int unit, bcm_port_t port) 152 { 153 bcm_field_qset_t qset; 154 bcm_field_group_t group; 155 bcm_field_entry_t entry; 156 157 BCM_IF_ERROR_RETURN(bcm_port_loopback_set(unit, port, BCM_PORT_LOOPBACK_MAC)); 158 BCM_IF_ERROR_RETURN(bcm_port_discard_set(unit, port, BCM_PORT_DISCARD_ALL)); 159 160 BCM_FIELD_QSET_INIT(qset); 161 BCM_FIELD_QSET_ADD(qset, bcmFieldQualifyInPort); 162 163 BCM_IF_ERROR_RETURN(bcm_field_group_create(unit, qset, BCM_FIELD_GROUP_PRIO_ANY, &group)); 164 165 BCM_IF_ERROR_RETURN(bcm_field_entry_create(unit, group, &entry)); 166 167 BCM_IF_ERROR_RETURN(bcm_field_qualify_InPort(unit, entry, port, BCM_FIELD_EXACT_MATCH_MASK)); 168 BCM_IF_ERROR_RETURN(bcm_field_action_add(unit, entry, bcmFieldActionCopyToCpu, 0, 0)); 169 BCM_IF_ERROR_RETURN(bcm_field_action_add(unit, entry, bcmFieldActionDrop, 0, 0)); 170 171 BCM_IF_ERROR_RETURN(bcm_field_entry_install(unit, entry)); 172 173 return BCM_E_NONE; 174 } 175 /* 176 * This functions gets the port numbers and sets up ingress and 177 * egress ports. Check ingress_port_setup() and egress_port_setup(). 178 */ 179 bcm_error_t test_setup(int unit) 180 { 181 int port_list[2]; 182 183 if (BCM_E_NONE != portNumbersGet(unit, port_list, 2)) { 184 printf("portNumbersGet() failed\n"); 185 return -1; 186 } 187 188 ingress_port = port_list[0]; 189 egress_port = port_list[1]; 190 191 if (BCM_E_NONE != ingress_port_setup(unit, ingress_port)) { 192 printf("ingress_port_setup() failed for port %d\n", ingress_port); 193 return -1; 194 } 195 196 if (BCM_E_NONE != egress_port_setup(unit, egress_port)) { 197 printf("egress_port_setup() failed for port %d\n", egress_port); 198 return -1; 199 } 200 201 bshell(unit, "pw start report +raw +decode"); 202 return BCM_E_NONE; 203 } 204 205 /* Setup port configuration w.r.t untagged vlan id, port priority and drop precedence*/ 206 bcm_error_t port_config(int unit, bcm_port_t port, int vlan, uint8 priority, uint8 CFI) 207 { 208 bcm_error_t rv; 209 bcm_vlan_action_set_t action; 210 211 rv = bcm_port_untagged_vlan_set(unit,port,vlan); 212 if (BCM_FAILURE(rv)) { 213 printf("Error executing bcm_port_untagged_vlan_set(): %s.\n", bcm_errmsg(rv)); 214 return rv; 215 } 216 217 /* set default packet priority value in port table */ 218 rv = bcm_port_untagged_priority_set(unit, port, priority); 219 if (BCM_FAILURE(rv)) { 220 printf("Error executing bcm_port_untagged_priority_set(): %s.\n", bcm_errmsg(rv)); 221 return rv; 222 } 223 224 rv = bcm_vlan_port_default_action_get(unit, port, &action); 225 if (BCM_FAILURE(rv)) { 226 printf("Error executing bcm_vlan_port_default_action_get(): %s.\n", bcm_errmsg(rv)); 227 return rv; 228 } 229 230 rv = bcm_vlan_port_default_action_delete(unit,port); 231 if (BCM_FAILURE(rv)) { 232 printf("Error executing bcm_vlan_port_default_action_delete(): %s.\n", bcm_errmsg(rv)); 233 return rv; 234 } 235 236 action.new_outer_cfi = CFI; 237 action.priority = priority; 238 rv = bcm_vlan_port_default_action_set(unit,port,action); 239 if (BCM_FAILURE(rv)) { 240 printf("Error executing bcm_vlan_port_default_action_set(): %s.\n", bcm_errmsg(rv)); 241 return rv; 242 } 243 244 return BCM_E_NONE; 245 } 246 /* Setup L2 qos mapping */ 247 bcm_error_t 248 qos_port_setup(int unit, bcm_port_t port, unsigned int flags, uint8 internal_pri, bcm_color_t clr, uint8 priority, uint8 CFI) 249 { 250 int qMapId = 0; 251 bcm_error_t rv; 252 bcm_qos_map_t qMap; 253 bcm_gport_t gport; 254 BCM_GPORT_MODPORT_SET(gport, unit, port); 255 /* Reserve hardware resources for QoS mapping */ 256 rv = bcm_qos_map_create(unit, flags, &qMapId); 257 if (BCM_FAILURE(rv)) { 258 printf("Error executing bcm_qos_map_create(): %s.\n", bcm_errmsg(rv)); 259 return rv; 260 } 261 262 qMap.int_pri = internal_pri; 263 qMap.color = clr; 264 qMap.pkt_pri = priority; 265 qMap.pkt_cfi = CFI; 266 rv = bcm_qos_map_add(unit, flags, &qMap, qMapId); 267 if (BCM_FAILURE(rv)) { 268 printf("Error executing bcm_qos_map_add(): %s.\n", bcm_errmsg(rv)); 269 return rv; 270 } 271 272 if(flags & BCM_QOS_MAP_INGRESS) { 273 rv = bcm_qos_port_map_set(unit, gport, qMapId, -1); 274 if (BCM_FAILURE(rv)) { 275 printf("Error executing bcm_qos_port_map_set(): %s.\n", bcm_errmsg(rv)); 276 return rv; 277 } 278 } else { 279 rv = bcm_qos_port_map_set(unit, gport, -1, qMapId); 280 if (BCM_FAILURE(rv)) { 281 printf("Error executing bcm_qos_port_map_set(): %s.\n", bcm_errmsg(rv)); 282 return rv; 283 } 284 } 285 return BCM_E_NONE; 286 } 287 /* Creates a VLAN(20) and add ingress port and egress port as members. 288 * 289 * Configure ingress port's default VLAN as 20, default packet priority as 4 and CFI as 1. 290 * 291 * Configure ingress QoS mapping as below and attach it to ingress_port. 292 * {packet priority(4) + CFI(1)} is mapped to {internal_priority(10) + CNG(Yellow)}. 293 * 294 * Configure egress QoS mapping as below and attach it to egress_port. 295 * {{internal_priority(10) + CNG(Yellow)} is mapped {packet priority(2) + CFI(0)}. 296 */ 297 298 bcm_error_t l2_qos(int unit) 299 { 300 bcm_error_t rv; 301 bcm_pbmp_t pbmp, ubmp; 302 bcm_vlan_t vlanId = 20; 303 uint8 priority = 4, internal_priority = 10, CFI; 304 /* Create the vlan with specific id if it is already present then error will be returned */ 305 rv = bcm_vlan_create(unit, vlanId); 306 if (BCM_FAILURE(rv)) { 307 printf("Error executing bcm_vlan_create(): %s.\n", bcm_errmsg(rv)); 308 return rv; 309 } 310 311 /*Add ingress_port and egress_port as members of vlanId*/ 312 BCM_PBMP_CLEAR(ubmp); 313 BCM_PBMP_CLEAR(pbmp); 314 BCM_PBMP_PORT_ADD(pbmp, ingress_port); 315 BCM_PBMP_PORT_ADD(pbmp, egress_port); 316 317 rv = bcm_vlan_port_add(unit, vlanId, pbmp, ubmp); 318 if (BCM_FAILURE(rv)) { 319 printf("Error executing bcm_vlan_port_add(): %s.\n", bcm_errmsg(rv)); 320 return rv; 321 } 322 323 /* set CFI and default packet priority values in port table for untagged packets */ 324 CFI = 1; 325 rv = port_config(unit, ingress_port, vlanId, priority, CFI); 326 if (BCM_FAILURE(rv)) { 327 printf("Error executing port_config(): %s.\n", bcm_errmsg(rv)); 328 return rv; 329 } 330 331 /* Configure ingress priority mapping on port "ingress_port" 332 * for mapping {packet priority 4 + CFI 1} to internal priority 10 333 */ 334 rv = qos_port_setup(unit, ingress_port, BCM_QOS_MAP_INGRESS | BCM_QOS_MAP_L2, internal_priority, bcmColorYellow, priority, CFI); 335 if (BCM_FAILURE(rv)) { 336 printf("Error executing qos_port_setup() for ingress mapping: %s.\n", bcm_errmsg(rv)); 337 return rv; 338 } 339 340 /*Required for CFI remarking on egress port. Sets EGR_VLAN_CONTROL_1r.CFI_AS_CNGf = 1*/ 341 rv = bcm_switch_control_port_set(unit, egress_port, bcmSwitchColorSelect, BCM_COLOR_OUTER_CFI); 342 if (BCM_FAILURE(rv)) { 343 printf("Error executing bcm_switch_control_port_set(): %s.\n", bcm_errmsg(rv)); 344 return rv; 345 } 346 347 CFI = 0; 348 /* 349 * Configure egress QoS mapping as below and attach it to egress_port. 350 * {{internal_priority(10) + CNG(Yellow)} to {packet priority(2) + CFI(0)}. 351 */ 352 rv = qos_port_setup(unit, egress_port, BCM_QOS_MAP_EGRESS | BCM_QOS_MAP_L2, internal_priority, bcmColorYellow, 2, CFI); 353 if (BCM_FAILURE(rv)) { 354 printf("Error executing qos_port_setup() for egress mapping: %s.\n", bcm_errmsg(rv)); 355 return rv; 356 } 357 358 return BCM_E_NONE; 359 } 360 /* This function does the following. 361 * ============================== 362 * Send the below untagged packet on ingress port. 363 * 364 * Packet: 365 * ====== 366 * Ethernet header: DA=00:00:00:00:00:02, SA=00:00:00:00:00:01 367 * 368 * 0000 0000 0002 0000 0000 0001 0001 0203 369 * 0405 0607 0809 0A0B 0C0D 0E0F 1011 1213 370 * 1415 1617 1819 1A1B 1C1D 1E1F 2021 2223 371 * 2425 2627 2829 2A2B 2C2D 2E2F DF52 E538 372 * 373 * The below packet egresses on egress_port with packet priority 2 and CFI 0. 374 * 375 * Packet: 376 * ====== 377 * Ethernet II, Src: 00:00:00_00:00:01 (00:00:00:00:00:01), Dst: 00:00:00_00:00:02 (00:00:00:00:00:02) 378 * 802.1Q Virtual LAN, PRI: 2, CFI: 0, ID: 20 379 * 010. .... .... .... = Priority: Spare (2) 380 * ...0 .... .... .... = CFI: Canonical (0) 381 * .... 0000 0001 0100 = ID: 20 382 * 383 * 0000 0000 0002 0000 0000 0001 8100 4014 384 * 0001 0203 0405 0607 0809 0a0b 0c0d 0e0f 385 * 1011 1213 1415 1617 1819 1a1b 1c1d 1e1f 386 * 2021 2223 2425 2627 2829 2a2b 2c2d 2e2f 387 * df52 e538 388 */ 389 390 void verify(int unit) 391 { 392 char str[512]; 393 394 bshell(unit, "hm ieee"); 395 396 printf("Sending untagged packet on ingress_port:%d\n", ingress_port); 397 snprintf(str, 512, "tx 1 pbm=%d data=0x000000000002000000000001000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F202122232425262728292A2B2C2D2E2FDF52E538; sleep 1", ingress_port); 398 bshell(unit, str); 399 400 } 401 /* 402 * This functions does the following 403 * a)test setup 404 * b)actual configuration (Done in l2_qos()) 405 * c)demonstrates the functionality (Done in verify()). 406 */ 407 bcm_error_t execute() 408 { 409 bcm_error_t rv; 410 int unit =0; 411 412 bshell(unit, "config show; a ; version"); 413 414 if (BCM_FAILURE((rv = test_setup(unit)))) { 415 printf("test_setup() failed.\n"); 416 return -1; 417 } 418 printf("Completed test setup successfully.\n"); 419 420 if (BCM_FAILURE((rv = l2_qos(unit)))) { 421 printf("l2_qos() failed.\n"); 422 return -1; 423 } 424 printf("Completed configuration(i.e executing l2_qos()) successfully.\n"); 425 426 verify(unit); 427 return BCM_E_NONE; 428 } 429 430 const char *auto_execute = (ARGC == 1) ? ARGV[0] : "YES"; 431 if (!sal_strcmp(auto_execute, "YES")) { 432 print execute(); 433 } 434