3 * Copyright (C) 2008 Everton da Silva Marques
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.
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.
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
28 #include "lib_errors.h"
31 #include "pim_neighbor.h"
34 #include "pim_iface.h"
36 #include "pim_upstream.h"
37 #include "pim_ifchannel.h"
39 #include "pim_zebra.h"
41 #include "pim_jp_agg.h"
43 #include "pim_register.h"
45 static void dr_election_by_addr(struct interface
*ifp
)
47 struct pim_interface
*pim_ifp
;
48 struct listnode
*node
;
49 struct pim_neighbor
*neigh
;
54 pim_ifp
->pim_dr_addr
= pim_ifp
->primary_address
;
56 if (PIM_DEBUG_PIM_TRACE
) {
57 zlog_debug("%s: on interface %s", __func__
, ifp
->name
);
60 for (ALL_LIST_ELEMENTS_RO(pim_ifp
->pim_neighbor_list
, node
, neigh
)) {
61 if (ntohl(neigh
->source_addr
.s_addr
)
62 > ntohl(pim_ifp
->pim_dr_addr
.s_addr
)) {
63 pim_ifp
->pim_dr_addr
= neigh
->source_addr
;
68 static void dr_election_by_pri(struct interface
*ifp
)
70 struct pim_interface
*pim_ifp
;
71 struct listnode
*node
;
72 struct pim_neighbor
*neigh
;
78 pim_ifp
->pim_dr_addr
= pim_ifp
->primary_address
;
79 dr_pri
= pim_ifp
->pim_dr_priority
;
81 if (PIM_DEBUG_PIM_TRACE
) {
82 zlog_debug("%s: dr pri %u on interface %s", __func__
, dr_pri
,
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 __func__
, neigh
->dr_priority
,
90 ntohl(neigh
->source_addr
.s_addr
),
91 ntohl(pim_ifp
->pim_dr_addr
.s_addr
));
93 if ((neigh
->dr_priority
> dr_pri
)
94 || ((neigh
->dr_priority
== dr_pri
)
95 && (ntohl(neigh
->source_addr
.s_addr
)
96 > ntohl(pim_ifp
->pim_dr_addr
.s_addr
)))) {
97 pim_ifp
->pim_dr_addr
= neigh
->source_addr
;
98 dr_pri
= neigh
->dr_priority
;
104 RFC 4601: 4.3.2. DR Election
106 A router's idea of the current DR on an interface can change when a
107 PIM Hello message is received, when a neighbor times out, or when a
108 router's own DR Priority changes.
110 int pim_if_dr_election(struct interface
*ifp
)
112 struct pim_interface
*pim_ifp
= ifp
->info
;
113 struct in_addr old_dr_addr
;
115 ++pim_ifp
->pim_dr_election_count
;
117 old_dr_addr
= pim_ifp
->pim_dr_addr
;
119 if (pim_ifp
->pim_dr_num_nondrpri_neighbors
) {
120 dr_election_by_addr(ifp
);
122 dr_election_by_pri(ifp
);
126 if (old_dr_addr
.s_addr
!= pim_ifp
->pim_dr_addr
.s_addr
) {
128 if (PIM_DEBUG_PIM_EVENTS
) {
129 char dr_old_str
[INET_ADDRSTRLEN
];
130 char dr_new_str
[INET_ADDRSTRLEN
];
131 pim_inet4_dump("<old_dr?>", old_dr_addr
, dr_old_str
,
133 pim_inet4_dump("<new_dr?>", pim_ifp
->pim_dr_addr
,
134 dr_new_str
, sizeof(dr_new_str
));
135 zlog_debug("%s: DR was %s now is %s on interface %s",
136 __func__
, dr_old_str
, dr_new_str
, ifp
->name
);
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
);
146 if (PIM_I_am_DR(pim_ifp
))
147 pim_ifp
->am_i_dr
= true;
149 if (pim_ifp
->am_i_dr
== true) {
150 pim_reg_del_on_couldreg_fail(ifp
);
151 pim_ifp
->am_i_dr
= false;
161 static void update_dr_priority(struct pim_neighbor
*neigh
,
162 pim_hello_options hello_options
,
163 uint32_t dr_priority
)
165 pim_hello_options will_set_pri
; /* boolean */
166 pim_hello_options bit_flip
; /* boolean */
167 pim_hello_options pri_change
; /* boolean */
170 PIM_OPTION_IS_SET(hello_options
, PIM_OPTION_MASK_DR_PRIORITY
);
172 bit_flip
= (will_set_pri
173 != PIM_OPTION_IS_SET(neigh
->hello_options
,
174 PIM_OPTION_MASK_DR_PRIORITY
));
177 struct pim_interface
*pim_ifp
= neigh
->interface
->info
;
179 /* update num. of neighbors without dr_pri */
182 --pim_ifp
->pim_dr_num_nondrpri_neighbors
;
184 ++pim_ifp
->pim_dr_num_nondrpri_neighbors
;
188 pri_change
= (bit_flip
|| (neigh
->dr_priority
!= dr_priority
));
191 neigh
->dr_priority
= dr_priority
;
193 neigh
->dr_priority
= 0; /* cosmetic unset */
198 RFC 4601: 4.3.2. DR Election
200 A router's idea of the current DR on an interface can change
202 PIM Hello message is received, when a neighbor times out, or
204 router's own DR Priority changes.
207 neigh
->interface
); // router's own DR Priority changes
211 static int on_neighbor_timer(struct thread
*t
)
213 struct pim_neighbor
*neigh
;
214 struct interface
*ifp
;
217 neigh
= THREAD_ARG(t
);
219 ifp
= neigh
->interface
;
221 if (PIM_DEBUG_PIM_TRACE
) {
222 char src_str
[INET_ADDRSTRLEN
];
223 pim_inet4_dump("<src?>", neigh
->source_addr
, src_str
,
226 "Expired %d sec holdtime for neighbor %s on interface %s",
227 neigh
->holdtime
, src_str
, ifp
->name
);
230 snprintf(msg
, sizeof(msg
), "%d-sec holdtime expired", neigh
->holdtime
);
231 pim_neighbor_delete(ifp
, neigh
, msg
);
234 RFC 4601: 4.3.2. DR Election
236 A router's idea of the current DR on an interface can change when a
237 PIM Hello message is received, when a neighbor times out, or when a
238 router's own DR Priority changes.
240 pim_if_dr_election(ifp
); // neighbor times out
245 void pim_neighbor_timer_reset(struct pim_neighbor
*neigh
, uint16_t holdtime
)
247 neigh
->holdtime
= holdtime
;
249 THREAD_OFF(neigh
->t_expire_timer
);
252 0xFFFF is request for no holdtime
254 if (neigh
->holdtime
== 0xFFFF) {
258 if (PIM_DEBUG_PIM_TRACE_DETAIL
) {
259 char src_str
[INET_ADDRSTRLEN
];
260 pim_inet4_dump("<src?>", neigh
->source_addr
, src_str
,
262 zlog_debug("%s: starting %u sec timer for neighbor %s on %s",
263 __func__
, neigh
->holdtime
, src_str
,
264 neigh
->interface
->name
);
267 thread_add_timer(router
->master
, on_neighbor_timer
, neigh
,
268 neigh
->holdtime
, &neigh
->t_expire_timer
);
271 static int on_neighbor_jp_timer(struct thread
*t
)
273 struct pim_neighbor
*neigh
= THREAD_ARG(t
);
276 if (PIM_DEBUG_PIM_TRACE
) {
277 char src_str
[INET_ADDRSTRLEN
];
278 pim_inet4_dump("<src?>", neigh
->source_addr
, src_str
,
280 zlog_debug("%s:Sending JP Agg to %s on %s with %d groups",
281 __func__
, src_str
, neigh
->interface
->name
,
282 neigh
->upstream_jp_agg
->count
);
285 rpf
.source_nexthop
.interface
= neigh
->interface
;
286 rpf
.rpf_addr
.u
.prefix4
= neigh
->source_addr
;
287 pim_joinprune_send(&rpf
, neigh
->upstream_jp_agg
);
289 thread_add_timer(router
->master
, on_neighbor_jp_timer
, neigh
,
290 router
->t_periodic
, &neigh
->jp_timer
);
295 static void pim_neighbor_start_jp_timer(struct pim_neighbor
*neigh
)
297 THREAD_OFF(neigh
->jp_timer
);
298 thread_add_timer(router
->master
, on_neighbor_jp_timer
, neigh
,
299 router
->t_periodic
, &neigh
->jp_timer
);
302 static struct pim_neighbor
*
303 pim_neighbor_new(struct interface
*ifp
, struct in_addr source_addr
,
304 pim_hello_options hello_options
, uint16_t holdtime
,
305 uint16_t propagation_delay
, uint16_t override_interval
,
306 uint32_t dr_priority
, uint32_t generation_id
,
307 struct list
*addr_list
)
309 struct pim_interface
*pim_ifp
;
310 struct pim_neighbor
*neigh
;
311 char src_str
[INET_ADDRSTRLEN
];
317 neigh
= XCALLOC(MTYPE_PIM_NEIGHBOR
, sizeof(*neigh
));
319 neigh
->creation
= pim_time_monotonic_sec();
320 neigh
->source_addr
= source_addr
;
321 neigh
->hello_options
= hello_options
;
322 neigh
->propagation_delay_msec
= propagation_delay
;
323 neigh
->override_interval_msec
= override_interval
;
324 neigh
->dr_priority
= dr_priority
;
325 neigh
->generation_id
= generation_id
;
326 neigh
->prefix_list
= addr_list
;
327 neigh
->t_expire_timer
= NULL
;
328 neigh
->interface
= ifp
;
330 neigh
->upstream_jp_agg
= list_new();
331 neigh
->upstream_jp_agg
->cmp
= pim_jp_agg_group_list_cmp
;
332 neigh
->upstream_jp_agg
->del
=
333 (void (*)(void *))pim_jp_agg_group_list_free
;
334 pim_neighbor_start_jp_timer(neigh
);
336 pim_neighbor_timer_reset(neigh
, holdtime
);
338 * The pim_ifstat_hello_sent variable is used to decide if
339 * we should expedite a hello out the interface. If we
340 * establish a new neighbor, we unfortunately need to
341 * reset the value so that we can know to hurry up and
344 PIM_IF_FLAG_UNSET_HELLO_SENT(pim_ifp
->flags
);
346 pim_inet4_dump("<src?>", source_addr
, src_str
, sizeof(src_str
));
348 if (PIM_DEBUG_PIM_EVENTS
) {
349 zlog_debug("%s: creating PIM neighbor %s on interface %s",
350 __func__
, src_str
, ifp
->name
);
353 zlog_notice("PIM NEIGHBOR UP: neighbor %s on interface %s", src_str
,
356 if (neigh
->propagation_delay_msec
357 > pim_ifp
->pim_neighbors_highest_propagation_delay_msec
) {
358 pim_ifp
->pim_neighbors_highest_propagation_delay_msec
=
359 neigh
->propagation_delay_msec
;
361 if (neigh
->override_interval_msec
362 > pim_ifp
->pim_neighbors_highest_override_interval_msec
) {
363 pim_ifp
->pim_neighbors_highest_override_interval_msec
=
364 neigh
->override_interval_msec
;
367 if (!PIM_OPTION_IS_SET(neigh
->hello_options
,
368 PIM_OPTION_MASK_LAN_PRUNE_DELAY
)) {
369 /* update num. of neighbors without hello option lan_delay */
370 ++pim_ifp
->pim_number_of_nonlandelay_neighbors
;
373 if (!PIM_OPTION_IS_SET(neigh
->hello_options
,
374 PIM_OPTION_MASK_DR_PRIORITY
)) {
375 /* update num. of neighbors without hello option dr_pri */
376 ++pim_ifp
->pim_dr_num_nondrpri_neighbors
;
379 // Register PIM Neighbor with BFD
380 pim_bfd_info_nbr_create(pim_ifp
, neigh
);
385 static void delete_prefix_list(struct pim_neighbor
*neigh
)
387 if (neigh
->prefix_list
) {
389 #ifdef DUMP_PREFIX_LIST
390 struct listnode
*p_node
;
393 int list_size
= neigh
->prefix_list
394 ? (int)listcount(neigh
->prefix_list
)
397 for (ALL_LIST_ELEMENTS_RO(neigh
->prefix_list
, p_node
, p
)) {
398 pim_inet4_dump("<addr?>", p
->u
.prefix4
, addr_str
,
401 "%s: DUMP_PREFIX_LIST neigh=%x prefix_list=%x prefix=%x addr=%s [%d/%d]",
402 __func__
, (unsigned)neigh
,
403 (unsigned)neigh
->prefix_list
, (unsigned)p
,
404 addr_str
, i
, list_size
);
409 list_delete(&neigh
->prefix_list
);
413 void pim_neighbor_free(struct pim_neighbor
*neigh
)
415 assert(!neigh
->t_expire_timer
);
417 delete_prefix_list(neigh
);
419 list_delete(&neigh
->upstream_jp_agg
);
420 THREAD_OFF(neigh
->jp_timer
);
422 bfd_sess_free(&neigh
->bfd_session
);
424 XFREE(MTYPE_PIM_NEIGHBOR
, neigh
);
427 struct pim_neighbor
*pim_neighbor_find_by_secondary(struct interface
*ifp
,
430 struct pim_interface
*pim_ifp
;
431 struct listnode
*node
, *pnode
;
432 struct pim_neighbor
*neigh
;
435 if (!ifp
|| !ifp
->info
)
440 for (ALL_LIST_ELEMENTS_RO(pim_ifp
->pim_neighbor_list
, node
, neigh
)) {
441 for (ALL_LIST_ELEMENTS_RO(neigh
->prefix_list
, pnode
, p
)) {
442 if (prefix_same(p
, src
))
450 struct pim_neighbor
*pim_neighbor_find(struct interface
*ifp
,
451 struct in_addr source_addr
)
453 struct pim_interface
*pim_ifp
;
454 struct listnode
*node
;
455 struct pim_neighbor
*neigh
;
464 for (ALL_LIST_ELEMENTS_RO(pim_ifp
->pim_neighbor_list
, node
, neigh
)) {
465 if (source_addr
.s_addr
== neigh
->source_addr
.s_addr
) {
474 * Find the *one* interface out
475 * this interface. If more than
478 struct pim_neighbor
*pim_neighbor_find_if(struct interface
*ifp
)
480 struct pim_interface
*pim_ifp
= ifp
->info
;
482 if (!pim_ifp
|| pim_ifp
->pim_neighbor_list
->count
!= 1)
485 return listnode_head(pim_ifp
->pim_neighbor_list
);
488 struct pim_neighbor
*
489 pim_neighbor_add(struct interface
*ifp
, struct in_addr source_addr
,
490 pim_hello_options hello_options
, uint16_t holdtime
,
491 uint16_t propagation_delay
, uint16_t override_interval
,
492 uint32_t dr_priority
, uint32_t generation_id
,
493 struct list
*addr_list
, int send_hello_now
)
495 struct pim_interface
*pim_ifp
;
496 struct pim_neighbor
*neigh
;
498 neigh
= pim_neighbor_new(ifp
, source_addr
, hello_options
, holdtime
,
499 propagation_delay
, override_interval
,
500 dr_priority
, generation_id
, addr_list
);
508 listnode_add(pim_ifp
->pim_neighbor_list
, neigh
);
510 if (PIM_DEBUG_PIM_TRACE_DETAIL
) {
511 char str
[INET_ADDRSTRLEN
];
512 pim_inet4_dump("<nht_nbr?>", source_addr
, str
, sizeof(str
));
513 zlog_debug("%s: neighbor %s added ", __func__
, str
);
516 RFC 4601: 4.3.2. DR Election
518 A router's idea of the current DR on an interface can change when a
519 PIM Hello message is received, when a neighbor times out, or when a
520 router's own DR Priority changes.
522 pim_if_dr_election(neigh
->interface
); // new neighbor -- should not
523 // trigger dr election...
526 RFC 4601: 4.3.1. Sending Hello Messages
528 To allow new or rebooting routers to learn of PIM neighbors quickly,
529 when a Hello message is received from a new neighbor, or a Hello
530 message with a new GenID is received from an existing neighbor, a
531 new Hello message should be sent on this interface after a
532 randomized delay between 0 and Triggered_Hello_Delay.
534 This is a bit silly to do it that way. If I get a new
535 genid we need to send the hello *now* because we've
536 lined up a bunch of join/prune messages to go out the
540 pim_hello_restart_now(ifp
);
542 pim_hello_restart_triggered(neigh
->interface
);
544 pim_upstream_find_new_rpf(pim_ifp
->pim
);
546 /* RNH can send nexthop update prior to PIM neibhor UP
547 in that case nexthop cache would not consider this neighbor
549 Upon PIM neighbor UP, iterate all RPs and update
550 nexthop cache with this neighbor.
552 pim_resolve_rp_nh(pim_ifp
->pim
, neigh
);
554 pim_rp_setup(pim_ifp
->pim
);
556 sched_rpf_cache_refresh(pim_ifp
->pim
);
560 static uint16_t find_neighbors_next_highest_propagation_delay_msec(
561 struct interface
*ifp
, struct pim_neighbor
*highest_neigh
)
563 struct pim_interface
*pim_ifp
;
564 struct listnode
*neigh_node
;
565 struct pim_neighbor
*neigh
;
566 uint16_t next_highest_delay_msec
;
571 next_highest_delay_msec
= pim_ifp
->pim_propagation_delay_msec
;
573 for (ALL_LIST_ELEMENTS_RO(pim_ifp
->pim_neighbor_list
, neigh_node
,
575 if (neigh
== highest_neigh
)
577 if (neigh
->propagation_delay_msec
> next_highest_delay_msec
)
578 next_highest_delay_msec
= neigh
->propagation_delay_msec
;
581 return next_highest_delay_msec
;
584 static uint16_t find_neighbors_next_highest_override_interval_msec(
585 struct interface
*ifp
, struct pim_neighbor
*highest_neigh
)
587 struct pim_interface
*pim_ifp
;
588 struct listnode
*neigh_node
;
589 struct pim_neighbor
*neigh
;
590 uint16_t next_highest_interval_msec
;
595 next_highest_interval_msec
= pim_ifp
->pim_override_interval_msec
;
597 for (ALL_LIST_ELEMENTS_RO(pim_ifp
->pim_neighbor_list
, neigh_node
,
599 if (neigh
== highest_neigh
)
601 if (neigh
->override_interval_msec
> next_highest_interval_msec
)
602 next_highest_interval_msec
=
603 neigh
->override_interval_msec
;
606 return next_highest_interval_msec
;
609 void pim_neighbor_delete(struct interface
*ifp
, struct pim_neighbor
*neigh
,
610 const char *delete_message
)
612 struct pim_interface
*pim_ifp
;
613 char src_str
[INET_ADDRSTRLEN
];
618 pim_inet4_dump("<src?>", neigh
->source_addr
, src_str
, sizeof(src_str
));
619 zlog_notice("PIM NEIGHBOR DOWN: neighbor %s on interface %s: %s",
620 src_str
, ifp
->name
, delete_message
);
622 THREAD_OFF(neigh
->t_expire_timer
);
624 pim_if_assert_on_neighbor_down(ifp
, neigh
->source_addr
);
626 if (!PIM_OPTION_IS_SET(neigh
->hello_options
,
627 PIM_OPTION_MASK_LAN_PRUNE_DELAY
)) {
628 /* update num. of neighbors without hello option lan_delay */
630 --pim_ifp
->pim_number_of_nonlandelay_neighbors
;
633 if (!PIM_OPTION_IS_SET(neigh
->hello_options
,
634 PIM_OPTION_MASK_DR_PRIORITY
)) {
635 /* update num. of neighbors without dr_pri */
637 --pim_ifp
->pim_dr_num_nondrpri_neighbors
;
640 assert(neigh
->propagation_delay_msec
641 <= pim_ifp
->pim_neighbors_highest_propagation_delay_msec
);
642 assert(neigh
->override_interval_msec
643 <= pim_ifp
->pim_neighbors_highest_override_interval_msec
);
645 if (pim_if_lan_delay_enabled(ifp
)) {
647 /* will delete a neighbor with highest propagation delay? */
648 if (neigh
->propagation_delay_msec
649 == pim_ifp
->pim_neighbors_highest_propagation_delay_msec
) {
650 /* then find the next highest propagation delay */
651 pim_ifp
->pim_neighbors_highest_propagation_delay_msec
=
652 find_neighbors_next_highest_propagation_delay_msec(
656 /* will delete a neighbor with highest override interval? */
657 if (neigh
->override_interval_msec
658 == pim_ifp
->pim_neighbors_highest_override_interval_msec
) {
659 /* then find the next highest propagation delay */
660 pim_ifp
->pim_neighbors_highest_override_interval_msec
=
661 find_neighbors_next_highest_override_interval_msec(
666 if (PIM_DEBUG_PIM_TRACE
) {
667 zlog_debug("%s: deleting PIM neighbor %s on interface %s",
668 __func__
, src_str
, ifp
->name
);
671 listnode_delete(pim_ifp
->pim_neighbor_list
, neigh
);
673 pim_neighbor_free(neigh
);
675 sched_rpf_cache_refresh(pim_ifp
->pim
);
678 void pim_neighbor_delete_all(struct interface
*ifp
, const char *delete_message
)
680 struct pim_interface
*pim_ifp
;
681 struct listnode
*neigh_node
;
682 struct listnode
*neigh_nextnode
;
683 struct pim_neighbor
*neigh
;
688 for (ALL_LIST_ELEMENTS(pim_ifp
->pim_neighbor_list
, neigh_node
,
689 neigh_nextnode
, neigh
)) {
690 pim_neighbor_delete(ifp
, neigh
, delete_message
);
694 struct prefix
*pim_neighbor_find_secondary(struct pim_neighbor
*neigh
,
697 struct listnode
*node
;
700 if (!neigh
->prefix_list
)
703 for (ALL_LIST_ELEMENTS_RO(neigh
->prefix_list
, node
, p
)) {
704 if (prefix_same(p
, addr
))
712 RFC 4601: 4.3.4. Maintaining Secondary Address Lists
714 All the advertised secondary addresses in received Hello messages
715 must be checked against those previously advertised by all other
716 PIM neighbors on that interface. If there is a conflict and the
717 same secondary address was previously advertised by another
718 neighbor, then only the most recently received mapping MUST be
719 maintained, and an error message SHOULD be logged to the
720 administrator in a rate-limited manner.
722 static void delete_from_neigh_addr(struct interface
*ifp
,
723 struct list
*addr_list
,
724 struct in_addr neigh_addr
)
726 struct listnode
*addr_node
;
728 struct pim_interface
*pim_ifp
;
736 Scan secondary address list
738 for (ALL_LIST_ELEMENTS_RO(addr_list
, addr_node
, addr
)) {
739 struct listnode
*neigh_node
;
740 struct pim_neighbor
*neigh
;
742 if (addr
->family
!= AF_INET
)
748 for (ALL_LIST_ELEMENTS_RO(pim_ifp
->pim_neighbor_list
,
749 neigh_node
, neigh
)) {
751 struct prefix
*p
= pim_neighbor_find_secondary(
754 char addr_str
[INET_ADDRSTRLEN
];
755 char this_neigh_str
[INET_ADDRSTRLEN
];
756 char other_neigh_str
[INET_ADDRSTRLEN
];
759 "<addr?>", addr
->u
.prefix4
,
760 addr_str
, sizeof(addr_str
));
761 pim_inet4_dump("<neigh1?>", neigh_addr
,
763 sizeof(this_neigh_str
));
764 pim_inet4_dump("<neigh2?>",
767 sizeof(other_neigh_str
));
770 "secondary addr %s recvd from neigh %s deleted from neigh %s on %s",
771 addr_str
, this_neigh_str
,
772 other_neigh_str
, ifp
->name
);
774 listnode_delete(neigh
->prefix_list
, p
);
779 } /* scan neighbors */
781 } /* scan addr list */
784 void pim_neighbor_update(struct pim_neighbor
*neigh
,
785 pim_hello_options hello_options
, uint16_t holdtime
,
786 uint32_t dr_priority
, struct list
*addr_list
)
788 struct pim_interface
*pim_ifp
= neigh
->interface
->info
;
791 /* Received holdtime ? */
792 if (PIM_OPTION_IS_SET(hello_options
, PIM_OPTION_MASK_HOLDTIME
)) {
793 pim_neighbor_timer_reset(neigh
, holdtime
);
795 pim_neighbor_timer_reset(neigh
,
796 PIM_IF_DEFAULT_HOLDTIME(pim_ifp
));
799 #ifdef DUMP_PREFIX_LIST
801 "%s: DUMP_PREFIX_LIST old_prefix_list=%x old_size=%d new_prefix_list=%x new_size=%d",
802 __func__
, (unsigned)neigh
->prefix_list
,
803 neigh
->prefix_list
? (int)listcount(neigh
->prefix_list
) : -1,
805 addr_list
? (int)listcount(addr_list
) : -1);
808 if (neigh
->prefix_list
== addr_list
) {
812 "%s: internal error: trying to replace same prefix list=%p",
813 __func__
, (void *)addr_list
);
816 /* Delete existing secondary address list */
817 delete_prefix_list(neigh
);
821 delete_from_neigh_addr(neigh
->interface
, addr_list
,
825 /* Replace secondary address list */
826 neigh
->prefix_list
= addr_list
;
828 update_dr_priority(neigh
, hello_options
, dr_priority
);
829 new = PIM_OPTION_IS_SET(hello_options
, PIM_OPTION_MASK_LAN_PRUNE_DELAY
);
830 old
= PIM_OPTION_IS_SET(neigh
->hello_options
,
831 PIM_OPTION_MASK_LAN_PRUNE_DELAY
);
835 ++pim_ifp
->pim_number_of_nonlandelay_neighbors
;
837 --pim_ifp
->pim_number_of_nonlandelay_neighbors
;
842 neigh
->hello_options
= hello_options
;