FD.io VPP  v20.09-64-g4f7b92f0a
Vector Packet Processing
fib_entry_src_interpose.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 <vlib/vlib.h>
17 #include <vnet/ip/format.h>
18 #include <vnet/ip/lookup.h>
19 #include <vnet/adj/adj.h>
20 #include <vnet/dpo/drop_dpo.h>
21 
22 #include "fib_entry_src.h"
23 #include "fib_entry_src_rr.h"
24 #include "fib_entry_cover.h"
25 #include "fib_entry.h"
26 #include "fib_table.h"
27 
28 /*
29  * Source initialisation Function
30  */
31 static void
33 {
34  src->u.interpose.fesi_cover = FIB_NODE_INDEX_INVALID;
35  src->u.interpose.fesi_sibling = FIB_NODE_INDEX_INVALID;
36 }
37 
38 /*
39  * Source deinitialisation Function
40  */
41 static void
43 {
44  ASSERT(src->u.interpose.fesi_cover == FIB_NODE_INDEX_INVALID);
45 
46  src->u.interpose.fesi_cover = FIB_NODE_INDEX_INVALID;
47  src->u.interpose.fesi_sibling = FIB_NODE_INDEX_INVALID;
48 
49  dpo_reset(&src->u.interpose.fesi_dpo);
50 }
51 
52 static fib_entry_src_t *
54  const fib_entry_t *fib_entry)
55 {
56  fib_entry_src_t *next_src, *best_src = NULL;
57  fib_source_t source;
58 
59  FOR_EACH_SRC_ADDED(fib_entry, next_src, source,
60  ({
61  /*
62  * skip to the next best source after this one
63  */
64  switch (fib_source_cmp(source, src->fes_src))
65  {
66  case FIB_SOURCE_CMP_BETTER:
67  case FIB_SOURCE_CMP_EQUAL:
68  continue;
69  case FIB_SOURCE_CMP_WORSE:
70  best_src = next_src;
71  goto out;
72  }
73  }));
74  out:
75  return (best_src);
76 }
77 
78 /*
79  * Source activation. Called when the source is the new best source on the entry
80  */
81 static int
83  const fib_entry_t *fib_entry)
84 {
85  fib_entry_src_t *best_src;
86  fib_node_index_t old_pl;
87  fib_entry_t *cover;
88 
89  old_pl = src->fes_pl;
91 
92  /*
93  * The goal here is to find a path-list that will contribute forwarding
94  * for the entry.
95  * First check this entry for other sources that have a path-list
96  */
97  best_src = fib_entry_src_rr_get_next_best(src, fib_entry);
98 
99  if (NULL != best_src)
100  {
101  const fib_entry_src_vft_t *vft;
102 
104  vft = fib_entry_src_get_vft(best_src);
105  /*
106  * there is another source for this entry. activate it so it
107  * can provide forwarding
108  */
109  if (NULL != vft->fesv_activate)
110  {
111  if (vft->fesv_activate(best_src, fib_entry))
112  {
113  /*
114  * next best source activated ok, use its path list
115  */
116  src->fes_pl = best_src->fes_pl;
117  }
118  else
119  {
120  /*
121  * the best source won't install so will use a drop
122  */
123  dpo_proto_t dproto;
124 
125  dproto = fib_proto_to_dpo(fib_entry->fe_prefix.fp_proto);
126 
127  src->fes_pl =
130  drop_dpo_get(dproto));
131  }
132  }
133  else
134  {
135  /*
136  * next best source does not require activation, use its path list
137  */
138  src->fes_pl = best_src->fes_pl;
139  }
140  }
141  else
142  {
143  /*
144  * find the covering prefix. become a dependent thereof.
145  * for IP there should always be a cover, though it may be the default route.
146  * For MPLS there is never a cover.
147  */
148  if (FIB_PROTOCOL_MPLS == fib_entry->fe_prefix.fp_proto)
149  {
152  NULL);
153  }
154  else
155  {
156  src->u.interpose.fesi_cover =
158  &fib_entry->fe_prefix);
159 
160  ASSERT(FIB_NODE_INDEX_INVALID != src->u.interpose.fesi_cover);
161 
162  cover = fib_entry_get(src->u.interpose.fesi_cover);
163 
164  src->u.interpose.fesi_sibling =
165  fib_entry_cover_track(cover, fib_entry_get_index(fib_entry));
166 
167  /*
168  * if the cover is attached then install an attached-host path
169  * (like an adj-fib). Otherwise inherit the forwarding from the cover
170  */
172  {
173  fib_entry_src_rr_resolve_via_connected(src, fib_entry, cover);
174  }
175  else
176  {
177  fib_entry_src_rr_use_covers_pl(src, fib_entry, cover);
178  }
179  }
180  }
181 
182  fib_path_list_unlock(old_pl);
184 
185  /*
186  * return go for install
187  */
188  return (!0);
189 }
190 
191 /**
192  * Source Deactivate.
193  * Called when the source is no longer best source on the entry
194  */
195 static void
197  const fib_entry_t *fib_entry)
198 {
199  fib_entry_t *cover;
200 
201  if (FIB_NODE_INDEX_INVALID != src->u.interpose.fesi_cover)
202  {
203  /*
204  * remove the dependency on the covering entry, if that's
205  * what was contributing the path-list
206  */
207  cover = fib_entry_get(src->u.interpose.fesi_cover);
208  fib_entry_cover_untrack(cover, src->u.interpose.fesi_sibling);
209  src->u.interpose.fesi_cover = FIB_NODE_INDEX_INVALID;
210  }
211  else
212  {
213  fib_entry_src_t *best_src;
214 
215  best_src = fib_entry_src_rr_get_next_best(src, fib_entry);
216 
217  if (best_src)
218  {
220  /*
221  * there is another source for this entry. activate it so it
222  * can provide forwarding
223  */
224  FIB_ENTRY_SRC_VFT_INVOKE(fib_entry, best_src, fesv_deactivate,
225  (best_src, fib_entry));
226  }
227  }
228 
232 }
233 
234 static int
236  const fib_entry_t *fib_entry)
237 {
238  fib_entry_src_interpose_deactivate(src, fib_entry);
239  return (fib_entry_src_interpose_activate(src, fib_entry));
240 }
241 
244  const fib_entry_t *fib_entry)
245 {
247  .install = !0,
248  .bw_reason = FIB_NODE_BW_REASON_FLAG_NONE,
249  };
250 
251  if (FIB_NODE_INDEX_INVALID == src->u.interpose.fesi_cover)
252  {
253  /*
254  * the source may be added, but it is not active
255  * if it is not tracking the cover.
256  */
257  return (res);
258  }
259 
260  /*
261  * this function is called when this entry's cover has a more specific
262  * entry inserted beneath it. That does not necessarily mean that this
263  * entry is covered by the new prefix. check that
264  */
265  if (src->u.interpose.fesi_cover !=
267  &fib_entry->fe_prefix))
268  {
269  fib_entry_src_interpose_deactivate(src, fib_entry);
270  fib_entry_src_interpose_activate(src, fib_entry);
271 
272  /*
273  * dependent children need to re-resolve to the new forwarding info
274  */
276  }
277  return (res);
278 }
279 
280 static void
282  const fib_entry_t *entry,
285  const dpo_id_t *dpo)
286 {
287  dpo_copy(&src->u.interpose.fesi_dpo, dpo);
288 }
289 
290 static void
292 {
293  dpo_reset(&src->u.interpose.fesi_dpo);
294 }
295 
296 static void
298  const fib_entry_t *fib_entry,
299  const void *data)
300 {
301  const dpo_id_t *dpo = data;
302 
303  dpo_copy(&src->u.interpose.fesi_dpo, dpo);
304 }
305 
306 /**
307  * Contribute forwarding to interpose in the chain
308  */
310  const fib_entry_t *fib_entry)
311 {
312  return (&src->u.interpose.fesi_dpo);
313 }
314 
315 static void
317  const fib_entry_t *fib_entry,
318  fib_entry_src_t *copy_src)
319 {
320  copy_src->u.interpose.fesi_cover = orig_src->u.interpose.fesi_cover;
321 
322  if (FIB_NODE_INDEX_INVALID != copy_src->u.interpose.fesi_cover)
323  {
324  fib_entry_t *cover;
325 
326  cover = fib_entry_get(orig_src->u.interpose.fesi_cover);
327  copy_src->u.interpose.fesi_sibling =
328  fib_entry_cover_track(cover, fib_entry_get_index(fib_entry));
329  }
330 
331  dpo_copy(&copy_src->u.interpose.fesi_dpo,
332  &orig_src->u.interpose.fesi_dpo);
333 }
334 
335 static void
337  const fib_entry_t *fib_entry,
338  fib_entry_flag_t new_flags)
339 {
340  if (!(new_flags & FIB_ENTRY_FLAG_INTERPOSE))
341  {
342  /*
343  * stop tracking the source contributing forwarding
344  * and reset the interposer DPO
345  */
346  fib_entry_src_interpose_deactivate(src, fib_entry);
348  }
349 }
350 
351 static u8*
353  u8* s)
354 {
355  s = format(s, " cover:%d interpose:\n%U%U",
356  src->u.interpose.fesi_cover,
358  format_dpo_id, &src->u.interpose.fesi_dpo, 8);
359 
360  return (s);
361 }
362 
363 const static fib_entry_src_vft_t interpose_src_vft = {
365  .fesv_deinit = fib_entry_src_interpose_deinit,
366  .fesv_activate = fib_entry_src_interpose_activate,
367  .fesv_reactivate = fib_entry_src_interpose_reactivate,
368  .fesv_deactivate = fib_entry_src_interpose_deactivate,
369  .fesv_cover_change = fib_entry_src_interpose_cover_change,
370  .fesv_cover_update = fib_entry_src_rr_cover_update,
371  .fesv_format = fib_entry_src_interpose_format,
372  .fesv_add = fib_entry_src_interpose_add,
373  .fesv_remove = fib_entry_src_interpose_remove,
374  .fesv_contribute_interpose = fib_entry_src_interpose_contribute,
375  .fesv_set_data = fib_entry_src_interpose_set_data,
376  .fesv_copy = fib_entry_src_interpose_copy,
377  .fesv_flags_change = fib_entry_src_interpose_flag_change,
378 };
379 
380 void
382 {
384  &interpose_src_vft);
385 }
fib_protocol_t fp_proto
protocol type
Definition: fib_types.h:212
enum fib_source_t_ fib_source_t
The different sources that can create a route.
fib_entry_src_init_t fesv_init
void fib_entry_src_rr_resolve_via_connected(fib_entry_src_t *src, const fib_entry_t *fib_entry, const fib_entry_t *cover)
An entry in a FIB table.
Definition: fib_entry.h:305
fib_node_bw_reason_flag_t bw_reason
Definition: fib_entry_src.h:93
vl_api_wireguard_peer_flags_t flags
Definition: wireguard.api:103
fib_entry_flag_t fib_entry_get_flags_i(const fib_entry_t *fib_entry)
void fib_entry_cover_untrack(fib_entry_t *cover, u32 tracked_index)
Virtual function table each FIB entry source will register.
Definition: fib_entry.h:179
Definition: fib_entry.h:123
Definitions for all things IP (v4|v6) unicast and multicast lookup related.
Information related to the source of a FIB entry.
Definition: fib_entry.h:197
fib_node_index_t fib_path_list_create_special(dpo_proto_t nh_proto, fib_path_list_flags_t flags, const dpo_id_t *dpo)
static int fib_entry_src_interpose_activate(fib_entry_src_t *src, const fib_entry_t *fib_entry)
void dpo_copy(dpo_id_t *dst, const dpo_id_t *src)
atomic copy a data-plane object.
Definition: dpo.c:262
vl_api_address_t src
Definition: gre.api:54
Result from a cover update/change.
Definition: fib_entry_src.h:91
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:424
const dpo_id_t * fib_entry_src_interpose_contribute(const fib_entry_src_t *src, const fib_entry_t *fib_entry)
Contribute forwarding to interpose in the chain.
static void fib_entry_src_interpose_init(fib_entry_src_t *src)
u32 fe_fib_index
The index of the FIB table this entry is in.
Definition: fib_entry.h:318
Definition: fib_entry.h:114
unsigned char u8
Definition: types.h:56
u8 data[128]
Definition: ipsec_types.api:89
fib_source_priority_cmp_t fib_source_cmp(fib_source_t s1, fib_source_t s2)
Definition: fib_source.c:76
const dpo_id_t * drop_dpo_get(dpo_proto_t proto)
Definition: drop_dpo.c:25
u32 fib_entry_cover_track(fib_entry_t *cover, fib_node_index_t covered)
u8 * format_white_space(u8 *s, va_list *va)
Definition: std-formats.c:129
fib_node_index_t fib_entry_get_index(const fib_entry_t *fib_entry)
Definition: fib_entry.c:63
static void fib_entry_src_interpose_copy(const fib_entry_src_t *orig_src, const fib_entry_t *fib_entry, fib_entry_src_t *copy_src)
enum dpo_proto_t_ dpo_proto_t
Data path protocol.
static u8 * fib_entry_src_interpose_format(fib_entry_src_t *src, u8 *s)
u16 install
Definition: fib_entry_src.h:92
#define FOR_EACH_SRC_ADDED(_entry, _src, _source, action)
The identity of a DPO is a combination of its type and its instance number/index of objects of that t...
Definition: dpo.h:170
static fib_entry_src_t * fib_entry_src_rr_get_next_best(const fib_entry_src_t *src, const fib_entry_t *fib_entry)
static void fib_entry_src_interpose_set_data(fib_entry_src_t *src, const fib_entry_t *fib_entry, const void *data)
vl_api_ip_proto_t proto
Definition: acl_types.api:50
void fib_entry_src_interpose_register(void)
const fib_entry_src_vft_t * fib_entry_src_get_vft(const fib_entry_src_t *esrc)
Get the VFT for a given source.
Definition: fib_entry_src.c:38
void fib_path_list_lock(fib_node_index_t path_list_index)
u32 fib_node_index_t
A typedef of a node index.
Definition: fib_types.h:30
void fib_path_list_unlock(fib_node_index_t path_list_index)
fib_entry_t * fib_entry_get(fib_node_index_t index)
Definition: fib_entry.c:51
enum fib_entry_flag_t_ fib_entry_flag_t
fib_entry_flag_t fes_entry_flags
Flags the source contributes to the entry.
Definition: fib_entry.h:211
fib_source_t fes_src
Which source this info block is for.
Definition: fib_entry.h:216
#define ASSERT(truth)
fib_entry_src_flag_t fes_flags
Flags on the source.
Definition: fib_entry.h:221
dpo_proto_t fib_proto_to_dpo(fib_protocol_t fib_proto)
Definition: fib_types.c:324
u8 * format_dpo_id(u8 *s, va_list *args)
Format a DPO_id_t oject.
Definition: dpo.c:148
#define FIB_ENTRY_SRC_VFT_INVOKE(_fe, esrc, func, args)
void fib_entry_src_rr_use_covers_pl(fib_entry_src_t *src, const fib_entry_t *fib_entry, const fib_entry_t *cover)
fib_node_index_t fes_pl
The path-list created by the source.
Definition: fib_entry.h:206
static void fib_entry_src_interpose_deactivate(fib_entry_src_t *src, const fib_entry_t *fib_entry)
Source Deactivate.
static void fib_entry_src_interpose_flag_change(fib_entry_src_t *src, const fib_entry_t *fib_entry, fib_entry_flag_t new_flags)
#define FIB_ENTRY_FLAGS_RR_INHERITED
static fib_entry_src_cover_res_t fib_entry_src_interpose_cover_change(fib_entry_src_t *src, const fib_entry_t *fib_entry)
#define FIB_NODE_INDEX_INVALID
Definition: fib_types.h:31
union fib_entry_src_t_::@275 u
Source specific info.
static void fib_entry_src_interpose_deinit(fib_entry_src_t *src)
fib_entry_src_activate_t fesv_activate
fib_entry_src_cover_res_t fib_entry_src_rr_cover_update(fib_entry_src_t *src, const fib_entry_t *fib_entry)
static void fib_entry_src_interpose_remove(fib_entry_src_t *src)
void dpo_reset(dpo_id_t *dpo)
reset a DPO ID The DPO will be unlocked.
Definition: dpo.c:232
static void fib_entry_src_interpose_add(fib_entry_src_t *src, const fib_entry_t *entry, fib_entry_flag_t flags, dpo_proto_t proto, const dpo_id_t *dpo)
void fib_entry_src_behaviour_register(fib_source_behaviour_t bh, const fib_entry_src_vft_t *vft)
Definition: fib_entry_src.c:61
const fib_prefix_t fe_prefix
The prefix of the route.
Definition: fib_entry.h:314
fib_node_index_t fib_table_get_less_specific(u32 fib_index, const fib_prefix_t *prefix)
Get the less specific (covering) prefix.
Definition: fib_table.c:133
struct fib_entry_src_t_::@275::@277 interpose
static int fib_entry_src_interpose_reactivate(fib_entry_src_t *src, const fib_entry_t *fib_entry)