OpenNSL API Guide and Reference Manual
example_mpls.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_mpls.c
20  *
21  * \brief OPENNSL example program to demonstrate MPLS
22  *
23  * \details This example demonstrates swapping of an incoming MPLS label
24  * in addition to pushing of a new label for MPLS packets.
25  *
26  *
27  **********************************************************************/
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <sal/driver.h>
32 #include <opennsl/types.h>
33 #include <opennsl/error.h>
34 #include <opennsl/vlan.h>
35 #include <opennsl/l2.h>
36 #include <opennsl/l3.h>
37 #include <opennsl/mpls.h>
38 #include <examples/util.h>
39 
40 
41 char example_usage[] =
42 "Syntax: example_mpls \n\r"
43 " \n\r"
44 "Paramaters: None. \n\r"
45 " \n\r"
46 "Example: The following command is used to demonstrate MPLS by taking \n\r"
47 " ingress and egress port numbers as input. \n\r"
48 " example_mpls 5 6 \n\r"
49 " \n\r"
50 "Usage Guidelines: This program request the user to enter the \n\r"
51 " ingress and egress port numbers. \n\r"
52 " \n\r"
53 " in_sysport - Ingress port number on which test packet is \n\r"
54 " received. \n\r"
55 " out_sysport - Egress port number to which packet is forwarded. \n\r"
56 " \n\r"
57 " It looks for MPLS packets arrived on in_sysport with \n\r"
58 " VLAN = 10, destination MAC = 00:00:00:00:11:11 and take the \n\r"
59 " following actions before forwarding the packet to out_sysport. \n\r"
60 " \n\r"
61 " 1a) Swap incoming label 200 with 300 \n\r"
62 " 1b) Update TTL in this label to 33 \n\r"
63 " 2a) Push/Add label 400 with TTL 64 \n\r"
64 " \n\r";
65 
66 
67 /* debug prints */
68 int verbose = 3;
69 
70 
71 #define DEFAULT_UNIT 0
72 #define MY_MAC {0x00, 0x00, 0x00, 0x00, 0x11, 0x11}
73 /* __doxy_func_body_end__ */
74 #define MAC_SA {0x00, 0x11, 0x11, 0x11, 0x11, 0x0e}
75 /* __doxy_func_body_end__ */
76 #define MAC_DA {0x00, 0x11, 0x11, 0x11, 0x11, 0x0f}
77 /* __doxy_func_body_end__ */
78 
79 #define VRF_ID 0
80 #define VPN_ID_OFFSET (1 << 12)
81 #define VPN_ID (VRF_ID + VPN_ID_OFFSET)
82 
83 #define IN_VLAN 10
84 #define OUT_VLAN 20
85 
86 #define L3_OUT_INTF_ID 31
87 
88 #define INGRESS_LABEL1_ID 200
89 #define EGRESS_LABEL1_ID 300
90 #define LABEL1_TTL 33
91 #define EGRESS_LABEL2_ID 400
92 #define LABEL2_TTL 64
93 #define MAX_DIGITS_IN_CHOICE 5
94 
95 #define CALL_IF_ERROR_RETURN(op) \
96  do { \
97  int __rv__; \
98  if ((__rv__ = (op)) < 0) { \
99  printf("%s:%s: line %d rv: %d failed: %s\n", \
100  __FILE__, __FUNCTION__, __LINE__, __rv__, \
101  opennsl_errmsg(__rv__)); \
102  } \
103  } while(0)
104 /* __doxy_func_body_end__ */
105 
106 
107 /* Declarations below */
108 static int mpls_lsr_term(int unit, int in_sysport, int out_sysport);
109 
110 /*****************************************************************/
117 int main(int argc, char *argv[])
118 {
119  int rv = 0;
120  int choice;
121  int unit = DEFAULT_UNIT;
122  int in_sysport;
123  int out_sysport;
124 
125 
126  if((argc != 3) || ((argc > 1) && (strcmp(argv[1], "--help") == 0))) {
127  printf("%s\n\r", example_usage);
128  return OPENNSL_E_PARAM;
129  }
130 
131  /* Initialize the system */
133 
134  if(rv != OPENNSL_E_NONE) {
135  printf("\r\nFailed to initialize the system.\r\n");
136  return rv;
137  }
138 
139  /* cold boot initialization commands */
140  rv = example_port_default_config(unit);
141  if (rv != OPENNSL_E_NONE) {
142  printf("\r\nFailed to apply default config on ports, rc = %d (%s).\r\n",
143  rv, opennsl_errmsg(rv));
144  }
145 
146  /* Add ports to default vlan. */
147  printf("Adding ports to default vlan.\r\n");
149  if(rv != OPENNSL_E_NONE) {
150  printf("\r\nFailed to add default ports. Error: %s\r\n",
151  opennsl_errmsg(rv));
152  }
153 
154  /* Extract inputs parameters */
155  in_sysport = atoi(argv[1]);
156  out_sysport = atoi(argv[2]);
157 
158  /* Call the MPLS action routine */
159  mpls_lsr_term(unit, in_sysport, out_sysport);
160 
161  while(1) {
162  printf("\r\nUser menu: Select one of the following options\r\n");
163 #ifndef CDP_EXCLUDE
164  printf("9. Launch diagnostic shell\n");
165 #endif
166  printf("0. Quit the application.\r\n");
167 
169  {
170  printf("Invalid option entered. Please re-enter.\n");
171  continue;
172  }
173  switch(choice)
174  {
175 #ifndef CDP_EXCLUDE
176  case 9:
177  {
178  opennsl_driver_shell();
179  break;
180  }
181 #endif
182 
183  case 0:
184  {
185  printf("Exiting the application.\n");
186  rv = opennsl_driver_exit();
187  return rv;
188  }
189  default:
190  break;
191  } /* End of switch */
192  } /* End of while */
193  return rv;
194 }
195 /* __doxy_func_body_end__ */
196 
197 /**************************************************************************/
206 static int mpls_lsr_term(int unit, int in_port, int out_port)
207 {
208 
209  opennsl_vpn_t vpn_type_id;
210  opennsl_mpls_vpn_config_t vpn_info;
211  opennsl_pbmp_t pbmp, ubmp;
212  opennsl_mpls_tunnel_switch_t tunnel_switch;
213  opennsl_l3_intf_t l3_intf;
214  opennsl_mac_t mac_sa = MAC_SA;
215  opennsl_l3_egress_t l3_egress;
217  opennsl_mac_t mac_da = MAC_DA;
218  opennsl_mac_t local_mac = MY_MAC;
219  opennsl_if_t egr_obj_1;
220  opennsl_mpls_egress_label_t tun_label;
221 
224 
227 
230 
231  /* Create L3 MPLS vpn */
234  vpn_info.vpn = VPN_ID;
235  vpn_info.lookup_id = 0;
237  vpn_type_id = vpn_info.vpn;
238 
239  if(verbose >= 2) {
240  printf("VPN is created with ID: %d\n", vpn_type_id);
241  }
242 
243  /* Create Incoming VLAN and ingress port to the incoming VLAN */
245  OPENNSL_PBMP_CLEAR(ubmp);
246  OPENNSL_PBMP_CLEAR(pbmp);
247  OPENNSL_PBMP_PORT_ADD(pbmp, in_port);
249 
250  if(verbose >= 2) {
251  printf("Port %d is added to Ingress VLAN %d\n", in_port, IN_VLAN);
252  }
253 
254  /* Create egress VLAN and egress port to the egress VLAN */
256  OPENNSL_PBMP_CLEAR(ubmp);
257  OPENNSL_PBMP_CLEAR(pbmp);
258  OPENNSL_PBMP_PORT_ADD(pbmp, out_port);
260 
261  if(verbose >= 2) {
262  printf("Port %d is added to Egress VLAN %d\n", out_port, OUT_VLAN);
263  }
264 
265  /* Create outgoing L3 interface */
266  opennsl_l3_intf_t_init(&l3_intf);
267  l3_intf.l3a_flags = OPENNSL_L3_WITH_ID;
268  l3_intf.l3a_intf_id = L3_OUT_INTF_ID;
269  l3_intf.l3a_vid = OUT_VLAN;
270  l3_intf.l3a_vrf = VRF_ID;
271  memcpy(l3_intf.l3a_mac_addr, mac_sa, sizeof(opennsl_mac_t));
273 
274  if(verbose >= 2) {
275  printf("\r\nOutgoing L3 interface %d is created with the following "
276  "parameters\n", l3_intf.l3a_intf_id);
277  printf(" Egress VLAN %d\n", OUT_VLAN);
278  l2_print_mac(" MAC address:", mac_sa);
279  printf("\r\n");
280  }
281 
282  /* Create outgoing egress object */
283  opennsl_l3_egress_t_init(&l3_egress);
284  CALL_IF_ERROR_RETURN(opennsl_port_gport_get(unit, out_port, &gport));
285  l3_egress.intf = L3_OUT_INTF_ID;
286  memcpy(l3_egress.mac_addr, mac_da , sizeof(opennsl_mac_t));
287  l3_egress.vlan = OUT_VLAN;
288  l3_egress.port = gport;
290  &egr_obj_1));
291  if(verbose >= 2) {
292  printf("\r\n");
293  printf("Outgoing Egress object %d is created with the "
294  "following parameters\n", egr_obj_1);
295  printf(" Port %d Egress VLAN %d L3 interface %d\n", OUT_VLAN,
296  gport, L3_OUT_INTF_ID);
297  l2_print_mac(" Next hop MAC address:", mac_da);
298  printf("\r\n");
299  }
300 
301  /* Add Entry for Incoming label Matching and SWAP */
302  opennsl_mpls_tunnel_switch_t_init(&tunnel_switch);
303  tunnel_switch.label = INGRESS_LABEL1_ID;
304  tunnel_switch.port = OPENNSL_GPORT_INVALID;
305  tunnel_switch.action = OPENNSL_MPLS_SWITCH_ACTION_SWAP;
306  tunnel_switch.vpn = vpn_type_id;
307  tunnel_switch.egress_if = egr_obj_1;
309  tunnel_switch.egress_label.label = EGRESS_LABEL1_ID;
310  tunnel_switch.egress_label.exp = 0;
311  tunnel_switch.egress_label.ttl = LABEL1_TTL;
312  tunnel_switch.egress_label.pkt_pri = 0;
313  tunnel_switch.egress_label.pkt_cfi = 0;
315 
316  if(verbose >= 2) {
317  printf("\r\n");
318  printf("Added entry for incoming label matching and Swap with the "
319  "following parameters\n");
320  printf(" Incoming label %d (0x%x)\n", INGRESS_LABEL1_ID,
322  printf(" Action SWAP\n");
323  printf(" Egress label: %d (0x%x) TTL: %d\n", EGRESS_LABEL1_ID,
325  LABEL1_TTL);
326  }
327 
328  /* Install L2 tunnel MAC */
330 
331  if(verbose >= 2) {
332  printf("\n\r");
333  printf("Installed L2 tunnel for Ingress VLAN %d ", IN_VLAN);
334  l2_print_mac("MAC address:", local_mac);
335  printf("\n\r");
336  }
337 
338  /* Add MPLS label to packet */
341  tun_label.label = EGRESS_LABEL2_ID;
342  tun_label.ttl = LABEL2_TTL;
344  1, &tun_label));
345  if(verbose >= 2) {
346  printf("Updated tunnel to add MPLS label %d with TTL %d to the packet\n",
347  tun_label.label, tun_label.ttl);
348  }
349 
350  return OPENNSL_E_NONE;
351 }
352 /* __doxy_func_body_end__ */