FD.io VPP  v17.07.01-10-g3be13f0
Vector Packet Processing
fib_entry_src_adj.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 "fib_entry.h"
17 #include "fib_entry_src.h"
18 #include "fib_path_list.h"
19 #include "fib_table.h"
20 #include "fib_entry_cover.h"
21 #include "fib_attached_export.h"
22 #include "fib_path_ext.h"
23 
24 /**
25  * Source initialisation Function
26  */
27 static void
29 {
30  src->adj.fesa_cover = FIB_NODE_INDEX_INVALID;
31  src->adj.fesa_sibling = FIB_NODE_INDEX_INVALID;
32 }
33 
34 static void
36  const fib_entry_t *entry,
37  fib_path_list_flags_t pl_flags,
38  const fib_route_path_t *paths)
39 {
40  const fib_route_path_t *rpath;
41 
42  if (FIB_NODE_INDEX_INVALID == src->fes_pl)
43  {
44  src->fes_pl = fib_path_list_create(pl_flags, paths);
45  }
46  else
47  {
49  pl_flags,
50  paths);
51  }
52 
53  /*
54  * resolve the existing extensions
55  */
57 
58  /*
59  * and new extensions
60  */
61  vec_foreach(rpath, paths)
62  {
64  src->fes_pl,
66  rpath);
67  }
68 }
69 
70 static void
72  fib_path_list_flags_t pl_flags,
73  const fib_route_path_t *rpaths)
74 {
75  const fib_route_path_t *rpath;
76 
77  if (FIB_NODE_INDEX_INVALID != src->fes_pl)
78  {
80  pl_flags,
81  rpaths);
82  }
83 
84  /*
85  * remove the path-extension for the path
86  */
87  vec_foreach(rpath, rpaths)
88  {
90  };
91  /*
92  * resolve the remaining extensions
93  */
95 }
96 
97 static void
99  const fib_entry_t *entry,
100  fib_path_list_flags_t pl_flags,
101  const fib_route_path_t *paths)
102 {
103  const fib_route_path_t *rpath;
104 
105  /*
106  * flush all the old extensions before we create a brand new path-list
107  */
109 
110  src->fes_pl = fib_path_list_create(pl_flags, paths);
111 
112  /*
113  * and new extensions
114  */
115  vec_foreach(rpath, paths)
116  {
118  src->fes_pl,
120  rpath);
121  }
122 }
123 
124 static void
126 {
128 }
129 
130 /*
131  * Add a path-extension indicating whether this path is resolved,
132  * because it passed the refinement check
133  */
134 static void
136  fib_node_index_t path_index,
138 {
139  fib_path_ext_t *path_ext;
140 
142  path_index);
143 
144  if (NULL != path_ext)
145  {
146  path_ext->fpe_adj_flags = flags;
147  }
148  else
149  {
150  ASSERT(!"no path extension");
151  }
152 }
153 
155 {
160 
163  fib_node_index_t path_index,
164  void *arg)
165 {
167  u32 adj_itf;
168 
169  ctx = arg;
170  adj_itf = fib_path_get_resolving_interface(path_index);
171 
172  if (ctx->cover_itf == adj_itf)
173  {
174  fib_enty_src_adj_update_path_ext(ctx->src, path_index,
177  }
178  else
179  {
180  /*
181  * if the interface the adj is on is unnumbered to the
182  * cover's, then allow that too.
183  */
184  vnet_sw_interface_t *swif;
185 
186  swif = vnet_get_sw_interface (vnet_get_main(), adj_itf);
187 
189  ctx->cover_itf == swif->unnumbered_sw_if_index)
190  {
191  fib_enty_src_adj_update_path_ext(ctx->src, path_index,
194  }
195  else
196  {
197  fib_enty_src_adj_update_path_ext(ctx->src, path_index,
199  }
200  }
202 }
203 
204 /*
205  * Source activate.
206  * Called when the source is the new longer best source on the entry
207  */
208 static int
210  const fib_entry_t *fib_entry)
211 {
212  fib_entry_t *cover;
213 
214  /*
215  * find the covering prefix. become a dependent thereof.
216  * there should always be a cover, though it may be the default route.
217  */
218  src->adj.fesa_cover = fib_table_get_less_specific(fib_entry->fe_fib_index,
219  &fib_entry->fe_prefix);
220 
221  ASSERT(FIB_NODE_INDEX_INVALID != src->adj.fesa_cover);
222  ASSERT(fib_entry_get_index(fib_entry) != src->adj.fesa_cover);
223 
224  cover = fib_entry_get(src->adj.fesa_cover);
225 
226  ASSERT(cover != fib_entry);
227 
228  src->adj.fesa_sibling =
229  fib_entry_cover_track(cover,
230  fib_entry_get_index(fib_entry));
231 
232  /*
233  * if the cover is attached on the same interface as this adj source then
234  * install the FIB entry via the adj. otherwise install a drop.
235  * This prevents ARP/ND entries that on interface X that do not belong
236  * on X's subnet from being added to the FIB. To do so would allow
237  * nefarious gratuitous ARP requests from attracting traffic to the sender.
238  *
239  * and yes, I really do mean attached and not connected.
240  * this abomination;
241  * ip route add 10.0.0.0/24 Eth0
242  * is attached. and we want adj-fibs to install on Eth0.
243  */
245  {
247  .cover_itf = fib_entry_get_resolving_interface(src->adj.fesa_cover),
249  .src = src,
250  };
251 
254  &ctx);
255 
256  /*
257  * active the entry is one of the paths refines the cover.
258  */
260  }
261  return (0);
262 }
263 
264 /*
265  * Source Deactivate.
266  * Called when the source is no longer best source on the entry
267  */
268 static void
270  const fib_entry_t *fib_entry)
271 {
272  fib_entry_t *cover;
273 
274  /*
275  * remove the depednecy on the covering entry
276  */
277  ASSERT(FIB_NODE_INDEX_INVALID != src->adj.fesa_cover);
278  cover = fib_entry_get(src->adj.fesa_cover);
279 
280  fib_entry_cover_untrack(cover, src->adj.fesa_sibling);
281 
282  /*
283  * tell the cover this entry no longer needs exporting
284  */
286 
287  src->adj.fesa_cover = FIB_NODE_INDEX_INVALID;
288 }
289 
290 static u8*
292  u8* s)
293 {
294  return (format(s, "cover:%d", src->adj.fesa_cover));
295 }
296 
297 static void
299  const fib_entry_t *fib_entry)
300 {
301  /*
302  * The adj source now rules! poke our cover to get exported
303  */
304  fib_entry_t *cover;
305 
306  ASSERT(FIB_NODE_INDEX_INVALID != src->adj.fesa_cover);
307  cover = fib_entry_get(src->adj.fesa_cover);
308 
310  fib_entry_get_index(fib_entry));
311 }
312 
315  const fib_entry_t *fib_entry)
316 {
318  .install = !0,
319  .bw_reason = FIB_NODE_BW_REASON_FLAG_NONE,
320  };
321 
322  fib_entry_src_adj_deactivate(src, fib_entry);
323 
324  res.install = fib_entry_src_adj_activate(src, fib_entry);
325 
326  if (res.install) {
327  /*
328  * ADJ fib can install
329  */
331  }
332 
333  return (res);
334 }
335 
336 /*
337  * fib_entry_src_adj_cover_update
338  */
341  const fib_entry_t *fib_entry)
342 {
343  /*
344  * the cover has updated, i.e. its forwarding or flags
345  * have changed. don't decativate/activate here, since this
346  * prefix is updated during the covers walk.
347  */
349  .install = !0,
350  .bw_reason = FIB_NODE_BW_REASON_FLAG_NONE,
351  };
352  fib_entry_t *cover;
353 
354  ASSERT(FIB_NODE_INDEX_INVALID != src->adj.fesa_cover);
355 
356  cover = fib_entry_get(src->adj.fesa_cover);
357 
359 
360  return (res);
361 }
362 
363 const static fib_entry_src_vft_t adj_src_vft = {
365  .fesv_path_swap = fib_entry_src_adj_path_swap,
366  .fesv_path_add = fib_entry_src_adj_path_add,
367  .fesv_path_remove = fib_entry_src_adj_path_remove,
368  .fesv_remove = fib_entry_src_adj_remove,
369  .fesv_activate = fib_entry_src_adj_activate,
370  .fesv_deactivate = fib_entry_src_adj_deactivate,
371  .fesv_format = fib_entry_src_adj_format,
372  .fesv_installed = fib_entry_src_adj_installed,
373  .fesv_cover_change = fib_entry_src_adj_cover_change,
374  .fesv_cover_update = fib_entry_src_adj_cover_update,
375 };
376 
377 void
379 {
380  fib_entry_src_register(FIB_SOURCE_ADJ, &adj_src_vft);
381 }
#define VNET_SW_INTERFACE_FLAG_UNNUMBERED
Definition: interface.h:567
fib_entry_src_init_t fesv_init
An entry in a FIB table.
Definition: fib_entry.h:380
fib_node_bw_reason_flag_t bw_reason
Definition: fib_entry_src.h:89
static fib_path_list_walk_rc_t fib_entry_src_adj_path_list_walk(fib_node_index_t pl_index, fib_node_index_t path_index, void *arg)
fib_entry_flag_t fib_entry_get_flags_i(const fib_entry_t *fib_entry)
A representation of a path as described by a route producer.
Definition: fib_types.h:336
void fib_entry_cover_untrack(fib_entry_t *cover, u32 tracked_index)
vnet_main_t * vnet_get_main(void)
Definition: misc.c:46
Virtual function table each FIB entry source will register.
u32 cover_itf
#define NULL
Definition: clib.h:55
Information related to the source of a FIB entry.
Definition: fib_entry.h:289
static fib_entry_src_cover_res_t fib_entry_src_adj_cover_change(fib_entry_src_t *src, const fib_entry_t *fib_entry)
Result from a cover update/change.
Definition: fib_entry_src.h:87
void fib_path_list_walk(fib_node_index_t path_list_index, fib_path_list_walk_fn_t func, void *ctx)
static vnet_sw_interface_t * vnet_get_sw_interface(vnet_main_t *vnm, u32 sw_if_index)
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:419
u32 fe_fib_index
The index of the FIB table this entry is in.
Definition: fib_entry.h:393
static void fib_entry_src_adj_path_remove(fib_entry_src_t *src, fib_path_list_flags_t pl_flags, const fib_route_path_t *rpaths)
Definition: fib_entry.h:235
struct fib_entry_src_path_list_walk_cxt_t_ fib_entry_src_path_list_walk_cxt_t
static int fib_entry_src_adj_activate(fib_entry_src_t *src, const fib_entry_t *fib_entry)
void fib_attached_export_covered_added(fib_entry_t *cover, fib_node_index_t covered)
u32 fib_entry_cover_track(fib_entry_t *cover, fib_node_index_t covered)
fib_node_index_t fib_entry_get_index(const fib_entry_t *fib_entry)
Definition: fib_entry.c:56
fib_path_ext_t * fib_path_ext_list_find_by_path_index(const fib_path_ext_list_t *list, fib_node_index_t path_index)
Definition: fib_path_ext.c:280
u16 install
Definition: fib_entry_src.h:88
A adj-source extension indicating the path's refinement criteria result.
Definition: fib_path_ext.h:36
fib_node_index_t fib_path_list_copy_and_path_add(fib_node_index_t orig_path_list_index, fib_path_list_flags_t flags, const fib_route_path_t *rpaths)
static void fib_entry_src_adj_remove(fib_entry_src_t *src)
void fib_path_ext_list_flush(fib_path_ext_list_t *list)
Definition: fib_path_ext.c:399
static fib_entry_src_cover_res_t fib_entry_src_adj_cover_update(fib_entry_src_t *src, const fib_entry_t *fib_entry)
fib_node_index_t fib_path_list_create(fib_path_list_flags_t flags, const fib_route_path_t *rpaths)
Adjacency source.
Definition: fib_entry.h:92
static void fib_entry_src_adj_installed(fib_entry_src_t *src, const fib_entry_t *fib_entry)
void fib_entry_src_adj_register(void)
fib_entry_src_t * src
u32 fib_entry_get_resolving_interface(fib_node_index_t entry_index)
Definition: fib_entry.c:1338
static void fib_entry_src_adj_deactivate(fib_entry_src_t *src, const fib_entry_t *fib_entry)
struct fib_entry_src_t_::@101::@104 adj
fib_node_index_t fib_path_list_copy_and_path_remove(fib_node_index_t orig_path_list_index, fib_path_list_flags_t flags, const fib_route_path_t *rpaths)
static void fib_entry_src_adj_init(fib_entry_src_t *src)
Source initialisation Function.
void fib_attached_export_covered_removed(fib_entry_t *cover, fib_node_index_t covered)
void fib_path_ext_list_remove(fib_path_ext_list_t *list, fib_path_ext_type_t ext_type, const fib_route_path_t *rpath)
Definition: fib_path_ext.c:379
fib_path_ext_t * fib_path_ext_list_push_back(fib_path_ext_list_t *list, fib_node_index_t path_list_index, fib_path_ext_type_t ext_type, const fib_route_path_t *rpath)
Definition: fib_path_ext.c:297
u32 fib_node_index_t
A typedef of a node index.
Definition: fib_types.h:28
static void fib_entry_src_adj_path_add(fib_entry_src_t *src, const fib_entry_t *entry, fib_path_list_flags_t pl_flags, const fib_route_path_t *paths)
fib_entry_t * fib_entry_get(fib_node_index_t index)
Definition: fib_entry.c:44
static u8 * fib_entry_src_adj_format(fib_entry_src_t *src, u8 *s)
#define ASSERT(truth)
unsigned int u32
Definition: types.h:88
void fib_entry_src_register(fib_source_t source, const fib_entry_src_vft_t *vft)
Definition: fib_entry_src.c:39
static void fib_entry_src_adj_path_swap(fib_entry_src_t *src, const fib_entry_t *entry, fib_path_list_flags_t pl_flags, const fib_route_path_t *paths)
fib_node_index_t fes_pl
The path-list created by the source.
Definition: fib_entry.h:298
fib_path_ext_adj_flags_t fpe_adj_flags
For an ADJ type extension.
Definition: fib_path_ext.h:88
fib_path_ext_adj_flags_t flags
enum fib_path_list_walk_rc_t_ fib_path_list_walk_rc_t
return code to control pat-hlist walk
u32 fib_path_get_resolving_interface(fib_node_index_t path_index)
Definition: fib_path.c:1709
#define FIB_NODE_INDEX_INVALID
Definition: fib_types.h:29
void fib_path_ext_list_resolve(fib_path_ext_list_t *list, fib_node_index_t path_list_index)
Definition: fib_path_ext.c:367
unsigned char u8
Definition: types.h:56
enum fib_path_ext_adj_flags_t_ fib_path_ext_adj_flags_t
#define vec_foreach(var, vec)
Vector iterator.
A path extension is a per-entry addition to the forwarding information when packets are sent for that...
Definition: fib_path_ext.h:72
static void fib_enty_src_adj_update_path_ext(fib_entry_src_t *src, fib_node_index_t path_index, fib_path_ext_adj_flags_t flags)
fib_path_ext_list_t fes_path_exts
A vector of path extensions.
Definition: fib_entry.h:293
enum fib_path_list_flags_t_ fib_path_list_flags_t
u32 flags
Definition: vhost-user.h:76
const fib_prefix_t fe_prefix
The prefix of the route.
Definition: fib_entry.h:389
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
fib_path_ext_t * fib_path_ext_list_insert(fib_path_ext_list_t *list, fib_node_index_t path_list_index, fib_path_ext_type_t ext_type, const fib_route_path_t *rpath)
Definition: fib_path_ext.c:323