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
28 * along with GNU Zebra; see the file COPYING. If not, write to the Free
29 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
42 #include "eigrpd/eigrp_structs.h"
43 #include "eigrpd/eigrpd.h"
44 #include "eigrpd/eigrp_interface.h"
45 #include "eigrpd/eigrp_neighbor.h"
46 #include "eigrpd/eigrp_packet.h"
47 #include "eigrpd/eigrp_zebra.h"
48 #include "eigrpd/eigrp_vty.h"
49 #include "eigrpd/eigrp_network.h"
50 #include "eigrpd/eigrp_dump.h"
51 #include "eigrpd/eigrp_topology.h"
52 #include "eigrpd/eigrp_fsm.h"
53 #include "eigrpd/eigrp_memory.h"
56 eigrp_prefix_entry_cmp(struct eigrp_prefix_entry
*, struct eigrp_prefix_entry
*);
58 eigrp_prefix_entry_del(struct eigrp_prefix_entry
*);
60 eigrp_neighbor_entry_cmp(struct eigrp_neighbor_entry
*,
61 struct eigrp_neighbor_entry
*);
64 * asdf;laksdjf;lajsdf;kasdjf;asdjf;
65 * asdfaskdjfa;sdkjf;adlskj
66 * Returns linkedlist used as topology table
67 * cmp - assigned function for comparing topology nodes
68 * del - assigned function executed before deleting topology node by list function
73 struct list
* new = list_new();
75 (*)(void *, void *)) eigrp_prefix_entry_cmp
;
77 (*)(void *)) eigrp_prefix_entry_del
;
83 * Topology node comparison
87 eigrp_prefix_entry_cmp(struct eigrp_prefix_entry
*node1
,
88 struct eigrp_prefix_entry
*node2
)
90 if (node1
->af
== AF_INET
)
92 if (node2
->af
== AF_INET
)
94 if (node1
->destination_ipv4
->prefix
.s_addr
95 < node2
->destination_ipv4
->prefix
.s_addr
)
97 return -1; // if it belong above node2
101 if (node1
->destination_ipv4
->prefix
.s_addr
102 > node2
->destination_ipv4
->prefix
.s_addr
)
104 return 1; //if it belongs under node2
108 return 0; // same value... ERROR...in case of adding same prefix again
118 { // TODO check if the prefix dont exists
119 return 1; // add to end
124 * Topology node delete
128 eigrp_prefix_entry_del(struct eigrp_prefix_entry
*node
)
130 list_delete_all_node(node
->entries
);
131 list_free(node
->entries
);
135 * Returns new created toplogy node
136 * cmp - assigned function for comparing topology entry
139 struct eigrp_prefix_entry
*
140 eigrp_prefix_entry_new()
142 struct eigrp_prefix_entry
*new;
143 new = XCALLOC(MTYPE_EIGRP_PREFIX_ENTRY
, sizeof(struct eigrp_prefix_entry
));
144 new->entries
= list_new();
145 new->rij
= list_new();
146 new->entries
->cmp
= (int
147 (*)(void *, void *)) eigrp_neighbor_entry_cmp
;
148 new->distance
= new->fdistance
= new->rdistance
= EIGRP_MAX_METRIC
;
149 new->destination_ipv4
= NULL
;
150 new->destination_ipv6
= NULL
;
156 * Topology entry comparison
160 eigrp_neighbor_entry_cmp(struct eigrp_neighbor_entry
*entry1
,
161 struct eigrp_neighbor_entry
*entry2
)
163 if (entry1
->distance
< entry2
->distance
) // parameter used in list_add_sort ()
164 return -1; // actually set to sort by distance
165 if (entry1
->distance
> entry2
->distance
)
172 * Returns new topology entry
175 struct eigrp_neighbor_entry
*
176 eigrp_neighbor_entry_new()
178 struct eigrp_neighbor_entry
*new;
180 new = XCALLOC(MTYPE_EIGRP_NEIGHBOR_ENTRY
,
181 sizeof(struct eigrp_neighbor_entry
));
182 new->reported_distance
= EIGRP_MAX_METRIC
;
183 new->distance
= EIGRP_MAX_METRIC
;
189 * Freeing topology table list
193 eigrp_topology_free(struct list
*list
)
199 * Deleting all topology nodes in table
203 eigrp_topology_cleanup(struct list
*topology
)
207 eigrp_topology_delete_all(topology
);
211 * Adding topology node to topology table
215 eigrp_prefix_entry_add(struct list
*topology
, struct eigrp_prefix_entry
*node
)
217 if (listnode_lookup(topology
, node
) == NULL
)
219 listnode_add_sort(topology
, node
);
224 * Adding topology entry to topology node
228 eigrp_neighbor_entry_add(struct eigrp_prefix_entry
*node
,
229 struct eigrp_neighbor_entry
*entry
)
231 if (listnode_lookup(node
->entries
, entry
) == NULL
)
233 listnode_add_sort(node
->entries
, entry
);
234 entry
->prefix
= node
;
239 * Deleting topology node from topology table
243 eigrp_prefix_entry_delete(struct list
*topology
,
244 struct eigrp_prefix_entry
*node
)
246 if (listnode_lookup(topology
, node
) != NULL
)
248 list_delete_all_node(node
->entries
);
249 list_free(node
->entries
);
250 list_free(node
->rij
);
251 listnode_delete(topology
, node
);
252 XFREE(MTYPE_EIGRP_PREFIX_ENTRY
,node
);
257 * Deleting topology entry from topology node
261 eigrp_neighbor_entry_delete(struct eigrp_prefix_entry
*node
,
262 struct eigrp_neighbor_entry
*entry
)
264 if (listnode_lookup(node
->entries
, entry
) != NULL
)
266 listnode_delete(node
->entries
, entry
);
267 XFREE(MTYPE_EIGRP_NEIGHBOR_ENTRY
,entry
);
272 * Deleting all nodes from topology table
276 eigrp_topology_delete_all(struct list
*topology
)
278 list_delete_all_node(topology
);
282 * Return 0 if topology is not empty
287 eigrp_topology_table_isempty(struct list
*topology
)
295 struct eigrp_prefix_entry
*
296 eigrp_topology_table_lookup_ipv4(struct list
*topology_table
,
297 struct prefix_ipv4
* address
)
299 struct eigrp_prefix_entry
*data
;
300 struct listnode
*node
;
301 for (ALL_LIST_ELEMENTS_RO(topology_table
, node
, data
))
304 if ((data
->af
== AF_INET
)
305 && (data
->destination_ipv4
->prefix
.s_addr
== address
->prefix
.s_addr
)
306 && (data
->destination_ipv4
->prefixlen
== address
->prefixlen
))
313 struct eigrp_prefix_entry *
314 eigrp_topology_table_lookup_ipv6 (struct list *topology_table,
315 struct prefix_ipv6 * address)
317 struct eigrp_prefix_entry *data;
318 struct listnode *node, *nnode;
319 for (ALL_LIST_ELEMENTS (topology_table, node, nnode, data))
330 eigrp_topology_get_successor(struct eigrp_prefix_entry
*table_node
)
332 struct list
*successors
= list_new();
334 struct eigrp_neighbor_entry
*data
;
335 struct listnode
*node1
, *node2
;
336 for (ALL_LIST_ELEMENTS(table_node
->entries
, node1
, node2
, data
))
338 if (data
->flags
& EIGRP_NEIGHBOR_ENTRY_SUCCESSOR_FLAG
)
340 listnode_add(successors
, data
);
347 /*extern struct eigrp_neighbor_entry *
348 eigrp_topology_get_fsuccessor (struct eigrp_prefix_entry *table_node)
350 struct eigrp_neighbor_entry *data;
351 struct listnode *node, *nnode;
352 for (ALL_LIST_ELEMENTS (table_node->entries, node, nnode, data))
354 if ((data->flags & EIGRP_NEIGHBOR_ENTRY_FSUCCESSOR_FLAG) == 1)
363 struct eigrp_neighbor_entry
*
364 eigrp_prefix_entry_lookup(struct list
*entries
, struct eigrp_neighbor
*nbr
)
366 struct eigrp_neighbor_entry
*data
;
367 struct listnode
*node
, *nnode
;
368 for (ALL_LIST_ELEMENTS(entries
, node
, nnode
, data
))
370 if (data
->adv_router
== nbr
)
379 /* Lookup all prefixes from specified neighbor */
381 eigrp_neighbor_prefixes_lookup(struct eigrp
*eigrp
, struct eigrp_neighbor
*nbr
)
383 struct listnode
*node1
, *node11
, *node2
, *node22
;
384 struct eigrp_prefix_entry
*prefix
;
385 struct eigrp_neighbor_entry
*entry
;
387 /* create new empty list for prefixes storage */
388 struct list
*prefixes
= list_new();
390 /* iterate over all prefixes in topology table */
391 for (ALL_LIST_ELEMENTS(eigrp
->topology_table
, node1
, node11
, prefix
))
393 /* iterate over all neighbor entry in prefix */
394 for (ALL_LIST_ELEMENTS(prefix
->entries
, node2
, node22
, entry
))
396 /* if entry is from specified neighbor, add to list */
397 if (entry
->adv_router
== nbr
)
399 listnode_add(prefixes
, prefix
);
404 /* return list of prefixes from specified neighbor */
409 eigrp_topology_update_distance(struct eigrp_fsm_action_message
*msg
)
411 struct eigrp
*eigrp
= msg
->eigrp
;
412 struct eigrp_prefix_entry
*prefix
= msg
->prefix
;
413 struct eigrp_neighbor_entry
*entry
= msg
->entry
;
417 struct TLV_IPv4_External_type
*ext_data
= NULL
;
418 struct TLV_IPv4_Internal_type
*int_data
= NULL
;
419 if (msg
->data_type
== EIGRP_TLV_IPv4_INT
)
421 int_data
= msg
->data
.ipv4_int_type
;
422 if (eigrp_metrics_is_same(&int_data
->metric
,&entry
->reported_metric
))
424 return 0; // No change
427 entry
->reported_distance
428 < eigrp_calculate_metrics(eigrp
, &int_data
->metric
) ? 1 :
429 entry
->reported_distance
430 > eigrp_calculate_metrics(eigrp
, &int_data
->metric
) ? 2 : 3; // Increase : Decrease : No change
431 entry
->reported_metric
= int_data
->metric
;
432 entry
->reported_distance
= eigrp_calculate_metrics(eigrp
,
434 entry
->distance
= eigrp_calculate_total_metrics(eigrp
, entry
);
438 ext_data
= msg
->data
.ipv4_ext_data
;
439 if (eigrp_metrics_is_same (&ext_data
->metric
, &entry
->reported_metric
))
443 * Move to correct position in list according to new distance
445 listnode_delete(prefix
->entries
, entry
);
446 listnode_add_sort(prefix
->entries
, entry
);
452 eigrp_topology_update_all_node_flags(struct eigrp
*eigrp
)
454 struct list
*table
= eigrp
->topology_table
;
455 struct eigrp_prefix_entry
*data
;
456 struct listnode
*node
, *nnode
;
457 for (ALL_LIST_ELEMENTS(table
, node
, nnode
, data
))
459 eigrp_topology_update_node_flags(data
);
464 eigrp_topology_update_node_flags(struct eigrp_prefix_entry
*dest
)
466 struct listnode
*node
;
467 struct eigrp_neighbor_entry
*entry
;
468 struct eigrp
* eigrp
= eigrp_lookup();
470 for (ALL_LIST_ELEMENTS_RO(dest
->entries
, node
, entry
))
472 if ((entry
->distance
<= (u_int64_t
)(dest
->distance
*eigrp
->variance
)) && entry
->distance
!= EIGRP_MAX_METRIC
) // is successor
474 entry
->flags
|= EIGRP_NEIGHBOR_ENTRY_SUCCESSOR_FLAG
;
475 entry
->flags
&= 0xfd; // 1111 1101 set fs flag to zero
477 else if (entry
->reported_distance
< dest
->fdistance
) // is feasible successor
479 entry
->flags
|= EIGRP_NEIGHBOR_ENTRY_FSUCCESSOR_FLAG
;
480 entry
->flags
&= 0xfe; // 1111 1110 set successor flag to zero
484 entry
->flags
&= 0xfc; // 1111 1100 set successor and fs flag to zero
490 eigrp_update_routing_table(struct eigrp_prefix_entry
* prefix
)
492 struct listnode
*node
;
493 struct eigrp_neighbor_entry
*entry
;
495 for (ALL_LIST_ELEMENTS_RO(prefix
->entries
, node
, entry
))
497 if (entry
->flags
& EIGRP_NEIGHBOR_ENTRY_SUCCESSOR_FLAG
)
499 if (!(entry
->flags
& EIGRP_NEIGHBOR_ENTRY_INTABLE_FLAG
))
501 eigrp_zebra_route_add(prefix
->destination_ipv4
, entry
);
502 entry
->flags
+= EIGRP_NEIGHBOR_ENTRY_INTABLE_FLAG
;
505 else if (entry
->flags
& EIGRP_NEIGHBOR_ENTRY_INTABLE_FLAG
)
507 eigrp_zebra_route_delete(prefix
->destination_ipv4
, entry
);
508 entry
->flags
-= EIGRP_NEIGHBOR_ENTRY_INTABLE_FLAG
;
514 eigrp_topology_neighbor_down(struct eigrp
*eigrp
, struct eigrp_neighbor
* nbr
)
516 struct listnode
*node1
, *node11
, *node2
, *node22
;
517 struct eigrp_prefix_entry
*prefix
;
518 struct eigrp_neighbor_entry
*entry
;
520 for (ALL_LIST_ELEMENTS(eigrp
->topology_table
, node1
, node11
, prefix
))
522 for (ALL_LIST_ELEMENTS(prefix
->entries
, node2
, node22
, entry
))
524 if (entry
->adv_router
== nbr
)
526 struct eigrp_fsm_action_message
*msg
;
527 msg
= XCALLOC(MTYPE_EIGRP_FSM_MSG
,
528 sizeof(struct eigrp_fsm_action_message
));
529 struct TLV_IPv4_Internal_type
* tlv
= eigrp_IPv4_InternalTLV_new();
530 tlv
->metric
.delay
= EIGRP_MAX_METRIC
;
531 msg
->packet_type
= EIGRP_OPC_UPDATE
;
533 msg
->data_type
= EIGRP_TLV_IPv4_INT
;
534 msg
->adv_router
= nbr
;
535 msg
->data
.ipv4_int_type
= tlv
;
537 msg
->prefix
= prefix
;
538 int event
= eigrp_get_fsm_event(msg
);
539 eigrp_fsm_event(msg
, event
);
544 eigrp_query_send_all(eigrp
);
545 eigrp_update_send_all(eigrp
,nbr
->ei
);
550 eigrp_update_topology_table_prefix(struct list
* table
, struct eigrp_prefix_entry
* prefix
)
552 struct listnode
*node1
, *node2
;
554 struct eigrp_neighbor_entry
*entry
;
555 for (ALL_LIST_ELEMENTS(prefix
->entries
, node1
, node2
, entry
))
557 if(entry
->distance
== EIGRP_MAX_METRIC
)
559 eigrp_neighbor_entry_delete(prefix
,entry
);
562 if(prefix
->distance
== EIGRP_MAX_METRIC
&& prefix
->nt
!= EIGRP_TOPOLOGY_TYPE_CONNECTED
)
564 eigrp_prefix_entry_delete(table
,prefix
);
568 eigrp_topology_get_successor_count (struct eigrp_prefix_entry *prefix)
571 struct listnode *node;
572 struct eigrp_neighbor_entry *entry;
576 for (ALL_LIST_ELEMENTS_RO (prefix->entries,node,entry))
578 if ((entry->flags & EIGRP_NEIGHBOR_ENTRY_SUCCESSOR_FLAG) == EIGRP_NEIGHBOR_ENTRY_SUCCESSOR_FLAG)