OpenNSL API Guide and Reference Manual
example_qos.c
Go to the documentation of this file.
1 /*********************************************************************
2  *
3  * (C) Copyright Broadcom Corporation 2013-2017
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  **********************************************************************
18  *
19  * \file example_qos.c
20  *
21  * \brief OpenNSL example application for QoS based on port
22  *
23  * \details In this example, we will map TC and DP from the packet PCP
24  * (targeted for tagged packet) including three modes:
25  * 1. map dei without cfi for s tagged packet when use_de=0
26  * 2. map dei with cfi for s tagged packet when use_de=1
27  * 3. map up to dp for c tagged packet
28  *
29  * use_de can be 0 or 1. 0 stands for not mapping dei without cfi; 1 stands for mapping dei with cfi.
30  * Send Traffic from input port, say 2 and receive it on port 3 when use_de is 0:
31  * 1. In port 2 vid 100 prio 0 cfi 0 <-----CrossConnect-----> Out port 3 vid 300 prio 1 cfi 1
32  * 2. In port 2 vid 100 prio 1 cfi 1 <-----CrossConnect-----> Out port 3 vid 300 prio 2 cfi 0
33  * 3. In port 2 vid 100 prio 2 cfi 0 <-----CrossConnect-----> Out port 3 vid 300 prio 3 cfi 1
34  * 4. In port 2 vid 100 prio 3 cfi 1 <-----CrossConnect-----> Out port 3 vid 300 prio 4 cfi 0
35  * 5. In port 2 vid 100 prio 4 cfi 0 <-----CrossConnect-----> Out port 3 vid 300 prio 5 cfi 1
36  * 6. In port 2 vid 100 prio 5 cfi 1 <-----CrossConnect-----> Out port 3 vid 300 prio 6 cfi 0
37  * 7. In port 2 vid 100 prio 6 cfi 0 <-----CrossConnect-----> Out port 3 vid 300 prio 7 cfi 1
38  * 8. In port 2 vid 100 prio 7 cfi 1 <-----CrossConnect-----> Out port 3 vid 300 prio 7 cfi 0
39  * Send Traffic from port 2 and receive it on port 3 when use_de is 1:
40  * 1. In port 2 vid 100 prio 0 cfi 0 <-----CrossConnect-----> Out port 3 vid 300 prio 1 cfi 0
41  * 2. In port 2 vid 100 prio 1 cfi 1 <-----CrossConnect-----> Out port 3 vid 300 prio 2 cfi 1
42  * 3. In port 2 vid 100 prio 2 cfi 0 <-----CrossConnect-----> Out port 3 vid 300 prio 3 cfi 0
43  * 4. In port 2 vid 100 prio 3 cfi 1 <-----CrossConnect-----> Out port 3 vid 300 prio 4 cfi 1
44  * 5. In port 2 vid 100 prio 4 cfi 0 <-----CrossConnect-----> Out port 3 vid 300 prio 5 cfi 0
45  * 6. In port 2 vid 100 prio 5 cfi 1 <-----CrossConnect-----> Out port 3 vid 300 prio 6 cfi 1
46  * 7. In port 2 vid 100 prio 6 cfi 0 <-----CrossConnect-----> Out port 3 vid 300 prio 7 cfi 0
47  * 8. In port 2 vid 100 prio 7 cfi 1 <-----CrossConnect-----> Out port 3 vid 300 prio 7 cfi 1
48  *
49  **********************************************************************/
50 
51 #include <stdio.h>
52 #include <stdlib.h>
53 #include <string.h>
54 #include <opennsl/error.h>
55 #include <opennsl/init.h>
56 #include <opennsl/port.h>
57 #include <opennsl/l2.h>
58 #include <opennsl/vlan.h>
59 #include <opennsl/switch.h>
60 #include <opennsl/vswitch.h>
61 #include <opennsl/qos.h>
62 #include <examples/util.h>
63 
64 
65 char example_usage[] =
66 "Syntax: example_qos \n\r"
67 " \n\r"
68 "Paramaters: None. \n\r"
69 " \n\r"
70 "Example: The following command is used to map the TC and DP from the \n\r"
71 " VLAN tagged packet, with tag ID 100. \n\r"
72 " \n\r"
73 " example_qos \n\r"
74 " \n\r"
75 "Usage Guidelines: None. \n\r";
76 
77 #define DEFAULT_UNIT 0
78 #define DEFAULT_VLAN 1
79 #define MAC_DA {0x00, 0x00, 0x00, 0x00, 0x00, 0x01}
80 /* __doxy_func_body_end__ */
81 #define MAC_MASK {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}
82 /* __doxy_func_body_end__ */
83 
90 
91 int pkt_pri[8] = {0,1,2,3,4,5,6,7};
92 /* __doxy_func_body_end__ */
93 int pkt_cfi[8] = {0,1,0,1,0,1,0,1};
94 /* __doxy_func_body_end__ */
95 int internal_pri[8] = {1,2,3,4,5,6,7,7};
96 /* __doxy_func_body_end__ */
97 int internal_color_stag_with_use_de[8] = {0,1,0,1,0,1,0,1};
98 /* __doxy_func_body_end__ */
99 int internal_color_stag_with_no_use_de[8] = {1,0,1,0,1,0,1,0};
100 /* __doxy_func_body_end__ */
101 int internal_color_ctag[8] = {0,0,0,0,1,1,1,1};
102 /* __doxy_func_body_end__ */
103 
107 };
108 /* __doxy_func_body_end__ */
109 
113 };
114 /* __doxy_func_body_end__ */
115 
116 
117 /* Map TC and DP from the packet PCP */
118 int qos_pcp_map_create(int unit, int port, int is_use_de)
119 {
120  int color = 0;
121  int mode = 0;
122  int rv = OPENNSL_E_NONE;
123  int idx;
124 
125  /* set the mode of mapping pcp */
127  rv = opennsl_port_dscp_map_mode_set(unit, -1, mode); /* global configuration, port has to be -1 */
128  if (rv != OPENNSL_E_NONE)
129  {
130  printf("error in opennsl_port_dscp_map_mode_set() $rv\n");
131  return rv;
132  }
133 
134  switch (is_use_de)
135  {
136  case with_no_use_de:
137  /* set the mode of mapping dei without cfi for s tagged pkt */
139  if (rv != OPENNSL_E_NONE)
140  {
141  printf("error in opennsl_switch_control_port_set() $rv\n");
142  return rv;
143  }
144 
145  /* set the mapping of TC and DP for tagged packet */
146  for (idx = 0; idx < 8; idx++)
147  {
148  /* map tc and dp from PCP for tagged pkt */
149  rv = opennsl_port_vlan_priority_map_set(unit, port, pkt_pri[idx], 0, internal_pri[idx], internal_color_stag_with_no_use_de[idx]); /* cfi must be 0 because it isn't used */
150  if (rv != OPENNSL_E_NONE)
151  {
152  printf("error in opennsl_port_vlan_priority_map_set() $rv\n");
153  return rv;
154  }
155  }
156  break;
157  case with_use_de:
158  /* set the mapping of TC for tagged packet */
159  for (idx = 0; idx < 8; idx++)
160  {
161  /* map tc from PCP for tagged packet*/
162  rv = opennsl_port_vlan_priority_map_set(unit, port, pkt_pri[idx], 0, internal_pri[idx], color); /* cfi must be 0 because it isn't used */
163  if (rv != OPENNSL_E_NONE)
164  {
165  printf("error in opennsl_port_vlan_priority_map_set() $rv\n");
166  return rv;
167  }
168 
169  /* set the mode of mapping dei with cfi */
171  if (rv != OPENNSL_E_NONE)
172  {
173  printf("error in opennsl_switch_control_port_set() $rv\n");
174  return rv;
175  }
176 
177  /* map dei with cfi for s tagged pkt */
178  rv = opennsl_port_cfi_color_set(unit, -1, pkt_cfi[idx], internal_color_stag_with_use_de[idx]); /* global configuration, port has to be -1 */
179  if (rv != OPENNSL_E_NONE)
180  {
181  printf("error in opennsl_port_cfi_color_set() $rv\n");
182  return rv;
183  }
184  }
185  break;
186  default:
187  return OPENNSL_E_PARAM;
188  }
189 
190  /* map up to dp for c tagged pkt */
191  for (idx = 0x0; idx < 0x8; idx++)
192  {
193  rv = opennsl_port_priority_color_set(unit, port, pkt_pri[idx], internal_color_ctag[idx]);
194  if (rv != OPENNSL_E_NONE)
195  {
196  printf("error in opennsl_port_priority_color_set() $rv\n");
197  return rv;
198  }
199  }
200 
201  return rv;
202 }
203 /* __doxy_func_body_end__ */
204 
205 /*
206  * Create default l2 egress mapping profile.
207  * When adding or modifying a new VLAN tag, cos of the new tag is based on the default mapping profile.
208  */
209 int qos_map_l2_eg_dft_profile(int unit, int service_type)
210 {
211  opennsl_qos_map_t l2_eg_map;
212  int flags = 0;
213  int idx = 0;
214  int rv = OPENNSL_E_NONE;
215 
216  /* Clear structure */
218 
219  if (rv != OPENNSL_E_NONE)
220  {
221  printf("error in egress PCP opennsl_qos_map_create() $rv\n");
222  return rv;
223  }
224 
225  for (idx=0; idx<16; idx++)
226  {
227  opennsl_qos_map_t_init(&l2_eg_map);
228 
229  /* Set ingress pkt_pri/cfi Priority */
230  l2_eg_map.pkt_pri = idx>>1;
231  l2_eg_map.pkt_cfi = idx&1;
232 
233  /* Set internal priority for this ingress pri */
234  l2_eg_map.int_pri = idx>>1;
235 
236  /* Set color for this ingress Priority 0:opennslColorGreen 1:opennslColorYellow */
237  l2_eg_map.color = idx&1;
238 
239  if (service_type == match_untag)
240  {
242  }
243  else if (service_type == match_otag)
244  {
246  }
247 
248  rv = opennsl_qos_map_add(unit, flags, &l2_eg_map, qos_eg_map_id_dft[service_type]);
249  if (rv != OPENNSL_E_NONE)
250  {
251  printf("error in PCP egress opennsl_qos_map_add() $rv\n");
252  return rv;
253  }
254  }
255 
256  return rv;
257 }
258 /* __doxy_func_body_end__ */
259 
260 /* edit the eve action, map internal tc and dp to pkt_pri and pkt_cfi */
261 int initial_qos_service_vlan_action_set(int unit, int service_type)
262 {
263  int rv = OPENNSL_E_NONE;
264  opennsl_vlan_port_t *vlan_port = NULL;
267 
268  switch (service_type)
269  {
270  case match_untag:
271  /* eve action for untagged service */
273  action.new_outer_vlan = down_ovlan1;
275  action.priority = qos_eg_map_id_dft[service_type];
276  vlan_port = &out_vlan_port1;
277  break;
278  case match_otag:
279  /* eve action for tagged service */
281  action.new_outer_vlan = down_ovlan2;
282  action.ot_outer_pkt_prio = opennslVlanActionReplace; /* priority is set according to pcp_vlan_profile mapping */
284  vlan_port = &out_vlan_port2;
285  break;
286  default:
287  return OPENNSL_E_PARAM;
288  }
289 
291  if (rv != OPENNSL_E_NONE)
292  {
293  printf("error in eve translation opennsl_vlan_translate_egress_action_add() $rv\n");
294  }
295 
296  return rv;
297 }
298 /* __doxy_func_body_end__ */
299 
300 
301 /* initialize the vlan port and set the default egress qos profile
302  service model: untag pkt -> vid 200
303  vid 100 -> vid 300
304 */
305 int initial_qos_service_init(int unit, opennsl_port_t port_in, opennsl_port_t port_out)
306 {
307  /* initialize the vlan ports */
308  int rv = OPENNSL_E_NONE;
309  opennsl_vlan_port_t_init(&in_vlan_port1);
310  in_vlan_port1.criteria = OPENNSL_VLAN_PORT_MATCH_PORT;
311  in_vlan_port1.port = port_in;
313 
314  opennsl_vlan_port_t_init(&out_vlan_port1);
316  out_vlan_port1.match_vlan = down_ovlan1;
317  out_vlan_port1.egress_vlan = down_ovlan1;
318  out_vlan_port1.port = port_out;
319 
320  opennsl_vlan_port_t_init(&in_vlan_port2);
322  in_vlan_port2.match_vlan = up_ovlan;
323  in_vlan_port2.egress_vlan = up_ovlan;
324  in_vlan_port2.port = port_in;
326 
327  opennsl_vlan_port_t_init(&out_vlan_port2);
329  out_vlan_port2.match_vlan = down_ovlan2;
330  out_vlan_port2.egress_vlan = down_ovlan2;
331  out_vlan_port2.port = port_out;
332 
333  /* set port VLAN domain */
334  rv = opennsl_port_class_set(unit, port_in, opennslPortClassId, port_in);
335  if (rv != OPENNSL_E_NONE)
336  {
337  printf("error in opennsl_port_class_set() $rv\n");
338  return rv;
339  }
340 
341  rv = opennsl_port_class_set(unit, port_out, opennslPortClassId, port_out);
342  if (rv != OPENNSL_E_NONE)
343  {
344  printf("error in opennsl_port_class_set() $rv\n");
345  return rv;
346  }
347 
348  /* create default egress qos profile */
351 
352  return rv;
353 }
354 /* __doxy_func_body_end__ */
355 
356 /*
357 * Set up tagged and untagged sercies, using port cross connect.
358 */
359 int initial_qos_service(int unit)
360 {
361  int rv = OPENNSL_E_NONE;
362  opennsl_gport_t in_gport1, in_gport2, out_gport1, out_gport2;
363  in_gport1 = 0;
364  in_gport2 = 0;
365  out_gport1 = 0;
366  out_gport2 = 0;
367 
368  /* create inLIF for untagged service */
369  rv = opennsl_vlan_port_create(unit, &in_vlan_port1);
370  if (rv != OPENNSL_E_NONE)
371  {
372  printf("lif_create failed! %s\n", opennsl_errmsg(rv));
373  return rv;
374  }
375  in_gport1 = in_vlan_port1.vlan_port_id;
376  printf("%d\n", in_gport1);
377 
378  /* create inLIF for tagged service */
379  rv = opennsl_vlan_port_create(unit, &in_vlan_port2);
380  if (rv != OPENNSL_E_NONE)
381  {
382  printf("lif_create failed! %s\n", opennsl_errmsg(rv));
383  return rv;
384  }
385  in_gport2 = in_vlan_port2.vlan_port_id;
386  printf("%d\n", in_gport2);
387 
388  /* create outLIF for untagged service */
389  rv = opennsl_vlan_port_create(unit, &out_vlan_port1);
390  if (rv != OPENNSL_E_NONE)
391  {
392  printf("lif_create failed! %s\n", opennsl_errmsg(rv));
393  return rv;
394  }
395  out_gport1 = out_vlan_port1.vlan_port_id;
396  printf("%d\n", out_gport1);
397 
398  /* create outLIF for tagged service */
399  rv = opennsl_vlan_port_create(unit, &out_vlan_port2);
400  if (rv != OPENNSL_E_NONE)
401  {
402  printf("lif_create failed! %s\n", opennsl_errmsg(rv));
403  return rv;
404  }
405  out_gport2 = out_vlan_port2.vlan_port_id;
406  printf("%d\n", out_gport2);
407 
408  /* add eve action for untagged service */
411 
412  gports_untag.port1 = in_gport1;
413  gports_untag.port2 = out_gport1;
414 
415  /* cross connect two lifs for untagged service */
416  rv = opennsl_vswitch_cross_connect_add(unit, &gports_untag);
417  if (rv != OPENNSL_E_NONE)
418  {
419  printf("error in opennsl_vswitch_cross_connect_add() $rv\n");
420  return rv;
421  }
422 
423  /* add eve action for tagged service */
425 
427  gports_tag.port1 = in_gport2;
428  gports_tag.port2 = out_gport2;
429 
430  /* cross connect two lifs for tagged service */
431  rv = opennsl_vswitch_cross_connect_add(unit, &gports_tag);
432  if (rv != OPENNSL_E_NONE)
433  {
434  printf("error in opennsl_vswitch_cross_connect_add() $rv\n");
435  }
436 
437  return rv;
438 }
439 /* __doxy_func_body_end__ */
440 
441 /*
442 * clean tagged and untagged sercies
443 */
445 {
446  int rv = OPENNSL_E_NONE;
447 
448 
449  gports_untag.port1 = in_vlan_port1.vlan_port_id;
450  gports_untag.port2 = out_vlan_port1.vlan_port_id;
451  gports_tag.port1 = in_vlan_port2.vlan_port_id;
452  gports_tag.port2 = out_vlan_port2.vlan_port_id;
453 
454  /* Delete the cross connected LIFs for untagged service */
455  rv = opennsl_vswitch_cross_connect_delete(unit, &gports_untag);
456  if (rv != OPENNSL_E_NONE)
457  {
458  printf("Error, opennsl_vswitch_cross_connect_delete() $rv\n");
459  return rv;
460  }
461 
462  /* Delete the cross connected LIFs for tagged service */
463  rv = opennsl_vswitch_cross_connect_delete(unit, &gports_tag);
464  if (rv != OPENNSL_E_NONE)
465  {
466  printf("Error, opennsl_vswitch_cross_connect_delete() $rv\n");
467  return rv;
468  }
469 
470  /* Delete inLIF for untagged service */
471  rv = opennsl_vlan_port_destroy(unit, in_vlan_port1.vlan_port_id);
472  if (rv != OPENNSL_E_NONE)
473  {
474  printf("Error, opennsl_vlan_port_destroy() $rv\n");
475  return rv;
476  }
477 
478  /* Delete outLIF for untagged service */
479  rv = opennsl_vlan_port_destroy(unit, out_vlan_port1.vlan_port_id);
480  if (rv != OPENNSL_E_NONE)
481  {
482  printf("Error, opennsl_vlan_port_destroy() $rv\n");
483  return rv;
484  }
485 
486  /* Delete inLIF for tagged service */
487  rv = opennsl_vlan_port_destroy(unit, in_vlan_port2.vlan_port_id);
488  if (rv != OPENNSL_E_NONE)
489  {
490  printf("Error, opennsl_vlan_port_destroy() $rv\n");
491  return rv;
492  }
493 
494  /* Delete outLIF for tagged service*/
495  rv = opennsl_vlan_port_destroy(unit, out_vlan_port2.vlan_port_id);
496  if (rv != OPENNSL_E_NONE)
497  {
498  printf("Error, opennsl_vlan_port_destroy() $rv\n");
499  return rv;
500  }
501 
502  /* destroy the qos profile */
505 
506  return rv;
507 }
508 /* __doxy_func_body_end__ */
509 
510 
511 /*****************************************************************/
518 int main(int argc, char *argv[])
519 {
520  int rv = 0;
521  int unit = DEFAULT_UNIT;
522  int choice;
523  int inport, outport, use_de;
524 
525  if((argc != 1) || ((argc > 1) && (strcmp(argv[1], "--help") == 0)))
526  {
527  printf("%s\n\r", example_usage);
528  return OPENNSL_E_PARAM;
529  }
530 
531  /* Initialize the system. */
533  if(rv != OPENNSL_E_NONE)
534  {
535  printf("\r\nFailed to initialize the system. Error: %s\r\n",
536  opennsl_errmsg(rv));
537  return rv;
538  }
539 
540  /* cold boot initialization commands */
541  rv = example_port_default_config(unit);
542  if (rv != OPENNSL_E_NONE)
543  {
544  printf("\r\nFailed to apply default config on ports, rc = %d (%s).\r\n",
545  rv, opennsl_errmsg(rv));
546  }
547 
548  /* Add ports to default vlan. */
549  printf("Adding ports to default vlan.\r\n");
551  if(rv != OPENNSL_E_NONE)
552  {
553  printf("\r\nFailed to add default ports. Error: %s\r\n",
554  opennsl_errmsg(rv));
555 
556  return rv;
557  }
558 
559  while(1) {
560  printf("\r\nUser menu: Select one of the following options\r\n");
561  printf("1. Create QoS mapping\n");
562 #ifdef INCLUDE_DIAG_SHELL
563  printf("9. Launch diagnostic shell\n");
564 #endif
565  printf("0. Quit the application.\r\n");
566 
568  {
569  printf("Invalid option entered. Please re-enter.\n");
570  continue;
571  }
572  switch(choice)
573  {
574  case 1:
575  {
576  printf("Enter the input port number(belonging to core-0):\n");
578  {
579  printf("Invalid value entered. Please re-enter.\n");
580  continue;
581  }
582 
583  printf("Enter the output port number(belonging to core-0):\n");
585  {
586  printf("Invalid value entered. Please re-enter.\n");
587  continue;
588  }
589 
590  printf("Enter whether to use DEI for QoS mapping(0/1):\n");
591  if((example_read_user_choice(&use_de) != OPENNSL_E_NONE) ||
592  ((use_de != 0) && (use_de != 1)))
593  {
594  printf("Invalid value entered. Please re-enter.\n");
595  continue;
596  }
597 
598  rv = initial_qos_service_init(unit, inport, outport);
599  if (rv != OPENNSL_E_NONE)
600  {
601  printf("\r\nFailed to initialize the QoS service. Error: %s\r\n",
602  opennsl_errmsg(rv));
603  break;
604  }
605 
606  rv = initial_qos_service(unit);
607  if (rv != OPENNSL_E_NONE)
608  {
609  printf("\r\nFailed to start the initial QoS service. Error: %s\r\n",
610  opennsl_errmsg(rv));
611  break;
612  }
613 
614  rv = qos_pcp_map_create(unit, inport, use_de);
615  if (rv != OPENNSL_E_NONE)
616  {
617  printf("\r\nFailed to create the QoS PCP mapping. Error: %s\r\n",
618  opennsl_errmsg(rv));
619  }
620 
621  break;
622  }
623 
624 #ifdef INCLUDE_DIAG_SHELL
625  case 9:
626  {
627  opennsl_driver_shell();
628  break;
629  }
630 #endif
631 
632  case 0:
633  {
634  printf("Exiting the application.\n");
635  rv = opennsl_driver_exit();
636  return rv;
637  }
638  default:
639  break;
640  } /* End of switch */
641  } /* End of while */
642 
643  return rv;
644 }
645 /* __doxy_func_body_end__ */