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"
56 #include "eigrpd/eigrp_errors.h"
58 struct eigrp_neighbor
*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
*eigrp_nbr_add(struct eigrp_interface
*ei
,
82 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
*eigrp_nbr_get(struct eigrp_interface
*ei
,
98 struct eigrp_header
*eigrph
,
101 struct eigrp_neighbor
*nbr
;
102 struct listnode
*node
, *nnode
;
104 for (ALL_LIST_ELEMENTS(ei
->nbrs
, node
, nnode
, nbr
)) {
105 if (iph
->ip_src
.s_addr
== nbr
->src
.s_addr
) {
110 nbr
= eigrp_nbr_add(ei
, eigrph
, iph
);
111 listnode_add(ei
->nbrs
, nbr
);
117 * @fn eigrp_nbr_lookup_by_addr
119 * @param[in] ei EIGRP interface
120 * @param[in] nbr_addr Address of neighbor
125 * Function is used for neighbor lookup by address
126 * in specified interface.
128 struct eigrp_neighbor
*eigrp_nbr_lookup_by_addr(struct eigrp_interface
*ei
,
129 struct in_addr
*addr
)
131 struct eigrp_neighbor
*nbr
;
132 struct listnode
*node
, *nnode
;
134 for (ALL_LIST_ELEMENTS(ei
->nbrs
, node
, nnode
, nbr
)) {
135 if (addr
->s_addr
== nbr
->src
.s_addr
) {
144 * @fn eigrp_nbr_lookup_by_addr_process
146 * @param[in] eigrp EIGRP process
147 * @param[in] nbr_addr Address of neighbor
152 * Function is used for neighbor lookup by address
153 * in whole EIGRP process.
155 struct eigrp_neighbor
*eigrp_nbr_lookup_by_addr_process(struct eigrp
*eigrp
,
156 struct in_addr nbr_addr
)
158 struct eigrp_interface
*ei
;
159 struct listnode
*node
, *node2
, *nnode2
;
160 struct eigrp_neighbor
*nbr
;
162 /* iterate over all eigrp interfaces */
163 for (ALL_LIST_ELEMENTS_RO(eigrp
->eiflist
, node
, ei
)) {
164 /* iterate over all neighbors on eigrp interface */
165 for (ALL_LIST_ELEMENTS(ei
->nbrs
, node2
, nnode2
, nbr
)) {
166 /* compare if neighbor address is same as arg address */
167 if (nbr
->src
.s_addr
== nbr_addr
.s_addr
) {
177 /* Delete specified EIGRP neighbor from interface. */
178 void eigrp_nbr_delete(struct eigrp_neighbor
*nbr
)
180 eigrp_nbr_state_set(nbr
, EIGRP_NEIGHBOR_DOWN
);
182 eigrp_topology_neighbor_down(nbr
->ei
->eigrp
, nbr
);
184 /* Cancel all events. */ /* Thread lookup cost would be negligible. */
185 thread_cancel_event(master
, nbr
);
186 eigrp_fifo_free(nbr
->multicast_queue
);
187 eigrp_fifo_free(nbr
->retrans_queue
);
188 THREAD_OFF(nbr
->t_holddown
);
191 listnode_delete(nbr
->ei
->nbrs
, nbr
);
192 XFREE(MTYPE_EIGRP_NEIGHBOR
, nbr
);
195 int holddown_timer_expired(struct thread
*thread
)
197 struct eigrp_neighbor
*nbr
;
199 nbr
= THREAD_ARG(thread
);
201 zlog_info("Neighbor %s (%s) is down: holding time expired",
203 ifindex2ifname(nbr
->ei
->ifp
->ifindex
, VRF_DEFAULT
));
204 nbr
->state
= EIGRP_NEIGHBOR_DOWN
;
205 eigrp_nbr_delete(nbr
);
210 uint8_t eigrp_nbr_state_get(struct eigrp_neighbor
*nbr
)
215 void eigrp_nbr_state_set(struct eigrp_neighbor
*nbr
, uint8_t state
)
219 if (eigrp_nbr_state_get(nbr
) == EIGRP_NEIGHBOR_DOWN
) {
220 // reset all the seq/ack counters
221 nbr
->recv_sequence_number
= 0;
222 nbr
->init_sequence_number
= 0;
223 nbr
->retrans_counter
= 0;
226 nbr
->K1
= EIGRP_K1_DEFAULT
;
227 nbr
->K2
= EIGRP_K2_DEFAULT
;
228 nbr
->K3
= EIGRP_K3_DEFAULT
;
229 nbr
->K4
= EIGRP_K4_DEFAULT
;
230 nbr
->K5
= EIGRP_K5_DEFAULT
;
231 nbr
->K6
= EIGRP_K6_DEFAULT
;
234 nbr
->v_holddown
= EIGRP_HOLD_INTERVAL_DEFAULT
;
235 THREAD_OFF(nbr
->t_holddown
);
237 /* out with the old */
238 if (nbr
->multicast_queue
)
239 eigrp_fifo_free(nbr
->multicast_queue
);
240 if (nbr
->retrans_queue
)
241 eigrp_fifo_free(nbr
->retrans_queue
);
243 /* in with the new */
244 nbr
->retrans_queue
= eigrp_fifo_new();
245 nbr
->multicast_queue
= eigrp_fifo_new();
247 nbr
->crypt_seqnum
= 0;
251 const char *eigrp_nbr_state_str(struct eigrp_neighbor
*nbr
)
254 switch (nbr
->state
) {
255 case EIGRP_NEIGHBOR_DOWN
:
258 case EIGRP_NEIGHBOR_PENDING
:
259 state
= "Waiting for Init";
261 case EIGRP_NEIGHBOR_UP
:
272 void eigrp_nbr_state_update(struct eigrp_neighbor
*nbr
)
274 switch (nbr
->state
) {
275 case EIGRP_NEIGHBOR_DOWN
: {
276 /*Start Hold Down Timer for neighbor*/
277 // THREAD_OFF(nbr->t_holddown);
278 // THREAD_TIMER_ON(master, nbr->t_holddown,
279 // holddown_timer_expired,
280 // nbr, nbr->v_holddown);
283 case EIGRP_NEIGHBOR_PENDING
: {
284 /*Reset Hold Down Timer for neighbor*/
285 THREAD_OFF(nbr
->t_holddown
);
286 thread_add_timer(master
, holddown_timer_expired
, nbr
,
287 nbr
->v_holddown
, &nbr
->t_holddown
);
290 case EIGRP_NEIGHBOR_UP
: {
291 /*Reset Hold Down Timer for neighbor*/
292 THREAD_OFF(nbr
->t_holddown
);
293 thread_add_timer(master
, holddown_timer_expired
, nbr
,
294 nbr
->v_holddown
, &nbr
->t_holddown
);
300 int eigrp_nbr_count_get(void)
302 struct eigrp_interface
*iface
;
303 struct listnode
*node
, *node2
, *nnode2
;
304 struct eigrp_neighbor
*nbr
;
305 struct eigrp
*eigrp
= eigrp_lookup();
309 zlog_debug("EIGRP Routing Process not enabled");
314 for (ALL_LIST_ELEMENTS_RO(eigrp
->eiflist
, node
, iface
)) {
315 for (ALL_LIST_ELEMENTS(iface
->nbrs
, node2
, nnode2
, nbr
)) {
316 if (nbr
->state
== EIGRP_NEIGHBOR_UP
) {
325 * @fn eigrp_nbr_hard_restart
327 * @param[in] nbr Neighbor who would receive hard restart
328 * @param[in] vty Virtual terminal for log output
332 * Function used for executing hard restart for neighbor:
333 * Send Hello packet with Peer Termination TLV with
334 * neighbor's address, set it's state to DOWN and delete the neighbor
336 void eigrp_nbr_hard_restart(struct eigrp_neighbor
*nbr
, struct vty
*vty
)
339 zlog_ferr(EIGRP_ERR_CONFIG
,
340 "Nbr Hard restart: Neighbor not specified.");
344 zlog_debug("Neighbor %s (%s) is down: manually cleared",
346 ifindex2ifname(nbr
->ei
->ifp
->ifindex
, VRF_DEFAULT
));
348 vty_time_print(vty
, 0);
349 vty_out(vty
, "Neighbor %s (%s) is down: manually cleared\n",
351 ifindex2ifname(nbr
->ei
->ifp
->ifindex
, VRF_DEFAULT
));
354 /* send Hello with Peer Termination TLV */
355 eigrp_hello_send(nbr
->ei
, EIGRP_HELLO_GRACEFUL_SHUTDOWN_NBR
,
357 /* set neighbor to DOWN */
358 nbr
->state
= EIGRP_NEIGHBOR_DOWN
;
359 /* delete neighbor */
360 eigrp_nbr_delete(nbr
);
363 int eigrp_nbr_split_horizon_check(struct eigrp_nexthop_entry
*ne
,
364 struct eigrp_interface
*ei
)
366 if (ne
->distance
== EIGRP_MAX_METRIC
)
369 return (ne
->ei
== ei
);