FD.io VPP  v19.01.1-17-ge106252
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  if (source <= src->fes_src)
65  {
66  continue;
67  }
68  else
69  {
70  best_src = next_src;
71  break;
72  }
73  }));
74 
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  }
119  else
120  {
121  /*
122  * next best source does not require activation, use its path list
123  */
124  src->fes_pl = best_src->fes_pl;
125  }
126  }
127  else
128  {
129  /*
130  * find the covering prefix. become a dependent thereof.
131  * for IP there should always be a cover, though it may be the default route.
132  * For MPLS there is never a cover.
133  */
134  if (FIB_PROTOCOL_MPLS == fib_entry->fe_prefix.fp_proto)
135  {
138  NULL);
139  }
140  else
141  {
142  src->u.interpose.fesi_cover =
144  &fib_entry->fe_prefix);
145 
146  ASSERT(FIB_NODE_INDEX_INVALID != src->u.interpose.fesi_cover);
147 
148  cover = fib_entry_get(src->u.interpose.fesi_cover);
149 
150  src->u.interpose.fesi_sibling =
151  fib_entry_cover_track(cover, fib_entry_get_index(fib_entry));
152 
153  /*
154  * if the cover is attached then install an attached-host path
155  * (like an adj-fib). Otherwise inherit the forwarding from the cover
156  */
158  {
159  fib_entry_src_rr_resolve_via_connected(src, fib_entry, cover);
160  }
161  else
162  {
163  fib_entry_src_rr_use_covers_pl(src, fib_entry, cover);
164  }
165  }
166  }
167 
168  fib_path_list_unlock(old_pl);
170 
171  /*
172  * return go for install
173  */
174  return (!0);
175 }
176 
177 /**
178  * Source Deactivate.
179  * Called when the source is no longer best source on the entry
180  */
181 static void
183  const fib_entry_t *fib_entry)
184 {
185  fib_entry_t *cover;
186 
187  if (FIB_NODE_INDEX_INVALID != src->u.interpose.fesi_cover)
188  {
189  /*
190  * remove the depednecy on the covering entry, if that's
191  * what was contributing the path-list
192  */
193  cover = fib_entry_get(src->u.interpose.fesi_cover);
194  fib_entry_cover_untrack(cover, src->u.interpose.fesi_sibling);
195  src->u.interpose.fesi_cover = FIB_NODE_INDEX_INVALID;
196  }
197  else
198  {
199  fib_entry_src_t *best_src;
200 
201  best_src = fib_entry_src_rr_get_next_best(src, fib_entry);
202 
203  if (best_src)
204  {
206  /*
207  * there is another source for this entry. activate it so it
208  * can provide forwarding
209  */
210  FIB_ENTRY_SRC_VFT_INVOKE(best_src, fesv_deactivate,
211  (best_src, fib_entry));
212  }
213  }
214 
218 }
219 
220 static int
222  const fib_entry_t *fib_entry)
223 {
224  fib_entry_src_interpose_deactivate(src, fib_entry);
225  return (fib_entry_src_interpose_activate(src, fib_entry));
226 }
227 
230  const fib_entry_t *fib_entry)
231 {
233  .install = !0,
234  .bw_reason = FIB_NODE_BW_REASON_FLAG_NONE,
235  };
236 
237  if (FIB_NODE_INDEX_INVALID == src->u.interpose.fesi_cover)
238  {
239  /*
240  * the source may be added, but it is not active
241  * if it is not tracking the cover.
242  */
243  return (res);
244  }
245 
246  /*
247  * this function is called when this entry's cover has a more specific
248  * entry inserted benaeth it. That does not necessarily mean that this
249  * entry is covered by the new prefix. check that
250  */
251  if (src->u.interpose.fesi_cover !=
253  &fib_entry->fe_prefix))
254  {
255  fib_entry_src_interpose_deactivate(src, fib_entry);
256  fib_entry_src_interpose_activate(src, fib_entry);
257 
258  /*
259  * dependent children need to re-resolve to the new forwarding info
260  */
262  }
263  return (res);
264 }
265 
266 static void
268  const fib_entry_t *entry,
270  dpo_proto_t proto,
271  const dpo_id_t *dpo)
272 {
273  dpo_copy(&src->u.interpose.fesi_dpo, dpo);
274 }
275 
276 static void
278 {
279  dpo_reset(&src->u.interpose.fesi_dpo);
280 }
281 
282 static void
284  const fib_entry_t *fib_entry,
285  const void *data)
286 {
287  const dpo_id_t *dpo = data;
288 
289  dpo_copy(&src->u.interpose.fesi_dpo, dpo);
290 }
291 
292 /**
293  * Contribute forwarding to interpose in the chain
294  */
296  const fib_entry_t *fib_entry)
297 {
298  return (&src->u.interpose.fesi_dpo);
299 }
300 
301 static void
303  const fib_entry_t *fib_entry,
304  fib_entry_src_t *copy_src)
305 {
306  copy_src->u.interpose.fesi_cover = orig_src->u.interpose.fesi_cover;
307 
308  if (FIB_NODE_INDEX_INVALID != copy_src->u.interpose.fesi_cover)
309  {
310  fib_entry_t *cover;
311 
312  cover = fib_entry_get(orig_src->u.interpose.fesi_cover);
313  copy_src->u.interpose.fesi_sibling =
314  fib_entry_cover_track(cover, fib_entry_get_index(fib_entry));
315  }
316 
317  dpo_copy(&copy_src->u.interpose.fesi_dpo,
318  &orig_src->u.interpose.fesi_dpo);
319 }
320 
321 static void
323  const fib_entry_t *fib_entry,
324  fib_entry_flag_t new_flags)
325 {
326  if (!(new_flags & FIB_ENTRY_FLAG_INTERPOSE))
327  {
328  /*
329  * stop tracking the source contributing forwarding
330  * and reset the interposer DPO
331  */
332  fib_entry_src_interpose_deactivate(src, fib_entry);
334  }
335 }
336 
337 static u8*
339  u8* s)
340 {
341  s = format(s, " cover:%d interpose:\n%U%U",
342  src->u.interpose.fesi_cover,
344  format_dpo_id, &src->u.interpose.fesi_dpo, 8);
345 
346  return (s);
347 }
348 
349 const static fib_entry_src_vft_t interpose_src_vft = {
351  .fesv_deinit = fib_entry_src_interpose_deinit,
352  .fesv_activate = fib_entry_src_interpose_activate,
353  .fesv_reactivate = fib_entry_src_interpose_reactivate,
354  .fesv_deactivate = fib_entry_src_interpose_deactivate,
355  .fesv_cover_change = fib_entry_src_interpose_cover_change,
356  .fesv_cover_update = fib_entry_src_rr_cover_update,
357  .fesv_format = fib_entry_src_interpose_format,
358  .fesv_add = fib_entry_src_interpose_add,
359  .fesv_remove = fib_entry_src_interpose_remove,
360  .fesv_contribute_interpose = fib_entry_src_interpose_contribute,
361  .fesv_set_data = fib_entry_src_interpose_set_data,
362  .fesv_copy = fib_entry_src_interpose_copy,
363  .fesv_flags_change = fib_entry_src_interpose_flag_change,
364 };
365 
366 void
368 {
369  fib_entry_src_register(FIB_SOURCE_INTERPOSE, &interpose_src_vft);
370 }
fib_protocol_t fp_proto
protocol type
Definition: fib_types.h:212
fib_entry_src_init_t fesv_init
u32 flags
Definition: vhost_user.h:115
vl_api_address_t src
Definition: vxlan_gbp.api:32
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:462
struct fib_entry_src_t_::@124::@126 interpose
fib_node_bw_reason_flag_t bw_reason
Definition: fib_entry_src.h:93
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:337
Definition: fib_entry.h:286
Definitions for all things IP (v4|v6) unicast and multicast lookup related.
#define NULL
Definition: clib.h:58
Information related to the source of a FIB entry.
Definition: fib_entry.h:354
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:261
Result from a cover update/change.
Definition: fib_entry_src.h:91
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:419
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:475
Definition: fib_entry.h:277
unsigned char u8
Definition: types.h:56
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:113
fib_node_index_t fib_entry_get_index(const fib_entry_t *fib_entry)
Definition: fib_entry.c:62
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:168
static fib_entry_src_t * fib_entry_src_rr_get_next_best(const fib_entry_src_t *src, const fib_entry_t *fib_entry)
enum fib_source_t_ fib_source_t
The different sources that can create a route.
static void fib_entry_src_interpose_set_data(fib_entry_src_t *src, const fib_entry_t *fib_entry, const void *data)
#define FIB_ENTRY_SRC_VFT_INVOKE(esrc, func, args)
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:37
void fib_path_list_lock(fib_node_index_t path_list_index)
union fib_entry_src_t_::@124 u
Source specific info.
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:50
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:368
#define ASSERT(truth)
fib_entry_src_flag_t fes_flags
Flags on the source.
Definition: fib_entry.h:378
void fib_entry_src_register(fib_source_t source, const fib_entry_src_vft_t *vft)
Definition: fib_entry_src.c:56
The interpose source.
Definition: fib_entry.h:144
u8 * format_dpo_id(u8 *s, va_list *args)
Format a DPO_id_t oject
Definition: dpo.c:147
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:363
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
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:231
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)
const fib_prefix_t fe_prefix
The prefix of the route.
Definition: fib_entry.h:471
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:131
static int fib_entry_src_interpose_reactivate(fib_entry_src_t *src, const fib_entry_t *fib_entry)