]> git.proxmox.com Git - mirror_frr.git/blame - pimd/pim_neighbor.c
pimd: Remove unnecessary alloc failures
[mirror_frr.git] / pimd / pim_neighbor.c
CommitLineData
12e41d03 1/*
896014f4
DL
2 * PIM for Quagga
3 * Copyright (C) 2008 Everton da Silva Marques
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License along
16 * with this program; see the file COPYING; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
12e41d03
DL
19
20#include <zebra.h>
21
22#include "log.h"
23#include "prefix.h"
24#include "memory.h"
744d91b3 25#include "if.h"
e446de6a
DS
26#include "vty.h"
27#include "plist.h"
12e41d03
DL
28
29#include "pimd.h"
30#include "pim_neighbor.h"
31#include "pim_time.h"
32#include "pim_str.h"
33#include "pim_iface.h"
34#include "pim_pim.h"
35#include "pim_upstream.h"
36#include "pim_ifchannel.h"
e446de6a 37#include "pim_rp.h"
da72c9fd 38#include "pim_zebra.h"
982bff89
DS
39#include "pim_join.h"
40#include "pim_jp_agg.h"
ba4eb1bc 41#include "pim_bfd.h"
12e41d03
DL
42
43static void dr_election_by_addr(struct interface *ifp)
44{
d62a17ae 45 struct pim_interface *pim_ifp;
46 struct listnode *node;
47 struct pim_neighbor *neigh;
48
49 pim_ifp = ifp->info;
50 zassert(pim_ifp);
51
52 pim_ifp->pim_dr_addr = pim_ifp->primary_address;
53
54 if (PIM_DEBUG_PIM_TRACE) {
55 zlog_debug("%s: on interface %s", __PRETTY_FUNCTION__,
56 ifp->name);
57 }
58
59 for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, node, neigh)) {
60 if (ntohl(neigh->source_addr.s_addr)
61 > ntohl(pim_ifp->pim_dr_addr.s_addr)) {
62 pim_ifp->pim_dr_addr = neigh->source_addr;
63 }
64 }
12e41d03
DL
65}
66
67static void dr_election_by_pri(struct interface *ifp)
68{
d62a17ae 69 struct pim_interface *pim_ifp;
70 struct listnode *node;
71 struct pim_neighbor *neigh;
72 uint32_t dr_pri;
73
74 pim_ifp = ifp->info;
75 zassert(pim_ifp);
76
77 pim_ifp->pim_dr_addr = pim_ifp->primary_address;
78 dr_pri = pim_ifp->pim_dr_priority;
79
80 if (PIM_DEBUG_PIM_TRACE) {
81 zlog_debug("%s: dr pri %u on interface %s", __PRETTY_FUNCTION__,
82 dr_pri, ifp->name);
83 }
84
85 for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, node, neigh)) {
86 if (PIM_DEBUG_PIM_TRACE) {
87 zlog_info("%s: neigh pri %u addr %x if dr addr %x",
88 __PRETTY_FUNCTION__, neigh->dr_priority,
89 ntohl(neigh->source_addr.s_addr),
90 ntohl(pim_ifp->pim_dr_addr.s_addr));
91 }
92 if ((neigh->dr_priority > dr_pri)
93 || ((neigh->dr_priority == dr_pri)
94 && (ntohl(neigh->source_addr.s_addr)
95 > ntohl(pim_ifp->pim_dr_addr.s_addr)))) {
96 pim_ifp->pim_dr_addr = neigh->source_addr;
97 dr_pri = neigh->dr_priority;
98 }
99 }
12e41d03
DL
100}
101
102/*
103 RFC 4601: 4.3.2. DR Election
104
105 A router's idea of the current DR on an interface can change when a
106 PIM Hello message is received, when a neighbor times out, or when a
107 router's own DR Priority changes.
108 */
dedccda6 109int pim_if_dr_election(struct interface *ifp)
12e41d03 110{
d62a17ae 111 struct pim_interface *pim_ifp = ifp->info;
112 struct in_addr old_dr_addr;
113
114 ++pim_ifp->pim_dr_election_count;
115
116 old_dr_addr = pim_ifp->pim_dr_addr;
117
118 if (pim_ifp->pim_dr_num_nondrpri_neighbors) {
119 dr_election_by_addr(ifp);
120 } else {
121 dr_election_by_pri(ifp);
122 }
123
124 /* DR changed ? */
125 if (old_dr_addr.s_addr != pim_ifp->pim_dr_addr.s_addr) {
126
127 if (PIM_DEBUG_PIM_EVENTS) {
128 char dr_old_str[INET_ADDRSTRLEN];
129 char dr_new_str[INET_ADDRSTRLEN];
130 pim_inet4_dump("<old_dr?>", old_dr_addr, dr_old_str,
131 sizeof(dr_old_str));
132 pim_inet4_dump("<new_dr?>", pim_ifp->pim_dr_addr,
133 dr_new_str, sizeof(dr_new_str));
134 zlog_debug("%s: DR was %s now is %s on interface %s",
135 __PRETTY_FUNCTION__, dr_old_str, dr_new_str,
136 ifp->name);
137 }
138
139 pim_ifp->pim_dr_election_last =
140 pim_time_monotonic_sec(); /* timestamp */
141 ++pim_ifp->pim_dr_election_changes;
142 pim_if_update_join_desired(pim_ifp);
143 pim_if_update_could_assert(ifp);
144 pim_if_update_assert_tracking_desired(ifp);
145 return 1;
146 }
147
148 return 0;
12e41d03
DL
149}
150
151static void update_dr_priority(struct pim_neighbor *neigh,
152 pim_hello_options hello_options,
153 uint32_t dr_priority)
154{
d62a17ae 155 pim_hello_options will_set_pri; /* boolean */
156 pim_hello_options bit_flip; /* boolean */
157 pim_hello_options pri_change; /* boolean */
158
159 will_set_pri =
160 PIM_OPTION_IS_SET(hello_options, PIM_OPTION_MASK_DR_PRIORITY);
161
162 bit_flip = (will_set_pri
163 != PIM_OPTION_IS_SET(neigh->hello_options,
164 PIM_OPTION_MASK_DR_PRIORITY));
165
166 if (bit_flip) {
167 struct pim_interface *pim_ifp = neigh->interface->info;
168
169 /* update num. of neighbors without dr_pri */
170
171 if (will_set_pri) {
172 --pim_ifp->pim_dr_num_nondrpri_neighbors;
173 } else {
174 ++pim_ifp->pim_dr_num_nondrpri_neighbors;
175 }
176 }
177
178 pri_change = (bit_flip || (neigh->dr_priority != dr_priority));
179
180 if (will_set_pri) {
181 neigh->dr_priority = dr_priority;
182 } else {
183 neigh->dr_priority = 0; /* cosmetic unset */
184 }
185
186 if (pri_change) {
187 /*
188 RFC 4601: 4.3.2. DR Election
189
190 A router's idea of the current DR on an interface can change
191 when a
192 PIM Hello message is received, when a neighbor times out, or
193 when a
194 router's own DR Priority changes.
195 */
196 pim_if_dr_election(
197 neigh->interface); // router's own DR Priority changes
198 }
12e41d03
DL
199}
200
201static int on_neighbor_timer(struct thread *t)
202{
d62a17ae 203 struct pim_neighbor *neigh;
204 struct interface *ifp;
205 char msg[100];
206
207 neigh = THREAD_ARG(t);
208
209 ifp = neigh->interface;
210
211 if (PIM_DEBUG_PIM_TRACE) {
212 char src_str[INET_ADDRSTRLEN];
213 pim_inet4_dump("<src?>", neigh->source_addr, src_str,
214 sizeof(src_str));
215 zlog_debug(
216 "Expired %d sec holdtime for neighbor %s on interface %s",
217 neigh->holdtime, src_str, ifp->name);
218 }
219
220 snprintf(msg, sizeof(msg), "%d-sec holdtime expired", neigh->holdtime);
221 pim_neighbor_delete(ifp, neigh, msg);
222
223 /*
224 RFC 4601: 4.3.2. DR Election
225
226 A router's idea of the current DR on an interface can change when a
227 PIM Hello message is received, when a neighbor times out, or when a
228 router's own DR Priority changes.
229 */
230 pim_if_dr_election(ifp); // neighbor times out
231
232 return 0;
12e41d03
DL
233}
234
12e41d03
DL
235void pim_neighbor_timer_reset(struct pim_neighbor *neigh, uint16_t holdtime)
236{
d62a17ae 237 neigh->holdtime = holdtime;
238
239 THREAD_OFF(neigh->t_expire_timer);
240
241 /*
242 0xFFFF is request for no holdtime
243 */
244 if (neigh->holdtime == 0xFFFF) {
245 return;
246 }
247
248 if (PIM_DEBUG_PIM_TRACE_DETAIL) {
249 char src_str[INET_ADDRSTRLEN];
250 pim_inet4_dump("<src?>", neigh->source_addr, src_str,
251 sizeof(src_str));
252 zlog_debug("%s: starting %u sec timer for neighbor %s on %s",
253 __PRETTY_FUNCTION__, neigh->holdtime, src_str,
254 neigh->interface->name);
255 }
256
257 thread_add_timer(master, on_neighbor_timer, neigh, neigh->holdtime,
258 &neigh->t_expire_timer);
12e41d03
DL
259}
260
d62a17ae 261static int on_neighbor_jp_timer(struct thread *t)
982bff89 262{
d62a17ae 263 struct pim_neighbor *neigh = THREAD_ARG(t);
264 struct pim_rpf rpf;
265
266 if (PIM_DEBUG_PIM_TRACE) {
267 char src_str[INET_ADDRSTRLEN];
268 pim_inet4_dump("<src?>", neigh->source_addr, src_str,
269 sizeof(src_str));
270 zlog_debug("%s:Sending JP Agg to %s on %s with %d groups",
271 __PRETTY_FUNCTION__, src_str, neigh->interface->name,
272 neigh->upstream_jp_agg->count);
273 }
982bff89 274
d62a17ae 275 rpf.source_nexthop.interface = neigh->interface;
276 rpf.rpf_addr.u.prefix4 = neigh->source_addr;
277 pim_joinprune_send(&rpf, neigh->upstream_jp_agg);
982bff89 278
d62a17ae 279 thread_add_timer(master, on_neighbor_jp_timer, neigh, qpim_t_periodic,
280 &neigh->jp_timer);
982bff89 281
d62a17ae 282 return 0;
982bff89
DS
283}
284
d62a17ae 285static void pim_neighbor_start_jp_timer(struct pim_neighbor *neigh)
982bff89 286{
d62a17ae 287 THREAD_TIMER_OFF(neigh->jp_timer);
288 thread_add_timer(master, on_neighbor_jp_timer, neigh, qpim_t_periodic,
289 &neigh->jp_timer);
982bff89
DS
290}
291
d62a17ae 292static struct pim_neighbor *
293pim_neighbor_new(struct interface *ifp, struct in_addr source_addr,
294 pim_hello_options hello_options, uint16_t holdtime,
295 uint16_t propagation_delay, uint16_t override_interval,
296 uint32_t dr_priority, uint32_t generation_id,
297 struct list *addr_list)
12e41d03 298{
d62a17ae 299 struct pim_interface *pim_ifp;
300 struct pim_neighbor *neigh;
301 char src_str[INET_ADDRSTRLEN];
302
303 zassert(ifp);
304 pim_ifp = ifp->info;
305 zassert(pim_ifp);
306
307 neigh = XCALLOC(MTYPE_PIM_NEIGHBOR, sizeof(*neigh));
d62a17ae 308
309 neigh->creation = pim_time_monotonic_sec();
310 neigh->source_addr = source_addr;
311 neigh->hello_options = hello_options;
312 neigh->propagation_delay_msec = propagation_delay;
313 neigh->override_interval_msec = override_interval;
314 neigh->dr_priority = dr_priority;
315 neigh->generation_id = generation_id;
316 neigh->prefix_list = addr_list;
317 neigh->t_expire_timer = NULL;
318 neigh->interface = ifp;
319
320 neigh->upstream_jp_agg = list_new();
321 neigh->upstream_jp_agg->cmp = pim_jp_agg_group_list_cmp;
322 neigh->upstream_jp_agg->del =
323 (void (*)(void *))pim_jp_agg_group_list_free;
324 pim_neighbor_start_jp_timer(neigh);
325
326 pim_neighbor_timer_reset(neigh, holdtime);
327 /*
328 * The pim_ifstat_hello_sent variable is used to decide if
329 * we should expedite a hello out the interface. If we
330 * establish a new neighbor, we unfortunately need to
331 * reset the value so that we can know to hurry up and
332 * hello
333 */
334 pim_ifp->pim_ifstat_hello_sent = 0;
335
336 pim_inet4_dump("<src?>", source_addr, src_str, sizeof(src_str));
337
338 if (PIM_DEBUG_PIM_EVENTS) {
339 zlog_debug("%s: creating PIM neighbor %s on interface %s",
340 __PRETTY_FUNCTION__, src_str, ifp->name);
341 }
342
343 zlog_info("PIM NEIGHBOR UP: neighbor %s on interface %s", src_str,
344 ifp->name);
345
346 if (neigh->propagation_delay_msec
347 > pim_ifp->pim_neighbors_highest_propagation_delay_msec) {
348 pim_ifp->pim_neighbors_highest_propagation_delay_msec =
349 neigh->propagation_delay_msec;
350 }
351 if (neigh->override_interval_msec
352 > pim_ifp->pim_neighbors_highest_override_interval_msec) {
353 pim_ifp->pim_neighbors_highest_override_interval_msec =
354 neigh->override_interval_msec;
355 }
356
357 if (!PIM_OPTION_IS_SET(neigh->hello_options,
358 PIM_OPTION_MASK_LAN_PRUNE_DELAY)) {
359 /* update num. of neighbors without hello option lan_delay */
360 ++pim_ifp->pim_number_of_nonlandelay_neighbors;
361 }
362
363 if (!PIM_OPTION_IS_SET(neigh->hello_options,
364 PIM_OPTION_MASK_DR_PRIORITY)) {
365 /* update num. of neighbors without hello option dr_pri */
366 ++pim_ifp->pim_dr_num_nondrpri_neighbors;
367 }
368
369 // Register PIM Neighbor with BFD
370 pim_bfd_trigger_event(pim_ifp, neigh, 1);
371
372 return neigh;
12e41d03
DL
373}
374
375static void delete_prefix_list(struct pim_neighbor *neigh)
376{
d62a17ae 377 if (neigh->prefix_list) {
12e41d03
DL
378
379#ifdef DUMP_PREFIX_LIST
d62a17ae 380 struct listnode *p_node;
381 struct prefix *p;
382 char addr_str[10];
383 int list_size = neigh->prefix_list
384 ? (int)listcount(neigh->prefix_list)
385 : -1;
386 int i = 0;
387 for (ALL_LIST_ELEMENTS_RO(neigh->prefix_list, p_node, p)) {
388 pim_inet4_dump("<addr?>", p->u.prefix4, addr_str,
389 sizeof(addr_str));
390 zlog_debug(
391 "%s: DUMP_PREFIX_LIST neigh=%x prefix_list=%x prefix=%x addr=%s [%d/%d]",
392 __PRETTY_FUNCTION__, (unsigned)neigh,
393 (unsigned)neigh->prefix_list, (unsigned)p,
394 addr_str, i, list_size);
395 ++i;
396 }
12e41d03
DL
397#endif
398
affe9e99 399 list_delete_and_null(&neigh->prefix_list);
d62a17ae 400 }
12e41d03
DL
401}
402
403void pim_neighbor_free(struct pim_neighbor *neigh)
404{
d62a17ae 405 zassert(!neigh->t_expire_timer);
12e41d03 406
d62a17ae 407 delete_prefix_list(neigh);
12e41d03 408
affe9e99 409 list_delete_and_null(&neigh->upstream_jp_agg);
d62a17ae 410 THREAD_OFF(neigh->jp_timer);
982bff89 411
d62a17ae 412 XFREE(MTYPE_PIM_NEIGHBOR, neigh);
12e41d03
DL
413}
414
d62a17ae 415struct pim_neighbor *pim_neighbor_find_by_secondary(struct interface *ifp,
416 struct prefix *src)
07b17d59 417{
d62a17ae 418 struct pim_interface *pim_ifp;
419 struct listnode *node, *pnode;
420 struct pim_neighbor *neigh;
421 struct prefix *p;
422
423 pim_ifp = ifp->info;
424 if (!pim_ifp)
425 return NULL;
426
427 for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, node, neigh)) {
428 for (ALL_LIST_ELEMENTS_RO(neigh->prefix_list, pnode, p)) {
429 if (prefix_same(p, src))
430 return neigh;
431 }
432 }
433
434 return NULL;
07b17d59
DS
435}
436
12e41d03
DL
437struct pim_neighbor *pim_neighbor_find(struct interface *ifp,
438 struct in_addr source_addr)
439{
d62a17ae 440 struct pim_interface *pim_ifp;
441 struct listnode *node;
442 struct pim_neighbor *neigh;
12e41d03 443
d62a17ae 444 if (!ifp)
445 return NULL;
1131c2eb 446
d62a17ae 447 pim_ifp = ifp->info;
448 if (!pim_ifp)
449 return NULL;
12e41d03 450
d62a17ae 451 for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, node, neigh)) {
452 if (source_addr.s_addr == neigh->source_addr.s_addr) {
453 return neigh;
454 }
455 }
12e41d03 456
d62a17ae 457 return NULL;
12e41d03
DL
458}
459
99deb321
DS
460/*
461 * Find the *one* interface out
462 * this interface. If more than
463 * one return NULL
464 */
d62a17ae 465struct pim_neighbor *pim_neighbor_find_if(struct interface *ifp)
99deb321 466{
d62a17ae 467 struct pim_interface *pim_ifp = ifp->info;
99deb321 468
d62a17ae 469 if (!pim_ifp || pim_ifp->pim_neighbor_list->count != 1)
470 return NULL;
99deb321 471
d62a17ae 472 return listnode_head(pim_ifp->pim_neighbor_list);
99deb321
DS
473}
474
d62a17ae 475struct pim_neighbor *
476pim_neighbor_add(struct interface *ifp, struct in_addr source_addr,
477 pim_hello_options hello_options, uint16_t holdtime,
478 uint16_t propagation_delay, uint16_t override_interval,
479 uint32_t dr_priority, uint32_t generation_id,
480 struct list *addr_list, int send_hello_now)
12e41d03 481{
d62a17ae 482 struct pim_interface *pim_ifp;
483 struct pim_neighbor *neigh;
484
485 neigh = pim_neighbor_new(ifp, source_addr, hello_options, holdtime,
486 propagation_delay, override_interval,
487 dr_priority, generation_id, addr_list);
488 if (!neigh) {
489 return 0;
490 }
12e41d03 491
d62a17ae 492 pim_ifp = ifp->info;
493 zassert(pim_ifp);
12e41d03 494
d62a17ae 495 listnode_add(pim_ifp->pim_neighbor_list, neigh);
12e41d03 496
d62a17ae 497 if (PIM_DEBUG_PIM_TRACE_DETAIL) {
498 char str[INET_ADDRSTRLEN];
499 pim_inet4_dump("<nht_nbr?>", source_addr, str, sizeof(str));
500 zlog_debug("%s: neighbor %s added ", __PRETTY_FUNCTION__, str);
501 }
502 /*
503 RFC 4601: 4.3.2. DR Election
504
505 A router's idea of the current DR on an interface can change when a
506 PIM Hello message is received, when a neighbor times out, or when a
507 router's own DR Priority changes.
508 */
509 pim_if_dr_election(neigh->interface); // new neighbor -- should not
510 // trigger dr election...
511
512 /*
513 RFC 4601: 4.3.1. Sending Hello Messages
514
515 To allow new or rebooting routers to learn of PIM neighbors quickly,
516 when a Hello message is received from a new neighbor, or a Hello
517 message with a new GenID is received from an existing neighbor, a
518 new Hello message should be sent on this interface after a
519 randomized delay between 0 and Triggered_Hello_Delay.
520
521 This is a bit silly to do it that way. If I get a new
522 genid we need to send the hello *now* because we've
523 lined up a bunch of join/prune messages to go out the
524 interface.
525 */
526 if (send_hello_now)
527 pim_hello_restart_now(ifp);
528 else
529 pim_hello_restart_triggered(neigh->interface);
530
9b29ea95 531 pim_upstream_find_new_rpf(pim_ifp->pim);
d62a17ae 532
533 /* RNH can send nexthop update prior to PIM neibhor UP
534 in that case nexthop cache would not consider this neighbor
535 as RPF.
536 Upon PIM neighbor UP, iterate all RPs and update
537 nexthop cache with this neighbor.
538 */
fec883d9 539 pim_resolve_rp_nh(pim_ifp->pim);
d62a17ae 540
fec883d9 541 pim_rp_setup(pim_ifp->pim);
d62a17ae 542
da11e325 543 sched_rpf_cache_refresh(pim_ifp->pim);
d62a17ae 544 return neigh;
12e41d03
DL
545}
546
d62a17ae 547static uint16_t find_neighbors_next_highest_propagation_delay_msec(
548 struct interface *ifp, struct pim_neighbor *highest_neigh)
12e41d03 549{
d62a17ae 550 struct pim_interface *pim_ifp;
551 struct listnode *neigh_node;
552 struct pim_neighbor *neigh;
553 uint16_t next_highest_delay_msec;
554
555 pim_ifp = ifp->info;
556 zassert(pim_ifp);
557
558 next_highest_delay_msec = pim_ifp->pim_propagation_delay_msec;
559
560 for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, neigh_node,
561 neigh)) {
562 if (neigh == highest_neigh)
563 continue;
564 if (neigh->propagation_delay_msec > next_highest_delay_msec)
565 next_highest_delay_msec = neigh->propagation_delay_msec;
566 }
12e41d03 567
d62a17ae 568 return next_highest_delay_msec;
569}
12e41d03 570
d62a17ae 571static uint16_t find_neighbors_next_highest_override_interval_msec(
572 struct interface *ifp, struct pim_neighbor *highest_neigh)
573{
574 struct pim_interface *pim_ifp;
575 struct listnode *neigh_node;
576 struct pim_neighbor *neigh;
577 uint16_t next_highest_interval_msec;
578
579 pim_ifp = ifp->info;
580 zassert(pim_ifp);
581
582 next_highest_interval_msec = pim_ifp->pim_override_interval_msec;
583
584 for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, neigh_node,
585 neigh)) {
586 if (neigh == highest_neigh)
587 continue;
588 if (neigh->override_interval_msec > next_highest_interval_msec)
589 next_highest_interval_msec =
590 neigh->override_interval_msec;
591 }
12e41d03 592
d62a17ae 593 return next_highest_interval_msec;
12e41d03
DL
594}
595
d62a17ae 596void pim_neighbor_delete(struct interface *ifp, struct pim_neighbor *neigh,
12e41d03
DL
597 const char *delete_message)
598{
d62a17ae 599 struct pim_interface *pim_ifp;
600 char src_str[INET_ADDRSTRLEN];
12e41d03 601
d62a17ae 602 pim_ifp = ifp->info;
603 zassert(pim_ifp);
12e41d03 604
d62a17ae 605 pim_inet4_dump("<src?>", neigh->source_addr, src_str, sizeof(src_str));
606 zlog_info("PIM NEIGHBOR DOWN: neighbor %s on interface %s: %s", src_str,
607 ifp->name, delete_message);
12e41d03 608
d62a17ae 609 THREAD_OFF(neigh->t_expire_timer);
12e41d03 610
d62a17ae 611 pim_if_assert_on_neighbor_down(ifp, neigh->source_addr);
12e41d03 612
d62a17ae 613 if (!PIM_OPTION_IS_SET(neigh->hello_options,
614 PIM_OPTION_MASK_LAN_PRUNE_DELAY)) {
615 /* update num. of neighbors without hello option lan_delay */
12e41d03 616
d62a17ae 617 --pim_ifp->pim_number_of_nonlandelay_neighbors;
618 }
12e41d03 619
d62a17ae 620 if (!PIM_OPTION_IS_SET(neigh->hello_options,
621 PIM_OPTION_MASK_DR_PRIORITY)) {
622 /* update num. of neighbors without dr_pri */
12e41d03 623
d62a17ae 624 --pim_ifp->pim_dr_num_nondrpri_neighbors;
625 }
12e41d03 626
d62a17ae 627 zassert(neigh->propagation_delay_msec
628 <= pim_ifp->pim_neighbors_highest_propagation_delay_msec);
629 zassert(neigh->override_interval_msec
630 <= pim_ifp->pim_neighbors_highest_override_interval_msec);
631
632 if (pim_if_lan_delay_enabled(ifp)) {
633
634 /* will delete a neighbor with highest propagation delay? */
635 if (neigh->propagation_delay_msec
636 == pim_ifp->pim_neighbors_highest_propagation_delay_msec) {
637 /* then find the next highest propagation delay */
638 pim_ifp->pim_neighbors_highest_propagation_delay_msec =
639 find_neighbors_next_highest_propagation_delay_msec(
640 ifp, neigh);
641 }
642
643 /* will delete a neighbor with highest override interval? */
644 if (neigh->override_interval_msec
645 == pim_ifp->pim_neighbors_highest_override_interval_msec) {
646 /* then find the next highest propagation delay */
647 pim_ifp->pim_neighbors_highest_override_interval_msec =
648 find_neighbors_next_highest_override_interval_msec(
649 ifp, neigh);
650 }
651 }
12e41d03 652
d62a17ae 653 if (PIM_DEBUG_PIM_TRACE) {
654 zlog_debug("%s: deleting PIM neighbor %s on interface %s",
655 __PRETTY_FUNCTION__, src_str, ifp->name);
656 }
12e41d03 657
d62a17ae 658 // De-Register PIM Neighbor with BFD
659 pim_bfd_trigger_event(pim_ifp, neigh, 0);
ba4eb1bc 660
d62a17ae 661 listnode_delete(pim_ifp->pim_neighbor_list, neigh);
12e41d03 662
d62a17ae 663 pim_neighbor_free(neigh);
da72c9fd 664
da11e325 665 sched_rpf_cache_refresh(pim_ifp->pim);
12e41d03
DL
666}
667
d62a17ae 668void pim_neighbor_delete_all(struct interface *ifp, const char *delete_message)
12e41d03 669{
d62a17ae 670 struct pim_interface *pim_ifp;
671 struct listnode *neigh_node;
672 struct listnode *neigh_nextnode;
673 struct pim_neighbor *neigh;
674
675 pim_ifp = ifp->info;
676 zassert(pim_ifp);
677
678 for (ALL_LIST_ELEMENTS(pim_ifp->pim_neighbor_list, neigh_node,
679 neigh_nextnode, neigh)) {
680 pim_neighbor_delete(ifp, neigh, delete_message);
681 }
12e41d03
DL
682}
683
684struct prefix *pim_neighbor_find_secondary(struct pim_neighbor *neigh,
07b17d59 685 struct prefix *addr)
12e41d03 686{
d62a17ae 687 struct listnode *node;
688 struct prefix *p;
12e41d03 689
d62a17ae 690 if (!neigh->prefix_list)
691 return 0;
12e41d03 692
d62a17ae 693 for (ALL_LIST_ELEMENTS_RO(neigh->prefix_list, node, p)) {
694 if (prefix_same(p, addr))
695 return p;
696 }
12e41d03 697
d62a17ae 698 return NULL;
12e41d03
DL
699}
700
701/*
702 RFC 4601: 4.3.4. Maintaining Secondary Address Lists
d62a17ae 703
12e41d03
DL
704 All the advertised secondary addresses in received Hello messages
705 must be checked against those previously advertised by all other
706 PIM neighbors on that interface. If there is a conflict and the
707 same secondary address was previously advertised by another
708 neighbor, then only the most recently received mapping MUST be
709 maintained, and an error message SHOULD be logged to the
710 administrator in a rate-limited manner.
711*/
712static void delete_from_neigh_addr(struct interface *ifp,
713 struct list *addr_list,
714 struct in_addr neigh_addr)
715{
d62a17ae 716 struct listnode *addr_node;
717 struct prefix *addr;
718 struct pim_interface *pim_ifp;
719
720 pim_ifp = ifp->info;
721 zassert(pim_ifp);
722
723 zassert(addr_list);
724
725 /*
726 Scan secondary address list
727 */
728 for (ALL_LIST_ELEMENTS_RO(addr_list, addr_node, addr)) {
729 struct listnode *neigh_node;
730 struct pim_neighbor *neigh;
731
732 if (addr->family != AF_INET)
733 continue;
734
735 /*
736 Scan neighbors
737 */
738 for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list,
739 neigh_node, neigh)) {
740 {
741 struct prefix *p = pim_neighbor_find_secondary(
742 neigh, addr);
743 if (p) {
744 char addr_str[INET_ADDRSTRLEN];
745 char this_neigh_str[INET_ADDRSTRLEN];
746 char other_neigh_str[INET_ADDRSTRLEN];
747
748 pim_inet4_dump(
749 "<addr?>", addr->u.prefix4,
750 addr_str, sizeof(addr_str));
751 pim_inet4_dump("<neigh1?>", neigh_addr,
752 this_neigh_str,
753 sizeof(this_neigh_str));
754 pim_inet4_dump("<neigh2?>",
755 neigh->source_addr,
756 other_neigh_str,
757 sizeof(other_neigh_str));
758
759 zlog_info(
760 "secondary addr %s recvd from neigh %s deleted from neigh %s on %s",
761 addr_str, this_neigh_str,
762 other_neigh_str, ifp->name);
763
764 listnode_delete(neigh->prefix_list, p);
765 prefix_free(p);
766 }
767 }
768
769 } /* scan neighbors */
770
771 } /* scan addr list */
12e41d03
DL
772}
773
774void pim_neighbor_update(struct pim_neighbor *neigh,
d62a17ae 775 pim_hello_options hello_options, uint16_t holdtime,
776 uint32_t dr_priority, struct list *addr_list)
12e41d03 777{
d62a17ae 778 struct pim_interface *pim_ifp = neigh->interface->info;
779
780 /* Received holdtime ? */
781 if (PIM_OPTION_IS_SET(hello_options, PIM_OPTION_MASK_HOLDTIME)) {
782 pim_neighbor_timer_reset(neigh, holdtime);
783 } else {
784 pim_neighbor_timer_reset(neigh,
785 PIM_IF_DEFAULT_HOLDTIME(pim_ifp));
786 }
12e41d03
DL
787
788#ifdef DUMP_PREFIX_LIST
d62a17ae 789 zlog_debug(
790 "%s: DUMP_PREFIX_LIST old_prefix_list=%x old_size=%d new_prefix_list=%x new_size=%d",
791 __PRETTY_FUNCTION__, (unsigned)neigh->prefix_list,
792 neigh->prefix_list ? (int)listcount(neigh->prefix_list) : -1,
793 (unsigned)addr_list,
794 addr_list ? (int)listcount(addr_list) : -1);
12e41d03
DL
795#endif
796
d62a17ae 797 if (neigh->prefix_list == addr_list) {
798 if (addr_list) {
799 zlog_err(
800 "%s: internal error: trying to replace same prefix list=%p",
801 __PRETTY_FUNCTION__, (void *)addr_list);
802 }
803 } else {
804 /* Delete existing secondary address list */
805 delete_prefix_list(neigh);
806 }
807
808 if (addr_list) {
809 delete_from_neigh_addr(neigh->interface, addr_list,
810 neigh->source_addr);
811 }
812
813 /* Replace secondary address list */
814 neigh->prefix_list = addr_list;
815
816 update_dr_priority(neigh, hello_options, dr_priority);
817 /*
818 Copy flags
819 */
820 neigh->hello_options = hello_options;
12e41d03 821}