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