]> git.proxmox.com Git - mirror_frr.git/blame - eigrpd/eigrp_topology.c
Merge pull request #2545 from pacovn/Coverity_1468413_Explicit_null_dereferenced
[mirror_frr.git] / eigrpd / eigrp_topology.c
CommitLineData
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"
40
41#include "eigrpd/eigrp_structs.h"
42#include "eigrpd/eigrpd.h"
43#include "eigrpd/eigrp_interface.h"
44#include "eigrpd/eigrp_neighbor.h"
45#include "eigrpd/eigrp_packet.h"
46#include "eigrpd/eigrp_zebra.h"
47#include "eigrpd/eigrp_vty.h"
48#include "eigrpd/eigrp_network.h"
49#include "eigrpd/eigrp_dump.h"
50#include "eigrpd/eigrp_topology.h"
51#include "eigrpd/eigrp_fsm.h"
52#include "eigrpd/eigrp_memory.h"
53
255ab940 54static int eigrp_nexthop_entry_cmp(struct eigrp_nexthop_entry *,
996c9314 55 struct eigrp_nexthop_entry *);
7f57883e
DS
56
57/*
7f57883e
DS
58 * Returns linkedlist used as topology table
59 * cmp - assigned function for comparing topology nodes
d62a17ae 60 * del - assigned function executed before deleting topology node by list
61 * function
7f57883e 62 */
9ca66cc7 63struct route_table *eigrp_topology_new()
7f57883e 64{
9ca66cc7 65 return route_table_init();
7f57883e
DS
66}
67
68/*
69 * Returns new created toplogy node
70 * cmp - assigned function for comparing topology entry
71 */
d62a17ae 72struct eigrp_prefix_entry *eigrp_prefix_entry_new()
7f57883e 73{
d62a17ae 74 struct eigrp_prefix_entry *new;
75 new = XCALLOC(MTYPE_EIGRP_PREFIX_ENTRY,
76 sizeof(struct eigrp_prefix_entry));
77 new->entries = list_new();
78 new->rij = list_new();
255ab940 79 new->entries->cmp = (int (*)(void *, void *))eigrp_nexthop_entry_cmp;
d62a17ae 80 new->distance = new->fdistance = new->rdistance = EIGRP_MAX_METRIC;
02b45998 81 new->destination = NULL;
d62a17ae 82
83 return new;
7f57883e
DS
84}
85
86/*
87 * Topology entry comparison
88 */
255ab940 89static int eigrp_nexthop_entry_cmp(struct eigrp_nexthop_entry *entry1,
996c9314 90 struct eigrp_nexthop_entry *entry2)
7f57883e 91{
02b45998
DS
92 if (entry1->distance < entry2->distance)
93 return -1;
d62a17ae 94 if (entry1->distance > entry2->distance)
95 return 1;
7f57883e 96
d62a17ae 97 return 0;
7f57883e
DS
98}
99
100/*
101 * Returns new topology entry
102 */
103
255ab940 104struct eigrp_nexthop_entry *eigrp_nexthop_entry_new()
7f57883e 105{
255ab940 106 struct eigrp_nexthop_entry *new;
7f57883e 107
255ab940
DS
108 new = XCALLOC(MTYPE_EIGRP_NEXTHOP_ENTRY,
109 sizeof(struct eigrp_nexthop_entry));
d62a17ae 110 new->reported_distance = EIGRP_MAX_METRIC;
111 new->distance = EIGRP_MAX_METRIC;
7f57883e 112
d62a17ae 113 return new;
7f57883e
DS
114}
115
116/*
117 * Freeing topology table list
118 */
9ca66cc7 119void eigrp_topology_free(struct route_table *table)
7f57883e 120{
9ca66cc7 121 route_table_finish(table);
7f57883e
DS
122}
123
124/*
125 * Deleting all topology nodes in table
126 */
9ca66cc7 127void eigrp_topology_cleanup(struct route_table *table)
7f57883e 128{
9ca66cc7 129 eigrp_topology_delete_all(table);
7f57883e
DS
130}
131
132/*
133 * Adding topology node to topology table
134 */
9ca66cc7
DS
135void eigrp_prefix_entry_add(struct route_table *topology,
136 struct eigrp_prefix_entry *pe)
7f57883e 137{
9ca66cc7
DS
138 struct route_node *rn;
139
140 rn = route_node_get(topology, pe->destination);
141 if (rn->info) {
142 if (IS_DEBUG_EIGRP_EVENT) {
143 char buf[PREFIX_STRLEN];
144
996c9314
LB
145 zlog_debug(
146 "%s: %s Should we have found this entry in the topo table?",
147 __PRETTY_FUNCTION__,
148 prefix2str(pe->destination, buf, sizeof(buf)));
9ca66cc7 149 }
d62a17ae 150 }
9ca66cc7
DS
151
152 rn->info = pe;
153 route_lock_node(rn);
7f57883e
DS
154}
155
156/*
157 * Adding topology entry to topology node
158 */
255ab940 159void eigrp_nexthop_entry_add(struct eigrp_prefix_entry *node,
996c9314 160 struct eigrp_nexthop_entry *entry)
7f57883e 161{
d62a17ae 162 struct list *l = list_new();
76220653 163
d62a17ae 164 listnode_add(l, entry);
63863c47 165
d62a17ae 166 if (listnode_lookup(node->entries, entry) == NULL) {
167 listnode_add_sort(node->entries, entry);
168 entry->prefix = node;
63863c47 169
836aad7e 170 eigrp_zebra_route_add(node->destination, l);
d62a17ae 171 }
76220653 172
affe9e99 173 list_delete_and_null(&l);
7f57883e
DS
174}
175
176/*
177 * Deleting topology node from topology table
178 */
9ca66cc7
DS
179void eigrp_prefix_entry_delete(struct route_table *table,
180 struct eigrp_prefix_entry *pe)
7f57883e 181{
d62a17ae 182 struct eigrp *eigrp = eigrp_lookup();
9ca66cc7
DS
183 struct route_node *rn;
184
0bf75bd5 185 if (!eigrp)
186 return;
187
9ca66cc7
DS
188 rn = route_node_lookup(table, pe->destination);
189 if (!rn)
190 return;
d62a17ae 191
192 /*
193 * Emergency removal of the node from this list.
194 * Whatever it is.
195 */
9ca66cc7 196 listnode_delete(eigrp->topology_changes_internalIPV4, pe);
d62a17ae 197
9ca66cc7
DS
198 list_delete_and_null(&pe->entries);
199 list_delete_and_null(&pe->rij);
200 eigrp_zebra_route_delete(pe->destination);
201
202 rn->info = NULL;
996c9314
LB
203 route_unlock_node(rn); // Lookup above
204 route_unlock_node(rn); // Initial creation
9ca66cc7 205 XFREE(MTYPE_EIGRP_PREFIX_ENTRY, pe);
7f57883e
DS
206}
207
208/*
209 * Deleting topology entry from topology node
210 */
255ab940 211void eigrp_nexthop_entry_delete(struct eigrp_prefix_entry *node,
996c9314 212 struct eigrp_nexthop_entry *entry)
7f57883e 213{
d62a17ae 214 if (listnode_lookup(node->entries, entry) != NULL) {
215 listnode_delete(node->entries, entry);
836aad7e 216 eigrp_zebra_route_delete(node->destination);
255ab940 217 XFREE(MTYPE_EIGRP_NEXTHOP_ENTRY, entry);
d62a17ae 218 }
7f57883e
DS
219}
220
221/*
222 * Deleting all nodes from topology table
223 */
9ca66cc7 224void eigrp_topology_delete_all(struct route_table *topology)
7f57883e 225{
9ca66cc7
DS
226 struct route_node *rn;
227 struct eigrp_prefix_entry *pe;
228
229 for (rn = route_top(topology); rn; rn = route_next(rn)) {
230 pe = rn->info;
231
232 if (!pe)
233 continue;
234
235 eigrp_prefix_entry_delete(topology, pe);
236 }
7f57883e
DS
237}
238
239/*
240 * Return 0 if topology is not empty
241 * otherwise return 1
242 */
d62a17ae 243unsigned int eigrp_topology_table_isempty(struct list *topology)
7f57883e 244{
d62a17ae 245 if (topology->count)
246 return 1;
247 else
248 return 0;
7f57883e
DS
249}
250
251struct eigrp_prefix_entry *
9ca66cc7 252eigrp_topology_table_lookup_ipv4(struct route_table *table,
476a1469 253 struct prefix *address)
7f57883e 254{
9ca66cc7
DS
255 struct eigrp_prefix_entry *pe;
256 struct route_node *rn;
d62a17ae 257
9ca66cc7
DS
258 rn = route_node_lookup(table, address);
259 if (!rn)
260 return NULL;
261
262 pe = rn->info;
263
264 route_unlock_node(rn);
265
266 return pe;
7f57883e 267}
f6709c16 268
2118601d
DS
269/*
270 * For a future optimization, put the successor list into it's
271 * own separate list from the full list?
272 *
273 * That way we can clean up all the list_new and list_delete's
274 * that we are doing. DBS
275 */
d62a17ae 276struct list *eigrp_topology_get_successor(struct eigrp_prefix_entry *table_node)
7f57883e 277{
d62a17ae 278 struct list *successors = list_new();
255ab940 279 struct eigrp_nexthop_entry *data;
d62a17ae 280 struct listnode *node1, *node2;
281
282 for (ALL_LIST_ELEMENTS(table_node->entries, node1, node2, data)) {
255ab940 283 if (data->flags & EIGRP_NEXTHOP_ENTRY_SUCCESSOR_FLAG) {
d62a17ae 284 listnode_add(successors, data);
285 }
286 }
287
288 /*
289 * If we have no successors return NULL
290 */
291 if (!successors->count) {
affe9e99 292 list_delete_and_null(&successors);
d62a17ae 293 successors = NULL;
294 }
295
296 return successors;
7f57883e
DS
297}
298
962251ae
DS
299struct list *
300eigrp_topology_get_successor_max(struct eigrp_prefix_entry *table_node,
d62a17ae 301 unsigned int maxpaths)
962251ae 302{
d62a17ae 303 struct list *successors = eigrp_topology_get_successor(table_node);
962251ae 304
d62a17ae 305 if (successors && successors->count > maxpaths) {
306 do {
307 struct listnode *node = listtail(successors);
962251ae 308
d62a17ae 309 list_delete_node(successors, node);
962251ae 310
d62a17ae 311 } while (successors->count > maxpaths);
312 }
313
314 return successors;
962251ae
DS
315}
316
255ab940 317struct eigrp_nexthop_entry *
7f57883e
DS
318eigrp_prefix_entry_lookup(struct list *entries, struct eigrp_neighbor *nbr)
319{
255ab940 320 struct eigrp_nexthop_entry *data;
d62a17ae 321 struct listnode *node, *nnode;
322 for (ALL_LIST_ELEMENTS(entries, node, nnode, data)) {
323 if (data->adv_router == nbr) {
324 return data;
325 }
326 }
327
328 return NULL;
7f57883e
DS
329}
330
331/* Lookup all prefixes from specified neighbor */
d62a17ae 332struct list *eigrp_neighbor_prefixes_lookup(struct eigrp *eigrp,
333 struct eigrp_neighbor *nbr)
7f57883e 334{
9ca66cc7 335 struct listnode *node2, *node22;
255ab940 336 struct eigrp_nexthop_entry *entry;
9ca66cc7
DS
337 struct eigrp_prefix_entry *pe;
338 struct route_node *rn;
d62a17ae 339
340 /* create new empty list for prefixes storage */
341 struct list *prefixes = list_new();
342
343 /* iterate over all prefixes in topology table */
9ca66cc7
DS
344 for (rn = route_top(eigrp->topology_table); rn; rn = route_next(rn)) {
345 if (!rn->info)
346 continue;
347 pe = rn->info;
d62a17ae 348 /* iterate over all neighbor entry in prefix */
9ca66cc7 349 for (ALL_LIST_ELEMENTS(pe->entries, node2, node22, entry)) {
d62a17ae 350 /* if entry is from specified neighbor, add to list */
351 if (entry->adv_router == nbr) {
9ca66cc7 352 listnode_add(prefixes, pe);
d62a17ae 353 }
354 }
355 }
356
357 /* return list of prefixes from specified neighbor */
358 return prefixes;
7f57883e
DS
359}
360
996c9314
LB
361enum metric_change
362eigrp_topology_update_distance(struct eigrp_fsm_action_message *msg)
7f57883e 363{
d62a17ae 364 struct eigrp *eigrp = msg->eigrp;
365 struct eigrp_prefix_entry *prefix = msg->prefix;
255ab940 366 struct eigrp_nexthop_entry *entry = msg->entry;
92948863 367 enum metric_change change = METRIC_SAME;
d7c0a89a 368 uint32_t new_reported_distance;
db6ec9ff 369
d62a17ae 370 assert(entry);
371
996c9314 372 switch (msg->data_type) {
7cfa4322 373 case EIGRP_CONNECTED:
db6ec9ff
DS
374 if (prefix->nt == EIGRP_TOPOLOGY_TYPE_CONNECTED)
375 return change;
376
377 change = METRIC_DECREASE;
7cfa4322
DS
378 break;
379 case EIGRP_INT:
532e75e6
DS
380 if (prefix->nt == EIGRP_TOPOLOGY_TYPE_CONNECTED) {
381 change = METRIC_INCREASE;
382 goto distance_done;
383 }
db6ec9ff
DS
384 if (eigrp_metrics_is_same(msg->metrics,
385 entry->reported_metric)) {
386 return change; // No change
387 }
92948863 388
996c9314
LB
389 new_reported_distance =
390 eigrp_calculate_metrics(eigrp, msg->metrics);
92948863 391
532e75e6 392 if (entry->reported_distance < new_reported_distance) {
db6ec9ff 393 change = METRIC_INCREASE;
532e75e6
DS
394 goto distance_done;
395 } else
db6ec9ff 396 change = METRIC_DECREASE;
92948863 397
db6ec9ff
DS
398 entry->reported_metric = msg->metrics;
399 entry->reported_distance = new_reported_distance;
400 eigrp_calculate_metrics(eigrp, msg->metrics);
401 entry->distance = eigrp_calculate_total_metrics(eigrp, entry);
402 break;
7cfa4322 403 case EIGRP_EXT:
db6ec9ff
DS
404 if (prefix->nt == EIGRP_TOPOLOGY_TYPE_REMOTE_EXTERNAL) {
405 if (eigrp_metrics_is_same(msg->metrics,
406 entry->reported_metric))
407 return change;
4a64eed5 408 } else {
db6ec9ff 409 change = METRIC_INCREASE;
532e75e6 410 goto distance_done;
4a64eed5
DS
411 }
412 break;
7cfa4322
DS
413 default:
414 zlog_err("%s: Please implement handler", __PRETTY_FUNCTION__);
415 break;
d62a17ae 416 }
996c9314 417distance_done:
d62a17ae 418 /*
419 * Move to correct position in list according to new distance
420 */
421 listnode_delete(prefix->entries, entry);
422 listnode_add_sort(prefix->entries, entry);
423
424 return change;
7f57883e
DS
425}
426
d62a17ae 427void eigrp_topology_update_all_node_flags(struct eigrp *eigrp)
7f57883e 428{
9ca66cc7
DS
429 struct eigrp_prefix_entry *pe;
430 struct route_node *rn;
431
0bf75bd5 432 if (!eigrp)
433 return;
434
9ca66cc7
DS
435 for (rn = route_top(eigrp->topology_table); rn; rn = route_next(rn)) {
436 pe = rn->info;
437
438 if (!pe)
439 continue;
440
441 eigrp_topology_update_node_flags(pe);
d62a17ae 442 }
7f57883e
DS
443}
444
d62a17ae 445void eigrp_topology_update_node_flags(struct eigrp_prefix_entry *dest)
7f57883e 446{
d62a17ae 447 struct listnode *node;
255ab940 448 struct eigrp_nexthop_entry *entry;
d62a17ae 449 struct eigrp *eigrp = eigrp_lookup();
450
a2d7fdfe 451 assert(eigrp);
452
d62a17ae 453 for (ALL_LIST_ELEMENTS_RO(dest->entries, node, entry)) {
53765081
PJ
454 if (entry->reported_distance < dest->fdistance) {
455 // is feasible successor, can be successor
456 if (((uint64_t)entry->distance
457 <= (uint64_t)dest->distance
458 * (uint64_t)eigrp->variance)
459 && entry->distance != EIGRP_MAX_METRIC) {
460 // is successor
461 entry->flags |=
462 EIGRP_NEXTHOP_ENTRY_SUCCESSOR_FLAG;
463 entry->flags &=
464 ~EIGRP_NEXTHOP_ENTRY_FSUCCESSOR_FLAG;
465 } else {
466 // is feasible successor only
467 entry->flags |=
468 EIGRP_NEXTHOP_ENTRY_FSUCCESSOR_FLAG;
469 entry->flags &=
470 ~EIGRP_NEXTHOP_ENTRY_SUCCESSOR_FLAG;
471 }
d62a17ae 472 } else {
255ab940
DS
473 entry->flags &= ~EIGRP_NEXTHOP_ENTRY_FSUCCESSOR_FLAG;
474 entry->flags &= ~EIGRP_NEXTHOP_ENTRY_SUCCESSOR_FLAG;
d62a17ae 475 }
476 }
7f57883e
DS
477}
478
d62a17ae 479void eigrp_update_routing_table(struct eigrp_prefix_entry *prefix)
7f57883e 480{
d62a17ae 481 struct eigrp *eigrp = eigrp_lookup();
0bf75bd5 482 struct list *successors;
d62a17ae 483 struct listnode *node;
255ab940 484 struct eigrp_nexthop_entry *entry;
d62a17ae 485
0bf75bd5 486 if (!eigrp)
487 return;
488
489 successors = eigrp_topology_get_successor_max(prefix, eigrp->max_paths);
490
d62a17ae 491 if (successors) {
996c9314 492 eigrp_zebra_route_add(prefix->destination, successors);
d62a17ae 493 for (ALL_LIST_ELEMENTS_RO(successors, node, entry))
255ab940 494 entry->flags |= EIGRP_NEXTHOP_ENTRY_INTABLE_FLAG;
d62a17ae 495
affe9e99 496 list_delete_and_null(&successors);
d62a17ae 497 } else {
836aad7e 498 eigrp_zebra_route_delete(prefix->destination);
d62a17ae 499 for (ALL_LIST_ELEMENTS_RO(prefix->entries, node, entry))
255ab940 500 entry->flags &= ~EIGRP_NEXTHOP_ENTRY_INTABLE_FLAG;
d62a17ae 501 }
7f57883e
DS
502}
503
d62a17ae 504void eigrp_topology_neighbor_down(struct eigrp *eigrp,
505 struct eigrp_neighbor *nbr)
7f57883e 506{
9ca66cc7
DS
507 struct listnode *node2, *node22;
508 struct eigrp_prefix_entry *pe;
255ab940 509 struct eigrp_nexthop_entry *entry;
9ca66cc7
DS
510 struct route_node *rn;
511
512 for (rn = route_top(eigrp->topology_table); rn; rn = route_next(rn)) {
513 pe = rn->info;
514
515 if (!pe)
516 continue;
d62a17ae 517
9ca66cc7 518 for (ALL_LIST_ELEMENTS(pe->entries, node2, node22, entry)) {
5ca6df78
DS
519 struct eigrp_fsm_action_message msg;
520
521 if (entry->adv_router != nbr)
522 continue;
523
524 msg.metrics.delay = EIGRP_MAX_METRIC;
525 msg.packet_type = EIGRP_OPC_UPDATE;
526 msg.eigrp = eigrp;
527 msg.data_type = EIGRP_INT;
528 msg.adv_router = nbr;
529 msg.entry = entry;
9ca66cc7 530 msg.prefix = pe;
5ca6df78 531 eigrp_fsm_event(&msg);
d62a17ae 532 }
533 }
534
535 eigrp_query_send_all(eigrp);
536 eigrp_update_send_all(eigrp, nbr->ei);
7f57883e
DS
537}
538
9ca66cc7 539void eigrp_update_topology_table_prefix(struct route_table *table,
d62a17ae 540 struct eigrp_prefix_entry *prefix)
7f57883e 541{
d62a17ae 542 struct listnode *node1, *node2;
543
255ab940 544 struct eigrp_nexthop_entry *entry;
d62a17ae 545 for (ALL_LIST_ELEMENTS(prefix->entries, node1, node2, entry)) {
546 if (entry->distance == EIGRP_MAX_METRIC) {
255ab940 547 eigrp_nexthop_entry_delete(prefix, entry);
d62a17ae 548 }
549 }
550 if (prefix->distance == EIGRP_MAX_METRIC
551 && prefix->nt != EIGRP_TOPOLOGY_TYPE_CONNECTED) {
552 eigrp_prefix_entry_delete(table, prefix);
553 }
7f57883e 554}