]> git.proxmox.com Git - mirror_frr.git/blame - eigrpd/eigrp_neighbor.c
zebra: Allow ns delete to happen after under/over flow checks
[mirror_frr.git] / eigrpd / eigrp_neighbor.c
CommitLineData
7f57883e
DS
1/*
2 * EIGRP Neighbor Handling.
3 * Copyright (C) 2013-2016
4 * Authors:
5 * Donnie Savage
6 * Jan Janovic
7 * Matej Perina
8 * Peter Orsag
9 * Peter Paluch
10 * Frantisek Gazo
11 * Tomas Hvorkovy
12 * Martin Kontsek
13 * Lukas Koribsky
14 *
15 * This file is part of GNU Zebra.
16 *
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
20 * later version.
21 *
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.
26 *
896014f4
DL
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
7f57883e
DS
30 */
31
32#include <zebra.h>
33
34#include "linklist.h"
35#include "prefix.h"
36#include "memory.h"
37#include "command.h"
38#include "thread.h"
39#include "stream.h"
40#include "table.h"
41#include "log.h"
42#include "keychain.h"
43#include "vty.h"
44
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"
8b0a80f1 56#include "eigrpd/eigrp_errors.h"
7f57883e 57
d62a17ae 58struct eigrp_neighbor *eigrp_nbr_new(struct eigrp_interface *ei)
7f57883e 59{
d62a17ae 60 struct eigrp_neighbor *nbr;
7f57883e 61
d62a17ae 62 /* Allcate new neighbor. */
63 nbr = XCALLOC(MTYPE_EIGRP_NEIGHBOR, sizeof(struct eigrp_neighbor));
7f57883e 64
d62a17ae 65 /* Relate neighbor to the interface. */
66 nbr->ei = ei;
7f57883e 67
d62a17ae 68 /* Set default values. */
69 eigrp_nbr_state_set(nbr, EIGRP_NEIGHBOR_DOWN);
7f57883e 70
d62a17ae 71 return nbr;
7f57883e
DS
72}
73
74/**
75 *@fn void dissect_eigrp_sw_version (tvbuff_t *tvb, proto_tree *tree,
76 * proto_item *ti)
77 *
78 * @par
79 * Create a new neighbor structure and initalize it.
80 */
d62a17ae 81static struct eigrp_neighbor *eigrp_nbr_add(struct eigrp_interface *ei,
82 struct eigrp_header *eigrph,
83 struct ip *iph)
7f57883e 84{
d62a17ae 85 struct eigrp_neighbor *nbr;
7f57883e 86
d62a17ae 87 nbr = eigrp_nbr_new(ei);
88 nbr->src = iph->ip_src;
7f57883e 89
d62a17ae 90 // if (IS_DEBUG_EIGRP_EVENT)
91 // zlog_debug("NSM[%s:%s]: start", IF_NAME (nbr->oi),
92 // inet_ntoa (nbr->router_id));
7f57883e 93
d62a17ae 94 return nbr;
7f57883e
DS
95}
96
d62a17ae 97struct eigrp_neighbor *eigrp_nbr_get(struct eigrp_interface *ei,
98 struct eigrp_header *eigrph,
99 struct ip *iph)
7f57883e 100{
d62a17ae 101 struct eigrp_neighbor *nbr;
102 struct listnode *node, *nnode;
7f57883e 103
d62a17ae 104 for (ALL_LIST_ELEMENTS(ei->nbrs, node, nnode, nbr)) {
105 if (iph->ip_src.s_addr == nbr->src.s_addr) {
106 return nbr;
107 }
108 }
7f57883e 109
d62a17ae 110 nbr = eigrp_nbr_add(ei, eigrph, iph);
111 listnode_add(ei->nbrs, nbr);
7f57883e 112
d62a17ae 113 return nbr;
7f57883e
DS
114}
115
116/**
117 * @fn eigrp_nbr_lookup_by_addr
118 *
119 * @param[in] ei EIGRP interface
120 * @param[in] nbr_addr Address of neighbor
121 *
122 * @return void
123 *
124 * @par
125 * Function is used for neighbor lookup by address
126 * in specified interface.
127 */
d62a17ae 128struct eigrp_neighbor *eigrp_nbr_lookup_by_addr(struct eigrp_interface *ei,
129 struct in_addr *addr)
7f57883e 130{
d62a17ae 131 struct eigrp_neighbor *nbr;
132 struct listnode *node, *nnode;
133
134 for (ALL_LIST_ELEMENTS(ei->nbrs, node, nnode, nbr)) {
135 if (addr->s_addr == nbr->src.s_addr) {
136 return nbr;
137 }
138 }
139
140 return NULL;
7f57883e
DS
141}
142
143/**
144 * @fn eigrp_nbr_lookup_by_addr_process
145 *
f9e5c9ca
DS
146 * @param[in] eigrp EIGRP process
147 * @param[in] nbr_addr Address of neighbor
7f57883e
DS
148 *
149 * @return void
150 *
151 * @par
152 * Function is used for neighbor lookup by address
153 * in whole EIGRP process.
154 */
d62a17ae 155struct eigrp_neighbor *eigrp_nbr_lookup_by_addr_process(struct eigrp *eigrp,
156 struct in_addr nbr_addr)
7f57883e 157{
d62a17ae 158 struct eigrp_interface *ei;
159 struct listnode *node, *node2, *nnode2;
160 struct eigrp_neighbor *nbr;
161
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) {
168 return nbr;
169 }
170 }
171 }
172
173 return NULL;
7f57883e
DS
174}
175
176
177/* Delete specified EIGRP neighbor from interface. */
d62a17ae 178void eigrp_nbr_delete(struct eigrp_neighbor *nbr)
7f57883e 179{
d62a17ae 180 eigrp_nbr_state_set(nbr, EIGRP_NEIGHBOR_DOWN);
181 if (nbr->ei)
182 eigrp_topology_neighbor_down(nbr->ei->eigrp, nbr);
183
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);
189
190 if (nbr->ei)
191 listnode_delete(nbr->ei->nbrs, nbr);
192 XFREE(MTYPE_EIGRP_NEIGHBOR, nbr);
7f57883e
DS
193}
194
d62a17ae 195int holddown_timer_expired(struct thread *thread)
7f57883e 196{
d62a17ae 197 struct eigrp_neighbor *nbr;
7f57883e 198
d62a17ae 199 nbr = THREAD_ARG(thread);
7f57883e 200
d62a17ae 201 zlog_info("Neighbor %s (%s) is down: holding time expired",
202 inet_ntoa(nbr->src),
203 ifindex2ifname(nbr->ei->ifp->ifindex, VRF_DEFAULT));
204 nbr->state = EIGRP_NEIGHBOR_DOWN;
205 eigrp_nbr_delete(nbr);
7f57883e 206
d62a17ae 207 return 0;
7f57883e
DS
208}
209
d7c0a89a 210uint8_t eigrp_nbr_state_get(struct eigrp_neighbor *nbr)
7f57883e 211{
d62a17ae 212 return (nbr->state);
7f57883e
DS
213}
214
d7c0a89a 215void eigrp_nbr_state_set(struct eigrp_neighbor *nbr, uint8_t state)
7f57883e 216{
d62a17ae 217 nbr->state = state;
218
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;
224
225 // Kvalues
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;
232
233 // hold time..
234 nbr->v_holddown = EIGRP_HOLD_INTERVAL_DEFAULT;
235 THREAD_OFF(nbr->t_holddown);
236
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);
242
243 /* in with the new */
244 nbr->retrans_queue = eigrp_fifo_new();
245 nbr->multicast_queue = eigrp_fifo_new();
246
247 nbr->crypt_seqnum = 0;
248 }
7f57883e
DS
249}
250
d62a17ae 251const char *eigrp_nbr_state_str(struct eigrp_neighbor *nbr)
7f57883e 252{
d62a17ae 253 const char *state;
254 switch (nbr->state) {
255 case EIGRP_NEIGHBOR_DOWN:
256 state = "Down";
257 break;
258 case EIGRP_NEIGHBOR_PENDING:
259 state = "Waiting for Init";
260 break;
261 case EIGRP_NEIGHBOR_UP:
262 state = "Up";
263 break;
264 default:
265 state = "Unknown";
266 break;
267 }
268
269 return (state);
7f57883e
DS
270}
271
d62a17ae 272void eigrp_nbr_state_update(struct eigrp_neighbor *nbr)
7f57883e 273{
d62a17ae 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);
281 break;
282 }
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);
288 break;
289 }
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);
295 break;
296 }
297 }
7f57883e
DS
298}
299
d62a17ae 300int eigrp_nbr_count_get(void)
301{
302 struct eigrp_interface *iface;
303 struct listnode *node, *node2, *nnode2;
304 struct eigrp_neighbor *nbr;
305 struct eigrp *eigrp = eigrp_lookup();
d7c0a89a 306 uint32_t counter;
d62a17ae 307
308 if (eigrp == NULL) {
309 zlog_debug("EIGRP Routing Process not enabled");
310 return 0;
311 }
312
313 counter = 0;
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) {
317 counter++;
318 }
319 }
320 }
321 return counter;
7f57883e
DS
322}
323
324/**
325 * @fn eigrp_nbr_hard_restart
326 *
327 * @param[in] nbr Neighbor who would receive hard restart
328 * @param[in] vty Virtual terminal for log output
329 * @return void
330 *
331 * @par
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
335 */
336void eigrp_nbr_hard_restart(struct eigrp_neighbor *nbr, struct vty *vty)
337{
d62a17ae 338 if (nbr == NULL) {
f0132ab5 339 flog_err(EC_EIGRP_CONFIG,
1c50c1c0 340 "Nbr Hard restart: Neighbor not specified.");
d62a17ae 341 return;
342 }
343
344 zlog_debug("Neighbor %s (%s) is down: manually cleared",
345 inet_ntoa(nbr->src),
346 ifindex2ifname(nbr->ei->ifp->ifindex, VRF_DEFAULT));
347 if (vty != NULL) {
348 vty_time_print(vty, 0);
349 vty_out(vty, "Neighbor %s (%s) is down: manually cleared\n",
350 inet_ntoa(nbr->src),
351 ifindex2ifname(nbr->ei->ifp->ifindex, VRF_DEFAULT));
352 }
353
354 /* send Hello with Peer Termination TLV */
355 eigrp_hello_send(nbr->ei, EIGRP_HELLO_GRACEFUL_SHUTDOWN_NBR,
356 &(nbr->src));
357 /* set neighbor to DOWN */
358 nbr->state = EIGRP_NEIGHBOR_DOWN;
359 /* delete neighbor */
360 eigrp_nbr_delete(nbr);
7f57883e 361}
cd044247 362
996c9314
LB
363int eigrp_nbr_split_horizon_check(struct eigrp_nexthop_entry *ne,
364 struct eigrp_interface *ei)
cd044247
DS
365{
366 if (ne->distance == EIGRP_MAX_METRIC)
367 return 0;
368
369 return (ne->ei == ei);
370}