2 * EIGRP Neighbor Handling.
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
45 #include "eigrpd/eigrp_structs.h"
46 #include "eigrpd/eigrpd.h"
47 #include "eigrpd/eigrp_interface.h"
48 #include "eigrpd/eigrp_neighbor.h"
49 #include "eigrpd/eigrp_dump.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"
57 struct eigrp_neighbor
*
58 eigrp_nbr_new (struct eigrp_interface
*ei
)
60 struct eigrp_neighbor
*nbr
;
62 /* Allcate new neighbor. */
63 nbr
= XCALLOC (MTYPE_EIGRP_NEIGHBOR
, sizeof (struct eigrp_neighbor
));
65 /* Relate neighbor to the interface. */
68 /* Set default values. */
69 eigrp_nbr_state_set (nbr
, EIGRP_NEIGHBOR_DOWN
);
75 *@fn void dissect_eigrp_sw_version (tvbuff_t *tvb, proto_tree *tree,
79 * Create a new neighbor structure and initalize it.
81 static struct eigrp_neighbor
*
82 eigrp_nbr_add (struct eigrp_interface
*ei
, struct eigrp_header
*eigrph
,
85 struct eigrp_neighbor
*nbr
;
87 nbr
= eigrp_nbr_new (ei
);
88 nbr
->src
= iph
->ip_src
;
90 // if (IS_DEBUG_EIGRP_EVENT)
91 // zlog_debug("NSM[%s:%s]: start", IF_NAME (nbr->oi),
92 // inet_ntoa (nbr->router_id));
97 struct eigrp_neighbor
*
98 eigrp_nbr_get (struct eigrp_interface
*ei
, struct eigrp_header
*eigrph
,
101 struct eigrp_neighbor
*nbr
;
102 struct listnode
*node
, *nnode
;
104 for (ALL_LIST_ELEMENTS (ei
->nbrs
, node
, nnode
, nbr
))
106 if (iph
->ip_src
.s_addr
== nbr
->src
.s_addr
)
112 nbr
= eigrp_nbr_add (ei
, eigrph
, iph
);
113 listnode_add (ei
->nbrs
, nbr
);
119 * @fn eigrp_nbr_lookup_by_addr
121 * @param[in] ei EIGRP interface
122 * @param[in] nbr_addr Address of neighbor
127 * Function is used for neighbor lookup by address
128 * in specified interface.
130 struct eigrp_neighbor
*
131 eigrp_nbr_lookup_by_addr (struct eigrp_interface
*ei
, struct in_addr
*addr
)
133 struct eigrp_neighbor
*nbr
;
134 struct listnode
*node
, *nnode
;
136 for (ALL_LIST_ELEMENTS (ei
->nbrs
, node
, nnode
, nbr
))
138 if (addr
->s_addr
== nbr
->src
.s_addr
)
148 * @fn eigrp_nbr_lookup_by_addr_process
150 * @param[in] eigrp EIGRP process
151 * @param[in] nbr_addr Address of neighbor
156 * Function is used for neighbor lookup by address
157 * in whole EIGRP process.
159 struct eigrp_neighbor
*
160 eigrp_nbr_lookup_by_addr_process (struct eigrp
*eigrp
, struct in_addr nbr_addr
)
162 struct eigrp_interface
*ei
;
163 struct listnode
*node
, *node2
, *nnode2
;
164 struct eigrp_neighbor
*nbr
;
166 /* iterate over all eigrp interfaces */
167 for (ALL_LIST_ELEMENTS_RO (eigrp
->eiflist
, node
, ei
))
169 /* iterate over all neighbors on eigrp interface */
170 for (ALL_LIST_ELEMENTS (ei
->nbrs
, node2
, nnode2
, nbr
))
172 /* compare if neighbor address is same as arg address */
173 if (nbr
->src
.s_addr
== nbr_addr
.s_addr
)
184 /* Delete specified EIGRP neighbor from interface. */
186 eigrp_nbr_delete (struct eigrp_neighbor
*nbr
)
188 eigrp_nbr_state_set(nbr
, EIGRP_NEIGHBOR_DOWN
);
190 eigrp_topology_neighbor_down(nbr
->ei
->eigrp
, nbr
);
192 /* Cancel all events. *//* Thread lookup cost would be negligible. */
193 thread_cancel_event (master
, nbr
);
194 eigrp_fifo_free (nbr
->multicast_queue
);
195 eigrp_fifo_free (nbr
->retrans_queue
);
196 THREAD_OFF (nbr
->t_holddown
);
199 listnode_delete (nbr
->ei
->nbrs
,nbr
);
200 XFREE (MTYPE_EIGRP_NEIGHBOR
, nbr
);
204 holddown_timer_expired (struct thread
*thread
)
206 struct eigrp_neighbor
*nbr
;
208 nbr
= THREAD_ARG (thread
);
210 zlog_info ("Neighbor %s (%s) is down: holding time expired",
211 inet_ntoa(nbr
->src
), ifindex2ifname(nbr
->ei
->ifp
->ifindex
, VRF_DEFAULT
));
212 nbr
->state
= EIGRP_NEIGHBOR_DOWN
;
213 eigrp_nbr_delete (nbr
);
219 eigrp_nbr_state_get (struct eigrp_neighbor
*nbr
)
225 eigrp_nbr_state_set (struct eigrp_neighbor
*nbr
, u_char state
)
229 if (eigrp_nbr_state_get(nbr
) == EIGRP_NEIGHBOR_DOWN
)
231 // reset all the seq/ack counters
232 nbr
->recv_sequence_number
= 0;
233 nbr
->init_sequence_number
= 0;
234 nbr
->retrans_counter
= 0;
237 nbr
->K1
= EIGRP_K1_DEFAULT
;
238 nbr
->K2
= EIGRP_K2_DEFAULT
;
239 nbr
->K3
= EIGRP_K3_DEFAULT
;
240 nbr
->K4
= EIGRP_K4_DEFAULT
;
241 nbr
->K5
= EIGRP_K5_DEFAULT
;
242 nbr
->K6
= EIGRP_K6_DEFAULT
;
245 nbr
->v_holddown
= EIGRP_HOLD_INTERVAL_DEFAULT
;
246 THREAD_OFF(nbr
->t_holddown
);
248 /* out with the old */
249 if (nbr
->multicast_queue
)
250 eigrp_fifo_free (nbr
->multicast_queue
);
251 if (nbr
->retrans_queue
)
252 eigrp_fifo_free (nbr
->retrans_queue
);
254 /* in with the new */
255 nbr
->retrans_queue
= eigrp_fifo_new ();
256 nbr
->multicast_queue
= eigrp_fifo_new ();
258 nbr
->crypt_seqnum
= 0;
263 eigrp_nbr_state_str (struct eigrp_neighbor
*nbr
)
268 case EIGRP_NEIGHBOR_DOWN
:
271 case EIGRP_NEIGHBOR_PENDING
:
272 state
= "Waiting for Init";
274 case EIGRP_NEIGHBOR_UP
:
286 eigrp_nbr_state_update (struct eigrp_neighbor
*nbr
)
290 case EIGRP_NEIGHBOR_DOWN
:
292 /*Start Hold Down Timer for neighbor*/
293 // THREAD_OFF(nbr->t_holddown);
294 // THREAD_TIMER_ON(master, nbr->t_holddown, holddown_timer_expired,
295 // nbr, nbr->v_holddown);
298 case EIGRP_NEIGHBOR_PENDING
:
300 /*Reset Hold Down Timer for neighbor*/
301 THREAD_OFF(nbr
->t_holddown
);
302 thread_add_timer(master
, holddown_timer_expired
, nbr
,
303 nbr
->v_holddown
, &nbr
->t_holddown
);
306 case EIGRP_NEIGHBOR_UP
:
308 /*Reset Hold Down Timer for neighbor*/
309 THREAD_OFF(nbr
->t_holddown
);
310 thread_add_timer(master
, holddown_timer_expired
, nbr
,
311 nbr
->v_holddown
, &nbr
->t_holddown
);
317 int eigrp_nbr_count_get(void){
318 struct eigrp_interface
*iface
;
319 struct listnode
*node
, *node2
, *nnode2
;
320 struct eigrp_neighbor
*nbr
;
321 struct eigrp
*eigrp
= eigrp_lookup();
326 zlog_debug("EIGRP Routing Process not enabled");
331 for (ALL_LIST_ELEMENTS_RO(eigrp
->eiflist
, node
, iface
))
333 for (ALL_LIST_ELEMENTS(iface
->nbrs
, node2
, nnode2
, nbr
))
335 if (nbr
->state
== EIGRP_NEIGHBOR_UP
){
344 * @fn eigrp_nbr_hard_restart
346 * @param[in] nbr Neighbor who would receive hard restart
347 * @param[in] vty Virtual terminal for log output
351 * Function used for executing hard restart for neighbor:
352 * Send Hello packet with Peer Termination TLV with
353 * neighbor's address, set it's state to DOWN and delete the neighbor
355 void eigrp_nbr_hard_restart(struct eigrp_neighbor
*nbr
, struct vty
*vty
)
359 zlog_err("Nbr Hard restart: Neighbor not specified.");
363 zlog_debug ("Neighbor %s (%s) is down: manually cleared",
364 inet_ntoa (nbr
->src
),
365 ifindex2ifname (nbr
->ei
->ifp
->ifindex
, VRF_DEFAULT
));
368 vty_time_print (vty
, 0);
369 vty_out (vty
, "Neighbor %s (%s) is down: manually cleared%s",
370 inet_ntoa (nbr
->src
),
371 ifindex2ifname (nbr
->ei
->ifp
->ifindex
, VRF_DEFAULT
),
375 /* send Hello with Peer Termination TLV */
376 eigrp_hello_send(nbr
->ei
, EIGRP_HELLO_GRACEFUL_SHUTDOWN_NBR
, &(nbr
->src
));
377 /* set neighbor to DOWN */
378 nbr
->state
= EIGRP_NEIGHBOR_DOWN
;
379 /* delete neighbor */
380 eigrp_nbr_delete (nbr
);