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