]> git.proxmox.com Git - mirror_frr.git/blob - eigrpd/eigrp_interface.c
eigrpd: When deleting interface remove connected routes from topo table
[mirror_frr.git] / eigrpd / eigrp_interface.c
1 /*
2 * EIGRP Interface Functions.
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 "thread.h"
36 #include "linklist.h"
37 #include "prefix.h"
38 #include "if.h"
39 #include "table.h"
40 #include "memory.h"
41 #include "command.h"
42 #include "stream.h"
43 #include "log.h"
44 #include "keychain.h"
45 #include "vrf.h"
46
47 #include "eigrpd/eigrp_structs.h"
48 #include "eigrpd/eigrpd.h"
49 #include "eigrpd/eigrp_interface.h"
50 #include "eigrpd/eigrp_neighbor.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 static void
59 eigrp_delete_from_if (struct interface *, struct eigrp_interface *);
60
61 static void
62 eigrp_add_to_if (struct interface *ifp, struct eigrp_interface *ei)
63 {
64 struct route_node *rn;
65 struct prefix p;
66
67 p = *ei->address;
68 p.prefixlen = IPV4_MAX_PREFIXLEN;
69
70 rn = route_node_get (IF_OIFS (ifp), &p);
71 /* rn->info should either be NULL or equal to this ei
72 * as route_node_get may return an existing node
73 */
74 assert (!rn->info || rn->info == ei);
75 rn->info = ei;
76 }
77
78 struct eigrp_interface *
79 eigrp_if_new (struct eigrp *eigrp, struct interface *ifp, struct prefix *p)
80 {
81 struct eigrp_interface *ei;
82 int i;
83
84 if ((ei = eigrp_if_table_lookup (ifp, p)) == NULL)
85 {
86 ei = XCALLOC (MTYPE_EIGRP_IF, sizeof (struct eigrp_interface));
87 memset (ei, 0, sizeof (struct eigrp_interface));
88 }
89 else
90 return ei;
91
92 /* Set zebra interface pointer. */
93 ei->ifp = ifp;
94 ei->address = p;
95
96 eigrp_add_to_if (ifp, ei);
97 listnode_add (eigrp->eiflist, ei);
98
99 ei->type = EIGRP_IFTYPE_BROADCAST;
100
101 /* Initialize neighbor list. */
102 ei->nbrs = list_new ();
103
104 ei->crypt_seqnum = time (NULL);
105
106 /* Initialize lists */
107 for (i = 0; i < EIGRP_FILTER_MAX; i++)
108 {
109 ei->list[i] = NULL;
110 ei->prefix[i] = NULL;
111 ei->routemap[i] = NULL;
112 }
113
114 return ei;
115 }
116
117 /* lookup ei for specified prefix/ifp */
118 struct eigrp_interface *
119 eigrp_if_table_lookup (struct interface *ifp, struct prefix *prefix)
120 {
121 struct prefix p;
122 struct route_node *rn;
123 struct eigrp_interface *rninfo = NULL;
124
125 p = *prefix;
126 p.prefixlen = IPV4_MAX_PREFIXLEN;
127
128 /* route_node_get implicitly locks */
129 if ((rn = route_node_lookup (IF_OIFS (ifp), &p)))
130 {
131 rninfo = (struct eigrp_interface *) rn->info;
132 route_unlock_node (rn);
133 }
134
135 return rninfo;
136 }
137
138 int
139 eigrp_if_delete_hook (struct interface *ifp)
140 {
141
142 struct route_node *rn;
143
144 route_table_finish (IF_OIFS (ifp));
145
146 for (rn = route_top (IF_OIFS_PARAMS (ifp)); rn; rn = route_next (rn))
147 if (rn->info)
148 eigrp_del_if_params (rn->info);
149 route_table_finish (IF_OIFS_PARAMS (ifp));
150
151 XFREE (MTYPE_EIGRP_IF_INFO, ifp->info);
152 ifp->info = NULL;
153
154 return 0;
155 }
156
157 struct list *eigrp_iflist;
158
159 void
160 eigrp_if_init ()
161 {
162 /* Initialize Zebra interface data structure. */
163 if_add_hook (IF_NEW_HOOK, eigrp_if_new_hook);
164 if_add_hook (IF_DELETE_HOOK, eigrp_if_delete_hook);
165 }
166
167 int
168 eigrp_if_new_hook (struct interface *ifp)
169 {
170 int rc = 0;
171
172 ifp->info = XCALLOC (MTYPE_EIGRP_IF_INFO, sizeof (struct eigrp_if_info));
173
174 IF_OIFS (ifp) = route_table_init ();
175 IF_OIFS_PARAMS (ifp) = route_table_init ();
176
177 IF_DEF_PARAMS (ifp) = eigrp_new_if_params ();
178
179 SET_IF_PARAM (IF_DEF_PARAMS (ifp), v_hello);
180 IF_DEF_PARAMS (ifp)->v_hello = (u_int32_t) EIGRP_HELLO_INTERVAL_DEFAULT;
181
182 SET_IF_PARAM (IF_DEF_PARAMS (ifp), v_wait);
183 IF_DEF_PARAMS (ifp)->v_wait = (u_int16_t) EIGRP_HOLD_INTERVAL_DEFAULT;
184
185 SET_IF_PARAM (IF_DEF_PARAMS (ifp), bandwidth);
186 IF_DEF_PARAMS (ifp)->bandwidth = (u_int32_t) EIGRP_BANDWIDTH_DEFAULT;
187
188 SET_IF_PARAM (IF_DEF_PARAMS (ifp), delay);
189 IF_DEF_PARAMS (ifp)->delay = (u_int32_t) EIGRP_DELAY_DEFAULT;
190
191 SET_IF_PARAM (IF_DEF_PARAMS (ifp), reliability);
192 IF_DEF_PARAMS (ifp)->reliability = (u_char) EIGRP_RELIABILITY_DEFAULT;
193
194 SET_IF_PARAM (IF_DEF_PARAMS (ifp), load);
195 IF_DEF_PARAMS (ifp)->load = (u_char) EIGRP_LOAD_DEFAULT;
196
197 SET_IF_PARAM (IF_DEF_PARAMS (ifp), auth_type);
198 IF_DEF_PARAMS (ifp)->auth_type = EIGRP_AUTH_TYPE_NONE;
199
200 SET_IF_PARAM (IF_DEF_PARAMS (ifp), auth_keychain);
201 IF_DEF_PARAMS (ifp)->auth_keychain= NULL;
202
203 return rc;
204 }
205
206 struct eigrp_if_params *
207 eigrp_new_if_params (void)
208 {
209 struct eigrp_if_params *eip;
210
211 eip = XCALLOC (MTYPE_EIGRP_IF_PARAMS, sizeof (struct eigrp_if_params));
212 if (!eip)
213 return NULL;
214
215 UNSET_IF_PARAM (eip, passive_interface);
216 UNSET_IF_PARAM (eip, v_hello);
217 UNSET_IF_PARAM (eip, v_wait);
218 UNSET_IF_PARAM (eip, bandwidth);
219 UNSET_IF_PARAM (eip, delay);
220 UNSET_IF_PARAM (eip, reliability);
221 UNSET_IF_PARAM (eip, load);
222 UNSET_IF_PARAM (eip, auth_keychain);
223 UNSET_IF_PARAM (eip, auth_type);
224
225
226 return eip;
227 }
228
229 void
230 eigrp_del_if_params (struct eigrp_if_params *eip)
231 {
232 if(eip->auth_keychain)
233 free(eip->auth_keychain);
234
235 XFREE (MTYPE_EIGRP_IF_PARAMS, eip);
236 }
237
238 struct eigrp_if_params *
239 eigrp_lookup_if_params (struct interface *ifp, struct in_addr addr)
240 {
241 struct prefix_ipv4 p;
242 struct route_node *rn;
243
244 p.family = AF_INET;
245 p.prefixlen = IPV4_MAX_PREFIXLEN;
246 p.prefix = addr;
247
248 rn = route_node_lookup (IF_OIFS_PARAMS (ifp), (struct prefix*) &p);
249
250 if (rn)
251 {
252 route_unlock_node (rn);
253 return rn->info;
254 }
255
256 return NULL;
257 }
258
259 int
260 eigrp_if_up (struct eigrp_interface *ei)
261 {
262 struct eigrp_prefix_entry *pe;
263 struct eigrp_neighbor_entry *ne;
264 struct eigrp_metrics metric;
265 struct eigrp_interface *ei2;
266 struct listnode *node, *nnode;
267 struct eigrp *eigrp = eigrp_lookup ();
268
269 if (ei == NULL)
270 return 0;
271
272 if (eigrp != NULL)
273 eigrp_adjust_sndbuflen (eigrp, ei->ifp->mtu);
274 else
275 zlog_warn ("%s: eigrp_lookup () returned NULL", __func__);
276 eigrp_if_stream_set (ei);
277
278 /* Set multicast memberships appropriately for new state. */
279 eigrp_if_set_multicast (ei);
280
281 thread_add_event (master, eigrp_hello_timer, ei, (1));
282
283 /*Prepare metrics*/
284 metric.bandwith = eigrp_bandwidth_to_scaled (EIGRP_IF_PARAM (ei,bandwidth));
285 metric.delay = eigrp_delay_to_scaled (EIGRP_IF_PARAM (ei,delay));
286 metric.load = EIGRP_IF_PARAM (ei,load);
287 metric.reliability = EIGRP_IF_PARAM (ei,reliability);
288 metric.mtu[0] = 0xDC;
289 metric.mtu[1] = 0x05;
290 metric.mtu[2] = 0x00;
291 metric.hop_count = 0;
292 metric.flags = 0;
293 metric.tag = 0;
294
295 /*Add connected entry to topology table*/
296
297 struct prefix_ipv4 *dest_addr = prefix_ipv4_new ();
298
299 dest_addr->family = AF_INET;
300 dest_addr->prefix = ei->connected->address->u.prefix4;
301 dest_addr->prefixlen = ei->connected->address->prefixlen;
302 apply_mask_ipv4 (dest_addr);
303 pe = eigrp_topology_table_lookup_ipv4 (eigrp->topology_table, dest_addr);
304
305 if (pe == NULL)
306 {
307 pe = eigrp_prefix_entry_new ();
308 pe->serno = eigrp->serno;
309 pe->destination_ipv4 = dest_addr;
310 pe->af = AF_INET;
311 pe->nt = EIGRP_TOPOLOGY_TYPE_CONNECTED;
312
313 pe->state = EIGRP_FSM_STATE_PASSIVE;
314 pe->fdistance = eigrp_calculate_metrics (eigrp, &metric);
315 pe->req_action |= EIGRP_FSM_NEED_UPDATE;
316 eigrp_prefix_entry_add (eigrp->topology_table, pe);
317 listnode_add(eigrp->topology_changes_internalIPV4, pe);
318 }
319 ne = eigrp_neighbor_entry_new ();
320 ne->ei = ei;
321 ne->reported_metric = metric;
322 ne->total_metric = metric;
323 ne->distance = eigrp_calculate_metrics (eigrp, &metric);
324 ne->reported_distance = 0;
325 ne->prefix = pe;
326 ne->adv_router = eigrp->neighbor_self;
327 ne->flags = EIGRP_NEIGHBOR_ENTRY_SUCCESSOR_FLAG;
328 eigrp_neighbor_entry_add (pe, ne);
329
330 for (ALL_LIST_ELEMENTS (eigrp->eiflist, node, nnode, ei2))
331 {
332 if (ei2->nbrs->count != 0)
333 {
334 eigrp_update_send (ei2);
335 }
336 }
337
338 pe->req_action &= ~EIGRP_FSM_NEED_UPDATE;
339 listnode_delete(eigrp->topology_changes_internalIPV4, pe);
340
341 return 1;
342 }
343
344 int
345 eigrp_if_down (struct eigrp_interface *ei)
346 {
347 struct listnode *node, *nnode;
348 struct eigrp_neighbor *nbr;
349
350 if (ei == NULL)
351 return 0;
352
353 /* Shutdown packet reception and sending */
354 if(ei->t_hello)
355 THREAD_OFF (ei->t_hello);
356
357 eigrp_if_stream_unset (ei);
358
359 /*Set infinite metrics to routes learned by this interface and start query process*/
360 for (ALL_LIST_ELEMENTS (ei->nbrs, node, nnode, nbr))
361 {
362 eigrp_nbr_delete(nbr);
363 }
364
365 return 1;
366 }
367
368 void
369 eigrp_if_stream_set (struct eigrp_interface *ei)
370 {
371 /* set output fifo queue. */
372 if (ei->obuf == NULL)
373 ei->obuf = eigrp_fifo_new ();
374 }
375
376 void
377 eigrp_if_stream_unset (struct eigrp_interface *ei)
378 {
379 struct eigrp *eigrp = ei->eigrp;
380
381 if (ei->obuf)
382 {
383 eigrp_fifo_free (ei->obuf);
384 ei->obuf = NULL;
385
386 if (ei->on_write_q)
387 {
388 listnode_delete (eigrp->oi_write_q, ei);
389 if (list_isempty (eigrp->oi_write_q))
390 thread_cancel (eigrp->t_write);
391 ei->on_write_q = 0;
392 }
393 }
394 }
395
396 void
397 eigrp_if_set_multicast (struct eigrp_interface *ei)
398 {
399 if ((EIGRP_IF_PASSIVE_STATUS (ei) == EIGRP_IF_ACTIVE))
400 {
401 /* The interface should belong to the EIGRP-all-routers group. */
402 if (!EI_MEMBER_CHECK (ei, MEMBER_ALLROUTERS)
403 && (eigrp_if_add_allspfrouters (ei->eigrp, ei->address,
404 ei->ifp->ifindex) >= 0))
405 /* Set the flag only if the system call to join succeeded. */
406 EI_MEMBER_JOINED (ei, MEMBER_ALLROUTERS);
407 }
408 else
409 {
410 /* The interface should NOT belong to the EIGRP-all-routers group. */
411 if (EI_MEMBER_CHECK (ei, MEMBER_ALLROUTERS))
412 {
413 /* Only actually drop if this is the last reference */
414 if (EI_MEMBER_COUNT (ei, MEMBER_ALLROUTERS) == 1)
415 eigrp_if_drop_allspfrouters (ei->eigrp, ei->address,
416 ei->ifp->ifindex);
417 /* Unset the flag regardless of whether the system call to leave
418 the group succeeded, since it's much safer to assume that
419 we are not a member. */
420 EI_MEMBER_LEFT (ei, MEMBER_ALLROUTERS);
421 }
422 }
423 }
424
425 u_char
426 eigrp_default_iftype (struct interface *ifp)
427 {
428 if (if_is_pointopoint (ifp))
429 return EIGRP_IFTYPE_POINTOPOINT;
430 else if (if_is_loopback (ifp))
431 return EIGRP_IFTYPE_LOOPBACK;
432 else
433 return EIGRP_IFTYPE_BROADCAST;
434 }
435
436 void
437 eigrp_if_free (struct eigrp_interface *ei, int source)
438 {
439 struct prefix_ipv4 dest_addr;
440 struct eigrp_prefix_entry *pe;
441 struct eigrp *eigrp = eigrp_lookup ();
442
443 if (source == INTERFACE_DOWN_BY_VTY)
444 {
445 THREAD_OFF (ei->t_hello);
446 eigrp_hello_send(ei,EIGRP_HELLO_GRACEFUL_SHUTDOWN, NULL);
447 }
448
449 dest_addr.family = AF_INET;
450 dest_addr.prefix = ei->connected->address->u.prefix4;
451 dest_addr.prefixlen = ei->connected->address->prefixlen;
452 apply_mask_ipv4(&dest_addr);
453 pe = eigrp_topology_table_lookup_ipv4 (eigrp->topology_table, &dest_addr);
454 if (pe)
455 eigrp_prefix_entry_delete (eigrp->topology_table, pe);
456
457 eigrp_if_down (ei);
458
459 list_delete (ei->nbrs);
460 eigrp_delete_from_if (ei->ifp, ei);
461 listnode_delete (ei->eigrp->eiflist, ei);
462
463 thread_cancel_event (master, ei);
464
465 memset (ei, 0, sizeof (*ei));
466 XFREE (MTYPE_EIGRP_IF, ei);
467 }
468
469 static void
470 eigrp_delete_from_if (struct interface *ifp, struct eigrp_interface *ei)
471 {
472 struct route_node *rn;
473 struct prefix p;
474
475 p = *ei->address;
476 p.prefixlen = IPV4_MAX_PREFIXLEN;
477
478 rn = route_node_lookup (IF_OIFS (ei->ifp), &p);
479 assert (rn);
480 assert (rn->info);
481 rn->info = NULL;
482 route_unlock_node (rn);
483 route_unlock_node (rn);
484 }
485
486 /* Simulate down/up on the interface. This is needed, for example, when
487 the MTU changes. */
488 void
489 eigrp_if_reset (struct interface *ifp)
490 {
491 struct route_node *rn;
492
493 for (rn = route_top (IF_OIFS (ifp)); rn; rn = route_next (rn))
494 {
495 struct eigrp_interface *ei;
496
497 if ((ei = rn->info) == NULL)
498 continue;
499
500 eigrp_if_down (ei);
501 eigrp_if_up (ei);
502 }
503 }
504
505 struct eigrp_interface *
506 eigrp_if_lookup_by_local_addr (struct eigrp *eigrp, struct interface *ifp,
507 struct in_addr address)
508 {
509 struct listnode *node;
510 struct eigrp_interface *ei;
511
512 for (ALL_LIST_ELEMENTS_RO (eigrp->eiflist, node, ei))
513 {
514 if (ifp && ei->ifp != ifp)
515 continue;
516
517 if (IPV4_ADDR_SAME (&address, &ei->address->u.prefix4))
518 return ei;
519 }
520
521 return NULL;
522 }
523
524 /**
525 * @fn eigrp_if_lookup_by_name
526 *
527 * @param[in] eigrp EIGRP process
528 * @param[in] if_name Name of the interface
529 *
530 * @return struct eigrp_interface *
531 *
532 * @par
533 * Function is used for lookup interface by name.
534 */
535 struct eigrp_interface *
536 eigrp_if_lookup_by_name (struct eigrp *eigrp, const char *if_name)
537 {
538 struct eigrp_interface *ei;
539 struct listnode *node;
540
541 /* iterate over all eigrp interfaces */
542 for (ALL_LIST_ELEMENTS_RO (eigrp->eiflist, node, ei))
543 {
544 /* compare int name with eigrp interface's name */
545 if(strcmp(ei->ifp->name, if_name) == 0)
546 {
547 return ei;
548 }
549 }
550
551 return NULL;
552 }
553
554 /* determine receiving interface by ifp and source address */
555 struct eigrp_interface *
556 eigrp_if_lookup_recv_if (struct eigrp *eigrp, struct in_addr src,
557 struct interface *ifp)
558 {
559 struct route_node *rn;
560 struct prefix_ipv4 addr;
561 struct eigrp_interface *ei, *match;
562
563 addr.family = AF_INET;
564 addr.prefix = src;
565 addr.prefixlen = IPV4_MAX_BITLEN;
566
567 match = NULL;
568
569 for (rn = route_top (IF_OIFS (ifp)); rn; rn = route_next (rn))
570 {
571 ei = rn->info;
572
573 if (!ei) /* oi can be NULL for PtP aliases */
574 continue;
575
576 if (if_is_loopback (ei->ifp))
577 continue;
578
579 if (prefix_match (CONNECTED_PREFIX (ei->connected),
580 (struct prefix *) &addr))
581 {
582 if ((match == NULL)
583 || (match->address->prefixlen < ei->address->prefixlen))
584 match = ei;
585 }
586 }
587
588 return match;
589 }
590
591 u_int32_t
592 eigrp_bandwidth_to_scaled (u_int32_t bandwidth)
593 {
594 u_int64_t temp_bandwidth = (256ull * 10000000) / bandwidth;
595
596 temp_bandwidth =
597 temp_bandwidth < EIGRP_MAX_METRIC ? temp_bandwidth : EIGRP_MAX_METRIC;
598
599 return (u_int32_t) temp_bandwidth;
600
601 }
602
603 u_int32_t
604 eigrp_scaled_to_bandwidth (u_int32_t scaled)
605 {
606 u_int64_t temp_scaled = scaled * (256ull * 10000000);
607
608 temp_scaled =
609 temp_scaled < EIGRP_MAX_METRIC ? temp_scaled : EIGRP_MAX_METRIC;
610
611 return (u_int32_t) temp_scaled;
612 }
613
614 u_int32_t
615 eigrp_delay_to_scaled (u_int32_t delay)
616 {
617 return delay * 256;
618 }
619
620 u_int32_t
621 eigrp_scaled_to_delay (u_int32_t scaled)
622 {
623 return scaled / 256;
624 }