FD.io VPP  v20.09-64-g4f7b92f0a
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>
25 
26 #include <vnet/vnet_msg_enum.h>
27 
28 #define vl_typedefs /* define message structures */
29 #include <vnet/vnet_all_api_h.h>
30 #undef vl_typedefs
31 
32 #define vl_endianfun /* define message structures */
33 #include <vnet/vnet_all_api_h.h>
34 #undef vl_endianfun
35 
36 /* instantiate all the print functions we know about */
37 #define vl_print(handle, ...) vlib_cli_output (handle, __VA_ARGS__)
38 #define vl_printfun
39 #include <vnet/vnet_all_api_h.h>
40 #undef vl_printfun
41 
43 
44 int
46  u32 table_id,
47  u32 *fib_index)
48 {
49  *fib_index = fib_table_find(fproto, table_id);
50 
51  if (INDEX_INVALID == *fib_index)
52  {
53  return VNET_API_ERROR_NO_SUCH_FIB;
54  }
55 
56  return (0);
57 }
58 
59 int
61  u32 table_id,
62  u32 *fib_index)
63 {
64  *fib_index = mfib_table_find(fproto, table_id);
65 
66  if (~0 == *fib_index)
67  {
68  return VNET_API_ERROR_NO_SUCH_FIB;
69  }
70 
71  return (0);
72 }
73 
74 static void
75 fib_api_next_hop_decode (const vl_api_fib_path_t *in,
76  ip46_address_t *out)
77 {
78  if (in->proto == FIB_API_PATH_NH_PROTO_IP4)
79  clib_memcpy (&out->ip4, &in->nh.address.ip4, sizeof (out->ip4));
80  else if (in->proto == FIB_API_PATH_NH_PROTO_IP6)
81  clib_memcpy (&out->ip6, &in->nh.address.ip6, sizeof (out->ip6));
82 }
83 
84 static vl_api_fib_path_nh_proto_t
86 {
87  switch (dproto)
88  {
89  case DPO_PROTO_IP4:
91  case DPO_PROTO_IP6:
93  case DPO_PROTO_MPLS:
95  case DPO_PROTO_BIER:
97  case DPO_PROTO_ETHERNET:
99  case DPO_PROTO_NSH:
100  ASSERT(0);
101  break;
102  }
103  return (FIB_API_PATH_NH_PROTO_IP4);
104 }
105 
106 
107 static void
109  vl_api_fib_path_t *fp)
110 {
111  fp->proto = fib_api_path_dpo_proto_to_nh(rpath->frp_proto);
112 
113  if (rpath->frp_proto == DPO_PROTO_IP4)
114  clib_memcpy (&fp->nh.address.ip4,
115  &rpath->frp_addr.ip4,
116  sizeof (rpath->frp_addr.ip4));
117  else if (rpath->frp_proto == DPO_PROTO_IP6)
118  clib_memcpy (&fp->nh.address.ip6,
119  &rpath->frp_addr.ip6,
120  sizeof (rpath->frp_addr.ip6));
121 }
122 
123 static int
124 fib_api_path_nh_proto_to_dpo (vl_api_fib_path_nh_proto_t pp,
125  dpo_proto_t *dproto)
126 {
127  switch (pp)
128  {
130  *dproto = DPO_PROTO_IP4;
131  break;
133  *dproto = DPO_PROTO_IP6;
134  break;
136  *dproto = DPO_PROTO_MPLS;
137  break;
139  *dproto = DPO_PROTO_BIER;
140  break;
142  *dproto = DPO_PROTO_ETHERNET;
143  break;
144  default:
145  return (-1);
146  }
147  return (0);
148 }
149 
150 int
151 fib_api_path_decode (vl_api_fib_path_t *in,
152  fib_route_path_t *out)
153 {
155  int rv = 0, n_labels;
156  vnet_main_t *vnm;
157  u8 ii;
158 
159  vnm = vnet_get_main ();
160  clib_memset(&out->frp_dpo, 0, sizeof(out->frp_dpo));
161 
162  /* enums are u32 */
163  in->flags = ntohl (in->flags);
164  in->type = ntohl (in->type);
165  in->proto = ntohl (in->proto);
166 
167  /*
168  * attributes that apply to all path types
169  */
170  out->frp_flags = 0;
171  out->frp_weight = in->weight;
172  if (0 == out->frp_weight)
173  {
174  out->frp_weight = 1;
175  }
176  out->frp_preference = in->preference;
177 
178  rv = fib_api_path_nh_proto_to_dpo(in->proto, &out->frp_proto);
179 
180  if (0 != rv)
181  return (rv);
182 
183  /*
184  * convert the flags and the AFI to determine the path type
185  */
186  if (in->flags & FIB_API_PATH_FLAG_RESOLVE_VIA_HOST)
190  if (in->flags & FIB_API_PATH_FLAG_POP_PW_CW)
192 
193  switch (in->type)
194  {
196  out->frp_sw_if_index = ntohl(in->sw_if_index);
198  break;
200  out->frp_sw_if_index = ntohl(in->sw_if_index);
202  break;
205  break;
208  out->frp_sw_if_index = ntohl(in->sw_if_index);
209  break;
212  break;
215  break;
218 
219  if (pool_is_free_index (cm->tables, ntohl (in->nh.classify_table_index)))
220  {
221  return VNET_API_ERROR_NO_SUCH_TABLE;
222  }
223  out->frp_classify_table_id = ntohl (in->nh.classify_table_index);
224  break;
227  out->frp_udp_encap_id = ntohl(in->nh.obj_id);
228  break;
231  out->frp_bier_imp = ntohl (in->nh.obj_id);
232  break;
233 
236  /* fall through */
238  switch (out->frp_proto)
239  {
240  case DPO_PROTO_IP4:
241  case DPO_PROTO_IP6:
243  out->frp_sw_if_index = ntohl(in->sw_if_index);
244  out->frp_rpf_id = ntohl(in->rpf_id);
245 
246  if (0 == out->frp_rpf_id)
247  {
248  /* allow 0 to be an unset value on the API */
249  out->frp_rpf_id = ~0;
250  }
251 
252  if (~0 != out->frp_rpf_id)
253  {
255  }
256 
257  if (~0 == out->frp_sw_if_index)
258  {
259  /* recursive or deag, validate the next-hop FIB */
260  if (~0 != out->frp_rpf_id)
261  {
264  ntohl(in->table_id),
265  &out->frp_fib_index);
266  }
267  else
268  {
271  ntohl(in->table_id),
272  &out->frp_fib_index);
273  }
274  if (0 != rv)
275  {
276  return (rv);
277  }
278  }
279  else
280  {
282  out->frp_sw_if_index))
283  {
284  return VNET_API_ERROR_NO_MATCHING_INTERFACE;
285  }
286  }
287 
288  if (ip46_address_is_zero(&out->frp_addr))
289  {
290  if (~0 == out->frp_sw_if_index &&
291  ~0 != out->frp_fib_index)
292  {
294  }
295  }
296 
297  break;
298  case DPO_PROTO_MPLS:
299  out->frp_local_label = ntohl (in->nh.via_label);
300  out->frp_eos = MPLS_NON_EOS;
301  out->frp_sw_if_index = ~0;
302  break;
303  case DPO_PROTO_BIER:
304  out->frp_sw_if_index = ntohl(in->sw_if_index);
305  out->frp_rpf_id = ntohl(in->rpf_id);
306 
307  if (!(out->frp_flags & FIB_ROUTE_PATH_BIER_IMP))
308  {
310 
311  if (ip46_address_is_zero(&out->frp_addr))
312  {
313  index_t bdti;
314 
315  bdti = bier_disp_table_find(ntohl(in->table_id));
316 
317  if (INDEX_INVALID != bdti)
318  {
319  out->frp_fib_index = bdti;
320  }
321  else
322  {
323  return (VNET_API_ERROR_NO_SUCH_FIB);
324  }
325  }
326  }
327  break;
328  case DPO_PROTO_ETHERNET:
329  out->frp_sw_if_index = ntohl(in->sw_if_index);
330  break;
331  case DPO_PROTO_NSH:
332  break;
333  }
334  }
335 
336  n_labels = in->n_labels;
337  if (n_labels != 0)
338  {
340  for (ii = 0; ii < n_labels; ii++)
341  {
342  out->frp_label_stack[ii].fml_value =
343  ntohl(in->label_stack[ii].label);
344  out->frp_label_stack[ii].fml_ttl =
345  in->label_stack[ii].ttl;
346  out->frp_label_stack[ii].fml_exp =
347  in->label_stack[ii].exp;
348  out->frp_label_stack[ii].fml_mode =
349  (in->label_stack[ii].is_uniform ?
352  }
353  }
354 
355  return (0);
356 }
357 
358 void
360  vl_api_fib_path_t *out)
361 {
362  memset (out, 0, sizeof (*out));
363 
364  out->weight = rpath->frp_weight;
365  out->preference = rpath->frp_preference;
366  out->sw_if_index = htonl (rpath->frp_sw_if_index);
367  out->proto = fib_api_path_dpo_proto_to_nh(rpath->frp_proto);
368  out->rpf_id = rpath->frp_rpf_id;
369  fib_api_next_hop_encode (rpath, out);
370 
371  if (0 != rpath->frp_fib_index)
372  {
373  if ((DPO_PROTO_IP6 == rpath->frp_proto) ||
374  (DPO_PROTO_IP4 == rpath->frp_proto))
375  {
376  if (rpath->frp_flags & FIB_ROUTE_PATH_RPF_ID)
377  {
378  out->table_id = htonl (mfib_table_get_table_id(
379  rpath->frp_fib_index,
380  dpo_proto_to_fib(rpath->frp_proto)));
381  }
382  else
383  {
384  out->table_id = htonl (fib_table_get_table_id(
385  rpath->frp_fib_index,
386  dpo_proto_to_fib(rpath->frp_proto)));
387  }
388  }
389  }
390 
391  if (rpath->frp_flags & FIB_ROUTE_PATH_DVR)
392  {
393  out->type = FIB_API_PATH_TYPE_DVR;
394  }
395  else if (rpath->frp_flags & FIB_ROUTE_PATH_ICMP_UNREACH)
396  {
397  out->type = FIB_API_PATH_TYPE_ICMP_UNREACH;
398  }
399  else if (rpath->frp_flags & FIB_ROUTE_PATH_ICMP_PROHIBIT)
400  {
402  }
403  else if (rpath->frp_flags & FIB_ROUTE_PATH_LOCAL)
404  {
405  out->type = FIB_API_PATH_TYPE_LOCAL;
406  }
407  else if (rpath->frp_flags & FIB_ROUTE_PATH_DROP)
408  {
409  out->type = FIB_API_PATH_TYPE_DROP;
410  }
411  else if (rpath->frp_flags & FIB_ROUTE_PATH_UDP_ENCAP)
412  {
413  out->type = FIB_API_PATH_TYPE_UDP_ENCAP;
414  out->nh.obj_id = rpath->frp_udp_encap_id;
415  }
416  else if (rpath->frp_flags & FIB_ROUTE_PATH_BIER_IMP)
417  {
418  out->type = FIB_API_PATH_TYPE_BIER_IMP;
419  out->nh.obj_id = rpath->frp_bier_imp;
420  }
421  else if (rpath->frp_flags & FIB_ROUTE_PATH_INTF_RX)
422  {
423  out->type = FIB_API_PATH_TYPE_INTERFACE_RX;
424  }
425  else
426  {
427  out->type = FIB_API_PATH_TYPE_NORMAL;
428  }
430  {
432  }
434  {
436  }
437 
438  out->flags = htonl (out->flags);
439  out->type = htonl (out->type);
440  out->proto = htonl (out->proto);
441 
442  if (rpath->frp_label_stack)
443  {
444  int ii;
445 
446  for (ii = 0; ii < vec_len(rpath->frp_label_stack); ii++)
447  {
448  out->label_stack[ii].label =
449  htonl(rpath->frp_label_stack[ii].fml_value);
450  out->label_stack[ii].ttl =
451  rpath->frp_label_stack[ii].fml_ttl;
452  out->label_stack[ii].exp =
453  rpath->frp_label_stack[ii].fml_exp;
454  }
455  out->n_labels = ii;
456  }
457 }
458 
459 int
461  u8 is_multipath,
462  u32 fib_index,
463  const fib_prefix_t * prefix,
465  fib_route_path_t *rpaths)
466 {
467  if (is_multipath)
468  {
469  if (vec_len(rpaths) == 0)
470  return (VNET_API_ERROR_NO_PATHS_IN_ROUTE);
471 
472  /* Iterative path add/remove */
473  if (is_add)
474  fib_table_entry_path_add2 (fib_index,
475  prefix,
477  entry_flags,
478  rpaths);
479  else
480  fib_table_entry_path_remove2 (fib_index,
481  prefix,
483  rpaths);
484  }
485  else
486  {
487  if (is_add)
488  {
489  if (vec_len(rpaths) == 0)
490  return (VNET_API_ERROR_NO_PATHS_IN_ROUTE);
491 
492  /* path replacement */
493  fib_table_entry_update (fib_index,
494  prefix,
496  entry_flags,
497  rpaths);
498  }
499  else
500  /* entry delete */
501  fib_table_entry_delete (fib_index,
502  prefix,
504  }
505 
506  return (0);
507 }
508 
509 u8*
510 format_vl_api_fib_path (u8 * s, va_list * args)
511 {
512  const vl_api_fib_path_t *path = va_arg (*args, vl_api_fib_path_t*);
513 
514  s = format (s, "sw_if_index %d", ntohl (path->sw_if_index));
515  switch (clib_net_to_host_u32(path->proto))
516  {
518  s = format (s, " %U", format_vl_api_address_union,
519  &path->nh.address, ADDRESS_IP4);
520  break;
522  s = format (s, " %U", format_vl_api_address_union,
523  &path->nh.address, ADDRESS_IP6);
524  break;
525  default:
526  break;
527  }
528  s = format (s, " weight %d", path->weight);
529  s = format (s, " preference %d", path->preference);
530  s = format (s, " type %d", ntohl(path->type));
531  s = format (s, " proto %d", ntohl(path->proto));
532  s = format (s, " flags %d", ntohl(path->flags));
533  s = format (s, " n_labels %d", ntohl(path->n_labels));
534  s = format (s, " table-id %d", ntohl(path->table_id));
535  s = format (s, " rpf-id %d", ntohl(path->rpf_id));
536 
537  return (s);
538 }
539 
540 int
541 fib_proto_from_api_address_family (vl_api_address_family_t af, fib_protocol_t * out)
542 {
543  switch (af)
544  {
545  case ADDRESS_IP4:
546  *out = (FIB_PROTOCOL_IP4);
547  return (0);
548  case ADDRESS_IP6:
549  *out = (FIB_PROTOCOL_IP6);
550  return (0);
551  }
552 
553  return (VNET_API_ERROR_INVALID_ADDRESS_FAMILY);
554 }
555 
556 vl_api_address_family_t
558 {
559  switch (fproto)
560  {
561  case FIB_PROTOCOL_IP4:
562  return (ADDRESS_IP4);
563  case FIB_PROTOCOL_IP6:
564  return (ADDRESS_IP6);
565  default:
566  break;
567  }
568 
569  ASSERT(0);
570  return (ADDRESS_IP4);
571 }
#define vec_validate(V, I)
Make sure vector is long enough for given index (no header, unspecified alignment) ...
Definition: vec.h:509
dpo_id_t frp_dpo
The DPO for use with exclusive paths.
Definition: fib_types.h:585
ip46_address_t frp_addr
The next-hop address.
Definition: fib_types.h:506
static void fib_api_next_hop_encode(const fib_route_path_t *rpath, vl_api_fib_path_t *fp)
Definition: fib_api.c:108
A path that resolves via a DVR DPO.
Definition: fib_types.h:387
Pipe Mode - the default.
Definition: fib_types.h:424
mpls_eos_bit_t frp_eos
EOS bit for the resolving label.
Definition: fib_types.h:517
u8 * format_vl_api_fib_path(u8 *s, va_list *args)
Definition: fib_api.c:510
A representation of a path as described by a route producer.
Definition: fib_types.h:490
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:460
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:59
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:756
void fib_api_path_encode(const fib_route_path_t *rpath, vl_api_fib_path_t *out)
Definition: fib_api.c:359
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:523
vl_api_address_family_t fib_proto_to_api_address_family(fib_protocol_t fproto)
Definition: fib_api.c:557
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:591
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:495
vl_api_fib_path_t path
Definition: mfib_types.api:34
vl_api_prefix_t prefix
Definition: ip.api:144
A path that result in received traffic being recieved/recirculated so that it appears to have arrived...
Definition: fib_types.h:355
int fib_proto_from_api_address_family(vl_api_address_family_t af, fib_protocol_t *out)
Definition: fib_api.c:541
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:535
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:530
static void fib_api_next_hop_decode(const vl_api_fib_path_t *in, ip46_address_t *out)
Definition: fib_api.c:75
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:85
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:1097
fib_protocol_t dpo_proto_to_fib(dpo_proto_t dpo_proto)
Definition: fib_types.c:340
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:124
vnet_crypto_main_t * cm
Definition: quic_crypto.c:53
static u8 ip46_address_is_zero(const ip46_address_t *ip46)
Definition: ip46_address.h:87
fib_mpls_label_t * frp_label_stack
The outgoing MPLS label Stack.
Definition: fib_types.h:551
Recursion constraint of via an attahced prefix.
Definition: fib_types.h:334
fib_mpls_lsp_mode_t fml_mode
The LSP mode.
Definition: fib_types.h:455
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:640
u32 frp_classify_table_id
Classify table ID.
Definition: fib_types.h:575
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:886
#define pool_is_free_index(P, I)
Use free bitmap to query whether given index is free.
Definition: pool.h:299
mpls_label_t fml_value
The label value.
Definition: fib_types.h:450
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:60
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:1086
u8 frp_preference
A path preference.
Definition: fib_types.h:596
int fib_api_path_decode(vl_api_fib_path_t *in, fib_route_path_t *out)
Definition: fib_api.c:151
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:600
From the control plane API.
Definition: fib_source.h:72
u8 n_labels
Definition: fib_types.api:127
vnet_classify_main_t vnet_classify_main
Definition: vnet_classify.c:29
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:544
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:513
int fib_api_table_id_decode(fib_protocol_t fproto, u32 table_id, u32 *fib_index)
Definition: fib_api.c:45
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:555
vnet_sw_interface_t * sw_interfaces
Definition: interface.h:872
u32 table_id
Definition: wireguard.api:100
u32 entry_flags
Definition: ip.api:307
u8 fml_exp
EXP bits; valid only at imposition.
Definition: fib_types.h:465
u8 frp_weight
[un]equal cost path weight
Definition: fib_types.h:590
u32 frp_udp_encap_id
UDP encap ID.
Definition: fib_types.h:570
u32 frp_fib_index
The FIB index to lookup the nexthop Only valid for recursive paths.
Definition: fib_types.h:542
u8 * format_vl_api_address_union(u8 *s, va_list *args)
Definition: types.c:52