OpenNSL API Guide and Reference Manual
example_routing.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_routing.c
20  *
21  * \brief OPENNSL example program to demonstrate routing
22  *
23  * \details This example demonstrates routing of packets across
24  * two different VLAN's by using host route and default routes.
25  * In the first case, switch installs a host route to route
26  * packets from INGRESS_VLAN, destination MAC = MY_MAC to HOST1
27  * attached to EGRESS_VLAN. But, in the second case a default
28  * route is installed to route packets from INGRESS_VLAN,
29  * destination MAC = MY_MAC destined to DEFAULT_SUBNET_IP to
30  * egress port that is a member of EGRESS_VLAN.
31  *
32  **********************************************************************/
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <string.h>
36 #include <sal/driver.h>
37 #include <opennsl/error.h>
38 #include <opennsl/vlan.h>
39 #include <opennsl/switch.h>
40 #include <opennsl/l2.h>
41 #include <opennsl/l3.h>
42 #include <examples/util.h>
43 
44 char example_usage[] =
45 "Syntax: example_routing \n\r"
46 " \n\r"
47 "Paramaters: \n\r"
48 " in_sysport - Ingress port number on which test packet is \n\r"
49 " received \n\r"
50 " out_sysport - Egress port number to which packet is routed. \n\r"
51 " \n\r"
52 "Example: The following command is used to demonstrate routing from \n\r"
53 " port 2 to port 6. \n\r"
54 " example_routing 2 6 \n\r"
55 " \n\r"
56 "Usage Guidelines: This program request the user to enter the \n\r"
57 " ingress and egress port numbers. Using the host route, it routes\n\r"
58 " the packets arrived on ingress port with VLAN = 10, \n\r"
59 " destination MAC = 00:11:22:33:99:58 to host 20.1.1.2 attached \n\r"
60 " to egress port that is a member of VLAN 20. Using the default \n\r"
61 " route, it also routes packets with VLAN = 10, destination \n\r"
62 " MAC = 00:11:22:33:99:58 destinated to subnet 55.0.0.0 to egress \n\r"
63 " port that is a member of VLAN 20. \n\r"
64 " The routed packet should have destination MAC same as \n\r"
65 " 00:00:70:5B:C7:34 with TTL decremented by 1. \n\r";
66 
67 
68 #define DEFAULT_UNIT 0
69 #define INGRESS_VLAN 10
70 #define EGRESS_VLAN 20
71 #define HOST1 0x14010102 /* 20.1.1.2 */
72 #define MY_MAC {0x00, 0x11, 0x22, 0x33, 0x99, 0x58}
73 /* __doxy_func_body_end__ */
74 #define NEXTHOP_MAC {0x00, 0x00, 0x70, 0x5B, 0xC7, 0x34}
75 /* __doxy_func_body_end__ */
76 #define DEFAULT_SUBNET_IP 0x37000000 /* 55.0.0.0 */
77 #define DEFAULT_SUBNET_MASK 0xff000000 /* /8 network */
78 
79 /**************************************************************************/
88 void print_host(char *type, opennsl_ip_t host, int vrf)
89 {
90  printf("%s vrf : %d ", type, vrf);
91  print_ip_addr("", host);
92 }
93 /* __doxy_func_body_end__ */
94 
95 /**************************************************************************/
105 void print_route(char *type, uint32 addr, uint32 mask, int vrf)
106 {
107  printf("%s vrf : %d ", type, vrf);
108  print_ip_addr("", addr);
109  printf("/");
110  print_ip_addr("", mask);
111 }
112 /* __doxy_func_body_end__ */
113 
114 /**************************************************************************/
125 int example_host_add(int unit, uint32 addr, int vrf, int intf)
126 {
127  int rc;
128  opennsl_l3_host_t l3host;
129 
130  opennsl_l3_host_t_init(&l3host);
131 
132  l3host.l3a_flags = 0;
133  l3host.l3a_ip_addr = addr;
134  l3host.l3a_vrf = vrf;
135  l3host.l3a_intf = intf;
136  l3host.l3a_port_tgid = 0;
137 
138  rc = opennsl_l3_host_add(unit, &l3host);
139  if (rc != OPENNSL_E_NONE) {
140  printf ("opennsl_l3_host_add failed: %x \n", rc);
141  }
142 
143  return rc;
144 }
145 /* __doxy_func_body_end__ */
146 
147 /**************************************************************************/
160 int example_route_add(int unit, uint32 addr, uint32 mask, int vrf, int intf) {
161  int rc;
162  opennsl_l3_route_t l3rt;
163 
165 
166  l3rt.l3a_flags = 0;
167  l3rt.l3a_subnet = addr;
168  l3rt.l3a_ip_mask = mask;
169  l3rt.l3a_vrf = vrf;
170  l3rt.l3a_intf = intf;
171  l3rt.l3a_port_tgid = 0;
172 
173  rc = opennsl_l3_route_add(unit, &l3rt);
174  if (rc != OPENNSL_E_NONE) {
175  printf ("opennsl_l3_route_add failed: %x \n", rc);
176  }
177 
178  print_route("add route", addr, mask, vrf);
179  printf("---> egress-object=0x%08x, \n", intf);
180 
181  return rc;
182 }
183 /* __doxy_func_body_end__ */
184 
185 /**************************************************************************/
204 int example_create_l3_intf(int unit, uint32 flags, opennsl_gport_t port, int vlan,
205  int vrf, opennsl_mac_t mac_addr, int ttl, int *intf)
206 {
207  int rc, station_id;
208  opennsl_l3_intf_t l3if;
209  opennsl_l3_ingress_t l3_ing_if;
210  opennsl_l2_station_t station;
211 
212  opennsl_l3_intf_t_init(&l3if);
213  opennsl_l3_ingress_t_init(&l3_ing_if);
214  opennsl_l2_station_t_init(&station);
215 
216  /* set my-Mac global MSB */
217  station.flags = 0;
218  memcpy(station.dst_mac, mac_addr, 6);
219  station.vlan_mask = 0; /* vsi is not valid */
220  station.dst_mac_mask[0] = 0xff; /* dst_mac my-Mac MSB mask is -1 */
221  station.dst_mac_mask[1] = 0xff;
222  station.dst_mac_mask[2] = 0xff;
223  station.dst_mac_mask[3] = 0xff;
224  station.dst_mac_mask[4] = 0xff;
225  station.dst_mac_mask[5] = 0xff;
226 
227  rc = opennsl_l2_station_add(unit, &station_id, &station);
228  if (rc != OPENNSL_E_NONE) {
229  return rc;
230  }
231 
232  rc = opennsl_vlan_create(unit, vlan);
233  if (rc == OPENNSL_E_EXISTS) {
234  printf("vlan (%d) already exists", vlan);
235  }
236  else if (rc != OPENNSL_E_NONE) {
237  printf("fail open vlan (%d)", vlan);
238  printf(" continue..\n");
239  }
240 
241  rc = opennsl_vlan_gport_add(unit, vlan, port, 0);
242  if (rc != OPENNSL_E_NONE) {
243  printf("fail add port(0x%08x) to vlan(%d)\n", port, vlan);
244  return rc;
245  }
246 
247  memcpy(l3if.l3a_mac_addr, mac_addr, 6);
248  l3if.l3a_vid = vlan;
249  l3if.l3a_ttl = ttl;
250  l3if.l3a_mtu = 1524;
251  l3if.l3a_flags = flags;
252  l3if.l3a_intf_id = *intf;
253 
254  rc = opennsl_l3_intf_create(unit, &l3if);
255  if (rc != OPENNSL_E_NONE) {
256  return rc;
257  }
258  *intf = l3if.l3a_intf_id;
259 
260  l3_ing_if.flags = OPENNSL_L3_INGRESS_WITH_ID | OPENNSL_L3_INGRESS_GLOBAL_ROUTE; /* must, as we update exist RIF */
261  l3_ing_if.vrf = vrf;
262 
263  rc = opennsl_l3_ingress_create(unit, &l3_ing_if, &l3if.l3a_intf_id);
264  if (rc != OPENNSL_E_NONE) {
265  return rc;
266  }
267 
268  return rc;
269 }
270 /* __doxy_func_body_end__ */
271 
272 /**************************************************************************/
292 int example_create_l3_egress(int unit, uint32 flags, int out_port, int vlan,
293  int l3_eg_intf, opennsl_mac_t nhop_mac_addr, int *intf, int *encap_id)
294 {
295  int rc;
296  opennsl_l3_egress_t l3eg;
297  opennsl_if_t l3egid;
298  int mod = 0;
299 
301 
302  l3eg.intf = l3_eg_intf;
303  memcpy(l3eg.mac_addr, nhop_mac_addr, 6);
304  l3eg.vlan = vlan;
305  l3eg.module = mod;
306  l3eg.port = out_port;
307  l3eg.encap_id = *encap_id;
308  l3egid = *intf;
309  l3eg.flags = flags;
310 
311  rc = opennsl_l3_egress_create(unit, flags, &l3eg, &l3egid);
312  if (rc != OPENNSL_E_NONE) {
313  printf("Error, create egress object, out_port = %d, \n", out_port);
314  return rc;
315  }
316  *encap_id = l3eg.encap_id;
317  *intf = l3egid;
318 
319  return rc;
320 }
321 /* __doxy_func_body_end__ */
322 
323 /**************************************************************************/
332 int example_ipv4_route_setup(int unit, int in_port, int out_port)
333 {
334  int rv;
335  int ing_intf_in;
336  int ing_intf_out;
337  int fec[2];
338  int encap_id[2];
339  int flags = 0;
340  int in_vlan = INGRESS_VLAN;
341  int out_vlan = EGRESS_VLAN;
342  int vrf = 0;
343  opennsl_mac_t my_mac_address = MY_MAC;
344  opennsl_mac_t next_hop_mac = NEXTHOP_MAC;
345  uint32 host = HOST1;
346 
347  /*** create ingress router interface ***/
348  rv = example_create_l3_intf(unit, flags, in_port, in_vlan, vrf, my_mac_address, 62, &ing_intf_in);
349  if (rv != OPENNSL_E_NONE) {
350  printf("Error, create ingress interface, in_port = %d, \n", in_port);
351  }
352  printf("---> Ingress router intf = 0x%08x created on port %d\n", ing_intf_in, in_port);
353 
354  /*** create egress router interface ***/
355  rv = example_create_l3_intf(unit, flags, out_port, out_vlan, vrf, my_mac_address, 62, &ing_intf_out);
356  if (rv != OPENNSL_E_NONE) {
357  printf("Error, create ingress enterface, out_port = %d, \n", out_port);
358  }
359  printf("---> Ingress router intf = 0x%08x created on port %d\n", ing_intf_out, out_port);
360 
361  /*** create egress object 1 ***/
362  fec[0] = 0;
363  encap_id[0] = 0;
364  /* built FEC points to out-RIF and MAC address */
365  rv = example_create_l3_egress(unit, flags, out_port, out_vlan, ing_intf_out,
366  next_hop_mac, &fec[0], &encap_id[0]);
367  if (rv != OPENNSL_E_NONE) {
368  printf("Error, create egress object, out_port = %d, \n", out_port);
369  }
370  printf("---> Egress interface = 0x%08x, \n", ing_intf_out);
371  printf(" created FEC-id = 0x%08x, \n", fec[0]);
372  printf(" next hop mac at encap-id %08x, \n", encap_id[0]);
373 
374  /*** add IPV4 host entry with OUT-RIF + MAC + eg-port ***/
375  rv = example_host_add(unit, host, vrf, fec[0]);
376  if (rv != OPENNSL_E_NONE) {
377  printf("Error, example_host_add\n");
378  }
379 
380  print_host("add host ", host, vrf);
381  printf("---> egress-intf = 0x%08x, port = %d, \n", ing_intf_out, out_port);
382 
383  /*** add route point to FEC2 ***/
384  int route = DEFAULT_SUBNET_IP;
385  int mask = DEFAULT_SUBNET_MASK;
386 
387  rv = example_route_add(unit, route, mask, vrf, fec[0]) ;
388  if (rv != OPENNSL_E_NONE) {
389  printf("Error, failed to add route\n");
390  return rv;
391  }
392 
393  return rv;
394 }
395 /* __doxy_func_body_end__ */
396 
397 /*****************************************************************/
404 int main(int argc, char *argv[])
405 {
406  int rv = 0;
407  int choice;
408  int in_sysport;
409  int out_sysport;
410  int index = 0;
411  int unit = DEFAULT_UNIT;
412 
413  if(strcmp(argv[0], "gdb") == 0)
414  {
415  index = 1;
416  }
417  if((argc != (index + 3)) || ((argc > (index + 1))
418  && (strcmp(argv[index + 1], "--help") == 0))) {
419  printf("%s\n\r", example_usage);
420  return OPENNSL_E_PARAM;
421  }
422 
423  /* Initialize the system */
425 
426  if(rv != 0) {
427  printf("\r\nFailed to initialize the system.\r\n");
428  return rv;
429  }
430 
431  /* Extract inputs parameters */
432  in_sysport = atoi(argv[index + 1]);
433  out_sysport = atoi(argv[index + 2]);
434 
435  rv = example_port_default_config(unit);
436  if (rv != OPENNSL_E_NONE) {
437  printf("\r\nFailed to apply default config on ports, rc = %d (%s).\r\n",
438  rv, opennsl_errmsg(rv));
439  }
440 
441  rv = example_ipv4_route_setup(0, in_sysport, out_sysport);
442  if (rv != OPENNSL_E_NONE) {
443  printf("\r\nFailed to configure routing, rc = %d (%s).\r\n",
444  rv, opennsl_errmsg(rv));
445  }
446 
447  while(1) {
448  printf("\r\nUser menu: Select one of the following options\r\n");
449 #ifdef INCLUDE_DIAG_SHELL
450  printf("9. Launch diagnostic shell\n");
451 #endif
452  printf("0. Quit the application.\r\n");
453 
455  {
456  printf("Invalid option entered. Please re-enter.\n");
457  continue;
458  }
459  switch(choice)
460  {
461 #ifdef INCLUDE_DIAG_SHELL
462  case 9:
463  {
464  opennsl_driver_shell();
465  break;
466  }
467 #endif
468 
469  case 0:
470  {
471  printf("Exiting the application.\n");
472  rv = opennsl_driver_exit();
473  return rv;
474  }
475  default:
476  break;
477  } /* End of switch */
478  } /* End of while */
479 
480  return rv;
481 }
482 /* __doxy_func_body_end__ */