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