FD.io VPP  v19.08.3-2-gbabecb413
Vector Packet Processing
fib_api.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2016 Cisco and/or its affiliates.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at:
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include <vnet/vnet.h>
17 #include <vlibmemory/api.h>
18 #include <vnet/fib/fib_api.h>
19 #include <vnet/ip/ip_types_api.h>
20 #include <vnet/fib/fib_table.h>
21 #include <vnet/mfib/mfib_table.h>
23 #include <vpp/api/types.h>
24 
25 #include <vnet/vnet_msg_enum.h>
26 
27 #define vl_typedefs /* define message structures */
28 #include <vnet/vnet_all_api_h.h>
29 #undef vl_typedefs
30 
31 #define vl_endianfun /* define message structures */
32 #include <vnet/vnet_all_api_h.h>
33 #undef vl_endianfun
34 
35 /* instantiate all the print functions we know about */
36 #define vl_print(handle, ...) vlib_cli_output (handle, __VA_ARGS__)
37 #define vl_printfun
38 #include <vnet/vnet_all_api_h.h>
39 #undef vl_printfun
40 
42 
43 int
45  u32 table_id,
46  u32 *fib_index)
47 {
48  *fib_index = fib_table_find(fproto, table_id);
49 
50  if (INDEX_INVALID == *fib_index)
51  {
52  return VNET_API_ERROR_NO_SUCH_FIB;
53  }
54 
55  return (0);
56 }
57 
58 int
60  u32 table_id,
61  u32 *fib_index)
62 {
63  *fib_index = mfib_table_find(fproto, table_id);
64 
65  if (~0 == *fib_index)
66  {
67  return VNET_API_ERROR_NO_SUCH_FIB;
68  }
69 
70  return (0);
71 }
72 
73 static void
74 fib_api_next_hop_decode (const vl_api_fib_path_t *in,
75  ip46_address_t *out)
76 {
77  if (in->proto == FIB_API_PATH_NH_PROTO_IP4)
78  clib_memcpy (&out->ip4, &in->nh.address.ip4, sizeof (out->ip4));
79  else if (in->proto == FIB_API_PATH_NH_PROTO_IP6)
80  clib_memcpy (&out->ip6, &in->nh.address.ip6, sizeof (out->ip6));
81 }
82 
83 static vl_api_fib_path_nh_proto_t
85 {
86  switch (dproto)
87  {
88  case DPO_PROTO_IP4:
90  case DPO_PROTO_IP6:
92  case DPO_PROTO_MPLS:
94  case DPO_PROTO_BIER:
96  case DPO_PROTO_ETHERNET:
98  case DPO_PROTO_NSH:
99  ASSERT(0);
100  break;
101  }
102  return (FIB_API_PATH_NH_PROTO_IP4);
103 }
104 
105 
106 static void
108  vl_api_fib_path_t *fp)
109 {
110  fp->proto = fib_api_path_dpo_proto_to_nh(rpath->frp_proto);
111 
112  if (rpath->frp_proto == DPO_PROTO_IP4)
113  clib_memcpy (&fp->nh.address.ip4,
114  &rpath->frp_addr.ip4,
115  sizeof (rpath->frp_addr.ip4));
116  else if (rpath->frp_proto == DPO_PROTO_IP6)
117  clib_memcpy (&fp->nh.address.ip6,
118  &rpath->frp_addr.ip6,
119  sizeof (rpath->frp_addr.ip6));
120 }
121 
122 static int
123 fib_api_path_nh_proto_to_dpo (vl_api_fib_path_nh_proto_t pp,
124  dpo_proto_t *dproto)
125 {
126  switch (pp)
127  {
129  *dproto = DPO_PROTO_IP4;
130  break;
132  *dproto = DPO_PROTO_IP6;
133  break;
135  *dproto = DPO_PROTO_MPLS;
136  break;
138  *dproto = DPO_PROTO_BIER;
139  break;
141  *dproto = DPO_PROTO_ETHERNET;
142  break;
143  default:
144  return (-1);
145  }
146  return (0);
147 }
148 
149 int
150 fib_api_path_decode (vl_api_fib_path_t *in,
151  fib_route_path_t *out)
152 {
154  int rv = 0, n_labels;
155  vnet_main_t *vnm;
156  u8 ii;
157 
158  vnm = vnet_get_main ();
159  clib_memset(&out->frp_dpo, 0, sizeof(out->frp_dpo));
160 
161  /* enums are u32 */
162  in->flags = ntohl (in->flags);
163  in->type = ntohl (in->type);
164  in->proto = ntohl (in->proto);
165 
166  /*
167  * attributes that apply to all path types
168  */
169  out->frp_flags = 0;
170  out->frp_weight = in->weight;
171  if (0 == out->frp_weight)
172  {
173  out->frp_weight = 1;
174  }
175  out->frp_preference = in->preference;
176 
177  rv = fib_api_path_nh_proto_to_dpo(in->proto, &out->frp_proto);
178 
179  if (0 != rv)
180  return (rv);
181 
182  /*
183  * convert the flags and the AFI to determine the path type
184  */
185  if (in->flags & FIB_API_PATH_FLAG_RESOLVE_VIA_HOST)
189  if (in->flags & FIB_API_PATH_FLAG_POP_PW_CW)
191 
192  switch (in->type)
193  {
195  out->frp_sw_if_index = ntohl(in->sw_if_index);
197  break;
199  out->frp_sw_if_index = ntohl(in->sw_if_index);
201  break;
204  break;
207  out->frp_sw_if_index = ntohl(in->sw_if_index);
208  break;
211  break;
214  break;
217 
218  if (pool_is_free_index (cm->tables, ntohl (in->nh.classify_table_index)))
219  {
220  return VNET_API_ERROR_NO_SUCH_TABLE;
221  }
222  out->frp_classify_table_id = ntohl (in->nh.classify_table_index);
223  break;
226  out->frp_udp_encap_id = ntohl(in->nh.obj_id);
227  break;
230  out->frp_bier_imp = ntohl (in->nh.obj_id);
231  break;
232 
235  /* fall through */
237  switch (out->frp_proto)
238  {
239  case DPO_PROTO_IP4:
240  case DPO_PROTO_IP6:
242  out->frp_sw_if_index = ntohl(in->sw_if_index);
243  out->frp_rpf_id = ntohl(in->rpf_id);
244 
245  if (0 == out->frp_rpf_id)
246  {
247  /* allow 0 to be an unset value on the API */
248  out->frp_rpf_id = ~0;
249  }
250 
251  if (~0 != out->frp_rpf_id)
252  {
254  }
255 
256  if (~0 == out->frp_sw_if_index)
257  {
258  /* recursive or deag, validate the next-hop FIB */
259  if (~0 != out->frp_rpf_id)
260  {
263  ntohl(in->table_id),
264  &out->frp_fib_index);
265  }
266  else
267  {
270  ntohl(in->table_id),
271  &out->frp_fib_index);
272  }
273  if (0 != rv)
274  {
275  return (rv);
276  }
277  }
278  else
279  {
281  out->frp_sw_if_index))
282  {
283  return VNET_API_ERROR_NO_MATCHING_INTERFACE;
284  }
285  }
286 
287  if (ip46_address_is_zero(&out->frp_addr))
288  {
289  if (~0 == out->frp_sw_if_index &&
290  ~0 != out->frp_fib_index)
291  {
293  }
294  }
295 
296  break;
297  case DPO_PROTO_MPLS:
298  out->frp_local_label = ntohl (in->nh.via_label);
299  out->frp_eos = MPLS_NON_EOS;
300  out->frp_sw_if_index = ~0;
301  break;
302  case DPO_PROTO_BIER:
303  out->frp_sw_if_index = ntohl(in->sw_if_index);
304  out->frp_rpf_id = ntohl(in->rpf_id);
305 
306  if (!(out->frp_flags & FIB_ROUTE_PATH_BIER_IMP))
307  {
309 
310  if (ip46_address_is_zero(&out->frp_addr))
311  {
312  index_t bdti;
313 
314  bdti = bier_disp_table_find(ntohl(in->table_id));
315 
316  if (INDEX_INVALID != bdti)
317  {
318  out->frp_fib_index = bdti;
319  }
320  else
321  {
322  return (VNET_API_ERROR_NO_SUCH_FIB);
323  }
324  }
325  }
326  break;
327  case DPO_PROTO_ETHERNET:
328  out->frp_sw_if_index = ntohl(in->sw_if_index);
329  break;
330  case DPO_PROTO_NSH:
331  break;
332  }
333  }
334 
335  n_labels = in->n_labels;
336  if (n_labels != 0)
337  {
339  for (ii = 0; ii < n_labels; ii++)
340  {
341  out->frp_label_stack[ii].fml_value =
342  ntohl(in->label_stack[ii].label);
343  out->frp_label_stack[ii].fml_ttl =
344  in->label_stack[ii].ttl;
345  out->frp_label_stack[ii].fml_exp =
346  in->label_stack[ii].exp;
347  out->frp_label_stack[ii].fml_mode =
348  (in->label_stack[ii].is_uniform ?
351  }
352  }
353 
354  return (0);
355 }
356 
357 void
359  vl_api_fib_path_t *out)
360 {
361  memset (out, 0, sizeof (*out));
362 
363  out->weight = rpath->frp_weight;
364  out->preference = rpath->frp_preference;
365  out->sw_if_index = htonl (rpath->frp_sw_if_index);
366  out->proto = fib_api_path_dpo_proto_to_nh(rpath->frp_proto);
367  out->rpf_id = rpath->frp_rpf_id;
368  fib_api_next_hop_encode (rpath, out);
369 
370  if (0 != rpath->frp_fib_index)
371  {
372  if ((DPO_PROTO_IP6 == rpath->frp_proto) ||
373  (DPO_PROTO_IP4 == rpath->frp_proto))
374  {
375  if (rpath->frp_flags & FIB_ROUTE_PATH_RPF_ID)
376  {
377  out->table_id = htonl (mfib_table_get_table_id(
378  rpath->frp_fib_index,
379  dpo_proto_to_fib(rpath->frp_proto)));
380  }
381  else
382  {
383  out->table_id = htonl (fib_table_get_table_id(
384  rpath->frp_fib_index,
385  dpo_proto_to_fib(rpath->frp_proto)));
386  }
387  }
388  }
389 
390  if (rpath->frp_flags & FIB_ROUTE_PATH_DVR)
391  {
392  out->type = FIB_API_PATH_TYPE_DVR;
393  }
394  else if (rpath->frp_flags & FIB_ROUTE_PATH_ICMP_UNREACH)
395  {
396  out->type = FIB_API_PATH_TYPE_ICMP_UNREACH;
397  }
398  else if (rpath->frp_flags & FIB_ROUTE_PATH_ICMP_PROHIBIT)
399  {
401  }
402  else if (rpath->frp_flags & FIB_ROUTE_PATH_LOCAL)
403  {
404  out->type = FIB_API_PATH_TYPE_LOCAL;
405  }
406  else if (rpath->frp_flags & FIB_ROUTE_PATH_DROP)
407  {
408  out->type = FIB_API_PATH_TYPE_DROP;
409  }
410  else if (rpath->frp_flags & FIB_ROUTE_PATH_UDP_ENCAP)
411  {
412  out->type = FIB_API_PATH_TYPE_UDP_ENCAP;
413  out->nh.obj_id = rpath->frp_udp_encap_id;
414  }
415  else if (rpath->frp_flags & FIB_ROUTE_PATH_BIER_IMP)
416  {
417  out->type = FIB_API_PATH_TYPE_BIER_IMP;
418  out->nh.obj_id = rpath->frp_bier_imp;
419  }
420  else if (rpath->frp_flags & FIB_ROUTE_PATH_INTF_RX)
421  {
422  out->type = FIB_API_PATH_TYPE_INTERFACE_RX;
423  }
424  else
425  {
426  out->type = FIB_API_PATH_TYPE_NORMAL;
427  }
429  {
431  }
433  {
435  }
436 
437  out->flags = htonl (out->flags);
438  out->type = htonl (out->type);
439  out->proto = htonl (out->proto);
440 
441  if (rpath->frp_label_stack)
442  {
443  int ii;
444 
445  for (ii = 0; ii < vec_len(rpath->frp_label_stack); ii++)
446  {
447  out->label_stack[ii].label =
448  htonl(rpath->frp_label_stack[ii].fml_value);
449  out->label_stack[ii].ttl =
450  rpath->frp_label_stack[ii].fml_ttl;
451  out->label_stack[ii].exp =
452  rpath->frp_label_stack[ii].fml_exp;
453  }
454  out->n_labels = ii;
455  }
456 }
457 
458 int
460  u8 is_multipath,
461  u32 fib_index,
462  const fib_prefix_t * prefix,
464  fib_route_path_t *rpaths)
465 {
466  if (is_multipath)
467  {
468  if (vec_len(rpaths) == 0)
469  return (VNET_API_ERROR_NO_PATHS_IN_ROUTE);
470 
471  /* Iterative path add/remove */
472  if (is_add)
473  fib_table_entry_path_add2 (fib_index,
474  prefix,
476  entry_flags,
477  rpaths);
478  else
479  fib_table_entry_path_remove2 (fib_index,
480  prefix,
482  rpaths);
483  }
484  else
485  {
486  if (is_add)
487  {
488  if (vec_len(rpaths) == 0)
489  return (VNET_API_ERROR_NO_PATHS_IN_ROUTE);
490 
491  /* path replacement */
492  fib_table_entry_update (fib_index,
493  prefix,
495  entry_flags,
496  rpaths);
497  }
498  else
499  /* entry delete */
500  fib_table_entry_delete (fib_index,
501  prefix,
503  }
504 
505  return (0);
506 }
507 
508 u8*
509 format_vl_api_fib_path (u8 * s, va_list * args)
510 {
511  const vl_api_fib_path_t *path = va_arg (*args, vl_api_fib_path_t*);
512 
513  s = format (s, "sw_if_index %d", ntohl (path->sw_if_index));
514  switch (clib_net_to_host_u32(path->proto))
515  {
517  s = format (s, " %U", format_vl_api_address_union,
518  &path->nh.address, ADDRESS_IP4);
519  break;
521  s = format (s, " %U", format_vl_api_address_union,
522  &path->nh.address, ADDRESS_IP6);
523  break;
524  default:
525  break;
526  }
527  s = format (s, " weight %d", path->weight);
528  s = format (s, " preference %d", path->preference);
529  s = format (s, " type %d", ntohl(path->type));
530  s = format (s, " proto %d", ntohl(path->proto));
531  s = format (s, " flags %d", ntohl(path->flags));
532  s = format (s, " n_labels %d", ntohl(path->n_labels));
533  s = format (s, " table-id %d", ntohl(path->table_id));
534  s = format (s, " rpf-id %d", ntohl(path->rpf_id));
535 
536  return (s);
537 }
538 
541 {
542  switch (clib_net_to_host_u32 (af))
543  {
544  case ADDRESS_IP4:
545  return (FIB_PROTOCOL_IP4);
546  case ADDRESS_IP6:
547  return (FIB_PROTOCOL_IP6);
548  }
549 
550  ASSERT(0);
551  return (FIB_PROTOCOL_IP4);
552 }
553 
554 int
556 {
557  switch (fproto)
558  {
559  case FIB_PROTOCOL_IP4:
560  return (clib_net_to_host_u32 (ADDRESS_IP4));
561  case FIB_PROTOCOL_IP6:
562  return (clib_net_to_host_u32 (ADDRESS_IP6));
563  default:
564  break;
565  }
566 
567  ASSERT(0);
568  return (clib_net_to_host_u32 (ADDRESS_IP4));
569 }
#define vec_validate(V, I)
Make sure vector is long enough for given index (no header, unspecified alignment) ...
Definition: vec.h:439
dpo_id_t frp_dpo
The DPO for use with exclusive paths.
Definition: fib_types.h:580
ip46_address_t frp_addr
The next-hop address.
Definition: fib_types.h:501
static void fib_api_next_hop_encode(const fib_route_path_t *rpath, vl_api_fib_path_t *fp)
Definition: fib_api.c:107
A path that resolves via a DVR DPO.
Definition: fib_types.h:387
Pipe Mode - the default.
Definition: fib_types.h:419
mpls_eos_bit_t frp_eos
EOS bit for the resolving label.
Definition: fib_types.h:512
u8 * format_vl_api_fib_path(u8 *s, va_list *args)
Definition: fib_api.c:509
A representation of a path as described by a route producer.
Definition: fib_types.h:485
int fib_api_route_add_del(u8 is_add, u8 is_multipath, u32 fib_index, const fib_prefix_t *prefix, fib_entry_flag_t entry_flags, fib_route_path_t *rpaths)
Adding routes from the API.
Definition: fib_api.c:459
vnet_main_t * vnet_get_main(void)
Definition: misc.c:46
A Drop path - resolve the path on the drop DPO.
Definition: fib_types.h:346
vnet_interface_main_t interface_main
Definition: vnet.h:56
fib_node_index_t fib_table_entry_update(u32 fib_index, const fib_prefix_t *prefix, fib_source_t source, fib_entry_flag_t flags, fib_route_path_t *paths)
Update an entry to have a new set of paths.
Definition: fib_table.c:739
void fib_api_path_encode(const fib_route_path_t *rpath, vl_api_fib_path_t *out)
Definition: fib_api.c:358
clib_memset(h->entries, 0, sizeof(h->entries[0]) *entries)
A path that resolves via a BIER impostion object.
Definition: fib_types.h:379
index_t frp_bier_imp
A path via a BIER imposition object.
Definition: fib_types.h:518
fib_node_index_t fib_table_entry_path_add2(u32 fib_index, const fib_prefix_t *prefix, fib_source_t source, fib_entry_flag_t flags, fib_route_path_t *rpaths)
Add n paths to an entry (aka route) in the FIB.
Definition: fib_table.c:574
u32 index_t
A Data-Path Object is an object that represents actions that are applied to packets are they are swit...
Definition: dpo.h:41
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:424
dpo_proto_t frp_proto
The protocol of the address below.
Definition: fib_types.h:490
vl_api_mprefix_t prefix
Definition: ip.api:456
A path that result in received traffic being recieved/recirculated so that it appears to have arrived...
Definition: fib_types.h:355
unsigned char u8
Definition: types.h:56
enum fib_protocol_t_ fib_protocol_t
Protocol Type.
#define clib_memcpy(d, s, n)
Definition: string.h:180
fib_rpf_id_t frp_rpf_id
The RPF-ID.
Definition: fib_types.h:530
A local path with a RPF-ID => multicast traffic.
Definition: fib_types.h:359
u32 frp_sw_if_index
The interface.
Definition: fib_types.h:525
static void fib_api_next_hop_decode(const vl_api_fib_path_t *in, ip46_address_t *out)
Definition: fib_api.c:74
fib_protocol_t fib_proto_from_api_address_family(int af)
Definition: fib_api.c:540
Recursion constraint of via a host prefix.
Definition: fib_types.h:330
Aggregate type for a prefix.
Definition: fib_types.h:203
static vl_api_fib_path_nh_proto_t fib_api_path_dpo_proto_to_nh(dpo_proto_t dproto)
Definition: fib_api.c:84
A path via a UDP encap object.
Definition: fib_types.h:367
unsigned int u32
Definition: types.h:88
enum dpo_proto_t_ dpo_proto_t
Data path protocol.
u32 fib_table_find(fib_protocol_t proto, u32 table_id)
Get the index of the FIB for a Table-ID.
Definition: fib_table.c:1080
fib_protocol_t dpo_proto_to_fib(dpo_proto_t dpo_proto)
Definition: fib_types.c:263
static int fib_api_path_nh_proto_to_dpo(vl_api_fib_path_nh_proto_t pp, dpo_proto_t *dproto)
Definition: fib_api.c:123
vnet_crypto_main_t * cm
Definition: quic_crypto.c:41
fib_mpls_label_t * frp_label_stack
The outgoing MPLS label Stack.
Definition: fib_types.h:546
Recursion constraint of via an attahced prefix.
Definition: fib_types.h:334
int fib_proto_to_api_address_family(fib_protocol_t fproto)
Definition: fib_api.c:555
fib_mpls_lsp_mode_t fml_mode
The LSP mode.
Definition: fib_types.h:450
Pop a Psuedo Wire Control Word.
Definition: fib_types.h:396
void fib_table_entry_path_remove2(u32 fib_index, const fib_prefix_t *prefix, fib_source_t source, fib_route_path_t *rpaths)
Remove n paths to an entry (aka route) in the FIB.
Definition: fib_table.c:623
u32 frp_classify_table_id
Classify table ID.
Definition: fib_types.h:570
void fib_table_entry_delete(u32 fib_index, const fib_prefix_t *prefix, fib_source_t source)
Delete a FIB entry.
Definition: fib_table.c:869
#define pool_is_free_index(P, I)
Use free bitmap to query whether given index is free.
Definition: pool.h:283
mpls_label_t fml_value
The label value.
Definition: fib_types.h:445
index_t bier_disp_table_find(u32 table_id)
enum fib_entry_flag_t_ fib_entry_flag_t
struct _vnet_classify_main vnet_classify_main_t
Definition: vnet_classify.h:55
#define ASSERT(truth)
int fib_api_mtable_id_decode(fib_protocol_t fproto, u32 table_id, u32 *fib_index)
Definition: fib_api.c:59
u32 fib_table_get_table_id(u32 fib_index, fib_protocol_t proto)
Get the Table-ID of the FIB from protocol and index.
Definition: fib_table.c:1069
u8 frp_preference
A path preference.
Definition: fib_types.h:591
int fib_api_path_decode(vl_api_fib_path_t *in, fib_route_path_t *out)
Definition: fib_api.c:150
A deag path using the packet&#39;s source not destination address.
Definition: fib_types.h:363
fib_route_path_flags_t frp_flags
flags on the path
Definition: fib_types.h:595
u8 n_labels
Definition: fib_types.api:127
vnet_classify_main_t vnet_classify_main
Definition: vnet_classify.c:29
From the control plane API.
Definition: fib_entry.h:79
u32 mfib_table_get_table_id(u32 fib_index, fib_protocol_t proto)
Get the Table-ID of the FIB from protocol and index.
Definition: mfib_table.c:542
A path that resolves via another table.
Definition: fib_types.h:383
mpls_label_t frp_local_label
The MPLS local Label to reursively resolve through.
Definition: fib_types.h:508
int fib_api_table_id_decode(fib_protocol_t fproto, u32 table_id, u32 *fib_index)
Definition: fib_api.c:44
A for-us/local path.
Definition: fib_types.h:338
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
#define INDEX_INVALID
Invalid index - used when no index is known blazoned capitals INVALID speak volumes where ~0 does not...
Definition: dpo.h:47
u32 mfib_table_find(fib_protocol_t proto, u32 table_id)
Get the index of the FIB for a Table-ID.
Definition: mfib_table.c:553
vnet_sw_interface_t * sw_interfaces
Definition: interface.h:837
u32 entry_flags
Definition: ip.api:454
u8 fml_exp
EXP bits; valid only at imposition.
Definition: fib_types.h:460
u32 table_id
Definition: fib_types.api:118
u8 frp_weight
[un]equal cost path weight
Definition: fib_types.h:585
u32 frp_udp_encap_id
UDP encap ID.
Definition: fib_types.h:565
#define ip46_address_is_zero(ip46)
Definition: ip6_packet.h:93
u32 frp_fib_index
The FIB index to lookup the nexthop Only valid for recursive paths.
Definition: fib_types.h:537
u8 * format_vl_api_address_union(u8 *s, va_list *args)
Definition: types.c:52