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