]> git.proxmox.com Git - mirror_frr.git/blob - eigrpd/eigrp_neighbor.c
Merge remote-tracking branch 'origin/master' into EIGRP
[mirror_frr.git] / eigrpd / eigrp_neighbor.c
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 *
27 * You should have received a copy of the GNU General Public License
28 * along with GNU Zebra; see the file COPYING. If not, write to the Free
29 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
30 * 02111-1307, USA.
31 */
32
33 #include <zebra.h>
34
35 #include "linklist.h"
36 #include "prefix.h"
37 #include "memory.h"
38 #include "command.h"
39 #include "thread.h"
40 #include "stream.h"
41 #include "table.h"
42 #include "log.h"
43 #include "keychain.h"
44 #include "vty.h"
45
46 #include "eigrpd/eigrp_structs.h"
47 #include "eigrpd/eigrpd.h"
48 #include "eigrpd/eigrp_interface.h"
49 #include "eigrpd/eigrp_neighbor.h"
50 #include "eigrpd/eigrp_dump.h"
51 #include "eigrpd/eigrp_packet.h"
52 #include "eigrpd/eigrp_zebra.h"
53 #include "eigrpd/eigrp_vty.h"
54 #include "eigrpd/eigrp_network.h"
55 #include "eigrpd/eigrp_topology.h"
56 #include "eigrpd/eigrp_memory.h"
57
58 struct eigrp_neighbor *
59 eigrp_nbr_new (struct eigrp_interface *ei)
60 {
61 struct eigrp_neighbor *nbr;
62
63 /* Allcate new neighbor. */
64 nbr = XCALLOC (MTYPE_EIGRP_NEIGHBOR, sizeof (struct eigrp_neighbor));
65
66 /* Relate neighbor to the interface. */
67 nbr->ei = ei;
68
69 /* Set default values. */
70 eigrp_nbr_state_set (nbr, EIGRP_NEIGHBOR_DOWN);
71
72 return nbr;
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 */
82 static struct eigrp_neighbor *
83 eigrp_nbr_add (struct eigrp_interface *ei, struct eigrp_header *eigrph,
84 struct ip *iph)
85 {
86 struct eigrp_neighbor *nbr;
87
88 nbr = eigrp_nbr_new (ei);
89 nbr->src = iph->ip_src;
90
91 // if (IS_DEBUG_EIGRP_EVENT)
92 // zlog_debug("NSM[%s:%s]: start", IF_NAME (nbr->oi),
93 // inet_ntoa (nbr->router_id));
94
95 return nbr;
96 }
97
98 struct eigrp_neighbor *
99 eigrp_nbr_get (struct eigrp_interface *ei, struct eigrp_header *eigrph,
100 struct ip *iph)
101 {
102 struct eigrp_neighbor *nbr;
103 struct listnode *node, *nnode;
104
105 for (ALL_LIST_ELEMENTS (ei->nbrs, node, nnode, nbr))
106 {
107 if (iph->ip_src.s_addr == nbr->src.s_addr)
108 {
109 return nbr;
110 }
111 }
112
113 nbr = eigrp_nbr_add (ei, eigrph, iph);
114 listnode_add (ei->nbrs, nbr);
115
116 return nbr;
117 }
118
119 /**
120 * @fn eigrp_nbr_lookup_by_addr
121 *
122 * @param[in] ei EIGRP interface
123 * @param[in] nbr_addr Address of neighbor
124 *
125 * @return void
126 *
127 * @par
128 * Function is used for neighbor lookup by address
129 * in specified interface.
130 */
131 struct eigrp_neighbor *
132 eigrp_nbr_lookup_by_addr (struct eigrp_interface *ei, struct in_addr *addr)
133 {
134 struct eigrp_neighbor *nbr;
135 struct listnode *node, *nnode;
136
137 for (ALL_LIST_ELEMENTS (ei->nbrs, node, nnode, nbr))
138 {
139 if (addr->s_addr == nbr->src.s_addr)
140 {
141 return nbr;
142 }
143 }
144
145 return NULL;
146 }
147
148 /**
149 * @fn eigrp_nbr_lookup_by_addr_process
150 *
151 * @param[in] eigrp EIGRP process
152 * @param[in] nbr_addr Address of neighbor
153 *
154 * @return void
155 *
156 * @par
157 * Function is used for neighbor lookup by address
158 * in whole EIGRP process.
159 */
160 struct eigrp_neighbor *
161 eigrp_nbr_lookup_by_addr_process (struct eigrp *eigrp, struct in_addr nbr_addr)
162 {
163 struct eigrp_interface *ei;
164 struct listnode *node, *node2, *nnode2;
165 struct eigrp_neighbor *nbr;
166
167 /* iterate over all eigrp interfaces */
168 for (ALL_LIST_ELEMENTS_RO (eigrp->eiflist, node, ei))
169 {
170 /* iterate over all neighbors on eigrp interface */
171 for (ALL_LIST_ELEMENTS (ei->nbrs, node2, nnode2, nbr))
172 {
173 /* compare if neighbor address is same as arg address */
174 if (nbr->src.s_addr == nbr_addr.s_addr)
175 {
176 return nbr;
177 }
178 }
179 }
180
181 return NULL;
182 }
183
184
185 /* Delete specified EIGRP neighbor from interface. */
186 void
187 eigrp_nbr_delete (struct eigrp_neighbor *nbr)
188 {
189 eigrp_nbr_state_set(nbr, EIGRP_NEIGHBOR_DOWN);
190 eigrp_topology_neighbor_down(nbr->ei->eigrp, nbr);
191
192 /* Cancel all events. *//* Thread lookup cost would be negligible. */
193 thread_cancel_event (master, nbr);
194 eigrp_fifo_free (nbr->multicast_queue);
195 eigrp_fifo_free (nbr->retrans_queue);
196 THREAD_OFF (nbr->t_holddown);
197
198 listnode_delete (nbr->ei->nbrs,nbr);
199 XFREE (MTYPE_EIGRP_NEIGHBOR, nbr);
200 }
201
202 int
203 holddown_timer_expired (struct thread *thread)
204 {
205 struct eigrp_neighbor *nbr;
206
207 nbr = THREAD_ARG (thread);
208
209 zlog_info ("Neighbor %s (%s) is down: holding time expired",
210 inet_ntoa(nbr->src), ifindex2ifname(nbr->ei->ifp->ifindex, VRF_DEFAULT));
211 nbr->state = EIGRP_NEIGHBOR_DOWN;
212 eigrp_nbr_delete (nbr);
213
214 return 0;
215 }
216
217 u_char
218 eigrp_nbr_state_get (struct eigrp_neighbor *nbr)
219 {
220 return(nbr->state);
221 }
222
223 void
224 eigrp_nbr_state_set (struct eigrp_neighbor *nbr, u_char state)
225 {
226 nbr->state = state;
227
228 if (eigrp_nbr_state_get(nbr) == EIGRP_NEIGHBOR_DOWN)
229 {
230 // reset all the seq/ack counters
231 nbr->recv_sequence_number = 0;
232 nbr->init_sequence_number = 0;
233 nbr->retrans_counter = 0;
234
235 // Kvalues
236 nbr->K1 = EIGRP_K1_DEFAULT;
237 nbr->K2 = EIGRP_K2_DEFAULT;
238 nbr->K3 = EIGRP_K3_DEFAULT;
239 nbr->K4 = EIGRP_K4_DEFAULT;
240 nbr->K5 = EIGRP_K5_DEFAULT;
241 nbr->K6 = EIGRP_K6_DEFAULT;
242
243 // hold time..
244 nbr->v_holddown = EIGRP_HOLD_INTERVAL_DEFAULT;
245 THREAD_OFF(nbr->t_holddown);
246
247 /* out with the old */
248 if (nbr->multicast_queue)
249 eigrp_fifo_free (nbr->multicast_queue);
250 if (nbr->retrans_queue)
251 eigrp_fifo_free (nbr->retrans_queue);
252
253 /* in with the new */
254 nbr->retrans_queue = eigrp_fifo_new ();
255 nbr->multicast_queue = eigrp_fifo_new ();
256
257 nbr->crypt_seqnum = 0;
258 }
259 }
260
261 const char *
262 eigrp_nbr_state_str (struct eigrp_neighbor *nbr)
263 {
264 const char *state;
265 switch (nbr->state)
266 {
267 case EIGRP_NEIGHBOR_DOWN:
268 state = "Down";
269 break;
270 case EIGRP_NEIGHBOR_PENDING:
271 state = "Waiting for Init";
272 break;
273 case EIGRP_NEIGHBOR_UP:
274 state = "Up";
275 break;
276 default:
277 state = "Unknown";
278 break;
279 }
280
281 return(state);
282 }
283
284 void
285 eigrp_nbr_state_update (struct eigrp_neighbor *nbr)
286 {
287 switch (nbr->state)
288 {
289 case EIGRP_NEIGHBOR_DOWN:
290 {
291 /*Start Hold Down Timer for neighbor*/
292 // THREAD_OFF(nbr->t_holddown);
293 // THREAD_TIMER_ON(master, nbr->t_holddown, holddown_timer_expired,
294 // nbr, nbr->v_holddown);
295 break;
296 }
297 case EIGRP_NEIGHBOR_PENDING:
298 {
299 /*Reset Hold Down Timer for neighbor*/
300 THREAD_OFF(nbr->t_holddown);
301 THREAD_TIMER_ON(master, nbr->t_holddown, holddown_timer_expired, nbr,
302 nbr->v_holddown);
303 break;
304 }
305 case EIGRP_NEIGHBOR_UP:
306 {
307 /*Reset Hold Down Timer for neighbor*/
308 THREAD_OFF(nbr->t_holddown);
309 THREAD_TIMER_ON(master, nbr->t_holddown, holddown_timer_expired, nbr,
310 nbr->v_holddown);
311 break;
312 }
313 }
314 }
315
316 int eigrp_nbr_count_get(void){
317 struct eigrp_interface *iface;
318 struct listnode *node, *node2, *nnode2;
319 struct eigrp_neighbor *nbr;
320 struct eigrp *eigrp = eigrp_lookup();
321 u_int32_t counter;
322
323 if (eigrp == NULL)
324 {
325 zlog_debug("EIGRP Routing Process not enabled");
326 return 0;
327 }
328
329 counter=0;
330 for (ALL_LIST_ELEMENTS_RO(eigrp->eiflist, node, iface))
331 {
332 for (ALL_LIST_ELEMENTS(iface->nbrs, node2, nnode2, nbr))
333 {
334 if (nbr->state == EIGRP_NEIGHBOR_UP){
335 counter++;
336 }
337 }
338 }
339 return counter;
340 }
341
342 /**
343 * @fn eigrp_nbr_hard_restart
344 *
345 * @param[in] nbr Neighbor who would receive hard restart
346 * @param[in] vty Virtual terminal for log output
347 * @return void
348 *
349 * @par
350 * Function used for executing hard restart for neighbor:
351 * Send Hello packet with Peer Termination TLV with
352 * neighbor's address, set it's state to DOWN and delete the neighbor
353 */
354 void eigrp_nbr_hard_restart(struct eigrp_neighbor *nbr, struct vty *vty)
355 {
356 if(nbr == NULL)
357 {
358 zlog_err("Nbr Hard restart: Neighbor not specified.");
359 return;
360 }
361
362 zlog_debug ("Neighbor %s (%s) is down: manually cleared",
363 inet_ntoa (nbr->src),
364 ifindex2ifname (nbr->ei->ifp->ifindex, VRF_DEFAULT));
365 if(vty != NULL)
366 {
367 vty_time_print (vty, 0);
368 vty_out (vty, "Neighbor %s (%s) is down: manually cleared%s",
369 inet_ntoa (nbr->src),
370 ifindex2ifname (nbr->ei->ifp->ifindex, VRF_DEFAULT),
371 VTY_NEWLINE);
372 }
373
374 /* send Hello with Peer Termination TLV */
375 eigrp_hello_send(nbr->ei, EIGRP_HELLO_GRACEFUL_SHUTDOWN_NBR, &(nbr->src));
376 /* set neighbor to DOWN */
377 nbr->state = EIGRP_NEIGHBOR_DOWN;
378 /* delete neighbor */
379 eigrp_nbr_delete (nbr);
380 }