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. */
70 eigrp_nbr_state_set (nbr
, EIGRP_NEIGHBOR_DOWN
);
76 *@fn void dissect_eigrp_sw_version (tvbuff_t *tvb, proto_tree *tree,
80 * Create a new neighbor structure and initalize it.
82 static struct eigrp_neighbor
*
83 eigrp_nbr_add (struct eigrp_interface
*ei
, struct eigrp_header
*eigrph
,
86 struct eigrp_neighbor
*nbr
;
88 nbr
= eigrp_nbr_new (ei
);
89 nbr
->src
= iph
->ip_src
;
91 // if (IS_DEBUG_EIGRP_EVENT)
92 // zlog_debug("NSM[%s:%s]: start", IF_NAME (nbr->oi),
93 // inet_ntoa (nbr->router_id));
98 struct eigrp_neighbor
*
99 eigrp_nbr_get (struct eigrp_interface
*ei
, struct eigrp_header
*eigrph
,
102 struct eigrp_neighbor
*nbr
;
103 struct listnode
*node
, *nnode
;
105 for (ALL_LIST_ELEMENTS (ei
->nbrs
, node
, nnode
, nbr
))
107 if (iph
->ip_src
.s_addr
== nbr
->src
.s_addr
)
113 nbr
= eigrp_nbr_add (ei
, eigrph
, iph
);
114 listnode_add (ei
->nbrs
, nbr
);
120 * @fn eigrp_nbr_lookup_by_addr
122 * @param[in] ei EIGRP interface
123 * @param[in] nbr_addr Address of neighbor
128 * Function is used for neighbor lookup by address
129 * in specified interface.
131 struct eigrp_neighbor
*
132 eigrp_nbr_lookup_by_addr (struct eigrp_interface
*ei
, struct in_addr
*addr
)
134 struct eigrp_neighbor
*nbr
;
135 struct listnode
*node
, *nnode
;
137 for (ALL_LIST_ELEMENTS (ei
->nbrs
, node
, nnode
, nbr
))
139 if (addr
->s_addr
== nbr
->src
.s_addr
)
149 * @fn eigrp_nbr_lookup_by_addr_process
151 * @param[in] eigrp EIGRP process
152 * @param[in] nbr_addr Address of neighbor
157 * Function is used for neighbor lookup by address
158 * in whole EIGRP process.
160 struct eigrp_neighbor
*
161 eigrp_nbr_lookup_by_addr_process (struct eigrp
*eigrp
, struct in_addr nbr_addr
)
163 struct eigrp_interface
*ei
;
164 struct listnode
*node
, *node2
, *nnode2
;
165 struct eigrp_neighbor
*nbr
;
167 /* iterate over all eigrp interfaces */
168 for (ALL_LIST_ELEMENTS_RO (eigrp
->eiflist
, node
, ei
))
170 /* iterate over all neighbors on eigrp interface */
171 for (ALL_LIST_ELEMENTS (ei
->nbrs
, node2
, nnode2
, nbr
))
173 /* compare if neighbor address is same as arg address */
174 if (nbr
->src
.s_addr
== nbr_addr
.s_addr
)
185 /* Delete specified EIGRP neighbor from interface. */
187 eigrp_nbr_delete (struct eigrp_neighbor
*nbr
)
189 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
);
198 listnode_delete (nbr
->ei
->nbrs
,nbr
);
199 XFREE (MTYPE_EIGRP_NEIGHBOR
, nbr
);
203 holddown_timer_expired (struct thread
*thread
)
205 struct eigrp_neighbor
*nbr
;
207 nbr
= THREAD_ARG (thread
);
209 zlog_info ("Neighbor %s (%s) is down: holding time expired",
210 inet_ntoa(nbr
->src
), ifindex2ifname(nbr
->ei
->ifp
->ifindex
, VRF_DEFAULT
));
211 nbr
->state
= EIGRP_NEIGHBOR_DOWN
;
212 eigrp_nbr_delete (nbr
);
218 eigrp_nbr_state_get (struct eigrp_neighbor
*nbr
)
224 eigrp_nbr_state_set (struct eigrp_neighbor
*nbr
, u_char state
)
228 if (eigrp_nbr_state_get(nbr
) == EIGRP_NEIGHBOR_DOWN
)
230 // reset all the seq/ack counters
231 nbr
->recv_sequence_number
= 0;
232 nbr
->init_sequence_number
= 0;
233 nbr
->retrans_counter
= 0;
236 nbr
->K1
= EIGRP_K1_DEFAULT
;
237 nbr
->K2
= EIGRP_K2_DEFAULT
;
238 nbr
->K3
= EIGRP_K3_DEFAULT
;
239 nbr
->K4
= EIGRP_K4_DEFAULT
;
240 nbr
->K5
= EIGRP_K5_DEFAULT
;
241 nbr
->K6
= EIGRP_K6_DEFAULT
;
244 nbr
->v_holddown
= EIGRP_HOLD_INTERVAL_DEFAULT
;
245 THREAD_OFF(nbr
->t_holddown
);
247 /* out with the old */
248 if (nbr
->multicast_queue
)
249 eigrp_fifo_free (nbr
->multicast_queue
);
250 if (nbr
->retrans_queue
)
251 eigrp_fifo_free (nbr
->retrans_queue
);
253 /* in with the new */
254 nbr
->retrans_queue
= eigrp_fifo_new ();
255 nbr
->multicast_queue
= eigrp_fifo_new ();
257 nbr
->crypt_seqnum
= 0;
262 eigrp_nbr_state_str (struct eigrp_neighbor
*nbr
)
267 case EIGRP_NEIGHBOR_DOWN
:
270 case EIGRP_NEIGHBOR_PENDING
:
271 state
= "Waiting for Init";
273 case EIGRP_NEIGHBOR_UP
:
285 eigrp_nbr_state_update (struct eigrp_neighbor
*nbr
)
289 case EIGRP_NEIGHBOR_DOWN
:
291 /*Start Hold Down Timer for neighbor*/
292 // THREAD_OFF(nbr->t_holddown);
293 // THREAD_TIMER_ON(master, nbr->t_holddown, holddown_timer_expired,
294 // nbr, nbr->v_holddown);
297 case EIGRP_NEIGHBOR_PENDING
:
299 /*Reset Hold Down Timer for neighbor*/
300 THREAD_OFF(nbr
->t_holddown
);
301 THREAD_TIMER_ON(master
, nbr
->t_holddown
, holddown_timer_expired
, nbr
,
305 case EIGRP_NEIGHBOR_UP
:
307 /*Reset Hold Down Timer for neighbor*/
308 THREAD_OFF(nbr
->t_holddown
);
309 THREAD_TIMER_ON(master
, nbr
->t_holddown
, holddown_timer_expired
, nbr
,
316 int eigrp_nbr_count_get(void){
317 struct eigrp_interface
*iface
;
318 struct listnode
*node
, *node2
, *nnode2
;
319 struct eigrp_neighbor
*nbr
;
320 struct eigrp
*eigrp
= eigrp_lookup();
325 zlog_debug("EIGRP Routing Process not enabled");
330 for (ALL_LIST_ELEMENTS_RO(eigrp
->eiflist
, node
, iface
))
332 for (ALL_LIST_ELEMENTS(iface
->nbrs
, node2
, nnode2
, nbr
))
334 if (nbr
->state
== EIGRP_NEIGHBOR_UP
){
343 * @fn eigrp_nbr_hard_restart
345 * @param[in] nbr Neighbor who would receive hard restart
346 * @param[in] vty Virtual terminal for log output
350 * Function used for executing hard restart for neighbor:
351 * Send Hello packet with Peer Termination TLV with
352 * neighbor's address, set it's state to DOWN and delete the neighbor
354 void eigrp_nbr_hard_restart(struct eigrp_neighbor
*nbr
, struct vty
*vty
)
358 zlog_err("Nbr Hard restart: Neighbor not specified.");
362 zlog_debug ("Neighbor %s (%s) is down: manually cleared",
363 inet_ntoa (nbr
->src
),
364 ifindex2ifname (nbr
->ei
->ifp
->ifindex
, VRF_DEFAULT
));
367 vty_time_print (vty
, 0);
368 vty_out (vty
, "Neighbor %s (%s) is down: manually cleared%s",
369 inet_ntoa (nbr
->src
),
370 ifindex2ifname (nbr
->ei
->ifp
->ifindex
, VRF_DEFAULT
),
374 /* send Hello with Peer Termination TLV */
375 eigrp_hello_send(nbr
->ei
, EIGRP_HELLO_GRACEFUL_SHUTDOWN_NBR
, &(nbr
->src
));
376 /* set neighbor to DOWN */
377 nbr
->state
= EIGRP_NEIGHBOR_DOWN
;
378 /* delete neighbor */
379 eigrp_nbr_delete (nbr
);