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
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
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_dump.h"
51 #include "eigrpd/eigrp_packet.h"
52 #include "eigrpd/eigrp_zebra.h"
53 #include "eigrpd/eigrp_vty.h"
54 #include "eigrpd/eigrp_network.h"
55 #include "eigrpd/eigrp_topology.h"
56 #include "eigrpd/eigrp_memory.h"
58 struct eigrp_neighbor
*
59 eigrp_nbr_new (struct eigrp_interface
*ei
)
61 struct eigrp_neighbor
*nbr
;
63 /* Allcate new neighbor. */
64 nbr
= XCALLOC (MTYPE_EIGRP_NEIGHBOR
, sizeof (struct eigrp_neighbor
));
66 /* Relate neighbor to the interface. */
69 /* Set default values. */
71 eigrp_nbr_state_set (nbr
, EIGRP_NEIGHBOR_DOWN
);
77 *@fn void dissect_eigrp_sw_version (tvbuff_t *tvb, proto_tree *tree,
81 * Create a new neighbor structure and initalize it.
83 static struct eigrp_neighbor
*
84 eigrp_nbr_add (struct eigrp_interface
*ei
, struct eigrp_header
*eigrph
,
87 struct eigrp_neighbor
*nbr
;
89 nbr
= eigrp_nbr_new (ei
);
90 nbr
->src
= iph
->ip_src
;
92 // if (IS_DEBUG_EIGRP_EVENT)
93 // zlog_debug("NSM[%s:%s]: start", IF_NAME (nbr->oi),
94 // inet_ntoa (nbr->router_id));
99 struct eigrp_neighbor
*
100 eigrp_nbr_get (struct eigrp_interface
*ei
, struct eigrp_header
*eigrph
,
103 struct eigrp_neighbor
*nbr
;
104 struct listnode
*node
, *nnode
;
106 for (ALL_LIST_ELEMENTS (ei
->nbrs
, node
, nnode
, nbr
))
108 if (iph
->ip_src
.s_addr
== nbr
->src
.s_addr
)
114 nbr
= eigrp_nbr_add (ei
, eigrph
, iph
);
115 listnode_add (ei
->nbrs
, nbr
);
121 * @fn eigrp_nbr_lookup_by_addr
123 * @param[in] ei EIGRP interface
124 * @param[in] nbr_addr Address of neighbor
129 * Function is used for neighbor lookup by address
130 * in specified interface.
132 struct eigrp_neighbor
*
133 eigrp_nbr_lookup_by_addr (struct eigrp_interface
*ei
, struct in_addr
*addr
)
135 struct eigrp_neighbor
*nbr
;
136 struct listnode
*node
, *nnode
;
138 for (ALL_LIST_ELEMENTS (ei
->nbrs
, node
, nnode
, nbr
))
140 if (addr
->s_addr
== nbr
->src
.s_addr
)
150 * @fn eigrp_nbr_lookup_by_addr_process
152 * @param[in] eigrp EIGRP process
153 * @param[in] nbr_addr Address of neighbor
158 * Function is used for neighbor lookup by address
159 * in whole EIGRP process.
161 struct eigrp_neighbor
*
162 eigrp_nbr_lookup_by_addr_process (struct eigrp
*eigrp
, struct in_addr nbr_addr
)
164 struct eigrp_interface
*ei
;
165 struct listnode
*node
, *node2
, *nnode2
;
166 struct eigrp_neighbor
*nbr
;
168 /* iterate over all eigrp interfaces */
169 for (ALL_LIST_ELEMENTS_RO (eigrp
->eiflist
, node
, ei
))
171 /* iterate over all neighbors on eigrp interface */
172 for (ALL_LIST_ELEMENTS (ei
->nbrs
, node2
, nnode2
, nbr
))
174 /* compare if neighbor address is same as arg address */
175 if (nbr
->src
.s_addr
== nbr_addr
.s_addr
)
186 /* Delete specified EIGRP neighbor from interface. */
188 eigrp_nbr_delete (struct eigrp_neighbor
*nbr
)
191 eigrp_nbr_state_set(nbr
, EIGRP_NEIGHBOR_DOWN
);
192 eigrp_topology_neighbor_down(nbr
->ei
->eigrp
, nbr
);
194 /* Cancel all events. *//* Thread lookup cost would be negligible. */
195 thread_cancel_event (master
, nbr
);
196 eigrp_fifo_free (nbr
->multicast_queue
);
197 eigrp_fifo_free (nbr
->retrans_queue
);
198 THREAD_OFF (nbr
->t_holddown
);
200 listnode_delete (nbr
->ei
->nbrs
,nbr
);
201 XFREE (MTYPE_EIGRP_NEIGHBOR
, nbr
);
205 holddown_timer_expired (struct thread
*thread
)
207 struct eigrp_neighbor
*nbr
;
209 nbr
= THREAD_ARG (thread
);
211 zlog_info ("Neighbor %s (%s) is down: holding time expired",
212 inet_ntoa(nbr
->src
), ifindex2ifname(nbr
->ei
->ifp
->ifindex
));
213 nbr
->state
= EIGRP_NEIGHBOR_DOWN
;
214 eigrp_nbr_delete (nbr
);
220 eigrp_nbr_state_get (struct eigrp_neighbor
*nbr
)
226 eigrp_nbr_state_set (struct eigrp_neighbor
*nbr
, u_char state
)
231 if (eigrp_nbr_state_get(nbr
) == EIGRP_NEIGHBOR_DOWN
)
233 // reset all the seq/ack counters
234 nbr
->recv_sequence_number
= 0;
235 nbr
->init_sequence_number
= 0;
236 nbr
->retrans_counter
= 0;
239 nbr
->K1
= EIGRP_K1_DEFAULT
;
240 nbr
->K2
= EIGRP_K2_DEFAULT
;
241 nbr
->K3
= EIGRP_K3_DEFAULT
;
242 nbr
->K4
= EIGRP_K4_DEFAULT
;
243 nbr
->K5
= EIGRP_K5_DEFAULT
;
244 nbr
->K6
= EIGRP_K6_DEFAULT
;
247 nbr
->v_holddown
= EIGRP_HOLD_INTERVAL_DEFAULT
;
248 THREAD_OFF(nbr
->t_holddown
);
250 /* out with the old */
251 if (nbr
->multicast_queue
)
252 eigrp_fifo_free (nbr
->multicast_queue
);
253 if (nbr
->retrans_queue
)
254 eigrp_fifo_free (nbr
->retrans_queue
);
256 /* in with the new */
257 nbr
->retrans_queue
= eigrp_fifo_new ();
258 nbr
->multicast_queue
= eigrp_fifo_new ();
260 nbr
->crypt_seqnum
= 0;
265 eigrp_nbr_state_str (struct eigrp_neighbor
*nbr
)
270 case EIGRP_NEIGHBOR_DOWN
:
273 case EIGRP_NEIGHBOR_PENDING
:
274 state
= "Waiting for Init";
276 case EIGRP_NEIGHBOR_UP
:
288 eigrp_nbr_state_update (struct eigrp_neighbor
*nbr
)
292 case EIGRP_NEIGHBOR_DOWN
:
294 /*Start Hold Down Timer for neighbor*/
295 // THREAD_OFF(nbr->t_holddown);
296 // THREAD_TIMER_ON(master, nbr->t_holddown, holddown_timer_expired,
297 // nbr, nbr->v_holddown);
300 case EIGRP_NEIGHBOR_PENDING
:
302 /*Reset Hold Down Timer for neighbor*/
303 THREAD_OFF(nbr
->t_holddown
);
304 THREAD_TIMER_ON(master
, nbr
->t_holddown
, holddown_timer_expired
, nbr
,
308 case EIGRP_NEIGHBOR_UP
:
310 /*Reset Hold Down Timer for neighbor*/
311 THREAD_OFF(nbr
->t_holddown
);
312 THREAD_TIMER_ON(master
, nbr
->t_holddown
, holddown_timer_expired
, nbr
,
319 int eigrp_nbr_count_get(void){
321 struct eigrp_interface
*iface
;
322 struct listnode
*node
, *node2
, *nnode2
;
323 struct eigrp_neighbor
*nbr
;
324 struct eigrp
*eigrp
= eigrp_lookup();
329 zlog_debug("EIGRP Routing Process not enabled");
334 for (ALL_LIST_ELEMENTS_RO(eigrp
->eiflist
, node
, iface
))
336 for (ALL_LIST_ELEMENTS(iface
->nbrs
, node2
, nnode2
, nbr
))
338 if (nbr
->state
== EIGRP_NEIGHBOR_UP
){
347 * @fn eigrp_nbr_hard_restart
349 * @param[in] nbr Neighbor who would receive hard restart
350 * @param[in] vty Virtual terminal for log output
354 * Function used for executing hard restart for neighbor:
355 * Send Hello packet with Peer Termination TLV with
356 * neighbor's address, set it's state to DOWN and delete the neighbor
358 void eigrp_nbr_hard_restart(struct eigrp_neighbor
*nbr
, struct vty
*vty
)
362 zlog_err("Nbr Hard restart: Neighbor not specified.");
366 zlog_debug ("Neighbor %s (%s) is down: manually cleared",
367 inet_ntoa (nbr
->src
),
368 ifindex2ifname (nbr
->ei
->ifp
->ifindex
));
371 vty_time_print (vty
, 0);
372 vty_out (vty
, "Neighbor %s (%s) is down: manually cleared%s",
373 inet_ntoa (nbr
->src
),
374 ifindex2ifname (nbr
->ei
->ifp
->ifindex
),
378 /* send Hello with Peer Termination TLV */
379 eigrp_hello_send(nbr
->ei
, EIGRP_HELLO_GRACEFUL_SHUTDOWN_NBR
, &(nbr
->src
));
380 /* set neighbor to DOWN */
381 nbr
->state
= EIGRP_NEIGHBOR_DOWN
;
382 /* delete neighbor */
383 eigrp_nbr_delete (nbr
);