2 * EIGRP Topology Table.
3 * Copyright (C) 2013-2016
15 * This file is part of GNU Zebra.
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
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.
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
40 #include "lib_errors.h"
42 #include "eigrpd/eigrp_types.h"
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_metric.h"
56 DEFINE_MTYPE_STATIC(EIGRPD
, EIGRP_ROUTE_DESCRIPTOR
, "EIGRP Nexthop Entry");
57 DEFINE_MTYPE(EIGRPD
, EIGRP_PREFIX_DESCRIPTOR
, "EIGRP Prefix");
59 static int eigrp_route_descriptor_cmp(struct eigrp_route_descriptor
*rd1
,
60 struct eigrp_route_descriptor
*rd2
);
63 * Returns linkedlist used as topology table
64 * cmp - assigned function for comparing topology nodes
65 * del - assigned function executed before deleting topology node by list
68 struct route_table
*eigrp_topology_new(void)
70 return route_table_init();
74 * Returns new created toplogy node
75 * cmp - assigned function for comparing topology entry
77 struct eigrp_prefix_descriptor
*eigrp_prefix_descriptor_new(void)
79 struct eigrp_prefix_descriptor
*new;
80 new = XCALLOC(MTYPE_EIGRP_PREFIX_DESCRIPTOR
,
81 sizeof(struct eigrp_prefix_descriptor
));
82 new->entries
= list_new();
83 new->rij
= list_new();
84 new->entries
->cmp
= (int (*)(void *, void *))eigrp_route_descriptor_cmp
;
85 new->distance
= new->fdistance
= new->rdistance
= EIGRP_MAX_METRIC
;
86 new->destination
= NULL
;
92 * Topology entry comparison
94 static int eigrp_route_descriptor_cmp(struct eigrp_route_descriptor
*entry1
,
95 struct eigrp_route_descriptor
*entry2
)
97 if (entry1
->distance
< entry2
->distance
)
99 if (entry1
->distance
> entry2
->distance
)
106 * Returns new topology entry
109 struct eigrp_route_descriptor
*eigrp_route_descriptor_new(void)
111 struct eigrp_route_descriptor
*new;
113 new = XCALLOC(MTYPE_EIGRP_ROUTE_DESCRIPTOR
,
114 sizeof(struct eigrp_route_descriptor
));
115 new->reported_distance
= EIGRP_MAX_METRIC
;
116 new->distance
= EIGRP_MAX_METRIC
;
122 * Freeing topology table list
124 void eigrp_topology_free(struct eigrp
*eigrp
, struct route_table
*table
)
126 eigrp_topology_delete_all(eigrp
, table
);
127 route_table_finish(table
);
131 * Adding topology node to topology table
133 void eigrp_prefix_descriptor_add(struct route_table
*topology
,
134 struct eigrp_prefix_descriptor
*pe
)
136 struct route_node
*rn
;
138 rn
= route_node_get(topology
, pe
->destination
);
140 if (IS_DEBUG_EIGRP_EVENT
)
142 "%s: %pFX Should we have found this entry in the topo table?",
143 __func__
, pe
->destination
);
144 route_unlock_node(rn
);
151 * Adding topology entry to topology node
153 void eigrp_route_descriptor_add(struct eigrp
*eigrp
,
154 struct eigrp_prefix_descriptor
*node
,
155 struct eigrp_route_descriptor
*entry
)
157 struct list
*l
= list_new();
159 listnode_add(l
, entry
);
161 if (listnode_lookup(node
->entries
, entry
) == NULL
) {
162 listnode_add_sort(node
->entries
, entry
);
163 entry
->prefix
= node
;
165 eigrp_zebra_route_add(eigrp
, node
->destination
,
173 * Deleting topology node from topology table
175 void eigrp_prefix_descriptor_delete(struct eigrp
*eigrp
,
176 struct route_table
*table
,
177 struct eigrp_prefix_descriptor
*pe
)
179 struct eigrp_route_descriptor
*ne
;
180 struct listnode
*node
, *nnode
;
181 struct route_node
*rn
;
186 rn
= route_node_lookup(table
, pe
->destination
);
191 * Emergency removal of the node from this list.
194 listnode_delete(eigrp
->topology_changes_internalIPV4
, pe
);
196 for (ALL_LIST_ELEMENTS(pe
->entries
, node
, nnode
, ne
))
197 eigrp_route_descriptor_delete(eigrp
, pe
, ne
);
198 list_delete(&pe
->entries
);
199 list_delete(&pe
->rij
);
200 eigrp_zebra_route_delete(eigrp
, pe
->destination
);
201 prefix_free(&pe
->destination
);
204 route_unlock_node(rn
); // Lookup above
205 route_unlock_node(rn
); // Initial creation
206 XFREE(MTYPE_EIGRP_PREFIX_DESCRIPTOR
, pe
);
210 * Deleting topology entry from topology node
212 void eigrp_route_descriptor_delete(struct eigrp
*eigrp
,
213 struct eigrp_prefix_descriptor
*node
,
214 struct eigrp_route_descriptor
*entry
)
216 if (listnode_lookup(node
->entries
, entry
) != NULL
) {
217 listnode_delete(node
->entries
, entry
);
218 eigrp_zebra_route_delete(eigrp
, node
->destination
);
219 XFREE(MTYPE_EIGRP_ROUTE_DESCRIPTOR
, entry
);
224 * Deleting all nodes from topology table
226 void eigrp_topology_delete_all(struct eigrp
*eigrp
,
227 struct route_table
*topology
)
229 struct route_node
*rn
;
230 struct eigrp_prefix_descriptor
*pe
;
232 for (rn
= route_top(topology
); rn
; rn
= route_next(rn
)) {
238 eigrp_prefix_descriptor_delete(eigrp
, topology
, pe
);
242 struct eigrp_prefix_descriptor
*
243 eigrp_topology_table_lookup_ipv4(struct route_table
*table
,
244 struct prefix
*address
)
246 struct eigrp_prefix_descriptor
*pe
;
247 struct route_node
*rn
;
249 rn
= route_node_lookup(table
, address
);
255 route_unlock_node(rn
);
261 * For a future optimization, put the successor list into it's
262 * own separate list from the full list?
264 * That way we can clean up all the list_new and list_delete's
265 * that we are doing. DBS
268 eigrp_topology_get_successor(struct eigrp_prefix_descriptor
*table_node
)
270 struct list
*successors
= list_new();
271 struct eigrp_route_descriptor
*data
;
272 struct listnode
*node1
, *node2
;
274 for (ALL_LIST_ELEMENTS(table_node
->entries
, node1
, node2
, data
)) {
275 if (data
->flags
& EIGRP_ROUTE_DESCRIPTOR_SUCCESSOR_FLAG
) {
276 listnode_add(successors
, data
);
281 * If we have no successors return NULL
283 if (!successors
->count
) {
284 list_delete(&successors
);
292 eigrp_topology_get_successor_max(struct eigrp_prefix_descriptor
*table_node
,
293 unsigned int maxpaths
)
295 struct list
*successors
= eigrp_topology_get_successor(table_node
);
297 if (successors
&& successors
->count
> maxpaths
) {
299 struct listnode
*node
= listtail(successors
);
301 list_delete_node(successors
, node
);
303 } while (successors
->count
> maxpaths
);
309 struct eigrp_route_descriptor
*
310 eigrp_route_descriptor_lookup(struct list
*entries
, struct eigrp_neighbor
*nbr
)
312 struct eigrp_route_descriptor
*data
;
313 struct listnode
*node
, *nnode
;
314 for (ALL_LIST_ELEMENTS(entries
, node
, nnode
, data
)) {
315 if (data
->adv_router
== nbr
) {
323 /* Lookup all prefixes from specified neighbor */
324 struct list
*eigrp_neighbor_prefixes_lookup(struct eigrp
*eigrp
,
325 struct eigrp_neighbor
*nbr
)
327 struct listnode
*node2
, *node22
;
328 struct eigrp_route_descriptor
*entry
;
329 struct eigrp_prefix_descriptor
*pe
;
330 struct route_node
*rn
;
332 /* create new empty list for prefixes storage */
333 struct list
*prefixes
= list_new();
335 /* iterate over all prefixes in topology table */
336 for (rn
= route_top(eigrp
->topology_table
); rn
; rn
= route_next(rn
)) {
340 /* iterate over all neighbor entry in prefix */
341 for (ALL_LIST_ELEMENTS(pe
->entries
, node2
, node22
, entry
)) {
342 /* if entry is from specified neighbor, add to list */
343 if (entry
->adv_router
== nbr
) {
344 listnode_add(prefixes
, pe
);
349 /* return list of prefixes from specified neighbor */
354 eigrp_topology_update_distance(struct eigrp_fsm_action_message
*msg
)
356 struct eigrp
*eigrp
= msg
->eigrp
;
357 struct eigrp_prefix_descriptor
*prefix
= msg
->prefix
;
358 struct eigrp_route_descriptor
*entry
= msg
->entry
;
359 enum metric_change change
= METRIC_SAME
;
360 uint32_t new_reported_distance
;
364 switch (msg
->data_type
) {
365 case EIGRP_CONNECTED
:
366 if (prefix
->nt
== EIGRP_TOPOLOGY_TYPE_CONNECTED
)
369 change
= METRIC_DECREASE
;
372 if (prefix
->nt
== EIGRP_TOPOLOGY_TYPE_CONNECTED
) {
373 change
= METRIC_INCREASE
;
376 if (eigrp_metrics_is_same(msg
->metrics
,
377 entry
->reported_metric
)) {
378 return change
; // No change
381 new_reported_distance
=
382 eigrp_calculate_metrics(eigrp
, msg
->metrics
);
384 if (entry
->reported_distance
< new_reported_distance
) {
385 change
= METRIC_INCREASE
;
388 change
= METRIC_DECREASE
;
390 entry
->reported_metric
= msg
->metrics
;
391 entry
->reported_distance
= new_reported_distance
;
392 eigrp_calculate_metrics(eigrp
, msg
->metrics
);
393 entry
->distance
= eigrp_calculate_total_metrics(eigrp
, entry
);
396 if (prefix
->nt
== EIGRP_TOPOLOGY_TYPE_REMOTE_EXTERNAL
) {
397 if (eigrp_metrics_is_same(msg
->metrics
,
398 entry
->reported_metric
))
401 change
= METRIC_INCREASE
;
406 flog_err(EC_LIB_DEVELOPMENT
, "%s: Please implement handler",
412 * Move to correct position in list according to new distance
414 listnode_delete(prefix
->entries
, entry
);
415 listnode_add_sort(prefix
->entries
, entry
);
420 void eigrp_topology_update_all_node_flags(struct eigrp
*eigrp
)
422 struct eigrp_prefix_descriptor
*pe
;
423 struct route_node
*rn
;
428 for (rn
= route_top(eigrp
->topology_table
); rn
; rn
= route_next(rn
)) {
434 eigrp_topology_update_node_flags(eigrp
, pe
);
438 void eigrp_topology_update_node_flags(struct eigrp
*eigrp
,
439 struct eigrp_prefix_descriptor
*dest
)
441 struct listnode
*node
;
442 struct eigrp_route_descriptor
*entry
;
444 for (ALL_LIST_ELEMENTS_RO(dest
->entries
, node
, entry
)) {
445 if (entry
->reported_distance
< dest
->fdistance
) {
446 // is feasible successor, can be successor
447 if (((uint64_t)entry
->distance
448 <= (uint64_t)dest
->distance
449 * (uint64_t)eigrp
->variance
)
450 && entry
->distance
!= EIGRP_MAX_METRIC
) {
453 EIGRP_ROUTE_DESCRIPTOR_SUCCESSOR_FLAG
;
455 ~EIGRP_ROUTE_DESCRIPTOR_FSUCCESSOR_FLAG
;
457 // is feasible successor only
459 EIGRP_ROUTE_DESCRIPTOR_FSUCCESSOR_FLAG
;
461 ~EIGRP_ROUTE_DESCRIPTOR_SUCCESSOR_FLAG
;
464 entry
->flags
&= ~EIGRP_ROUTE_DESCRIPTOR_FSUCCESSOR_FLAG
;
465 entry
->flags
&= ~EIGRP_ROUTE_DESCRIPTOR_SUCCESSOR_FLAG
;
470 void eigrp_update_routing_table(struct eigrp
*eigrp
,
471 struct eigrp_prefix_descriptor
*prefix
)
473 struct list
*successors
;
474 struct listnode
*node
;
475 struct eigrp_route_descriptor
*entry
;
477 successors
= eigrp_topology_get_successor_max(prefix
, eigrp
->max_paths
);
480 eigrp_zebra_route_add(eigrp
, prefix
->destination
, successors
,
482 for (ALL_LIST_ELEMENTS_RO(successors
, node
, entry
))
483 entry
->flags
|= EIGRP_ROUTE_DESCRIPTOR_INTABLE_FLAG
;
485 list_delete(&successors
);
487 eigrp_zebra_route_delete(eigrp
, prefix
->destination
);
488 for (ALL_LIST_ELEMENTS_RO(prefix
->entries
, node
, entry
))
489 entry
->flags
&= ~EIGRP_ROUTE_DESCRIPTOR_INTABLE_FLAG
;
493 void eigrp_topology_neighbor_down(struct eigrp
*eigrp
,
494 struct eigrp_neighbor
*nbr
)
496 struct listnode
*node2
, *node22
;
497 struct eigrp_prefix_descriptor
*pe
;
498 struct eigrp_route_descriptor
*entry
;
499 struct route_node
*rn
;
501 for (rn
= route_top(eigrp
->topology_table
); rn
; rn
= route_next(rn
)) {
507 for (ALL_LIST_ELEMENTS(pe
->entries
, node2
, node22
, entry
)) {
508 struct eigrp_fsm_action_message msg
;
510 if (entry
->adv_router
!= nbr
)
513 memset(&msg
, 0, sizeof(msg
));
514 msg
.metrics
.delay
= EIGRP_MAX_METRIC
;
515 msg
.packet_type
= EIGRP_OPC_UPDATE
;
517 msg
.data_type
= EIGRP_INT
;
518 msg
.adv_router
= nbr
;
521 eigrp_fsm_event(&msg
);
525 eigrp_query_send_all(eigrp
);
526 eigrp_update_send_all(eigrp
, nbr
->ei
);
529 void eigrp_update_topology_table_prefix(struct eigrp
*eigrp
,
530 struct route_table
*table
,
531 struct eigrp_prefix_descriptor
*prefix
)
533 struct listnode
*node1
, *node2
;
535 struct eigrp_route_descriptor
*entry
;
536 for (ALL_LIST_ELEMENTS(prefix
->entries
, node1
, node2
, entry
)) {
537 if (entry
->distance
== EIGRP_MAX_METRIC
) {
538 eigrp_route_descriptor_delete(eigrp
, prefix
, entry
);
541 if (prefix
->distance
== EIGRP_MAX_METRIC
542 && prefix
->nt
!= EIGRP_TOPOLOGY_TYPE_CONNECTED
) {
543 eigrp_prefix_descriptor_delete(eigrp
, table
, prefix
);