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"
44 static void dr_election_by_addr(struct interface
*ifp
)
46 struct pim_interface
*pim_ifp
;
47 struct listnode
*node
;
48 struct pim_neighbor
*neigh
;
53 pim_ifp
->pim_dr_addr
= pim_ifp
->primary_address
;
55 if (PIM_DEBUG_PIM_TRACE
) {
56 zlog_debug("%s: on interface %s", __PRETTY_FUNCTION__
,
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", __PRETTY_FUNCTION__
,
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__
, 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 __PRETTY_FUNCTION__
, dr_old_str
, dr_new_str
,
140 pim_ifp
->pim_dr_election_last
=
141 pim_time_monotonic_sec(); /* timestamp */
142 ++pim_ifp
->pim_dr_election_changes
;
143 pim_if_update_join_desired(pim_ifp
);
144 pim_if_update_could_assert(ifp
);
145 pim_if_update_assert_tracking_desired(ifp
);
152 static void update_dr_priority(struct pim_neighbor
*neigh
,
153 pim_hello_options hello_options
,
154 uint32_t dr_priority
)
156 pim_hello_options will_set_pri
; /* boolean */
157 pim_hello_options bit_flip
; /* boolean */
158 pim_hello_options pri_change
; /* boolean */
161 PIM_OPTION_IS_SET(hello_options
, PIM_OPTION_MASK_DR_PRIORITY
);
163 bit_flip
= (will_set_pri
164 != PIM_OPTION_IS_SET(neigh
->hello_options
,
165 PIM_OPTION_MASK_DR_PRIORITY
));
168 struct pim_interface
*pim_ifp
= neigh
->interface
->info
;
170 /* update num. of neighbors without dr_pri */
173 --pim_ifp
->pim_dr_num_nondrpri_neighbors
;
175 ++pim_ifp
->pim_dr_num_nondrpri_neighbors
;
179 pri_change
= (bit_flip
|| (neigh
->dr_priority
!= dr_priority
));
182 neigh
->dr_priority
= dr_priority
;
184 neigh
->dr_priority
= 0; /* cosmetic unset */
189 RFC 4601: 4.3.2. DR Election
191 A router's idea of the current DR on an interface can change
193 PIM Hello message is received, when a neighbor times out, or
195 router's own DR Priority changes.
198 neigh
->interface
); // router's own DR Priority changes
202 static int on_neighbor_timer(struct thread
*t
)
204 struct pim_neighbor
*neigh
;
205 struct interface
*ifp
;
208 neigh
= THREAD_ARG(t
);
210 ifp
= neigh
->interface
;
212 if (PIM_DEBUG_PIM_TRACE
) {
213 char src_str
[INET_ADDRSTRLEN
];
214 pim_inet4_dump("<src?>", neigh
->source_addr
, src_str
,
217 "Expired %d sec holdtime for neighbor %s on interface %s",
218 neigh
->holdtime
, src_str
, ifp
->name
);
221 snprintf(msg
, sizeof(msg
), "%d-sec holdtime expired", neigh
->holdtime
);
222 pim_neighbor_delete(ifp
, neigh
, msg
);
225 RFC 4601: 4.3.2. DR Election
227 A router's idea of the current DR on an interface can change when a
228 PIM Hello message is received, when a neighbor times out, or when a
229 router's own DR Priority changes.
231 pim_if_dr_election(ifp
); // neighbor times out
236 void pim_neighbor_timer_reset(struct pim_neighbor
*neigh
, uint16_t holdtime
)
238 neigh
->holdtime
= holdtime
;
240 THREAD_OFF(neigh
->t_expire_timer
);
243 0xFFFF is request for no holdtime
245 if (neigh
->holdtime
== 0xFFFF) {
249 if (PIM_DEBUG_PIM_TRACE_DETAIL
) {
250 char src_str
[INET_ADDRSTRLEN
];
251 pim_inet4_dump("<src?>", neigh
->source_addr
, src_str
,
253 zlog_debug("%s: starting %u sec timer for neighbor %s on %s",
254 __PRETTY_FUNCTION__
, neigh
->holdtime
, src_str
,
255 neigh
->interface
->name
);
258 thread_add_timer(router
->master
, on_neighbor_timer
, neigh
,
259 neigh
->holdtime
, &neigh
->t_expire_timer
);
262 static int on_neighbor_jp_timer(struct thread
*t
)
264 struct pim_neighbor
*neigh
= THREAD_ARG(t
);
267 if (PIM_DEBUG_PIM_TRACE
) {
268 char src_str
[INET_ADDRSTRLEN
];
269 pim_inet4_dump("<src?>", neigh
->source_addr
, src_str
,
271 zlog_debug("%s:Sending JP Agg to %s on %s with %d groups",
272 __PRETTY_FUNCTION__
, src_str
, neigh
->interface
->name
,
273 neigh
->upstream_jp_agg
->count
);
276 rpf
.source_nexthop
.interface
= neigh
->interface
;
277 rpf
.rpf_addr
.u
.prefix4
= neigh
->source_addr
;
278 pim_joinprune_send(&rpf
, neigh
->upstream_jp_agg
);
280 thread_add_timer(router
->master
, on_neighbor_jp_timer
, neigh
,
281 router
->t_periodic
, &neigh
->jp_timer
);
286 static void pim_neighbor_start_jp_timer(struct pim_neighbor
*neigh
)
288 THREAD_TIMER_OFF(neigh
->jp_timer
);
289 thread_add_timer(router
->master
, on_neighbor_jp_timer
, neigh
,
290 router
->t_periodic
, &neigh
->jp_timer
);
293 static struct pim_neighbor
*
294 pim_neighbor_new(struct interface
*ifp
, struct in_addr source_addr
,
295 pim_hello_options hello_options
, uint16_t holdtime
,
296 uint16_t propagation_delay
, uint16_t override_interval
,
297 uint32_t dr_priority
, uint32_t generation_id
,
298 struct list
*addr_list
)
300 struct pim_interface
*pim_ifp
;
301 struct pim_neighbor
*neigh
;
302 char src_str
[INET_ADDRSTRLEN
];
308 neigh
= XCALLOC(MTYPE_PIM_NEIGHBOR
, sizeof(*neigh
));
310 neigh
->creation
= pim_time_monotonic_sec();
311 neigh
->source_addr
= source_addr
;
312 neigh
->hello_options
= hello_options
;
313 neigh
->propagation_delay_msec
= propagation_delay
;
314 neigh
->override_interval_msec
= override_interval
;
315 neigh
->dr_priority
= dr_priority
;
316 neigh
->generation_id
= generation_id
;
317 neigh
->prefix_list
= addr_list
;
318 neigh
->t_expire_timer
= NULL
;
319 neigh
->interface
= ifp
;
321 neigh
->upstream_jp_agg
= list_new();
322 neigh
->upstream_jp_agg
->cmp
= pim_jp_agg_group_list_cmp
;
323 neigh
->upstream_jp_agg
->del
=
324 (void (*)(void *))pim_jp_agg_group_list_free
;
325 pim_neighbor_start_jp_timer(neigh
);
327 pim_neighbor_timer_reset(neigh
, holdtime
);
329 * The pim_ifstat_hello_sent variable is used to decide if
330 * we should expedite a hello out the interface. If we
331 * establish a new neighbor, we unfortunately need to
332 * reset the value so that we can know to hurry up and
335 pim_ifp
->pim_ifstat_hello_sent
= 0;
337 pim_inet4_dump("<src?>", source_addr
, src_str
, sizeof(src_str
));
339 if (PIM_DEBUG_PIM_EVENTS
) {
340 zlog_debug("%s: creating PIM neighbor %s on interface %s",
341 __PRETTY_FUNCTION__
, src_str
, ifp
->name
);
344 zlog_info("PIM NEIGHBOR UP: neighbor %s on interface %s", src_str
,
347 if (neigh
->propagation_delay_msec
348 > pim_ifp
->pim_neighbors_highest_propagation_delay_msec
) {
349 pim_ifp
->pim_neighbors_highest_propagation_delay_msec
=
350 neigh
->propagation_delay_msec
;
352 if (neigh
->override_interval_msec
353 > pim_ifp
->pim_neighbors_highest_override_interval_msec
) {
354 pim_ifp
->pim_neighbors_highest_override_interval_msec
=
355 neigh
->override_interval_msec
;
358 if (!PIM_OPTION_IS_SET(neigh
->hello_options
,
359 PIM_OPTION_MASK_LAN_PRUNE_DELAY
)) {
360 /* update num. of neighbors without hello option lan_delay */
361 ++pim_ifp
->pim_number_of_nonlandelay_neighbors
;
364 if (!PIM_OPTION_IS_SET(neigh
->hello_options
,
365 PIM_OPTION_MASK_DR_PRIORITY
)) {
366 /* update num. of neighbors without hello option dr_pri */
367 ++pim_ifp
->pim_dr_num_nondrpri_neighbors
;
370 // Register PIM Neighbor with BFD
371 pim_bfd_trigger_event(pim_ifp
, neigh
, 1);
376 static void delete_prefix_list(struct pim_neighbor
*neigh
)
378 if (neigh
->prefix_list
) {
380 #ifdef DUMP_PREFIX_LIST
381 struct listnode
*p_node
;
384 int list_size
= neigh
->prefix_list
385 ? (int)listcount(neigh
->prefix_list
)
388 for (ALL_LIST_ELEMENTS_RO(neigh
->prefix_list
, p_node
, p
)) {
389 pim_inet4_dump("<addr?>", p
->u
.prefix4
, addr_str
,
392 "%s: DUMP_PREFIX_LIST neigh=%x prefix_list=%x prefix=%x addr=%s [%d/%d]",
393 __PRETTY_FUNCTION__
, (unsigned)neigh
,
394 (unsigned)neigh
->prefix_list
, (unsigned)p
,
395 addr_str
, i
, list_size
);
400 list_delete(&neigh
->prefix_list
);
404 void pim_neighbor_free(struct pim_neighbor
*neigh
)
406 zassert(!neigh
->t_expire_timer
);
408 delete_prefix_list(neigh
);
410 list_delete(&neigh
->upstream_jp_agg
);
411 THREAD_OFF(neigh
->jp_timer
);
414 pim_bfd_info_free(&neigh
->bfd_info
);
416 XFREE(MTYPE_PIM_NEIGHBOR
, neigh
);
419 struct pim_neighbor
*pim_neighbor_find_by_secondary(struct interface
*ifp
,
422 struct pim_interface
*pim_ifp
;
423 struct listnode
*node
, *pnode
;
424 struct pim_neighbor
*neigh
;
431 for (ALL_LIST_ELEMENTS_RO(pim_ifp
->pim_neighbor_list
, node
, neigh
)) {
432 for (ALL_LIST_ELEMENTS_RO(neigh
->prefix_list
, pnode
, p
)) {
433 if (prefix_same(p
, src
))
441 struct pim_neighbor
*pim_neighbor_find(struct interface
*ifp
,
442 struct in_addr source_addr
)
444 struct pim_interface
*pim_ifp
;
445 struct listnode
*node
;
446 struct pim_neighbor
*neigh
;
455 for (ALL_LIST_ELEMENTS_RO(pim_ifp
->pim_neighbor_list
, node
, neigh
)) {
456 if (source_addr
.s_addr
== neigh
->source_addr
.s_addr
) {
465 * Find the *one* interface out
466 * this interface. If more than
469 struct pim_neighbor
*pim_neighbor_find_if(struct interface
*ifp
)
471 struct pim_interface
*pim_ifp
= ifp
->info
;
473 if (!pim_ifp
|| pim_ifp
->pim_neighbor_list
->count
!= 1)
476 return listnode_head(pim_ifp
->pim_neighbor_list
);
479 struct pim_neighbor
*
480 pim_neighbor_add(struct interface
*ifp
, struct in_addr source_addr
,
481 pim_hello_options hello_options
, uint16_t holdtime
,
482 uint16_t propagation_delay
, uint16_t override_interval
,
483 uint32_t dr_priority
, uint32_t generation_id
,
484 struct list
*addr_list
, int send_hello_now
)
486 struct pim_interface
*pim_ifp
;
487 struct pim_neighbor
*neigh
;
489 neigh
= pim_neighbor_new(ifp
, source_addr
, hello_options
, holdtime
,
490 propagation_delay
, override_interval
,
491 dr_priority
, generation_id
, addr_list
);
499 listnode_add(pim_ifp
->pim_neighbor_list
, neigh
);
501 if (PIM_DEBUG_PIM_TRACE_DETAIL
) {
502 char str
[INET_ADDRSTRLEN
];
503 pim_inet4_dump("<nht_nbr?>", source_addr
, str
, sizeof(str
));
504 zlog_debug("%s: neighbor %s added ", __PRETTY_FUNCTION__
, str
);
507 RFC 4601: 4.3.2. DR Election
509 A router's idea of the current DR on an interface can change when a
510 PIM Hello message is received, when a neighbor times out, or when a
511 router's own DR Priority changes.
513 pim_if_dr_election(neigh
->interface
); // new neighbor -- should not
514 // trigger dr election...
517 RFC 4601: 4.3.1. Sending Hello Messages
519 To allow new or rebooting routers to learn of PIM neighbors quickly,
520 when a Hello message is received from a new neighbor, or a Hello
521 message with a new GenID is received from an existing neighbor, a
522 new Hello message should be sent on this interface after a
523 randomized delay between 0 and Triggered_Hello_Delay.
525 This is a bit silly to do it that way. If I get a new
526 genid we need to send the hello *now* because we've
527 lined up a bunch of join/prune messages to go out the
531 pim_hello_restart_now(ifp
);
533 pim_hello_restart_triggered(neigh
->interface
);
535 pim_upstream_find_new_rpf(pim_ifp
->pim
);
537 /* RNH can send nexthop update prior to PIM neibhor UP
538 in that case nexthop cache would not consider this neighbor
540 Upon PIM neighbor UP, iterate all RPs and update
541 nexthop cache with this neighbor.
543 pim_resolve_rp_nh(pim_ifp
->pim
);
545 pim_rp_setup(pim_ifp
->pim
);
547 sched_rpf_cache_refresh(pim_ifp
->pim
);
551 static uint16_t find_neighbors_next_highest_propagation_delay_msec(
552 struct interface
*ifp
, struct pim_neighbor
*highest_neigh
)
554 struct pim_interface
*pim_ifp
;
555 struct listnode
*neigh_node
;
556 struct pim_neighbor
*neigh
;
557 uint16_t next_highest_delay_msec
;
562 next_highest_delay_msec
= pim_ifp
->pim_propagation_delay_msec
;
564 for (ALL_LIST_ELEMENTS_RO(pim_ifp
->pim_neighbor_list
, neigh_node
,
566 if (neigh
== highest_neigh
)
568 if (neigh
->propagation_delay_msec
> next_highest_delay_msec
)
569 next_highest_delay_msec
= neigh
->propagation_delay_msec
;
572 return next_highest_delay_msec
;
575 static uint16_t find_neighbors_next_highest_override_interval_msec(
576 struct interface
*ifp
, struct pim_neighbor
*highest_neigh
)
578 struct pim_interface
*pim_ifp
;
579 struct listnode
*neigh_node
;
580 struct pim_neighbor
*neigh
;
581 uint16_t next_highest_interval_msec
;
586 next_highest_interval_msec
= pim_ifp
->pim_override_interval_msec
;
588 for (ALL_LIST_ELEMENTS_RO(pim_ifp
->pim_neighbor_list
, neigh_node
,
590 if (neigh
== highest_neigh
)
592 if (neigh
->override_interval_msec
> next_highest_interval_msec
)
593 next_highest_interval_msec
=
594 neigh
->override_interval_msec
;
597 return next_highest_interval_msec
;
600 void pim_neighbor_delete(struct interface
*ifp
, struct pim_neighbor
*neigh
,
601 const char *delete_message
)
603 struct pim_interface
*pim_ifp
;
604 char src_str
[INET_ADDRSTRLEN
];
609 pim_inet4_dump("<src?>", neigh
->source_addr
, src_str
, sizeof(src_str
));
610 zlog_info("PIM NEIGHBOR DOWN: neighbor %s on interface %s: %s", src_str
,
611 ifp
->name
, delete_message
);
613 THREAD_OFF(neigh
->t_expire_timer
);
615 pim_if_assert_on_neighbor_down(ifp
, neigh
->source_addr
);
617 if (!PIM_OPTION_IS_SET(neigh
->hello_options
,
618 PIM_OPTION_MASK_LAN_PRUNE_DELAY
)) {
619 /* update num. of neighbors without hello option lan_delay */
621 --pim_ifp
->pim_number_of_nonlandelay_neighbors
;
624 if (!PIM_OPTION_IS_SET(neigh
->hello_options
,
625 PIM_OPTION_MASK_DR_PRIORITY
)) {
626 /* update num. of neighbors without dr_pri */
628 --pim_ifp
->pim_dr_num_nondrpri_neighbors
;
631 zassert(neigh
->propagation_delay_msec
632 <= pim_ifp
->pim_neighbors_highest_propagation_delay_msec
);
633 zassert(neigh
->override_interval_msec
634 <= pim_ifp
->pim_neighbors_highest_override_interval_msec
);
636 if (pim_if_lan_delay_enabled(ifp
)) {
638 /* will delete a neighbor with highest propagation delay? */
639 if (neigh
->propagation_delay_msec
640 == pim_ifp
->pim_neighbors_highest_propagation_delay_msec
) {
641 /* then find the next highest propagation delay */
642 pim_ifp
->pim_neighbors_highest_propagation_delay_msec
=
643 find_neighbors_next_highest_propagation_delay_msec(
647 /* will delete a neighbor with highest override interval? */
648 if (neigh
->override_interval_msec
649 == pim_ifp
->pim_neighbors_highest_override_interval_msec
) {
650 /* then find the next highest propagation delay */
651 pim_ifp
->pim_neighbors_highest_override_interval_msec
=
652 find_neighbors_next_highest_override_interval_msec(
657 if (PIM_DEBUG_PIM_TRACE
) {
658 zlog_debug("%s: deleting PIM neighbor %s on interface %s",
659 __PRETTY_FUNCTION__
, src_str
, ifp
->name
);
662 // De-Register PIM Neighbor with BFD
663 pim_bfd_trigger_event(pim_ifp
, neigh
, 0);
665 listnode_delete(pim_ifp
->pim_neighbor_list
, neigh
);
667 pim_neighbor_free(neigh
);
669 sched_rpf_cache_refresh(pim_ifp
->pim
);
672 void pim_neighbor_delete_all(struct interface
*ifp
, const char *delete_message
)
674 struct pim_interface
*pim_ifp
;
675 struct listnode
*neigh_node
;
676 struct listnode
*neigh_nextnode
;
677 struct pim_neighbor
*neigh
;
682 for (ALL_LIST_ELEMENTS(pim_ifp
->pim_neighbor_list
, neigh_node
,
683 neigh_nextnode
, neigh
)) {
684 pim_neighbor_delete(ifp
, neigh
, delete_message
);
688 struct prefix
*pim_neighbor_find_secondary(struct pim_neighbor
*neigh
,
691 struct listnode
*node
;
694 if (!neigh
->prefix_list
)
697 for (ALL_LIST_ELEMENTS_RO(neigh
->prefix_list
, node
, p
)) {
698 if (prefix_same(p
, addr
))
706 RFC 4601: 4.3.4. Maintaining Secondary Address Lists
708 All the advertised secondary addresses in received Hello messages
709 must be checked against those previously advertised by all other
710 PIM neighbors on that interface. If there is a conflict and the
711 same secondary address was previously advertised by another
712 neighbor, then only the most recently received mapping MUST be
713 maintained, and an error message SHOULD be logged to the
714 administrator in a rate-limited manner.
716 static void delete_from_neigh_addr(struct interface
*ifp
,
717 struct list
*addr_list
,
718 struct in_addr neigh_addr
)
720 struct listnode
*addr_node
;
722 struct pim_interface
*pim_ifp
;
730 Scan secondary address list
732 for (ALL_LIST_ELEMENTS_RO(addr_list
, addr_node
, addr
)) {
733 struct listnode
*neigh_node
;
734 struct pim_neighbor
*neigh
;
736 if (addr
->family
!= AF_INET
)
742 for (ALL_LIST_ELEMENTS_RO(pim_ifp
->pim_neighbor_list
,
743 neigh_node
, neigh
)) {
745 struct prefix
*p
= pim_neighbor_find_secondary(
748 char addr_str
[INET_ADDRSTRLEN
];
749 char this_neigh_str
[INET_ADDRSTRLEN
];
750 char other_neigh_str
[INET_ADDRSTRLEN
];
753 "<addr?>", addr
->u
.prefix4
,
754 addr_str
, sizeof(addr_str
));
755 pim_inet4_dump("<neigh1?>", neigh_addr
,
757 sizeof(this_neigh_str
));
758 pim_inet4_dump("<neigh2?>",
761 sizeof(other_neigh_str
));
764 "secondary addr %s recvd from neigh %s deleted from neigh %s on %s",
765 addr_str
, this_neigh_str
,
766 other_neigh_str
, ifp
->name
);
768 listnode_delete(neigh
->prefix_list
, p
);
773 } /* scan neighbors */
775 } /* scan addr list */
778 void pim_neighbor_update(struct pim_neighbor
*neigh
,
779 pim_hello_options hello_options
, uint16_t holdtime
,
780 uint32_t dr_priority
, struct list
*addr_list
)
782 struct pim_interface
*pim_ifp
= neigh
->interface
->info
;
784 /* Received holdtime ? */
785 if (PIM_OPTION_IS_SET(hello_options
, PIM_OPTION_MASK_HOLDTIME
)) {
786 pim_neighbor_timer_reset(neigh
, holdtime
);
788 pim_neighbor_timer_reset(neigh
,
789 PIM_IF_DEFAULT_HOLDTIME(pim_ifp
));
792 #ifdef DUMP_PREFIX_LIST
794 "%s: DUMP_PREFIX_LIST old_prefix_list=%x old_size=%d new_prefix_list=%x new_size=%d",
795 __PRETTY_FUNCTION__
, (unsigned)neigh
->prefix_list
,
796 neigh
->prefix_list
? (int)listcount(neigh
->prefix_list
) : -1,
798 addr_list
? (int)listcount(addr_list
) : -1);
801 if (neigh
->prefix_list
== addr_list
) {
805 "%s: internal error: trying to replace same prefix list=%p",
806 __PRETTY_FUNCTION__
, (void *)addr_list
);
809 /* Delete existing secondary address list */
810 delete_prefix_list(neigh
);
814 delete_from_neigh_addr(neigh
->interface
, addr_list
,
818 /* Replace secondary address list */
819 neigh
->prefix_list
= addr_list
;
821 update_dr_priority(neigh
, hello_options
, dr_priority
);
825 neigh
->hello_options
= hello_options
;