FD.io VPP  v16.12-rc0-308-g931be3a
Vector Packet Processing
fib_attached_export.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/fib/fib_entry.h>
17 #include <vnet/fib/fib_table.h>
18 
19 #include "fib_attached_export.h"
20 #include "fib_entry_cover.h"
21 #include "fib_entry_src.h"
22 
23 /**
24  * A description of the need to import routes from the export table
25  */
26 typedef struct fib_ae_import_t_
27 {
28  /**
29  * The entry in the epxort table that this importer
30  * is importing covereds from
31  */
33 
34  /**
35  * The attached entry in the import table
36  */
38  /**
39  * the sibling index on the cover
40  */
42 
43  /**
44  * The index of the exporter tracker. Not set if the
45  * export entry is not valid for export
46  */
48 
49  /**
50  * A vector/list of imported entry indicies
51  */
53 
54  /**
55  * The FIB index and prefix we are tracking
56  */
59 
60  /**
61  * The FIB index we are importing into
62  */
65 
66 /**
67  * A description of the need to export routes to one or more export tables
68  */
69 typedef struct fib_ae_export_t_ {
70  /**
71  * The vector/list of import tracker indicies
72  */
74 
75  /**
76  * THe connected entry this export is acting on behalf of
77  */
79 
80  /**
81  * Reference counting locks
82  */
85 
86 /*
87  * memory pools for the importers and exportes
88  */
91 
92 static fib_ae_export_t *
94 {
95  fib_ae_export_t *export;
96  fib_entry_t *entry;
97 
98  entry = fib_entry_get(connected);
99 
100  if (FIB_NODE_INDEX_INVALID == entry->fe_export)
101  {
102  pool_get(fib_ae_export_pool, export);
103  memset(export, 0, sizeof(*export));
104 
105  entry->fe_export = (export - fib_ae_export_pool);
106  export->faee_ei = connected;
107  }
108  else
109  {
110  export = pool_elt_at_index(fib_ae_export_pool, entry->fe_export);
111  }
112 
113  export->faee_locks++;
114 
115  return (export);
116 }
117 
118 static void
120  fib_node_index_t entry_index)
121 {
122  fib_prefix_t prefix;
123  u32 index;
124 
125  /*
126  * find the index in the vector of the entry we are removing
127  */
128  index = vec_search(import->faei_importeds, entry_index);
129 
130  if (index < vec_len(import->faei_importeds))
131  {
132  /*
133  * this is an entry that was previsouly imported
134  */
135  fib_entry_get_prefix(entry_index, &prefix);
136 
137  fib_table_entry_special_remove(import->faei_import_fib,
138  &prefix,
139  FIB_SOURCE_AE);
140 
141  fib_entry_unlock(entry_index);
142  vec_del1(import->faei_importeds, index);
143  }
144 }
145 
146 static void
148  fib_node_index_t entry_index)
149 {
150  fib_node_index_t *existing;
151  fib_prefix_t prefix;
152 
153  /*
154  * ensure we only add the exported entry once, since
155  * sourcing prefixes in the table is reference counted
156  */
157  vec_foreach(existing, import->faei_importeds)
158  {
159  if (*existing == entry_index)
160  {
161  return;
162  }
163  }
164 
165  /*
166  * this is the first time this export entry has been imported
167  * Add it to the import FIB and to the list of importeds
168  */
169  fib_entry_get_prefix(entry_index, &prefix);
170 
171  /*
172  * don't import entries that have the same prefix the import entry
173  */
174  if (0 != fib_prefix_cmp(&prefix,
175  &import->faei_prefix))
176  {
177  const dpo_id_t *dpo;
178 
179  dpo = fib_entry_contribute_ip_forwarding(entry_index);
180 
181  if (dpo_id_is_valid(dpo))
182  {
183  fib_table_entry_special_dpo_add(import->faei_import_fib,
184  &prefix,
188 
189  fib_entry_lock(entry_index);
190  vec_add1(import->faei_importeds, entry_index);
191  }
192  /*
193  * else
194  * the entry currently has no valid forwarding. when it
195  * does it will export itself
196  */
197  }
198 }
199 
200 /**
201  * Call back when walking a connected prefix's covered prefixes for import
202  */
203 static int
205  fib_node_index_t covered,
206  void *ctx)
207 {
208  fib_ae_import_t *import = ctx;
209 
210  fib_entry_import_add(import, covered);
211 
212  return (0);
213 }
214 
215 /*
216  * fib_entry_ae_import_add
217  *
218  * Add an importer to a connected entry
219  */
220 static void
222  fib_ae_import_t *import)
223 {
224  fib_entry_t *entry;
225 
226  import->faei_exporter = (export - fib_ae_export_pool);
227  entry = fib_entry_get(export->faee_ei);
228 
229  fib_entry_cover_walk(entry,
231  import);
232 }
233 
234 void
236  fib_node_index_t export_fib)
237 {
238  fib_ae_import_t *import;
239 
240  pool_get(fib_ae_import_pool, import);
241 
242  import->faei_import_fib = fib_entry->fe_fib_index;
243  import->faei_export_fib = export_fib;
244  import->faei_prefix = fib_entry->fe_prefix;
245  import->faei_import_entry = fib_entry_get_index(fib_entry);
246  import->faei_export_sibling = ~0;
247 
248  /*
249  * do an exact match in the export table
250  */
251  import->faei_export_entry =
252  fib_table_lookup_exact_match(import->faei_export_fib,
253  &import->faei_prefix);
254 
255  if (FIB_NODE_INDEX_INVALID == import->faei_export_entry)
256  {
257  /*
258  * no exact matching entry in the export table. can't be good.
259  * track the next best thing
260  */
261  import->faei_export_entry =
262  fib_table_lookup(import->faei_export_fib,
263  &import->faei_prefix);
264  import->faei_exporter = FIB_NODE_INDEX_INVALID;
265  }
266  else
267  {
268  /*
269  * found the entry in the export table. import the
270  * the prefixes that it covers.
271  * only if the prefix found in the export FIB really is
272  * attached do we want to import its covered
273  */
275  fib_entry_get_flags_i(fib_entry_get(import->faei_export_entry)))
276  {
277  fib_ae_export_t *export;
278 
279  export = fib_entry_ae_add_or_lock(import->faei_export_entry);
280  vec_add1(export->faee_importers, (import - fib_ae_import_pool));
281  fib_ae_export_import_add(export, import);
282  }
283  }
284 
285  /*
286  * track the entry in the export table so we can update appropriately
287  * when it changes
288  */
289  import->faei_export_sibling =
290  fib_entry_cover_track(fib_entry_get(import->faei_export_entry),
291  fib_entry_get_index(fib_entry));
292 
293  fib_entry->fe_import = (import - fib_ae_import_pool);
294 }
295 
296 /**
297  * \brief All the imported entries need to be pruged
298  */
299 void
301 {
302  if (FIB_NODE_INDEX_INVALID != fib_entry->fe_import)
303  {
304  fib_node_index_t *import_index;
305  fib_entry_t *export_entry;
306  fib_ae_import_t *import;
307  fib_ae_export_t *export;
308 
309  import = pool_elt_at_index(fib_ae_import_pool,
310  fib_entry->fe_import);
311 
312  /*
313  * remove each imported entry
314  */
315  vec_foreach(import_index, import->faei_importeds)
316  {
317  fib_prefix_t prefix;
318 
319  fib_entry_get_prefix(*import_index, &prefix);
320 
321  fib_table_entry_delete(import->faei_import_fib,
322  &prefix,
323  FIB_SOURCE_AE);
324  fib_entry_unlock(*import_index);
325  }
326  vec_free(import->faei_importeds);
327 
328  /*
329  * stop tracking the export entry
330  */
331  if (~0 != import->faei_export_sibling)
332  {
333  fib_entry_cover_untrack(fib_entry_get(import->faei_export_entry),
334  import->faei_export_sibling);
335  }
336  import->faei_export_sibling = ~0;
337 
338  /*
339  * remove this import tracker from the export's list,
340  * if it is attached to one. It won't be in the case the tracked
341  * export entry is not an attached exact match.
342  */
343  if (FIB_NODE_INDEX_INVALID != import->faei_exporter)
344  {
345  export_entry = fib_entry_get(import->faei_export_entry);
346  ASSERT(FIB_NODE_INDEX_INVALID != export_entry->fe_export);
347  export = pool_elt_at_index(fib_ae_export_pool, export_entry->fe_export);
348 
349  u32 index = vec_search(export->faee_importers,
350  (import - fib_ae_import_pool));
351 
352  ASSERT(index < vec_len(export->faee_importers));
353  vec_del1(export->faee_importers, index);
354 
355  /*
356  * free the exporter if there are no longer importers
357  */
358  if (0 == --export->faee_locks)
359  {
360  pool_put(fib_ae_export_pool, export);
361  export_entry->fe_export = FIB_NODE_INDEX_INVALID;
362  }
363  }
364 
365  /*
366  * free the import tracker
367  */
368  pool_put(fib_ae_import_pool, import);
369  fib_entry->fe_import = FIB_NODE_INDEX_INVALID;
370  }
371 }
372 
373 void
375  fib_node_index_t covered)
376 {
377  if (FIB_NODE_INDEX_INVALID != cover->fe_export)
378  {
379  /*
380  * the covering prefix is exporting to other tables
381  */
382  fib_node_index_t *import_index;
383  fib_ae_import_t *import;
384  fib_ae_export_t *export;
385 
386  export = pool_elt_at_index(fib_ae_export_pool, cover->fe_export);
387 
388  /*
389  * export the covered entry to each of the importers
390  */
391  vec_foreach(import_index, export->faee_importers)
392  {
393  import = pool_elt_at_index(fib_ae_import_pool, *import_index);
394 
395  fib_entry_import_add(import, covered);
396  }
397  }
398 }
399 
400 void
402  fib_node_index_t covered)
403 {
404  if (FIB_NODE_INDEX_INVALID != cover->fe_export)
405  {
406  /*
407  * the covering prefix is exporting to other tables
408  */
409  fib_node_index_t *import_index;
410  fib_ae_import_t *import;
411  fib_ae_export_t *export;
412 
413  export = pool_elt_at_index(fib_ae_export_pool, cover->fe_export);
414 
415  /*
416  * remove the covered entry from each of the importers
417  */
418  vec_foreach(import_index, export->faee_importers)
419  {
420  import = pool_elt_at_index(fib_ae_import_pool, *import_index);
421 
422  fib_entry_import_remove(import, covered);
423  }
424  }
425 }
426 
427 static void
429 {
430  if (FIB_NODE_INDEX_INVALID != fib_entry->fe_import)
431  {
432  fib_ae_import_t *import;
433  u32 export_fib;
434 
435  /*
436  * safe the temporaries we need from the existing import
437  * since it will be toast after the purge.
438  */
439  import = pool_elt_at_index(fib_ae_import_pool, fib_entry->fe_import);
440  export_fib = import->faei_export_fib;
441 
442  /*
443  * keep it simple. purge anything that was previously imported.
444  * then re-evaluate the need to import.
445  */
446  fib_attached_export_purge(fib_entry);
447  fib_attached_export_import(fib_entry, export_fib);
448  }
449 }
450 
451 /**
452  * \brief If this entry is tracking a cover (in another table)
453  * then that cover has changed. re-evaluate import.
454  */
455 void
457 {
459 }
460 
461 /**
462  * \brief If this entry is tracking a cover (in another table)
463  * then that cover has been updated. re-evaluate import.
464  */
465 void
467 {
469 }
470 
471 u8*
473  u8* s)
474 {
475  if (FIB_NODE_INDEX_INVALID != import_index)
476  {
477  fib_node_index_t *index;
478  fib_ae_import_t *import;
479 
480  import = pool_elt_at_index(fib_ae_import_pool, import_index);
481 
482  s = format(s, "\n Attached-Import:%d:[", (import - fib_ae_import_pool));
483  s = format(s, "export-prefix:%U ", format_fib_prefix, &import->faei_prefix);
484  s = format(s, "export-entry:%d ", import->faei_export_entry);
485  s = format(s, "export-sibling:%d ", import->faei_export_sibling);
486  s = format(s, "exporter:%d ", import->faei_exporter);
487  s = format(s, "export-fib:%d ", import->faei_export_fib);
488 
489  s = format(s, "import-entry:%d ", import->faei_import_entry);
490  s = format(s, "import-fib:%d ", import->faei_import_fib);
491 
492  s = format(s, "importeds:[");
493  vec_foreach(index, import->faei_importeds)
494  {
495  s = format(s, "%d, ", *index);
496  }
497  s = format(s, "]]");
498  }
499 
500  return (s);
501 }
502 
503 u8*
505 {
506  if (FIB_NODE_INDEX_INVALID != export_index)
507  {
508  fib_node_index_t *index;
509  fib_ae_export_t *export;
510 
511  export = pool_elt_at_index(fib_ae_export_pool, export_index);
512 
513  s = format(s, "\n Attached-Export:%d:[", (export - fib_ae_export_pool));
514  s = format(s, "export-entry:%d ", export->faee_ei);
515 
516  s = format(s, "importers:[");
517  vec_foreach(index, export->faee_importers)
518  {
519  s = format(s, "%d, ", *index);
520  }
521  s = format(s, "]]");
522  }
523  return (s);
524 }
void fib_entry_unlock(fib_node_index_t fib_entry_index)
Definition: fib_entry.c:1460
An entry in a FIB table.
Definition: fib_entry.h:360
fib_node_index_t fib_table_lookup_exact_match(u32 fib_index, const fib_prefix_t *prefix)
Perfom an exact match in the non-forwarding table.
Definition: fib_table.c:95
fib_entry_flag_t fib_entry_get_flags_i(const fib_entry_t *fib_entry)
void fib_attached_export_cover_change(fib_entry_t *fib_entry)
If this entry is tracking a cover (in another table) then that cover has changed. ...
void fib_entry_cover_untrack(fib_entry_t *cover, u32 tracked_index)
u8 * fib_ae_import_format(fib_node_index_t import_index, u8 *s)
A description of the need to import routes from the export table.
static int dpo_id_is_valid(const dpo_id_t *dpoi)
Return true if the DPO object is valid, i.e.
Definition: dpo.h:170
void fib_entry_get_prefix(fib_node_index_t fib_entry_index, fib_prefix_t *pfx)
Definition: fib_entry.c:1476
const dpo_id_t * fib_entry_contribute_ip_forwarding(fib_node_index_t fib_entry_index)
Definition: fib_entry.c:515
#define vec_add1(V, E)
Add 1 element to end of vector (unspecified alignment).
Definition: vec.h:482
fib_node_index_t faei_exporter
The index of the exporter tracker.
fib_node_index_t faei_import_entry
The attached entry in the import table.
Attached Export source.
Definition: fib_entry.h:99
fib_node_index_t faei_export_entry
The entry in the epxort table that this importer is importing covereds from.
u32 fe_fib_index
The index of the FIB table this entry is in.
Definition: fib_entry.h:372
Definition: fib_entry.h:217
#define pool_get(P, E)
Allocate an object E from a pool P (unspecified alignment).
Definition: pool.h:200
static void fib_entry_import_add(fib_ae_import_t *import, fib_node_index_t entry_index)
fib_node_index_t faee_ei
THe connected entry this export is acting on behalf of.
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)
void fib_attached_export_purge(fib_entry_t *fib_entry)
All the imported entries need to be pruged.
fib_node_index_t faei_export_fib
The FIB index and prefix we are tracking.
void fib_table_entry_special_remove(u32 fib_index, const fib_prefix_t *prefix, fib_source_t source)
Remove a &#39;special&#39; entry from the FIB.
Definition: fib_table.c:399
u8 * format_fib_prefix(u8 *s, va_list *args)
Definition: fib_types.c:140
Aggregrate type for a prefix.
Definition: fib_types.h:149
fib_node_index_t fib_entry_get_index(const fib_entry_t *fib_entry)
Definition: fib_entry.c:56
#define vec_search(v, E)
Search a vector for the index of the entry that matches.
Definition: vec.h:901
fib_node_index_t fib_table_lookup(u32 fib_index, const fib_prefix_t *prefix)
Perfom a longest prefix match in the non-forwarding table.
Definition: fib_table.c:66
The identity of a DPO is a combination of its type and its instance number/index of objects of that t...
Definition: dpo.h:138
Definition: fib_entry.h:219
#define pool_elt_at_index(p, i)
Returns pointer to element at given index.
Definition: pool.h:369
struct fib_ae_export_t_ fib_ae_export_t
A description of the need to export routes to one or more export tables.
#define pool_put(P, E)
Free an object E in pool P.
Definition: pool.h:214
#define vec_del1(v, i)
Delete the element at index I.
Definition: vec.h:765
const dpo_id_t * load_balance_get_bucket(index_t lbi, u32 bucket)
Definition: load_balance.c:271
fib_node_index_t fe_export
exporter
Definition: fib_entry.h:412
fib_prefix_t fe_prefix
The prefix of the route.
Definition: fib_entry.h:368
static void fib_ae_export_import_add(fib_ae_export_t *export, fib_ae_import_t *import)
u32 faee_locks
Reference counting locks.
void fib_attached_export_covered_removed(fib_entry_t *cover, fib_node_index_t covered)
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:300
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:793
u8 * fib_ae_export_format(fib_node_index_t export_index, u8 *s)
u32 fib_node_index_t
A typedef of a node index.
Definition: fib_types.h:28
fib_entry_t * fib_entry_get(fib_node_index_t index)
Definition: fib_entry.c:44
u32 faei_export_sibling
the sibling index on the cover
void fib_entry_lock(fib_node_index_t fib_entry_index)
Definition: fib_entry.c:1450
fib_node_index_t fib_table_entry_special_dpo_add(u32 fib_index, const fib_prefix_t *prefix, fib_source_t source, fib_entry_flag_t flags, const dpo_id_t *dpo)
Add a &#39;special&#39; entry to the FIB that links to the DPO passed A special entry is an entry that the FI...
Definition: fib_table.c:288
#define ASSERT(truth)
unsigned int u32
Definition: types.h:88
A description of the need to export routes to one or more export tables.
fib_prefix_t faei_prefix
fib_node_index_t * faee_importers
The vector/list of import tracker indicies.
void fib_attached_export_cover_update(fib_entry_t *fib_entry)
If this entry is tracking a cover (in another table) then that cover has been updated.
void fib_attached_export_import(fib_entry_t *fib_entry, fib_node_index_t export_fib)
FIB attached export.
void fib_entry_cover_walk(fib_entry_t *cover, fib_entry_covered_walk_t walk, void *args)
static fib_ae_import_t * fib_ae_import_pool
static fib_ae_export_t * fib_ae_export_pool
int fib_prefix_cmp(const fib_prefix_t *p1, const fib_prefix_t *p2)
Compare two prefixes for equality.
Definition: fib_types.c:68
index_t dpoi_index
the index of objects of that type
Definition: dpo.h:154
#define FIB_NODE_INDEX_INVALID
Definition: fib_types.h:29
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
unsigned char u8
Definition: types.h:56
static void fib_entry_import_remove(fib_ae_import_t *import, fib_node_index_t entry_index)
fib_node_index_t * faei_importeds
A vector/list of imported entry indicies.
u8 * format(u8 *s, const char *fmt,...)
Definition: format.c:418
static void fib_attached_export_cover_modified_i(fib_entry_t *fib_entry)
#define vec_foreach(var, vec)
Vector iterator.
static fib_ae_export_t * fib_entry_ae_add_or_lock(fib_node_index_t connected)
fib_node_index_t faei_import_fib
The FIB index we are importing into.
static int fib_entry_covered_walk_import(fib_entry_t *cover, fib_node_index_t covered, void *ctx)
Call back when walking a connected prefix&#39;s covered prefixes for import.
fib_node_index_t fe_import
Definition: fib_entry.h:413
struct fib_ae_import_t_ fib_ae_import_t
A description of the need to import routes from the export table.