blob: 206d10e7140f593089a6dde24ecae14a9d86256e [file] [log] [blame]
Neale Ranns0bfe5d82016-08-25 15:29:12 +01001/*
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
Neale Rannsad422ed2016-11-02 14:20:04 +000019#include <vnet/fib/fib_attached_export.h>
20#include <vnet/fib/fib_entry_cover.h>
21#include <vnet/fib/fib_entry_src.h>
22#include <vnet/fib/fib_entry_delegate.h>
Neale Ranns2303cb12018-02-21 04:57:17 -080023#include <vnet/dpo/drop_dpo.h>
Neale Ranns0bfe5d82016-08-25 15:29:12 +010024
25/**
26 * A description of the need to import routes from the export table
27 */
28typedef struct fib_ae_import_t_
29{
30 /**
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -070031 * The entry in the export table that this importer
Neale Ranns0bfe5d82016-08-25 15:29:12 +010032 * is importing covereds from
33 */
34 fib_node_index_t faei_export_entry;
35
36 /**
37 * The attached entry in the import table
38 */
39 fib_node_index_t faei_import_entry;
40 /**
41 * the sibling index on the cover
42 */
43 u32 faei_export_sibling;
44
45 /**
46 * The index of the exporter tracker. Not set if the
47 * export entry is not valid for export
48 */
49 fib_node_index_t faei_exporter;
50
51 /**
52 * A vector/list of imported entry indicies
53 */
54 fib_node_index_t *faei_importeds;
55
56 /**
57 * The FIB index and prefix we are tracking
58 */
59 fib_node_index_t faei_export_fib;
60 fib_prefix_t faei_prefix;
61
62 /**
63 * The FIB index we are importing into
64 */
65 fib_node_index_t faei_import_fib;
66} fib_ae_import_t;
67
68/**
69 * A description of the need to export routes to one or more export tables
70 */
71typedef struct fib_ae_export_t_ {
72 /**
73 * The vector/list of import tracker indicies
74 */
75 fib_node_index_t *faee_importers;
76
77 /**
78 * THe connected entry this export is acting on behalf of
79 */
80 fib_node_index_t faee_ei;
81
82 /**
83 * Reference counting locks
84 */
85 u32 faee_locks;
86} fib_ae_export_t;
87
88/*
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -070089 * memory pools for the importers and exporters
Neale Ranns0bfe5d82016-08-25 15:29:12 +010090 */
91static fib_ae_import_t *fib_ae_import_pool;
92static fib_ae_export_t *fib_ae_export_pool;
93
94static fib_ae_export_t *
95fib_entry_ae_add_or_lock (fib_node_index_t connected)
96{
Neale Rannsad422ed2016-11-02 14:20:04 +000097 fib_entry_delegate_t *fed;
Neale Ranns0bfe5d82016-08-25 15:29:12 +010098 fib_ae_export_t *export;
99 fib_entry_t *entry;
100
101 entry = fib_entry_get(connected);
Neale Ranns1f50bf82019-07-16 15:28:52 +0000102 fed = fib_entry_delegate_find(entry,
103 FIB_ENTRY_DELEGATE_ATTACHED_EXPORT);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100104
Neale Rannsad422ed2016-11-02 14:20:04 +0000105 if (NULL == fed)
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100106 {
Neale Rannsad422ed2016-11-02 14:20:04 +0000107 fed = fib_entry_delegate_find_or_add(entry,
108 FIB_ENTRY_DELEGATE_ATTACHED_EXPORT);
Vladislav Grishenkoc022b2f2021-09-18 17:32:17 +0500109 pool_get_zero(fib_ae_export_pool, export);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100110
Neale Rannsad422ed2016-11-02 14:20:04 +0000111 fed->fd_index = (export - fib_ae_export_pool);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100112 export->faee_ei = connected;
113 }
114 else
115 {
Neale Rannsad422ed2016-11-02 14:20:04 +0000116 export = pool_elt_at_index(fib_ae_export_pool, fed->fd_index);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100117 }
118
119 export->faee_locks++;
120
121 return (export);
122}
123
124static void
125fib_entry_import_remove (fib_ae_import_t *import,
126 fib_node_index_t entry_index)
127{
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100128 u32 index;
129
130 /*
131 * find the index in the vector of the entry we are removing
132 */
133 index = vec_search(import->faei_importeds, entry_index);
134
135 if (index < vec_len(import->faei_importeds))
136 {
137 /*
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -0700138 * this is an entry that was previously imported
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100139 */
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100140 fib_table_entry_special_remove(import->faei_import_fib,
Neale Rannsc5d43172018-07-30 08:04:40 -0700141 fib_entry_get_prefix(entry_index),
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100142 FIB_SOURCE_AE);
143
144 fib_entry_unlock(entry_index);
145 vec_del1(import->faei_importeds, index);
146 }
147}
148
149static void
150fib_entry_import_add (fib_ae_import_t *import,
151 fib_node_index_t entry_index)
152{
153 fib_node_index_t *existing;
Neale Ranns320dfcf2019-11-06 11:17:54 +0000154 fib_prefix_t prefix;
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100155
156 /*
157 * ensure we only add the exported entry once, since
158 * sourcing prefixes in the table is reference counted
159 */
160 vec_foreach(existing, import->faei_importeds)
161 {
162 if (*existing == entry_index)
163 {
164 return;
165 }
166 }
167
168 /*
169 * this is the first time this export entry has been imported
Neale Ranns320dfcf2019-11-06 11:17:54 +0000170 * Add it to the import FIB and to the list of importeds.
171 * make a copy of the prefix in case the underlying entry reallocs.
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100172 */
Neale Ranns320dfcf2019-11-06 11:17:54 +0000173 fib_prefix_copy(&prefix, fib_entry_get_prefix(entry_index));
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100174
175 /*
176 * don't import entries that have the same prefix the import entry
177 */
Neale Ranns320dfcf2019-11-06 11:17:54 +0000178 if (0 != fib_prefix_cmp(&prefix, &import->faei_prefix))
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100179 {
180 const dpo_id_t *dpo;
181
182 dpo = fib_entry_contribute_ip_forwarding(entry_index);
183
Neale Ranns2303cb12018-02-21 04:57:17 -0800184 if (dpo_id_is_valid(dpo) && !dpo_is_drop(dpo))
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100185 {
186 fib_table_entry_special_dpo_add(import->faei_import_fib,
Neale Ranns320dfcf2019-11-06 11:17:54 +0000187 &prefix,
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100188 FIB_SOURCE_AE,
Neale Rannsfa0fb582016-12-10 21:59:14 +0000189 (fib_entry_get_flags(entry_index) |
190 FIB_ENTRY_FLAG_EXCLUSIVE),
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100191 load_balance_get_bucket(dpo->dpoi_index, 0));
192
193 fib_entry_lock(entry_index);
194 vec_add1(import->faei_importeds, entry_index);
195 }
196 /*
197 * else
198 * the entry currently has no valid forwarding. when it
199 * does it will export itself
200 */
201 }
202}
203
204/**
205 * Call back when walking a connected prefix's covered prefixes for import
206 */
Neale Rannsfdf6b6f2020-11-26 09:34:39 +0000207static walk_rc_t
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100208fib_entry_covered_walk_import (fib_entry_t *cover,
209 fib_node_index_t covered,
210 void *ctx)
211{
212 fib_ae_import_t *import = ctx;
213
214 fib_entry_import_add(import, covered);
215
Neale Rannsfdf6b6f2020-11-26 09:34:39 +0000216 return (WALK_CONTINUE);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100217}
218
219/*
220 * fib_entry_ae_import_add
221 *
222 * Add an importer to a connected entry
223 */
224static void
225fib_ae_export_import_add (fib_ae_export_t *export,
226 fib_ae_import_t *import)
227{
228 fib_entry_t *entry;
229
230 import->faei_exporter = (export - fib_ae_export_pool);
231 entry = fib_entry_get(export->faee_ei);
232
233 fib_entry_cover_walk(entry,
234 fib_entry_covered_walk_import,
235 import);
236}
237
238void
239fib_attached_export_import (fib_entry_t *fib_entry,
240 fib_node_index_t export_fib)
241{
Neale Rannsad422ed2016-11-02 14:20:04 +0000242 fib_entry_delegate_t *fed;
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100243 fib_ae_import_t *import;
Neale Rannsf8fc0f62017-01-10 18:13:41 +0100244 fib_node_index_t fei;
245
246 /*
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -0700247 * save index for later post-realloc retrieval
Neale Rannsf8fc0f62017-01-10 18:13:41 +0100248 */
249 fei = fib_entry_get_index(fib_entry);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100250
Vladislav Grishenkoc022b2f2021-09-18 17:32:17 +0500251 pool_get_zero(fib_ae_import_pool, import);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100252
253 import->faei_import_fib = fib_entry->fe_fib_index;
254 import->faei_export_fib = export_fib;
255 import->faei_prefix = fib_entry->fe_prefix;
256 import->faei_import_entry = fib_entry_get_index(fib_entry);
257 import->faei_export_sibling = ~0;
Vladislav Grishenkoc022b2f2021-09-18 17:32:17 +0500258 import->faei_exporter = FIB_NODE_INDEX_INVALID;
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100259
260 /*
261 * do an exact match in the export table
262 */
263 import->faei_export_entry =
264 fib_table_lookup_exact_match(import->faei_export_fib,
265 &import->faei_prefix);
266
267 if (FIB_NODE_INDEX_INVALID == import->faei_export_entry)
268 {
269 /*
270 * no exact matching entry in the export table. can't be good.
271 * track the next best thing
272 */
273 import->faei_export_entry =
274 fib_table_lookup(import->faei_export_fib,
275 &import->faei_prefix);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100276 }
277 else
278 {
279 /*
280 * found the entry in the export table. import the
281 * the prefixes that it covers.
282 * only if the prefix found in the export FIB really is
283 * attached do we want to import its covered
284 */
285 if (FIB_ENTRY_FLAG_ATTACHED &
286 fib_entry_get_flags_i(fib_entry_get(import->faei_export_entry)))
287 {
288 fib_ae_export_t *export;
289
290 export = fib_entry_ae_add_or_lock(import->faei_export_entry);
291 vec_add1(export->faee_importers, (import - fib_ae_import_pool));
292 fib_ae_export_import_add(export, import);
293 }
294 }
295
296 /*
297 * track the entry in the export table so we can update appropriately
Neale Rannsf8fc0f62017-01-10 18:13:41 +0100298 * when it changes.
299 * Exporting prefixes will have allocated new fib_entry_t objects, so the pool
300 * may have realloc'd.
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100301 */
Neale Rannsf8fc0f62017-01-10 18:13:41 +0100302 fib_entry = fib_entry_get(fei);
Neale Ranns32e1c012016-11-22 17:07:28 +0000303 import->faei_export_sibling =
304 fib_entry_cover_track(fib_entry_get(import->faei_export_entry), fei);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100305
Neale Rannsad422ed2016-11-02 14:20:04 +0000306 fed = fib_entry_delegate_find_or_add(fib_entry,
307 FIB_ENTRY_DELEGATE_ATTACHED_IMPORT);
308 fed->fd_index = (import - fib_ae_import_pool);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100309}
310
311/**
Paul Vinciguerra8feeaff2019-03-27 11:25:48 -0700312 * \brief All the imported entries need to be purged
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100313 */
314void
315fib_attached_export_purge (fib_entry_t *fib_entry)
316{
Neale Rannsad422ed2016-11-02 14:20:04 +0000317 fib_entry_delegate_t *fed;
318
Neale Ranns1f50bf82019-07-16 15:28:52 +0000319 fed = fib_entry_delegate_find(fib_entry,
320 FIB_ENTRY_DELEGATE_ATTACHED_IMPORT);
Neale Rannsad422ed2016-11-02 14:20:04 +0000321
322 if (NULL != fed)
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100323 {
324 fib_node_index_t *import_index;
325 fib_entry_t *export_entry;
326 fib_ae_import_t *import;
327 fib_ae_export_t *export;
328
Neale Rannsad422ed2016-11-02 14:20:04 +0000329 import = pool_elt_at_index(fib_ae_import_pool, fed->fd_index);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100330
331 /*
332 * remove each imported entry
333 */
334 vec_foreach(import_index, import->faei_importeds)
335 {
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100336 fib_table_entry_delete(import->faei_import_fib,
Neale Rannsc5d43172018-07-30 08:04:40 -0700337 fib_entry_get_prefix(*import_index),
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100338 FIB_SOURCE_AE);
339 fib_entry_unlock(*import_index);
340 }
341 vec_free(import->faei_importeds);
342
343 /*
344 * stop tracking the export entry
345 */
346 if (~0 != import->faei_export_sibling)
347 {
348 fib_entry_cover_untrack(fib_entry_get(import->faei_export_entry),
349 import->faei_export_sibling);
350 }
351 import->faei_export_sibling = ~0;
352
353 /*
354 * remove this import tracker from the export's list,
355 * if it is attached to one. It won't be in the case the tracked
356 * export entry is not an attached exact match.
357 */
358 if (FIB_NODE_INDEX_INVALID != import->faei_exporter)
359 {
Neale Rannsad422ed2016-11-02 14:20:04 +0000360 fib_entry_delegate_t *fed;
361
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100362 export_entry = fib_entry_get(import->faei_export_entry);
Neale Rannsad422ed2016-11-02 14:20:04 +0000363
Neale Ranns1f50bf82019-07-16 15:28:52 +0000364 fed = fib_entry_delegate_find(export_entry,
365 FIB_ENTRY_DELEGATE_ATTACHED_EXPORT);
Dave Barach47d41ad2020-02-17 09:13:26 -0500366 ALWAYS_ASSERT(NULL != fed);
Neale Rannsad422ed2016-11-02 14:20:04 +0000367
368 export = pool_elt_at_index(fib_ae_export_pool, fed->fd_index);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100369
370 u32 index = vec_search(export->faee_importers,
371 (import - fib_ae_import_pool));
372
373 ASSERT(index < vec_len(export->faee_importers));
374 vec_del1(export->faee_importers, index);
375
376 /*
377 * free the exporter if there are no longer importers
378 */
379 if (0 == --export->faee_locks)
380 {
381 pool_put(fib_ae_export_pool, export);
Neale Rannsad422ed2016-11-02 14:20:04 +0000382 fib_entry_delegate_remove(export_entry,
383 FIB_ENTRY_DELEGATE_ATTACHED_EXPORT);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100384 }
385 }
386
387 /*
388 * free the import tracker
389 */
390 pool_put(fib_ae_import_pool, import);
Neale Rannsad422ed2016-11-02 14:20:04 +0000391 fib_entry_delegate_remove(fib_entry,
392 FIB_ENTRY_DELEGATE_ATTACHED_IMPORT);
Dave Barach47d41ad2020-02-17 09:13:26 -0500393 }
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100394}
395
396void
397fib_attached_export_covered_added (fib_entry_t *cover,
398 fib_node_index_t covered)
399{
Neale Rannsad422ed2016-11-02 14:20:04 +0000400 fib_entry_delegate_t *fed;
401
Neale Ranns1f50bf82019-07-16 15:28:52 +0000402 fed = fib_entry_delegate_find(cover,
403 FIB_ENTRY_DELEGATE_ATTACHED_EXPORT);
Neale Rannsad422ed2016-11-02 14:20:04 +0000404
405 if (NULL != fed)
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100406 {
407 /*
408 * the covering prefix is exporting to other tables
409 */
410 fib_node_index_t *import_index;
411 fib_ae_import_t *import;
412 fib_ae_export_t *export;
413
Neale Rannsad422ed2016-11-02 14:20:04 +0000414 export = pool_elt_at_index(fib_ae_export_pool, fed->fd_index);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100415
416 /*
417 * export the covered entry to each of the importers
418 */
419 vec_foreach(import_index, export->faee_importers)
420 {
421 import = pool_elt_at_index(fib_ae_import_pool, *import_index);
422
423 fib_entry_import_add(import, covered);
424 }
425 }
426}
427
428void
429fib_attached_export_covered_removed (fib_entry_t *cover,
430 fib_node_index_t covered)
431{
Neale Rannsad422ed2016-11-02 14:20:04 +0000432 fib_entry_delegate_t *fed;
433
Neale Ranns1f50bf82019-07-16 15:28:52 +0000434 fed = fib_entry_delegate_find(cover,
435 FIB_ENTRY_DELEGATE_ATTACHED_EXPORT);
Neale Rannsad422ed2016-11-02 14:20:04 +0000436
437 if (NULL != fed)
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100438 {
439 /*
440 * the covering prefix is exporting to other tables
441 */
442 fib_node_index_t *import_index;
443 fib_ae_import_t *import;
444 fib_ae_export_t *export;
445
Neale Rannsad422ed2016-11-02 14:20:04 +0000446 export = pool_elt_at_index(fib_ae_export_pool, fed->fd_index);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100447
448 /*
449 * remove the covered entry from each of the importers
450 */
451 vec_foreach(import_index, export->faee_importers)
452 {
453 import = pool_elt_at_index(fib_ae_import_pool, *import_index);
454
455 fib_entry_import_remove(import, covered);
456 }
457 }
458}
459
460static void
461fib_attached_export_cover_modified_i (fib_entry_t *fib_entry)
462{
Neale Rannsad422ed2016-11-02 14:20:04 +0000463 fib_entry_delegate_t *fed;
464
Neale Ranns1f50bf82019-07-16 15:28:52 +0000465 fed = fib_entry_delegate_find(fib_entry,
466 FIB_ENTRY_DELEGATE_ATTACHED_IMPORT);
Neale Rannsad422ed2016-11-02 14:20:04 +0000467
468 if (NULL != fed)
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100469 {
470 fib_ae_import_t *import;
471 u32 export_fib;
472
473 /*
474 * safe the temporaries we need from the existing import
475 * since it will be toast after the purge.
476 */
Neale Rannsad422ed2016-11-02 14:20:04 +0000477 import = pool_elt_at_index(fib_ae_import_pool, fed->fd_index);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100478 export_fib = import->faei_export_fib;
479
480 /*
481 * keep it simple. purge anything that was previously imported.
482 * then re-evaluate the need to import.
483 */
484 fib_attached_export_purge(fib_entry);
485 fib_attached_export_import(fib_entry, export_fib);
486 }
487}
488
489/**
490 * \brief If this entry is tracking a cover (in another table)
491 * then that cover has changed. re-evaluate import.
492 */
493void
494fib_attached_export_cover_change (fib_entry_t *fib_entry)
495{
496 fib_attached_export_cover_modified_i(fib_entry);
497}
498
499/**
500 * \brief If this entry is tracking a cover (in another table)
501 * then that cover has been updated. re-evaluate import.
502 */
503void
504fib_attached_export_cover_update (fib_entry_t *fib_entry)
505{
506 fib_attached_export_cover_modified_i(fib_entry);
507}
508
509u8*
Neale Ranns88fc83e2017-04-05 08:11:14 -0700510fib_ae_import_format (fib_node_index_t impi,
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100511 u8* s)
512{
Neale Ranns88fc83e2017-04-05 08:11:14 -0700513 fib_node_index_t *index;
514 fib_ae_import_t *import;
Neale Rannsad422ed2016-11-02 14:20:04 +0000515
Neale Ranns88fc83e2017-04-05 08:11:14 -0700516 import = pool_elt_at_index(fib_ae_import_pool, impi);
Neale Rannsad422ed2016-11-02 14:20:04 +0000517
Neale Ranns88fc83e2017-04-05 08:11:14 -0700518 s = format(s, "\n Attached-Import:%d:[", (import - fib_ae_import_pool));
519 s = format(s, "export-prefix:%U ", format_fib_prefix, &import->faei_prefix);
520 s = format(s, "export-entry:%d ", import->faei_export_entry);
521 s = format(s, "export-sibling:%d ", import->faei_export_sibling);
522 s = format(s, "exporter:%d ", import->faei_exporter);
523 s = format(s, "export-fib:%d ", import->faei_export_fib);
Dave Barach47d41ad2020-02-17 09:13:26 -0500524
Neale Ranns88fc83e2017-04-05 08:11:14 -0700525 s = format(s, "import-entry:%d ", import->faei_import_entry);
526 s = format(s, "import-fib:%d ", import->faei_import_fib);
527
528 s = format(s, "importeds:[");
529 vec_foreach(index, import->faei_importeds)
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100530 {
Neale Ranns88fc83e2017-04-05 08:11:14 -0700531 s = format(s, "%d, ", *index);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100532 }
Neale Ranns88fc83e2017-04-05 08:11:14 -0700533 s = format(s, "]]");
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100534
535 return (s);
536}
537
538u8*
Neale Ranns88fc83e2017-04-05 08:11:14 -0700539fib_ae_export_format (fib_node_index_t expi,
Neale Rannsad422ed2016-11-02 14:20:04 +0000540 u8* s)
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100541{
Neale Ranns88fc83e2017-04-05 08:11:14 -0700542 fib_node_index_t *index;
543 fib_ae_export_t *export;
Neale Rannsad422ed2016-11-02 14:20:04 +0000544
Neale Ranns88fc83e2017-04-05 08:11:14 -0700545 export = pool_elt_at_index(fib_ae_export_pool, expi);
Dave Barach47d41ad2020-02-17 09:13:26 -0500546
Neale Ranns88fc83e2017-04-05 08:11:14 -0700547 s = format(s, "\n Attached-Export:%d:[", (export - fib_ae_export_pool));
548 s = format(s, "export-entry:%d ", export->faee_ei);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100549
Neale Ranns88fc83e2017-04-05 08:11:14 -0700550 s = format(s, "importers:[");
551 vec_foreach(index, export->faee_importers)
552 {
553 s = format(s, "%d, ", *index);
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100554 }
Neale Ranns88fc83e2017-04-05 08:11:14 -0700555 s = format(s, "]]");
556
Neale Ranns0bfe5d82016-08-25 15:29:12 +0100557 return (s);
558}