]>
Commit | Line | Data |
---|---|---|
acddc0ed | 1 | // SPDX-License-Identifier: GPL-2.0-or-later |
7f57883e DS |
2 | /* |
3 | * EIGRP Topology Table. | |
4 | * Copyright (C) 2013-2016 | |
5 | * Authors: | |
6 | * Donnie Savage | |
7 | * Jan Janovic | |
8 | * Matej Perina | |
9 | * Peter Orsag | |
10 | * Peter Paluch | |
11 | * Frantisek Gazo | |
12 | * Tomas Hvorkovy | |
13 | * Martin Kontsek | |
14 | * Lukas Koribsky | |
7f57883e DS |
15 | */ |
16 | ||
17 | #include <zebra.h> | |
18 | ||
19 | #include "prefix.h" | |
20 | #include "table.h" | |
21 | #include "memory.h" | |
22 | #include "log.h" | |
23 | #include "linklist.h" | |
24 | #include "vty.h" | |
6ae7ed45 | 25 | #include "lib_errors.h" |
7f57883e | 26 | |
e9f1847e | 27 | #include "eigrpd/eigrp_types.h" |
7f57883e DS |
28 | #include "eigrpd/eigrp_structs.h" |
29 | #include "eigrpd/eigrpd.h" | |
30 | #include "eigrpd/eigrp_interface.h" | |
31 | #include "eigrpd/eigrp_neighbor.h" | |
32 | #include "eigrpd/eigrp_packet.h" | |
33 | #include "eigrpd/eigrp_zebra.h" | |
34 | #include "eigrpd/eigrp_vty.h" | |
35 | #include "eigrpd/eigrp_network.h" | |
36 | #include "eigrpd/eigrp_dump.h" | |
37 | #include "eigrpd/eigrp_topology.h" | |
38 | #include "eigrpd/eigrp_fsm.h" | |
e9f1847e | 39 | #include "eigrpd/eigrp_metric.h" |
7f57883e | 40 | |
b4216e2c DL |
41 | DEFINE_MTYPE_STATIC(EIGRPD, EIGRP_ROUTE_DESCRIPTOR, "EIGRP Nexthop Entry"); |
42 | DEFINE_MTYPE(EIGRPD, EIGRP_PREFIX_DESCRIPTOR, "EIGRP Prefix"); | |
43 | ||
dc4accdd DS |
44 | static int eigrp_route_descriptor_cmp(struct eigrp_route_descriptor *rd1, |
45 | struct eigrp_route_descriptor *rd2); | |
7f57883e DS |
46 | |
47 | /* | |
7f57883e DS |
48 | * Returns linkedlist used as topology table |
49 | * cmp - assigned function for comparing topology nodes | |
d62a17ae | 50 | * del - assigned function executed before deleting topology node by list |
51 | * function | |
7f57883e | 52 | */ |
4d762f26 | 53 | struct route_table *eigrp_topology_new(void) |
7f57883e | 54 | { |
9ca66cc7 | 55 | return route_table_init(); |
7f57883e DS |
56 | } |
57 | ||
58 | /* | |
59 | * Returns new created toplogy node | |
60 | * cmp - assigned function for comparing topology entry | |
61 | */ | |
dc4accdd | 62 | struct eigrp_prefix_descriptor *eigrp_prefix_descriptor_new(void) |
7f57883e | 63 | { |
dc4accdd DS |
64 | struct eigrp_prefix_descriptor *new; |
65 | new = XCALLOC(MTYPE_EIGRP_PREFIX_DESCRIPTOR, | |
66 | sizeof(struct eigrp_prefix_descriptor)); | |
d62a17ae | 67 | new->entries = list_new(); |
68 | new->rij = list_new(); | |
dc4accdd | 69 | new->entries->cmp = (int (*)(void *, void *))eigrp_route_descriptor_cmp; |
d62a17ae | 70 | new->distance = new->fdistance = new->rdistance = EIGRP_MAX_METRIC; |
02b45998 | 71 | new->destination = NULL; |
d62a17ae | 72 | |
73 | return new; | |
7f57883e DS |
74 | } |
75 | ||
76 | /* | |
77 | * Topology entry comparison | |
78 | */ | |
dc4accdd DS |
79 | static int eigrp_route_descriptor_cmp(struct eigrp_route_descriptor *entry1, |
80 | struct eigrp_route_descriptor *entry2) | |
7f57883e | 81 | { |
02b45998 DS |
82 | if (entry1->distance < entry2->distance) |
83 | return -1; | |
d62a17ae | 84 | if (entry1->distance > entry2->distance) |
85 | return 1; | |
7f57883e | 86 | |
d62a17ae | 87 | return 0; |
7f57883e DS |
88 | } |
89 | ||
90 | /* | |
91 | * Returns new topology entry | |
92 | */ | |
93 | ||
dc4accdd | 94 | struct eigrp_route_descriptor *eigrp_route_descriptor_new(void) |
7f57883e | 95 | { |
dc4accdd | 96 | struct eigrp_route_descriptor *new; |
7f57883e | 97 | |
dc4accdd DS |
98 | new = XCALLOC(MTYPE_EIGRP_ROUTE_DESCRIPTOR, |
99 | sizeof(struct eigrp_route_descriptor)); | |
d62a17ae | 100 | new->reported_distance = EIGRP_MAX_METRIC; |
101 | new->distance = EIGRP_MAX_METRIC; | |
7f57883e | 102 | |
d62a17ae | 103 | return new; |
7f57883e DS |
104 | } |
105 | ||
106 | /* | |
107 | * Freeing topology table list | |
108 | */ | |
0da93ecf | 109 | void eigrp_topology_free(struct eigrp *eigrp, struct route_table *table) |
7f57883e | 110 | { |
0da93ecf | 111 | eigrp_topology_delete_all(eigrp, table); |
7eee7ef6 | 112 | route_table_finish(table); |
7f57883e DS |
113 | } |
114 | ||
115 | /* | |
116 | * Adding topology node to topology table | |
117 | */ | |
dc4accdd DS |
118 | void eigrp_prefix_descriptor_add(struct route_table *topology, |
119 | struct eigrp_prefix_descriptor *pe) | |
7f57883e | 120 | { |
9ca66cc7 DS |
121 | struct route_node *rn; |
122 | ||
123 | rn = route_node_get(topology, pe->destination); | |
124 | if (rn->info) { | |
2dbe669b | 125 | if (IS_DEBUG_EIGRP_EVENT) |
996c9314 | 126 | zlog_debug( |
2dbe669b DA |
127 | "%s: %pFX Should we have found this entry in the topo table?", |
128 | __func__, pe->destination); | |
051da24e | 129 | route_unlock_node(rn); |
d62a17ae | 130 | } |
9ca66cc7 DS |
131 | |
132 | rn->info = pe; | |
7f57883e DS |
133 | } |
134 | ||
135 | /* | |
136 | * Adding topology entry to topology node | |
137 | */ | |
dc4accdd DS |
138 | void eigrp_route_descriptor_add(struct eigrp *eigrp, |
139 | struct eigrp_prefix_descriptor *node, | |
140 | struct eigrp_route_descriptor *entry) | |
7f57883e | 141 | { |
d62a17ae | 142 | struct list *l = list_new(); |
76220653 | 143 | |
d62a17ae | 144 | listnode_add(l, entry); |
63863c47 | 145 | |
d62a17ae | 146 | if (listnode_lookup(node->entries, entry) == NULL) { |
147 | listnode_add_sort(node->entries, entry); | |
148 | entry->prefix = node; | |
63863c47 | 149 | |
0e64ed02 DS |
150 | eigrp_zebra_route_add(eigrp, node->destination, |
151 | l, node->fdistance); | |
d62a17ae | 152 | } |
76220653 | 153 | |
6a154c88 | 154 | list_delete(&l); |
7f57883e DS |
155 | } |
156 | ||
157 | /* | |
158 | * Deleting topology node from topology table | |
159 | */ | |
dc4accdd DS |
160 | void eigrp_prefix_descriptor_delete(struct eigrp *eigrp, |
161 | struct route_table *table, | |
162 | struct eigrp_prefix_descriptor *pe) | |
7f57883e | 163 | { |
dc4accdd | 164 | struct eigrp_route_descriptor *ne; |
7eee7ef6 | 165 | struct listnode *node, *nnode; |
9ca66cc7 DS |
166 | struct route_node *rn; |
167 | ||
0bf75bd5 | 168 | if (!eigrp) |
169 | return; | |
170 | ||
9ca66cc7 DS |
171 | rn = route_node_lookup(table, pe->destination); |
172 | if (!rn) | |
173 | return; | |
d62a17ae | 174 | |
175 | /* | |
176 | * Emergency removal of the node from this list. | |
177 | * Whatever it is. | |
178 | */ | |
9ca66cc7 | 179 | listnode_delete(eigrp->topology_changes_internalIPV4, pe); |
d62a17ae | 180 | |
7eee7ef6 | 181 | for (ALL_LIST_ELEMENTS(pe->entries, node, nnode, ne)) |
dc4accdd | 182 | eigrp_route_descriptor_delete(eigrp, pe, ne); |
6a154c88 DL |
183 | list_delete(&pe->entries); |
184 | list_delete(&pe->rij); | |
0e64ed02 | 185 | eigrp_zebra_route_delete(eigrp, pe->destination); |
63265b5c | 186 | prefix_free(&pe->destination); |
9ca66cc7 DS |
187 | |
188 | rn->info = NULL; | |
996c9314 LB |
189 | route_unlock_node(rn); // Lookup above |
190 | route_unlock_node(rn); // Initial creation | |
dc4accdd | 191 | XFREE(MTYPE_EIGRP_PREFIX_DESCRIPTOR, pe); |
7f57883e DS |
192 | } |
193 | ||
194 | /* | |
195 | * Deleting topology entry from topology node | |
196 | */ | |
dc4accdd DS |
197 | void eigrp_route_descriptor_delete(struct eigrp *eigrp, |
198 | struct eigrp_prefix_descriptor *node, | |
199 | struct eigrp_route_descriptor *entry) | |
7f57883e | 200 | { |
d62a17ae | 201 | if (listnode_lookup(node->entries, entry) != NULL) { |
202 | listnode_delete(node->entries, entry); | |
0e64ed02 | 203 | eigrp_zebra_route_delete(eigrp, node->destination); |
dc4accdd | 204 | XFREE(MTYPE_EIGRP_ROUTE_DESCRIPTOR, entry); |
d62a17ae | 205 | } |
7f57883e DS |
206 | } |
207 | ||
208 | /* | |
209 | * Deleting all nodes from topology table | |
210 | */ | |
0da93ecf DS |
211 | void eigrp_topology_delete_all(struct eigrp *eigrp, |
212 | struct route_table *topology) | |
7f57883e | 213 | { |
9ca66cc7 | 214 | struct route_node *rn; |
dc4accdd | 215 | struct eigrp_prefix_descriptor *pe; |
9ca66cc7 DS |
216 | |
217 | for (rn = route_top(topology); rn; rn = route_next(rn)) { | |
218 | pe = rn->info; | |
219 | ||
220 | if (!pe) | |
221 | continue; | |
222 | ||
dc4accdd | 223 | eigrp_prefix_descriptor_delete(eigrp, topology, pe); |
9ca66cc7 | 224 | } |
7f57883e DS |
225 | } |
226 | ||
dc4accdd | 227 | struct eigrp_prefix_descriptor * |
9ca66cc7 | 228 | eigrp_topology_table_lookup_ipv4(struct route_table *table, |
476a1469 | 229 | struct prefix *address) |
7f57883e | 230 | { |
dc4accdd | 231 | struct eigrp_prefix_descriptor *pe; |
9ca66cc7 | 232 | struct route_node *rn; |
d62a17ae | 233 | |
9ca66cc7 DS |
234 | rn = route_node_lookup(table, address); |
235 | if (!rn) | |
236 | return NULL; | |
237 | ||
238 | pe = rn->info; | |
239 | ||
240 | route_unlock_node(rn); | |
241 | ||
242 | return pe; | |
7f57883e | 243 | } |
f6709c16 | 244 | |
2118601d DS |
245 | /* |
246 | * For a future optimization, put the successor list into it's | |
247 | * own separate list from the full list? | |
248 | * | |
249 | * That way we can clean up all the list_new and list_delete's | |
250 | * that we are doing. DBS | |
251 | */ | |
dc4accdd DS |
252 | struct list * |
253 | eigrp_topology_get_successor(struct eigrp_prefix_descriptor *table_node) | |
7f57883e | 254 | { |
d62a17ae | 255 | struct list *successors = list_new(); |
dc4accdd | 256 | struct eigrp_route_descriptor *data; |
d62a17ae | 257 | struct listnode *node1, *node2; |
258 | ||
259 | for (ALL_LIST_ELEMENTS(table_node->entries, node1, node2, data)) { | |
dc4accdd | 260 | if (data->flags & EIGRP_ROUTE_DESCRIPTOR_SUCCESSOR_FLAG) { |
d62a17ae | 261 | listnode_add(successors, data); |
262 | } | |
263 | } | |
264 | ||
265 | /* | |
266 | * If we have no successors return NULL | |
267 | */ | |
268 | if (!successors->count) { | |
6a154c88 | 269 | list_delete(&successors); |
d62a17ae | 270 | successors = NULL; |
271 | } | |
272 | ||
273 | return successors; | |
7f57883e DS |
274 | } |
275 | ||
962251ae | 276 | struct list * |
dc4accdd | 277 | eigrp_topology_get_successor_max(struct eigrp_prefix_descriptor *table_node, |
d62a17ae | 278 | unsigned int maxpaths) |
962251ae | 279 | { |
d62a17ae | 280 | struct list *successors = eigrp_topology_get_successor(table_node); |
962251ae | 281 | |
d62a17ae | 282 | if (successors && successors->count > maxpaths) { |
283 | do { | |
284 | struct listnode *node = listtail(successors); | |
962251ae | 285 | |
d62a17ae | 286 | list_delete_node(successors, node); |
962251ae | 287 | |
d62a17ae | 288 | } while (successors->count > maxpaths); |
289 | } | |
290 | ||
291 | return successors; | |
962251ae DS |
292 | } |
293 | ||
dc4accdd DS |
294 | struct eigrp_route_descriptor * |
295 | eigrp_route_descriptor_lookup(struct list *entries, struct eigrp_neighbor *nbr) | |
7f57883e | 296 | { |
dc4accdd | 297 | struct eigrp_route_descriptor *data; |
d62a17ae | 298 | struct listnode *node, *nnode; |
299 | for (ALL_LIST_ELEMENTS(entries, node, nnode, data)) { | |
300 | if (data->adv_router == nbr) { | |
301 | return data; | |
302 | } | |
303 | } | |
304 | ||
305 | return NULL; | |
7f57883e DS |
306 | } |
307 | ||
308 | /* Lookup all prefixes from specified neighbor */ | |
d62a17ae | 309 | struct list *eigrp_neighbor_prefixes_lookup(struct eigrp *eigrp, |
310 | struct eigrp_neighbor *nbr) | |
7f57883e | 311 | { |
9ca66cc7 | 312 | struct listnode *node2, *node22; |
dc4accdd DS |
313 | struct eigrp_route_descriptor *entry; |
314 | struct eigrp_prefix_descriptor *pe; | |
9ca66cc7 | 315 | struct route_node *rn; |
d62a17ae | 316 | |
317 | /* create new empty list for prefixes storage */ | |
318 | struct list *prefixes = list_new(); | |
319 | ||
320 | /* iterate over all prefixes in topology table */ | |
9ca66cc7 DS |
321 | for (rn = route_top(eigrp->topology_table); rn; rn = route_next(rn)) { |
322 | if (!rn->info) | |
323 | continue; | |
324 | pe = rn->info; | |
d62a17ae | 325 | /* iterate over all neighbor entry in prefix */ |
9ca66cc7 | 326 | for (ALL_LIST_ELEMENTS(pe->entries, node2, node22, entry)) { |
d62a17ae | 327 | /* if entry is from specified neighbor, add to list */ |
328 | if (entry->adv_router == nbr) { | |
9ca66cc7 | 329 | listnode_add(prefixes, pe); |
d62a17ae | 330 | } |
331 | } | |
332 | } | |
333 | ||
334 | /* return list of prefixes from specified neighbor */ | |
335 | return prefixes; | |
7f57883e DS |
336 | } |
337 | ||
996c9314 LB |
338 | enum metric_change |
339 | eigrp_topology_update_distance(struct eigrp_fsm_action_message *msg) | |
7f57883e | 340 | { |
d62a17ae | 341 | struct eigrp *eigrp = msg->eigrp; |
dc4accdd DS |
342 | struct eigrp_prefix_descriptor *prefix = msg->prefix; |
343 | struct eigrp_route_descriptor *entry = msg->entry; | |
92948863 | 344 | enum metric_change change = METRIC_SAME; |
d7c0a89a | 345 | uint32_t new_reported_distance; |
db6ec9ff | 346 | |
d62a17ae | 347 | assert(entry); |
348 | ||
996c9314 | 349 | switch (msg->data_type) { |
7cfa4322 | 350 | case EIGRP_CONNECTED: |
db6ec9ff DS |
351 | if (prefix->nt == EIGRP_TOPOLOGY_TYPE_CONNECTED) |
352 | return change; | |
353 | ||
354 | change = METRIC_DECREASE; | |
7cfa4322 DS |
355 | break; |
356 | case EIGRP_INT: | |
532e75e6 DS |
357 | if (prefix->nt == EIGRP_TOPOLOGY_TYPE_CONNECTED) { |
358 | change = METRIC_INCREASE; | |
359 | goto distance_done; | |
360 | } | |
db6ec9ff DS |
361 | if (eigrp_metrics_is_same(msg->metrics, |
362 | entry->reported_metric)) { | |
363 | return change; // No change | |
364 | } | |
92948863 | 365 | |
996c9314 LB |
366 | new_reported_distance = |
367 | eigrp_calculate_metrics(eigrp, msg->metrics); | |
92948863 | 368 | |
532e75e6 | 369 | if (entry->reported_distance < new_reported_distance) { |
db6ec9ff | 370 | change = METRIC_INCREASE; |
532e75e6 DS |
371 | goto distance_done; |
372 | } else | |
db6ec9ff | 373 | change = METRIC_DECREASE; |
92948863 | 374 | |
db6ec9ff DS |
375 | entry->reported_metric = msg->metrics; |
376 | entry->reported_distance = new_reported_distance; | |
377 | eigrp_calculate_metrics(eigrp, msg->metrics); | |
378 | entry->distance = eigrp_calculate_total_metrics(eigrp, entry); | |
379 | break; | |
7cfa4322 | 380 | case EIGRP_EXT: |
db6ec9ff DS |
381 | if (prefix->nt == EIGRP_TOPOLOGY_TYPE_REMOTE_EXTERNAL) { |
382 | if (eigrp_metrics_is_same(msg->metrics, | |
383 | entry->reported_metric)) | |
384 | return change; | |
4a64eed5 | 385 | } else { |
db6ec9ff | 386 | change = METRIC_INCREASE; |
532e75e6 | 387 | goto distance_done; |
4a64eed5 DS |
388 | } |
389 | break; | |
7cfa4322 | 390 | default: |
450971aa | 391 | flog_err(EC_LIB_DEVELOPMENT, "%s: Please implement handler", |
15569c58 | 392 | __func__); |
7cfa4322 | 393 | break; |
d62a17ae | 394 | } |
996c9314 | 395 | distance_done: |
d62a17ae | 396 | /* |
397 | * Move to correct position in list according to new distance | |
398 | */ | |
399 | listnode_delete(prefix->entries, entry); | |
400 | listnode_add_sort(prefix->entries, entry); | |
401 | ||
402 | return change; | |
7f57883e DS |
403 | } |
404 | ||
d62a17ae | 405 | void eigrp_topology_update_all_node_flags(struct eigrp *eigrp) |
7f57883e | 406 | { |
dc4accdd | 407 | struct eigrp_prefix_descriptor *pe; |
9ca66cc7 DS |
408 | struct route_node *rn; |
409 | ||
0bf75bd5 | 410 | if (!eigrp) |
411 | return; | |
412 | ||
9ca66cc7 DS |
413 | for (rn = route_top(eigrp->topology_table); rn; rn = route_next(rn)) { |
414 | pe = rn->info; | |
415 | ||
416 | if (!pe) | |
417 | continue; | |
418 | ||
0da93ecf | 419 | eigrp_topology_update_node_flags(eigrp, pe); |
d62a17ae | 420 | } |
7f57883e DS |
421 | } |
422 | ||
0da93ecf | 423 | void eigrp_topology_update_node_flags(struct eigrp *eigrp, |
dc4accdd | 424 | struct eigrp_prefix_descriptor *dest) |
7f57883e | 425 | { |
d62a17ae | 426 | struct listnode *node; |
dc4accdd | 427 | struct eigrp_route_descriptor *entry; |
a2d7fdfe | 428 | |
d62a17ae | 429 | for (ALL_LIST_ELEMENTS_RO(dest->entries, node, entry)) { |
53765081 PJ |
430 | if (entry->reported_distance < dest->fdistance) { |
431 | // is feasible successor, can be successor | |
432 | if (((uint64_t)entry->distance | |
433 | <= (uint64_t)dest->distance | |
434 | * (uint64_t)eigrp->variance) | |
435 | && entry->distance != EIGRP_MAX_METRIC) { | |
436 | // is successor | |
437 | entry->flags |= | |
dc4accdd | 438 | EIGRP_ROUTE_DESCRIPTOR_SUCCESSOR_FLAG; |
53765081 | 439 | entry->flags &= |
dc4accdd | 440 | ~EIGRP_ROUTE_DESCRIPTOR_FSUCCESSOR_FLAG; |
53765081 PJ |
441 | } else { |
442 | // is feasible successor only | |
443 | entry->flags |= | |
dc4accdd | 444 | EIGRP_ROUTE_DESCRIPTOR_FSUCCESSOR_FLAG; |
53765081 | 445 | entry->flags &= |
dc4accdd | 446 | ~EIGRP_ROUTE_DESCRIPTOR_SUCCESSOR_FLAG; |
53765081 | 447 | } |
d62a17ae | 448 | } else { |
dc4accdd DS |
449 | entry->flags &= ~EIGRP_ROUTE_DESCRIPTOR_FSUCCESSOR_FLAG; |
450 | entry->flags &= ~EIGRP_ROUTE_DESCRIPTOR_SUCCESSOR_FLAG; | |
d62a17ae | 451 | } |
452 | } | |
7f57883e DS |
453 | } |
454 | ||
0da93ecf | 455 | void eigrp_update_routing_table(struct eigrp *eigrp, |
dc4accdd | 456 | struct eigrp_prefix_descriptor *prefix) |
7f57883e | 457 | { |
0bf75bd5 | 458 | struct list *successors; |
d62a17ae | 459 | struct listnode *node; |
dc4accdd | 460 | struct eigrp_route_descriptor *entry; |
d62a17ae | 461 | |
0bf75bd5 | 462 | successors = eigrp_topology_get_successor_max(prefix, eigrp->max_paths); |
463 | ||
d62a17ae | 464 | if (successors) { |
0e64ed02 | 465 | eigrp_zebra_route_add(eigrp, prefix->destination, successors, |
0f9bc496 | 466 | prefix->fdistance); |
d62a17ae | 467 | for (ALL_LIST_ELEMENTS_RO(successors, node, entry)) |
dc4accdd | 468 | entry->flags |= EIGRP_ROUTE_DESCRIPTOR_INTABLE_FLAG; |
d62a17ae | 469 | |
6a154c88 | 470 | list_delete(&successors); |
d62a17ae | 471 | } else { |
0e64ed02 | 472 | eigrp_zebra_route_delete(eigrp, prefix->destination); |
d62a17ae | 473 | for (ALL_LIST_ELEMENTS_RO(prefix->entries, node, entry)) |
dc4accdd | 474 | entry->flags &= ~EIGRP_ROUTE_DESCRIPTOR_INTABLE_FLAG; |
d62a17ae | 475 | } |
7f57883e DS |
476 | } |
477 | ||
d62a17ae | 478 | void eigrp_topology_neighbor_down(struct eigrp *eigrp, |
479 | struct eigrp_neighbor *nbr) | |
7f57883e | 480 | { |
9ca66cc7 | 481 | struct listnode *node2, *node22; |
dc4accdd DS |
482 | struct eigrp_prefix_descriptor *pe; |
483 | struct eigrp_route_descriptor *entry; | |
9ca66cc7 DS |
484 | struct route_node *rn; |
485 | ||
486 | for (rn = route_top(eigrp->topology_table); rn; rn = route_next(rn)) { | |
487 | pe = rn->info; | |
488 | ||
489 | if (!pe) | |
490 | continue; | |
d62a17ae | 491 | |
9ca66cc7 | 492 | for (ALL_LIST_ELEMENTS(pe->entries, node2, node22, entry)) { |
5ca6df78 DS |
493 | struct eigrp_fsm_action_message msg; |
494 | ||
495 | if (entry->adv_router != nbr) | |
496 | continue; | |
497 | ||
de8b27a6 | 498 | memset(&msg, 0, sizeof(msg)); |
5ca6df78 DS |
499 | msg.metrics.delay = EIGRP_MAX_METRIC; |
500 | msg.packet_type = EIGRP_OPC_UPDATE; | |
501 | msg.eigrp = eigrp; | |
502 | msg.data_type = EIGRP_INT; | |
503 | msg.adv_router = nbr; | |
504 | msg.entry = entry; | |
9ca66cc7 | 505 | msg.prefix = pe; |
5ca6df78 | 506 | eigrp_fsm_event(&msg); |
d62a17ae | 507 | } |
508 | } | |
509 | ||
510 | eigrp_query_send_all(eigrp); | |
511 | eigrp_update_send_all(eigrp, nbr->ei); | |
7f57883e DS |
512 | } |
513 | ||
0da93ecf DS |
514 | void eigrp_update_topology_table_prefix(struct eigrp *eigrp, |
515 | struct route_table *table, | |
dc4accdd | 516 | struct eigrp_prefix_descriptor *prefix) |
7f57883e | 517 | { |
d62a17ae | 518 | struct listnode *node1, *node2; |
519 | ||
dc4accdd | 520 | struct eigrp_route_descriptor *entry; |
d62a17ae | 521 | for (ALL_LIST_ELEMENTS(prefix->entries, node1, node2, entry)) { |
522 | if (entry->distance == EIGRP_MAX_METRIC) { | |
dc4accdd | 523 | eigrp_route_descriptor_delete(eigrp, prefix, entry); |
d62a17ae | 524 | } |
525 | } | |
526 | if (prefix->distance == EIGRP_MAX_METRIC | |
527 | && prefix->nt != EIGRP_TOPOLOGY_TYPE_CONNECTED) { | |
dc4accdd | 528 | eigrp_prefix_descriptor_delete(eigrp, table, prefix); |
d62a17ae | 529 | } |
7f57883e | 530 | } |