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
30 #include "pim_neighbor.h"
33 #include "pim_iface.h"
35 #include "pim_upstream.h"
36 #include "pim_ifchannel.h"
38 #include "pim_zebra.h"
40 #include "pim_jp_agg.h"
42 static void dr_election_by_addr(struct interface
*ifp
)
44 struct pim_interface
*pim_ifp
;
45 struct listnode
*node
;
46 struct pim_neighbor
*neigh
;
51 pim_ifp
->pim_dr_addr
= pim_ifp
->primary_address
;
53 if (PIM_DEBUG_PIM_TRACE
) {
54 zlog_debug("%s: on interface %s",
59 for (ALL_LIST_ELEMENTS_RO(pim_ifp
->pim_neighbor_list
, node
, neigh
)) {
60 if (ntohl(neigh
->source_addr
.s_addr
) > ntohl(pim_ifp
->pim_dr_addr
.s_addr
)) {
61 pim_ifp
->pim_dr_addr
= neigh
->source_addr
;
66 static void dr_election_by_pri(struct interface
*ifp
)
68 struct pim_interface
*pim_ifp
;
69 struct listnode
*node
;
70 struct pim_neighbor
*neigh
;
76 pim_ifp
->pim_dr_addr
= pim_ifp
->primary_address
;
77 dr_pri
= pim_ifp
->pim_dr_priority
;
79 if (PIM_DEBUG_PIM_TRACE
) {
80 zlog_debug("%s: dr pri %u on interface %s",
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",
90 ntohl(neigh
->source_addr
.s_addr
),
91 ntohl(pim_ifp
->pim_dr_addr
.s_addr
));
94 (neigh
->dr_priority
> dr_pri
) ||
96 (neigh
->dr_priority
== dr_pri
) &&
97 (ntohl(neigh
->source_addr
.s_addr
) > ntohl(pim_ifp
->pim_dr_addr
.s_addr
))
100 pim_ifp
->pim_dr_addr
= neigh
->source_addr
;
101 dr_pri
= neigh
->dr_priority
;
107 RFC 4601: 4.3.2. DR Election
109 A router's idea of the current DR on an interface can change when a
110 PIM Hello message is received, when a neighbor times out, or when a
111 router's own DR Priority changes.
113 int pim_if_dr_election(struct interface
*ifp
)
115 struct pim_interface
*pim_ifp
= ifp
->info
;
116 struct in_addr old_dr_addr
;
118 ++pim_ifp
->pim_dr_election_count
;
120 old_dr_addr
= pim_ifp
->pim_dr_addr
;
122 if (pim_ifp
->pim_dr_num_nondrpri_neighbors
) {
123 dr_election_by_addr(ifp
);
126 dr_election_by_pri(ifp
);
130 if (old_dr_addr
.s_addr
!= pim_ifp
->pim_dr_addr
.s_addr
) {
132 if (PIM_DEBUG_PIM_EVENTS
) {
133 char dr_old_str
[INET_ADDRSTRLEN
];
134 char dr_new_str
[INET_ADDRSTRLEN
];
135 pim_inet4_dump("<old_dr?>", old_dr_addr
, dr_old_str
, sizeof(dr_old_str
));
136 pim_inet4_dump("<new_dr?>", pim_ifp
->pim_dr_addr
, dr_new_str
, sizeof(dr_new_str
));
137 zlog_debug("%s: DR was %s now is %s on interface %s",
139 dr_old_str
, dr_new_str
, ifp
->name
);
142 pim_ifp
->pim_dr_election_last
= pim_time_monotonic_sec(); /* timestamp */
143 ++pim_ifp
->pim_dr_election_changes
;
144 pim_if_update_join_desired(pim_ifp
);
145 pim_if_update_could_assert(ifp
);
146 pim_if_update_assert_tracking_desired(ifp
);
153 static void update_dr_priority(struct pim_neighbor
*neigh
,
154 pim_hello_options hello_options
,
155 uint32_t dr_priority
)
157 pim_hello_options will_set_pri
; /* boolean */
158 pim_hello_options bit_flip
; /* boolean */
159 pim_hello_options pri_change
; /* boolean */
161 will_set_pri
= PIM_OPTION_IS_SET(hello_options
,
162 PIM_OPTION_MASK_DR_PRIORITY
);
167 PIM_OPTION_IS_SET(neigh
->hello_options
, PIM_OPTION_MASK_DR_PRIORITY
)
171 struct pim_interface
*pim_ifp
= neigh
->interface
->info
;
173 /* update num. of neighbors without dr_pri */
176 --pim_ifp
->pim_dr_num_nondrpri_neighbors
;
179 ++pim_ifp
->pim_dr_num_nondrpri_neighbors
;
187 (neigh
->dr_priority
!= dr_priority
)
191 neigh
->dr_priority
= dr_priority
;
194 neigh
->dr_priority
= 0; /* cosmetic unset */
199 RFC 4601: 4.3.2. DR Election
201 A router's idea of the current DR on an interface can change when a
202 PIM Hello message is received, when a neighbor times out, or when a
203 router's own DR Priority changes.
205 pim_if_dr_election(neigh
->interface
); // router's own DR Priority changes
209 static int on_neighbor_timer(struct thread
*t
)
211 struct pim_neighbor
*neigh
;
212 struct interface
*ifp
;
215 neigh
= THREAD_ARG(t
);
217 ifp
= neigh
->interface
;
219 if (PIM_DEBUG_PIM_TRACE
) {
220 char src_str
[INET_ADDRSTRLEN
];
221 pim_inet4_dump("<src?>", neigh
->source_addr
, src_str
, sizeof(src_str
));
222 zlog_debug("Expired %d sec holdtime for neighbor %s on interface %s",
223 neigh
->holdtime
, src_str
, ifp
->name
);
226 neigh
->t_expire_timer
= NULL
;
228 snprintf(msg
, sizeof(msg
), "%d-sec holdtime expired", neigh
->holdtime
);
229 pim_neighbor_delete(ifp
, neigh
, msg
);
232 RFC 4601: 4.3.2. DR Election
234 A router's idea of the current DR on an interface can change when a
235 PIM Hello message is received, when a neighbor times out, or when a
236 router's own DR Priority changes.
238 pim_if_dr_election(ifp
); // neighbor times out
243 void pim_neighbor_timer_reset(struct pim_neighbor
*neigh
, uint16_t holdtime
)
245 neigh
->holdtime
= holdtime
;
247 THREAD_OFF(neigh
->t_expire_timer
);
250 0xFFFF is request for no holdtime
252 if (neigh
->holdtime
== 0xFFFF) {
256 if (PIM_DEBUG_PIM_TRACE_DETAIL
) {
257 char src_str
[INET_ADDRSTRLEN
];
258 pim_inet4_dump("<src?>", neigh
->source_addr
, src_str
, sizeof(src_str
));
259 zlog_debug("%s: starting %u sec timer for neighbor %s on %s",
261 neigh
->holdtime
, src_str
, neigh
->interface
->name
);
264 thread_add_timer(master
, on_neighbor_timer
, neigh
, neigh
->holdtime
,
265 &neigh
->t_expire_timer
);
269 on_neighbor_jp_timer (struct thread
*t
)
271 struct pim_neighbor
*neigh
= THREAD_ARG(t
);
274 if (PIM_DEBUG_PIM_TRACE
)
276 char src_str
[INET_ADDRSTRLEN
];
277 pim_inet4_dump("<src?>", neigh
->source_addr
, src_str
, sizeof(src_str
));
278 zlog_debug("%s:Sending JP Agg to %s on %s with %d groups", __PRETTY_FUNCTION__
,
279 src_str
, neigh
->interface
->name
, neigh
->upstream_jp_agg
->count
);
281 neigh
->jp_timer
= NULL
;
283 rpf
.source_nexthop
.interface
= neigh
->interface
;
284 rpf
.rpf_addr
.u
.prefix4
= neigh
->source_addr
;
285 pim_joinprune_send(&rpf
, neigh
->upstream_jp_agg
);
287 thread_add_timer(master
, on_neighbor_jp_timer
, neigh
, qpim_t_periodic
,
294 pim_neighbor_start_jp_timer (struct pim_neighbor
*neigh
)
296 THREAD_TIMER_OFF(neigh
->jp_timer
);
297 thread_add_timer(master
, on_neighbor_jp_timer
, neigh
, qpim_t_periodic
,
301 static struct pim_neighbor
*pim_neighbor_new(struct interface
*ifp
,
302 struct in_addr source_addr
,
303 pim_hello_options hello_options
,
305 uint16_t propagation_delay
,
306 uint16_t override_interval
,
307 uint32_t dr_priority
,
308 uint32_t generation_id
,
309 struct list
*addr_list
)
311 struct pim_interface
*pim_ifp
;
312 struct pim_neighbor
*neigh
;
313 char src_str
[INET_ADDRSTRLEN
];
319 neigh
= XCALLOC(MTYPE_PIM_NEIGHBOR
, sizeof(*neigh
));
321 zlog_err("%s: PIM XCALLOC(%zu) failure",
322 __PRETTY_FUNCTION__
, sizeof(*neigh
));
326 neigh
->creation
= pim_time_monotonic_sec();
327 neigh
->source_addr
= source_addr
;
328 neigh
->hello_options
= hello_options
;
329 neigh
->propagation_delay_msec
= propagation_delay
;
330 neigh
->override_interval_msec
= override_interval
;
331 neigh
->dr_priority
= dr_priority
;
332 neigh
->generation_id
= generation_id
;
333 neigh
->prefix_list
= addr_list
;
334 neigh
->t_expire_timer
= NULL
;
335 neigh
->interface
= ifp
;
337 neigh
->upstream_jp_agg
= list_new();
338 neigh
->upstream_jp_agg
->cmp
= pim_jp_agg_group_list_cmp
;
339 neigh
->upstream_jp_agg
->del
= (void (*)(void *))pim_jp_agg_group_list_free
;
340 pim_neighbor_start_jp_timer(neigh
);
342 pim_neighbor_timer_reset(neigh
, holdtime
);
344 * The pim_ifstat_hello_sent variable is used to decide if
345 * we should expedite a hello out the interface. If we
346 * establish a new neighbor, we unfortunately need to
347 * reset the value so that we can know to hurry up and
350 pim_ifp
->pim_ifstat_hello_sent
= 0;
352 pim_inet4_dump("<src?>", source_addr
, src_str
, sizeof(src_str
));
354 if (PIM_DEBUG_PIM_EVENTS
) {
355 zlog_debug("%s: creating PIM neighbor %s on interface %s",
360 zlog_info("PIM NEIGHBOR UP: neighbor %s on interface %s",
363 if (neigh
->propagation_delay_msec
> pim_ifp
->pim_neighbors_highest_propagation_delay_msec
) {
364 pim_ifp
->pim_neighbors_highest_propagation_delay_msec
= neigh
->propagation_delay_msec
;
366 if (neigh
->override_interval_msec
> pim_ifp
->pim_neighbors_highest_override_interval_msec
) {
367 pim_ifp
->pim_neighbors_highest_override_interval_msec
= neigh
->override_interval_msec
;
370 if (!PIM_OPTION_IS_SET(neigh
->hello_options
,
371 PIM_OPTION_MASK_LAN_PRUNE_DELAY
)) {
372 /* update num. of neighbors without hello option lan_delay */
373 ++pim_ifp
->pim_number_of_nonlandelay_neighbors
;
376 if (!PIM_OPTION_IS_SET(neigh
->hello_options
,
377 PIM_OPTION_MASK_DR_PRIORITY
)) {
378 /* update num. of neighbors without hello option dr_pri */
379 ++pim_ifp
->pim_dr_num_nondrpri_neighbors
;
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
? (int) listcount(neigh
->prefix_list
) : -1;
395 for (ALL_LIST_ELEMENTS_RO(neigh
->prefix_list
, p_node
, p
)) {
396 pim_inet4_dump("<addr?>", p
->u
.prefix4
, addr_str
, sizeof(addr_str
));
397 zlog_debug("%s: DUMP_PREFIX_LIST neigh=%x prefix_list=%x prefix=%x addr=%s [%d/%d]",
399 (unsigned) neigh
, (unsigned) neigh
->prefix_list
, (unsigned) p
,
400 addr_str
, i
, list_size
);
405 list_delete(neigh
->prefix_list
);
406 neigh
->prefix_list
= 0;
410 void pim_neighbor_free(struct pim_neighbor
*neigh
)
412 zassert(!neigh
->t_expire_timer
);
414 delete_prefix_list(neigh
);
416 list_delete(neigh
->upstream_jp_agg
);
417 THREAD_OFF(neigh
->jp_timer
);
419 XFREE(MTYPE_PIM_NEIGHBOR
, neigh
);
422 struct pim_neighbor
*
423 pim_neighbor_find_by_secondary (struct interface
*ifp
,
426 struct pim_interface
*pim_ifp
;
427 struct listnode
*node
, *pnode
;
428 struct pim_neighbor
*neigh
;
435 for (ALL_LIST_ELEMENTS_RO(pim_ifp
->pim_neighbor_list
, node
, neigh
))
437 for (ALL_LIST_ELEMENTS_RO(neigh
->prefix_list
, pnode
, p
))
439 if (prefix_same (p
, src
))
447 struct pim_neighbor
*pim_neighbor_find(struct interface
*ifp
,
448 struct in_addr source_addr
)
450 struct pim_interface
*pim_ifp
;
451 struct listnode
*node
;
452 struct pim_neighbor
*neigh
;
461 for (ALL_LIST_ELEMENTS_RO(pim_ifp
->pim_neighbor_list
, node
, neigh
)) {
462 if (source_addr
.s_addr
== neigh
->source_addr
.s_addr
) {
471 * Find the *one* interface out
472 * this interface. If more than
475 struct pim_neighbor
*
476 pim_neighbor_find_if (struct interface
*ifp
)
478 struct pim_interface
*pim_ifp
= ifp
->info
;
480 if (!pim_ifp
|| pim_ifp
->pim_neighbor_list
->count
!= 1)
483 return listnode_head (pim_ifp
->pim_neighbor_list
);
486 /* rpf info associated with an upstream entry needs to be re-evaluated
487 * when an RPF neighbor comes or goes */
489 pim_neighbor_rpf_update(void)
491 /* XXX: for the time being piggyback on the timer used on rib changes
492 * to scan and update the rpf nexthop. This is expensive processing
493 * and we should be able to optimize neighbor changes differently than
494 * nexthop changes. */
495 sched_rpf_cache_refresh();
498 struct pim_neighbor
*pim_neighbor_add(struct interface
*ifp
,
499 struct in_addr source_addr
,
500 pim_hello_options hello_options
,
502 uint16_t propagation_delay
,
503 uint16_t override_interval
,
504 uint32_t dr_priority
,
505 uint32_t generation_id
,
506 struct list
*addr_list
,
509 struct pim_interface
*pim_ifp
;
510 struct pim_neighbor
*neigh
;
512 neigh
= pim_neighbor_new(ifp
, source_addr
,
527 listnode_add(pim_ifp
->pim_neighbor_list
, neigh
);
529 if (PIM_DEBUG_PIM_TRACE_DETAIL
)
531 char str
[INET_ADDRSTRLEN
];
532 pim_inet4_dump("<nht_nbr?>", source_addr
, str
, sizeof (str
));
533 zlog_debug ("%s: neighbor %s added ", __PRETTY_FUNCTION__
, str
);
536 RFC 4601: 4.3.2. DR Election
538 A router's idea of the current DR on an interface can change when a
539 PIM Hello message is received, when a neighbor times out, or when a
540 router's own DR Priority changes.
542 pim_if_dr_election(neigh
->interface
); // new neighbor -- should not trigger dr election...
545 RFC 4601: 4.3.1. Sending Hello Messages
547 To allow new or rebooting routers to learn of PIM neighbors quickly,
548 when a Hello message is received from a new neighbor, or a Hello
549 message with a new GenID is received from an existing neighbor, a
550 new Hello message should be sent on this interface after a
551 randomized delay between 0 and Triggered_Hello_Delay.
553 This is a bit silly to do it that way. If I get a new
554 genid we need to send the hello *now* because we've
555 lined up a bunch of join/prune messages to go out the
559 pim_hello_restart_now (ifp
);
561 pim_hello_restart_triggered(neigh
->interface
);
563 pim_upstream_find_new_rpf();
565 /* RNH can send nexthop update prior to PIM neibhor UP
566 in that case nexthop cache would not consider this neighbor
568 Upon PIM neighbor UP, iterate all RPs and update
569 nexthop cache with this neighbor.
571 pim_resolve_rp_nh ();
575 pim_neighbor_rpf_update();
580 find_neighbors_next_highest_propagation_delay_msec(struct interface
*ifp
,
581 struct pim_neighbor
*highest_neigh
)
583 struct pim_interface
*pim_ifp
;
584 struct listnode
*neigh_node
;
585 struct pim_neighbor
*neigh
;
586 uint16_t next_highest_delay_msec
;
591 next_highest_delay_msec
= pim_ifp
->pim_propagation_delay_msec
;
593 for (ALL_LIST_ELEMENTS_RO(pim_ifp
->pim_neighbor_list
, neigh_node
, neigh
)) {
594 if (neigh
== highest_neigh
)
596 if (neigh
->propagation_delay_msec
> next_highest_delay_msec
)
597 next_highest_delay_msec
= neigh
->propagation_delay_msec
;
600 return next_highest_delay_msec
;
604 find_neighbors_next_highest_override_interval_msec(struct interface
*ifp
,
605 struct pim_neighbor
*highest_neigh
)
607 struct pim_interface
*pim_ifp
;
608 struct listnode
*neigh_node
;
609 struct pim_neighbor
*neigh
;
610 uint16_t next_highest_interval_msec
;
615 next_highest_interval_msec
= pim_ifp
->pim_override_interval_msec
;
617 for (ALL_LIST_ELEMENTS_RO(pim_ifp
->pim_neighbor_list
, neigh_node
, neigh
)) {
618 if (neigh
== highest_neigh
)
620 if (neigh
->override_interval_msec
> next_highest_interval_msec
)
621 next_highest_interval_msec
= neigh
->override_interval_msec
;
624 return next_highest_interval_msec
;
627 void pim_neighbor_delete(struct interface
*ifp
,
628 struct pim_neighbor
*neigh
,
629 const char *delete_message
)
631 struct pim_interface
*pim_ifp
;
632 char src_str
[INET_ADDRSTRLEN
];
637 pim_inet4_dump("<src?>", neigh
->source_addr
, src_str
, sizeof(src_str
));
638 zlog_info("PIM NEIGHBOR DOWN: neighbor %s on interface %s: %s",
639 src_str
, ifp
->name
, delete_message
);
641 THREAD_OFF(neigh
->t_expire_timer
);
643 pim_if_assert_on_neighbor_down(ifp
, neigh
->source_addr
);
645 if (!PIM_OPTION_IS_SET(neigh
->hello_options
,
646 PIM_OPTION_MASK_LAN_PRUNE_DELAY
)) {
647 /* update num. of neighbors without hello option lan_delay */
649 --pim_ifp
->pim_number_of_nonlandelay_neighbors
;
652 if (!PIM_OPTION_IS_SET(neigh
->hello_options
,
653 PIM_OPTION_MASK_DR_PRIORITY
)) {
654 /* update num. of neighbors without dr_pri */
656 --pim_ifp
->pim_dr_num_nondrpri_neighbors
;
659 zassert(neigh
->propagation_delay_msec
<= pim_ifp
->pim_neighbors_highest_propagation_delay_msec
);
660 zassert(neigh
->override_interval_msec
<= pim_ifp
->pim_neighbors_highest_override_interval_msec
);
662 if (pim_if_lan_delay_enabled(ifp
)) {
664 /* will delete a neighbor with highest propagation delay? */
665 if (neigh
->propagation_delay_msec
== pim_ifp
->pim_neighbors_highest_propagation_delay_msec
) {
666 /* then find the next highest propagation delay */
667 pim_ifp
->pim_neighbors_highest_propagation_delay_msec
=
668 find_neighbors_next_highest_propagation_delay_msec(ifp
, neigh
);
671 /* will delete a neighbor with highest override interval? */
672 if (neigh
->override_interval_msec
== pim_ifp
->pim_neighbors_highest_override_interval_msec
) {
673 /* then find the next highest propagation delay */
674 pim_ifp
->pim_neighbors_highest_override_interval_msec
=
675 find_neighbors_next_highest_override_interval_msec(ifp
, neigh
);
679 if (PIM_DEBUG_PIM_TRACE
) {
680 zlog_debug("%s: deleting PIM neighbor %s on interface %s",
685 listnode_delete(pim_ifp
->pim_neighbor_list
, neigh
);
687 pim_neighbor_free(neigh
);
689 pim_neighbor_rpf_update();
692 void pim_neighbor_delete_all(struct interface
*ifp
,
693 const char *delete_message
)
695 struct pim_interface
*pim_ifp
;
696 struct listnode
*neigh_node
;
697 struct listnode
*neigh_nextnode
;
698 struct pim_neighbor
*neigh
;
703 for (ALL_LIST_ELEMENTS(pim_ifp
->pim_neighbor_list
, neigh_node
,
704 neigh_nextnode
, neigh
)) {
705 pim_neighbor_delete(ifp
, neigh
, delete_message
);
709 struct prefix
*pim_neighbor_find_secondary(struct pim_neighbor
*neigh
,
712 struct listnode
*node
;
715 if (!neigh
->prefix_list
)
718 for (ALL_LIST_ELEMENTS_RO(neigh
->prefix_list
, node
, p
)) {
719 if (prefix_same (p
, addr
))
727 RFC 4601: 4.3.4. Maintaining Secondary Address Lists
729 All the advertised secondary addresses in received Hello messages
730 must be checked against those previously advertised by all other
731 PIM neighbors on that interface. If there is a conflict and the
732 same secondary address was previously advertised by another
733 neighbor, then only the most recently received mapping MUST be
734 maintained, and an error message SHOULD be logged to the
735 administrator in a rate-limited manner.
737 static void delete_from_neigh_addr(struct interface
*ifp
,
738 struct list
*addr_list
,
739 struct in_addr neigh_addr
)
741 struct listnode
*addr_node
;
743 struct pim_interface
*pim_ifp
;
751 Scan secondary address list
753 for (ALL_LIST_ELEMENTS_RO(addr_list
, addr_node
,
755 struct listnode
*neigh_node
;
756 struct pim_neighbor
*neigh
;
758 if (addr
->family
!= AF_INET
)
764 for (ALL_LIST_ELEMENTS_RO(pim_ifp
->pim_neighbor_list
, neigh_node
,
767 struct prefix
*p
= pim_neighbor_find_secondary(neigh
, addr
);
769 char addr_str
[INET_ADDRSTRLEN
];
770 char this_neigh_str
[INET_ADDRSTRLEN
];
771 char other_neigh_str
[INET_ADDRSTRLEN
];
773 pim_inet4_dump("<addr?>", addr
->u
.prefix4
, addr_str
, sizeof(addr_str
));
774 pim_inet4_dump("<neigh1?>", neigh_addr
, this_neigh_str
, sizeof(this_neigh_str
));
775 pim_inet4_dump("<neigh2?>", neigh
->source_addr
, other_neigh_str
, sizeof(other_neigh_str
));
777 zlog_info("secondary addr %s recvd from neigh %s deleted from neigh %s on %s",
778 addr_str
, this_neigh_str
, other_neigh_str
, ifp
->name
);
780 listnode_delete(neigh
->prefix_list
, p
);
785 } /* scan neighbors */
787 } /* scan addr list */
791 void pim_neighbor_update(struct pim_neighbor
*neigh
,
792 pim_hello_options hello_options
,
794 uint32_t dr_priority
,
795 struct list
*addr_list
)
797 struct pim_interface
*pim_ifp
= neigh
->interface
->info
;
799 /* Received holdtime ? */
800 if (PIM_OPTION_IS_SET(hello_options
, PIM_OPTION_MASK_HOLDTIME
)) {
801 pim_neighbor_timer_reset(neigh
, holdtime
);
804 pim_neighbor_timer_reset(neigh
, PIM_IF_DEFAULT_HOLDTIME(pim_ifp
));
807 #ifdef DUMP_PREFIX_LIST
808 zlog_debug("%s: DUMP_PREFIX_LIST old_prefix_list=%x old_size=%d new_prefix_list=%x new_size=%d",
810 (unsigned) neigh
->prefix_list
,
811 neigh
->prefix_list
? (int) listcount(neigh
->prefix_list
) : -1,
812 (unsigned) addr_list
,
813 addr_list
? (int) listcount(addr_list
) : -1);
816 if (neigh
->prefix_list
== addr_list
) {
818 zlog_err("%s: internal error: trying to replace same prefix list=%p",
819 __PRETTY_FUNCTION__
, (void *) addr_list
);
823 /* Delete existing secondary address list */
824 delete_prefix_list(neigh
);
828 delete_from_neigh_addr(neigh
->interface
, addr_list
, neigh
->source_addr
);
831 /* Replace secondary address list */
832 neigh
->prefix_list
= addr_list
;
834 update_dr_priority(neigh
,
840 neigh
->hello_options
= hello_options
;