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