2 * EIGRP Interface Functions.
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
46 #include "eigrpd/eigrp_structs.h"
47 #include "eigrpd/eigrpd.h"
48 #include "eigrpd/eigrp_interface.h"
49 #include "eigrpd/eigrp_neighbor.h"
50 #include "eigrpd/eigrp_packet.h"
51 #include "eigrpd/eigrp_zebra.h"
52 #include "eigrpd/eigrp_vty.h"
53 #include "eigrpd/eigrp_network.h"
54 #include "eigrpd/eigrp_topology.h"
55 #include "eigrpd/eigrp_memory.h"
58 eigrp_delete_from_if (struct interface
*, struct eigrp_interface
*);
61 eigrp_add_to_if (struct interface
*ifp
, struct eigrp_interface
*ei
)
63 struct route_node
*rn
;
67 p
.prefixlen
= IPV4_MAX_PREFIXLEN
;
69 rn
= route_node_get (IF_OIFS (ifp
), &p
);
70 /* rn->info should either be NULL or equal to this ei
71 * as route_node_get may return an existing node
73 assert (!rn
->info
|| rn
->info
== ei
);
77 struct eigrp_interface
*
78 eigrp_if_new (struct eigrp
*eigrp
, struct interface
*ifp
, struct prefix
*p
)
80 struct eigrp_interface
*ei
;
83 if ((ei
= eigrp_if_table_lookup (ifp
, p
)) == NULL
)
85 ei
= XCALLOC (MTYPE_EIGRP_IF
, sizeof (struct eigrp_interface
));
86 memset (ei
, 0, sizeof (struct eigrp_interface
));
91 /* Set zebra interface pointer. */
95 eigrp_add_to_if (ifp
, ei
);
96 listnode_add (eigrp
->eiflist
, ei
);
98 ei
->type
= EIGRP_IFTYPE_BROADCAST
;
100 /* Initialize neighbor list. */
101 ei
->nbrs
= list_new ();
103 ei
->crypt_seqnum
= time (NULL
);
105 /* Initialize lists */
106 for (i
= 0; i
< EIGRP_FILTER_MAX
; i
++)
109 ei
->prefix
[i
] = NULL
;
110 ei
->routemap
[i
] = NULL
;
116 /* lookup ei for specified prefix/ifp */
117 struct eigrp_interface
*
118 eigrp_if_table_lookup (struct interface
*ifp
, struct prefix
*prefix
)
121 struct route_node
*rn
;
122 struct eigrp_interface
*rninfo
= NULL
;
125 p
.prefixlen
= IPV4_MAX_PREFIXLEN
;
127 /* route_node_get implicitly locks */
128 if ((rn
= route_node_lookup (IF_OIFS (ifp
), &p
)))
130 rninfo
= (struct eigrp_interface
*) rn
->info
;
131 route_unlock_node (rn
);
138 eigrp_if_delete_hook (struct interface
*ifp
)
140 struct route_node
*rn
;
142 route_table_finish (IF_OIFS (ifp
));
144 for (rn
= route_top (IF_OIFS_PARAMS (ifp
)); rn
; rn
= route_next (rn
))
146 eigrp_del_if_params (rn
->info
);
147 route_table_finish (IF_OIFS_PARAMS (ifp
));
149 XFREE (MTYPE_EIGRP_IF_INFO
, ifp
->info
);
155 struct list
*eigrp_iflist
;
160 /* Initialize Zebra interface data structure. */
161 if_add_hook (IF_NEW_HOOK
, eigrp_if_new_hook
);
162 if_add_hook (IF_DELETE_HOOK
, eigrp_if_delete_hook
);
166 eigrp_if_new_hook (struct interface
*ifp
)
170 ifp
->info
= XCALLOC (MTYPE_EIGRP_IF_INFO
, sizeof (struct eigrp_if_info
));
172 IF_OIFS (ifp
) = route_table_init ();
173 IF_OIFS_PARAMS (ifp
) = route_table_init ();
175 IF_DEF_PARAMS (ifp
) = eigrp_new_if_params ();
177 SET_IF_PARAM (IF_DEF_PARAMS (ifp
), v_hello
);
178 IF_DEF_PARAMS (ifp
)->v_hello
= (u_int32_t
) EIGRP_HELLO_INTERVAL_DEFAULT
;
180 SET_IF_PARAM (IF_DEF_PARAMS (ifp
), v_wait
);
181 IF_DEF_PARAMS (ifp
)->v_wait
= (u_int16_t
) EIGRP_HOLD_INTERVAL_DEFAULT
;
183 SET_IF_PARAM (IF_DEF_PARAMS (ifp
), bandwidth
);
184 IF_DEF_PARAMS (ifp
)->bandwidth
= (u_int32_t
) EIGRP_BANDWIDTH_DEFAULT
;
186 SET_IF_PARAM (IF_DEF_PARAMS (ifp
), delay
);
187 IF_DEF_PARAMS (ifp
)->delay
= (u_int32_t
) EIGRP_DELAY_DEFAULT
;
189 SET_IF_PARAM (IF_DEF_PARAMS (ifp
), reliability
);
190 IF_DEF_PARAMS (ifp
)->reliability
= (u_char
) EIGRP_RELIABILITY_DEFAULT
;
192 SET_IF_PARAM (IF_DEF_PARAMS (ifp
), load
);
193 IF_DEF_PARAMS (ifp
)->load
= (u_char
) EIGRP_LOAD_DEFAULT
;
195 SET_IF_PARAM (IF_DEF_PARAMS (ifp
), auth_type
);
196 IF_DEF_PARAMS (ifp
)->auth_type
= EIGRP_AUTH_TYPE_NONE
;
198 SET_IF_PARAM (IF_DEF_PARAMS (ifp
), auth_keychain
);
199 IF_DEF_PARAMS (ifp
)->auth_keychain
= NULL
;
204 struct eigrp_if_params
*
205 eigrp_new_if_params (void)
207 struct eigrp_if_params
*eip
;
209 eip
= XCALLOC (MTYPE_EIGRP_IF_PARAMS
, sizeof (struct eigrp_if_params
));
213 UNSET_IF_PARAM (eip
, passive_interface
);
214 UNSET_IF_PARAM (eip
, v_hello
);
215 UNSET_IF_PARAM (eip
, v_wait
);
216 UNSET_IF_PARAM (eip
, bandwidth
);
217 UNSET_IF_PARAM (eip
, delay
);
218 UNSET_IF_PARAM (eip
, reliability
);
219 UNSET_IF_PARAM (eip
, load
);
220 UNSET_IF_PARAM (eip
, auth_keychain
);
221 UNSET_IF_PARAM (eip
, auth_type
);
227 eigrp_del_if_params (struct eigrp_if_params
*eip
)
229 if(eip
->auth_keychain
)
230 free(eip
->auth_keychain
);
232 XFREE (MTYPE_EIGRP_IF_PARAMS
, eip
);
235 struct eigrp_if_params
*
236 eigrp_lookup_if_params (struct interface
*ifp
, struct in_addr addr
)
238 struct prefix_ipv4 p
;
239 struct route_node
*rn
;
242 p
.prefixlen
= IPV4_MAX_PREFIXLEN
;
245 rn
= route_node_lookup (IF_OIFS_PARAMS (ifp
), (struct prefix
*) &p
);
249 route_unlock_node (rn
);
257 eigrp_if_up (struct eigrp_interface
*ei
)
259 struct eigrp_prefix_entry
*pe
;
260 struct eigrp_neighbor_entry
*ne
;
261 struct eigrp_metrics metric
;
262 struct eigrp_interface
*ei2
;
263 struct listnode
*node
, *nnode
;
264 struct eigrp
*eigrp
= eigrp_lookup ();
270 eigrp_adjust_sndbuflen (eigrp
, ei
->ifp
->mtu
);
272 zlog_warn ("%s: eigrp_lookup () returned NULL", __func__
);
273 eigrp_if_stream_set (ei
);
275 /* Set multicast memberships appropriately for new state. */
276 eigrp_if_set_multicast (ei
);
278 thread_add_event(master
, eigrp_hello_timer
, ei
, (1), NULL
);
281 metric
.bandwith
= eigrp_bandwidth_to_scaled (EIGRP_IF_PARAM (ei
,bandwidth
));
282 metric
.delay
= eigrp_delay_to_scaled (EIGRP_IF_PARAM (ei
,delay
));
283 metric
.load
= EIGRP_IF_PARAM (ei
,load
);
284 metric
.reliability
= EIGRP_IF_PARAM (ei
,reliability
);
285 metric
.mtu
[0] = 0xDC;
286 metric
.mtu
[1] = 0x05;
287 metric
.mtu
[2] = 0x00;
288 metric
.hop_count
= 0;
292 /*Add connected entry to topology table*/
294 struct prefix_ipv4
*dest_addr
= prefix_ipv4_new ();
296 dest_addr
->family
= AF_INET
;
297 dest_addr
->prefix
= ei
->connected
->address
->u
.prefix4
;
298 dest_addr
->prefixlen
= ei
->connected
->address
->prefixlen
;
299 apply_mask_ipv4 (dest_addr
);
300 pe
= eigrp_topology_table_lookup_ipv4 (eigrp
->topology_table
, dest_addr
);
304 pe
= eigrp_prefix_entry_new ();
305 pe
->serno
= eigrp
->serno
;
306 pe
->destination_ipv4
= prefix_ipv4_new ();
307 prefix_copy ((struct prefix
*)pe
->destination_ipv4
,
308 (struct prefix
*)dest_addr
);
310 pe
->nt
= EIGRP_TOPOLOGY_TYPE_CONNECTED
;
312 pe
->state
= EIGRP_FSM_STATE_PASSIVE
;
313 pe
->fdistance
= eigrp_calculate_metrics (eigrp
, &metric
);
314 pe
->req_action
|= EIGRP_FSM_NEED_UPDATE
;
315 eigrp_prefix_entry_add (eigrp
->topology_table
, pe
);
316 listnode_add(eigrp
->topology_changes_internalIPV4
, pe
);
318 ne
= eigrp_neighbor_entry_new ();
320 ne
->reported_metric
= metric
;
321 ne
->total_metric
= metric
;
322 ne
->distance
= eigrp_calculate_metrics (eigrp
, &metric
);
323 ne
->reported_distance
= 0;
325 ne
->adv_router
= eigrp
->neighbor_self
;
326 ne
->flags
= EIGRP_NEIGHBOR_ENTRY_SUCCESSOR_FLAG
;
327 eigrp_neighbor_entry_add (pe
, ne
);
329 for (ALL_LIST_ELEMENTS (eigrp
->eiflist
, node
, nnode
, ei2
))
331 if (ei2
->nbrs
->count
!= 0)
333 eigrp_update_send (ei2
);
337 pe
->req_action
&= ~EIGRP_FSM_NEED_UPDATE
;
338 listnode_delete(eigrp
->topology_changes_internalIPV4
, pe
);
344 eigrp_if_down (struct eigrp_interface
*ei
)
346 struct listnode
*node
, *nnode
;
347 struct eigrp_neighbor
*nbr
;
352 /* Shutdown packet reception and sending */
354 THREAD_OFF (ei
->t_hello
);
356 eigrp_if_stream_unset (ei
);
358 /*Set infinite metrics to routes learned by this interface and start query process*/
359 for (ALL_LIST_ELEMENTS (ei
->nbrs
, node
, nnode
, nbr
))
361 eigrp_nbr_delete(nbr
);
368 eigrp_if_stream_set (struct eigrp_interface
*ei
)
370 /* set output fifo queue. */
371 if (ei
->obuf
== NULL
)
372 ei
->obuf
= eigrp_fifo_new ();
376 eigrp_if_stream_unset (struct eigrp_interface
*ei
)
378 struct eigrp
*eigrp
= ei
->eigrp
;
382 eigrp_fifo_free (ei
->obuf
);
387 listnode_delete (eigrp
->oi_write_q
, ei
);
388 if (list_isempty (eigrp
->oi_write_q
))
389 thread_cancel (eigrp
->t_write
);
396 eigrp_if_set_multicast (struct eigrp_interface
*ei
)
398 if ((EIGRP_IF_PASSIVE_STATUS (ei
) == EIGRP_IF_ACTIVE
))
400 /* The interface should belong to the EIGRP-all-routers group. */
401 if (!EI_MEMBER_CHECK (ei
, MEMBER_ALLROUTERS
)
402 && (eigrp_if_add_allspfrouters (ei
->eigrp
, ei
->address
,
403 ei
->ifp
->ifindex
) >= 0))
404 /* Set the flag only if the system call to join succeeded. */
405 EI_MEMBER_JOINED (ei
, MEMBER_ALLROUTERS
);
409 /* The interface should NOT belong to the EIGRP-all-routers group. */
410 if (EI_MEMBER_CHECK (ei
, MEMBER_ALLROUTERS
))
412 /* Only actually drop if this is the last reference */
413 if (EI_MEMBER_COUNT (ei
, MEMBER_ALLROUTERS
) == 1)
414 eigrp_if_drop_allspfrouters (ei
->eigrp
, ei
->address
,
416 /* Unset the flag regardless of whether the system call to leave
417 the group succeeded, since it's much safer to assume that
418 we are not a member. */
419 EI_MEMBER_LEFT (ei
, MEMBER_ALLROUTERS
);
425 eigrp_default_iftype (struct interface
*ifp
)
427 if (if_is_pointopoint (ifp
))
428 return EIGRP_IFTYPE_POINTOPOINT
;
429 else if (if_is_loopback (ifp
))
430 return EIGRP_IFTYPE_LOOPBACK
;
432 return EIGRP_IFTYPE_BROADCAST
;
436 eigrp_if_free (struct eigrp_interface
*ei
, int source
)
438 struct prefix_ipv4 dest_addr
;
439 struct eigrp_prefix_entry
*pe
;
440 struct eigrp
*eigrp
= eigrp_lookup ();
442 if (source
== INTERFACE_DOWN_BY_VTY
)
444 THREAD_OFF (ei
->t_hello
);
445 eigrp_hello_send(ei
,EIGRP_HELLO_GRACEFUL_SHUTDOWN
, NULL
);
448 dest_addr
.family
= AF_INET
;
449 dest_addr
.prefix
= ei
->connected
->address
->u
.prefix4
;
450 dest_addr
.prefixlen
= ei
->connected
->address
->prefixlen
;
451 apply_mask_ipv4(&dest_addr
);
452 pe
= eigrp_topology_table_lookup_ipv4 (eigrp
->topology_table
, &dest_addr
);
454 eigrp_prefix_entry_delete (eigrp
->topology_table
, pe
);
458 list_delete (ei
->nbrs
);
459 eigrp_delete_from_if (ei
->ifp
, ei
);
460 listnode_delete (ei
->eigrp
->eiflist
, ei
);
462 thread_cancel_event (master
, ei
);
464 memset (ei
, 0, sizeof (*ei
));
465 XFREE (MTYPE_EIGRP_IF
, ei
);
469 eigrp_delete_from_if (struct interface
*ifp
, struct eigrp_interface
*ei
)
471 struct route_node
*rn
;
475 p
.prefixlen
= IPV4_MAX_PREFIXLEN
;
477 rn
= route_node_lookup (IF_OIFS (ei
->ifp
), &p
);
481 route_unlock_node (rn
);
482 route_unlock_node (rn
);
485 /* Simulate down/up on the interface. This is needed, for example, when
488 eigrp_if_reset (struct interface
*ifp
)
490 struct route_node
*rn
;
492 for (rn
= route_top (IF_OIFS (ifp
)); rn
; rn
= route_next (rn
))
494 struct eigrp_interface
*ei
;
496 if ((ei
= rn
->info
) == NULL
)
504 struct eigrp_interface
*
505 eigrp_if_lookup_by_local_addr (struct eigrp
*eigrp
, struct interface
*ifp
,
506 struct in_addr address
)
508 struct listnode
*node
;
509 struct eigrp_interface
*ei
;
511 for (ALL_LIST_ELEMENTS_RO (eigrp
->eiflist
, node
, ei
))
513 if (ifp
&& ei
->ifp
!= ifp
)
516 if (IPV4_ADDR_SAME (&address
, &ei
->address
->u
.prefix4
))
524 * @fn eigrp_if_lookup_by_name
526 * @param[in] eigrp EIGRP process
527 * @param[in] if_name Name of the interface
529 * @return struct eigrp_interface *
532 * Function is used for lookup interface by name.
534 struct eigrp_interface
*
535 eigrp_if_lookup_by_name (struct eigrp
*eigrp
, const char *if_name
)
537 struct eigrp_interface
*ei
;
538 struct listnode
*node
;
540 /* iterate over all eigrp interfaces */
541 for (ALL_LIST_ELEMENTS_RO (eigrp
->eiflist
, node
, ei
))
543 /* compare int name with eigrp interface's name */
544 if(strcmp(ei
->ifp
->name
, if_name
) == 0)
553 /* determine receiving interface by ifp and source address */
554 struct eigrp_interface
*
555 eigrp_if_lookup_recv_if (struct eigrp
*eigrp
, struct in_addr src
,
556 struct interface
*ifp
)
558 struct route_node
*rn
;
559 struct prefix_ipv4 addr
;
560 struct eigrp_interface
*ei
, *match
;
562 addr
.family
= AF_INET
;
564 addr
.prefixlen
= IPV4_MAX_BITLEN
;
568 for (rn
= route_top (IF_OIFS (ifp
)); rn
; rn
= route_next (rn
))
572 if (!ei
) /* oi can be NULL for PtP aliases */
575 if (if_is_loopback (ei
->ifp
))
578 if (prefix_match (CONNECTED_PREFIX (ei
->connected
),
579 (struct prefix
*) &addr
))
582 || (match
->address
->prefixlen
< ei
->address
->prefixlen
))
591 eigrp_bandwidth_to_scaled (u_int32_t bandwidth
)
593 uint64_t temp_bandwidth
= (256ull * 10000000) / bandwidth
;
596 temp_bandwidth
< EIGRP_MAX_METRIC
? temp_bandwidth
: EIGRP_MAX_METRIC
;
598 return (u_int32_t
) temp_bandwidth
;
602 eigrp_scaled_to_bandwidth (u_int32_t scaled
)
604 uint64_t temp_scaled
= scaled
* (256ull * 10000000);
607 temp_scaled
< EIGRP_MAX_METRIC
? temp_scaled
: EIGRP_MAX_METRIC
;
609 return (u_int32_t
) temp_scaled
;
613 eigrp_delay_to_scaled (u_int32_t delay
)
619 eigrp_scaled_to_delay (u_int32_t scaled
)