]> git.proxmox.com Git - mirror_frr.git/blame - eigrpd/eigrp_neighbor.c
nhrpd: Add NHRP_ERR_XXXX for zlog_err to zlog_ferr conversion
[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"
56
d62a17ae 57struct eigrp_neighbor *eigrp_nbr_new(struct eigrp_interface *ei)
7f57883e 58{
d62a17ae 59 struct eigrp_neighbor *nbr;
7f57883e 60
d62a17ae 61 /* Allcate new neighbor. */
62 nbr = XCALLOC(MTYPE_EIGRP_NEIGHBOR, sizeof(struct eigrp_neighbor));
7f57883e 63
d62a17ae 64 /* Relate neighbor to the interface. */
65 nbr->ei = ei;
7f57883e 66
d62a17ae 67 /* Set default values. */
68 eigrp_nbr_state_set(nbr, EIGRP_NEIGHBOR_DOWN);
7f57883e 69
d62a17ae 70 return nbr;
7f57883e
DS
71}
72
73/**
74 *@fn void dissect_eigrp_sw_version (tvbuff_t *tvb, proto_tree *tree,
75 * proto_item *ti)
76 *
77 * @par
78 * Create a new neighbor structure and initalize it.
79 */
d62a17ae 80static struct eigrp_neighbor *eigrp_nbr_add(struct eigrp_interface *ei,
81 struct eigrp_header *eigrph,
82 struct ip *iph)
7f57883e 83{
d62a17ae 84 struct eigrp_neighbor *nbr;
7f57883e 85
d62a17ae 86 nbr = eigrp_nbr_new(ei);
87 nbr->src = iph->ip_src;
7f57883e 88
d62a17ae 89 // if (IS_DEBUG_EIGRP_EVENT)
90 // zlog_debug("NSM[%s:%s]: start", IF_NAME (nbr->oi),
91 // inet_ntoa (nbr->router_id));
7f57883e 92
d62a17ae 93 return nbr;
7f57883e
DS
94}
95
d62a17ae 96struct eigrp_neighbor *eigrp_nbr_get(struct eigrp_interface *ei,
97 struct eigrp_header *eigrph,
98 struct ip *iph)
7f57883e 99{
d62a17ae 100 struct eigrp_neighbor *nbr;
101 struct listnode *node, *nnode;
7f57883e 102
d62a17ae 103 for (ALL_LIST_ELEMENTS(ei->nbrs, node, nnode, nbr)) {
104 if (iph->ip_src.s_addr == nbr->src.s_addr) {
105 return nbr;
106 }
107 }
7f57883e 108
d62a17ae 109 nbr = eigrp_nbr_add(ei, eigrph, iph);
110 listnode_add(ei->nbrs, nbr);
7f57883e 111
d62a17ae 112 return nbr;
7f57883e
DS
113}
114
115/**
116 * @fn eigrp_nbr_lookup_by_addr
117 *
118 * @param[in] ei EIGRP interface
119 * @param[in] nbr_addr Address of neighbor
120 *
121 * @return void
122 *
123 * @par
124 * Function is used for neighbor lookup by address
125 * in specified interface.
126 */
d62a17ae 127struct eigrp_neighbor *eigrp_nbr_lookup_by_addr(struct eigrp_interface *ei,
128 struct in_addr *addr)
7f57883e 129{
d62a17ae 130 struct eigrp_neighbor *nbr;
131 struct listnode *node, *nnode;
132
133 for (ALL_LIST_ELEMENTS(ei->nbrs, node, nnode, nbr)) {
134 if (addr->s_addr == nbr->src.s_addr) {
135 return nbr;
136 }
137 }
138
139 return NULL;
7f57883e
DS
140}
141
142/**
143 * @fn eigrp_nbr_lookup_by_addr_process
144 *
f9e5c9ca
DS
145 * @param[in] eigrp EIGRP process
146 * @param[in] nbr_addr Address of neighbor
7f57883e
DS
147 *
148 * @return void
149 *
150 * @par
151 * Function is used for neighbor lookup by address
152 * in whole EIGRP process.
153 */
d62a17ae 154struct eigrp_neighbor *eigrp_nbr_lookup_by_addr_process(struct eigrp *eigrp,
155 struct in_addr nbr_addr)
7f57883e 156{
d62a17ae 157 struct eigrp_interface *ei;
158 struct listnode *node, *node2, *nnode2;
159 struct eigrp_neighbor *nbr;
160
161 /* iterate over all eigrp interfaces */
162 for (ALL_LIST_ELEMENTS_RO(eigrp->eiflist, node, ei)) {
163 /* iterate over all neighbors on eigrp interface */
164 for (ALL_LIST_ELEMENTS(ei->nbrs, node2, nnode2, nbr)) {
165 /* compare if neighbor address is same as arg address */
166 if (nbr->src.s_addr == nbr_addr.s_addr) {
167 return nbr;
168 }
169 }
170 }
171
172 return NULL;
7f57883e
DS
173}
174
175
176/* Delete specified EIGRP neighbor from interface. */
d62a17ae 177void eigrp_nbr_delete(struct eigrp_neighbor *nbr)
7f57883e 178{
d62a17ae 179 eigrp_nbr_state_set(nbr, EIGRP_NEIGHBOR_DOWN);
180 if (nbr->ei)
181 eigrp_topology_neighbor_down(nbr->ei->eigrp, nbr);
182
183 /* Cancel all events. */ /* Thread lookup cost would be negligible. */
184 thread_cancel_event(master, nbr);
185 eigrp_fifo_free(nbr->multicast_queue);
186 eigrp_fifo_free(nbr->retrans_queue);
187 THREAD_OFF(nbr->t_holddown);
188
189 if (nbr->ei)
190 listnode_delete(nbr->ei->nbrs, nbr);
191 XFREE(MTYPE_EIGRP_NEIGHBOR, nbr);
7f57883e
DS
192}
193
d62a17ae 194int holddown_timer_expired(struct thread *thread)
7f57883e 195{
d62a17ae 196 struct eigrp_neighbor *nbr;
7f57883e 197
d62a17ae 198 nbr = THREAD_ARG(thread);
7f57883e 199
d62a17ae 200 zlog_info("Neighbor %s (%s) is down: holding time expired",
201 inet_ntoa(nbr->src),
202 ifindex2ifname(nbr->ei->ifp->ifindex, VRF_DEFAULT));
203 nbr->state = EIGRP_NEIGHBOR_DOWN;
204 eigrp_nbr_delete(nbr);
7f57883e 205
d62a17ae 206 return 0;
7f57883e
DS
207}
208
d7c0a89a 209uint8_t eigrp_nbr_state_get(struct eigrp_neighbor *nbr)
7f57883e 210{
d62a17ae 211 return (nbr->state);
7f57883e
DS
212}
213
d7c0a89a 214void eigrp_nbr_state_set(struct eigrp_neighbor *nbr, uint8_t state)
7f57883e 215{
d62a17ae 216 nbr->state = state;
217
218 if (eigrp_nbr_state_get(nbr) == EIGRP_NEIGHBOR_DOWN) {
219 // reset all the seq/ack counters
220 nbr->recv_sequence_number = 0;
221 nbr->init_sequence_number = 0;
222 nbr->retrans_counter = 0;
223
224 // Kvalues
225 nbr->K1 = EIGRP_K1_DEFAULT;
226 nbr->K2 = EIGRP_K2_DEFAULT;
227 nbr->K3 = EIGRP_K3_DEFAULT;
228 nbr->K4 = EIGRP_K4_DEFAULT;
229 nbr->K5 = EIGRP_K5_DEFAULT;
230 nbr->K6 = EIGRP_K6_DEFAULT;
231
232 // hold time..
233 nbr->v_holddown = EIGRP_HOLD_INTERVAL_DEFAULT;
234 THREAD_OFF(nbr->t_holddown);
235
236 /* out with the old */
237 if (nbr->multicast_queue)
238 eigrp_fifo_free(nbr->multicast_queue);
239 if (nbr->retrans_queue)
240 eigrp_fifo_free(nbr->retrans_queue);
241
242 /* in with the new */
243 nbr->retrans_queue = eigrp_fifo_new();
244 nbr->multicast_queue = eigrp_fifo_new();
245
246 nbr->crypt_seqnum = 0;
247 }
7f57883e
DS
248}
249
d62a17ae 250const char *eigrp_nbr_state_str(struct eigrp_neighbor *nbr)
7f57883e 251{
d62a17ae 252 const char *state;
253 switch (nbr->state) {
254 case EIGRP_NEIGHBOR_DOWN:
255 state = "Down";
256 break;
257 case EIGRP_NEIGHBOR_PENDING:
258 state = "Waiting for Init";
259 break;
260 case EIGRP_NEIGHBOR_UP:
261 state = "Up";
262 break;
263 default:
264 state = "Unknown";
265 break;
266 }
267
268 return (state);
7f57883e
DS
269}
270
d62a17ae 271void eigrp_nbr_state_update(struct eigrp_neighbor *nbr)
7f57883e 272{
d62a17ae 273 switch (nbr->state) {
274 case EIGRP_NEIGHBOR_DOWN: {
275 /*Start Hold Down Timer for neighbor*/
276 // THREAD_OFF(nbr->t_holddown);
277 // THREAD_TIMER_ON(master, nbr->t_holddown,
278 // holddown_timer_expired,
279 // nbr, nbr->v_holddown);
280 break;
281 }
282 case EIGRP_NEIGHBOR_PENDING: {
283 /*Reset Hold Down Timer for neighbor*/
284 THREAD_OFF(nbr->t_holddown);
285 thread_add_timer(master, holddown_timer_expired, nbr,
286 nbr->v_holddown, &nbr->t_holddown);
287 break;
288 }
289 case EIGRP_NEIGHBOR_UP: {
290 /*Reset Hold Down Timer for neighbor*/
291 THREAD_OFF(nbr->t_holddown);
292 thread_add_timer(master, holddown_timer_expired, nbr,
293 nbr->v_holddown, &nbr->t_holddown);
294 break;
295 }
296 }
7f57883e
DS
297}
298
d62a17ae 299int eigrp_nbr_count_get(void)
300{
301 struct eigrp_interface *iface;
302 struct listnode *node, *node2, *nnode2;
303 struct eigrp_neighbor *nbr;
304 struct eigrp *eigrp = eigrp_lookup();
d7c0a89a 305 uint32_t counter;
d62a17ae 306
307 if (eigrp == NULL) {
308 zlog_debug("EIGRP Routing Process not enabled");
309 return 0;
310 }
311
312 counter = 0;
313 for (ALL_LIST_ELEMENTS_RO(eigrp->eiflist, node, iface)) {
314 for (ALL_LIST_ELEMENTS(iface->nbrs, node2, nnode2, nbr)) {
315 if (nbr->state == EIGRP_NEIGHBOR_UP) {
316 counter++;
317 }
318 }
319 }
320 return counter;
7f57883e
DS
321}
322
323/**
324 * @fn eigrp_nbr_hard_restart
325 *
326 * @param[in] nbr Neighbor who would receive hard restart
327 * @param[in] vty Virtual terminal for log output
328 * @return void
329 *
330 * @par
331 * Function used for executing hard restart for neighbor:
332 * Send Hello packet with Peer Termination TLV with
333 * neighbor's address, set it's state to DOWN and delete the neighbor
334 */
335void eigrp_nbr_hard_restart(struct eigrp_neighbor *nbr, struct vty *vty)
336{
d62a17ae 337 if (nbr == NULL) {
338 zlog_err("Nbr Hard restart: Neighbor not specified.");
339 return;
340 }
341
342 zlog_debug("Neighbor %s (%s) is down: manually cleared",
343 inet_ntoa(nbr->src),
344 ifindex2ifname(nbr->ei->ifp->ifindex, VRF_DEFAULT));
345 if (vty != NULL) {
346 vty_time_print(vty, 0);
347 vty_out(vty, "Neighbor %s (%s) is down: manually cleared\n",
348 inet_ntoa(nbr->src),
349 ifindex2ifname(nbr->ei->ifp->ifindex, VRF_DEFAULT));
350 }
351
352 /* send Hello with Peer Termination TLV */
353 eigrp_hello_send(nbr->ei, EIGRP_HELLO_GRACEFUL_SHUTDOWN_NBR,
354 &(nbr->src));
355 /* set neighbor to DOWN */
356 nbr->state = EIGRP_NEIGHBOR_DOWN;
357 /* delete neighbor */
358 eigrp_nbr_delete(nbr);
7f57883e 359}
cd044247 360
996c9314
LB
361int eigrp_nbr_split_horizon_check(struct eigrp_nexthop_entry *ne,
362 struct eigrp_interface *ei)
cd044247
DS
363{
364 if (ne->distance == EIGRP_MAX_METRIC)
365 return 0;
366
367 return (ne->ei == ei);
368}