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"
43 static void dr_election_by_addr(struct interface
*ifp
)
45 struct pim_interface
*pim_ifp
;
46 struct listnode
*node
;
47 struct pim_neighbor
*neigh
;
52 pim_ifp
->pim_dr_addr
= pim_ifp
->primary_address
;
54 if (PIM_DEBUG_PIM_TRACE
) {
55 zlog_debug("%s: on interface %s",
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
;
67 static void dr_election_by_pri(struct interface
*ifp
)
69 struct pim_interface
*pim_ifp
;
70 struct listnode
*node
;
71 struct pim_neighbor
*neigh
;
77 pim_ifp
->pim_dr_addr
= pim_ifp
->primary_address
;
78 dr_pri
= pim_ifp
->pim_dr_priority
;
80 if (PIM_DEBUG_PIM_TRACE
) {
81 zlog_debug("%s: dr pri %u on interface %s",
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",
91 ntohl(neigh
->source_addr
.s_addr
),
92 ntohl(pim_ifp
->pim_dr_addr
.s_addr
));
95 (neigh
->dr_priority
> dr_pri
) ||
97 (neigh
->dr_priority
== dr_pri
) &&
98 (ntohl(neigh
->source_addr
.s_addr
) > ntohl(pim_ifp
->pim_dr_addr
.s_addr
))
101 pim_ifp
->pim_dr_addr
= neigh
->source_addr
;
102 dr_pri
= neigh
->dr_priority
;
108 RFC 4601: 4.3.2. DR Election
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.
114 int pim_if_dr_election(struct interface
*ifp
)
116 struct pim_interface
*pim_ifp
= ifp
->info
;
117 struct in_addr old_dr_addr
;
119 ++pim_ifp
->pim_dr_election_count
;
121 old_dr_addr
= pim_ifp
->pim_dr_addr
;
123 if (pim_ifp
->pim_dr_num_nondrpri_neighbors
) {
124 dr_election_by_addr(ifp
);
127 dr_election_by_pri(ifp
);
131 if (old_dr_addr
.s_addr
!= pim_ifp
->pim_dr_addr
.s_addr
) {
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",
140 dr_old_str
, dr_new_str
, ifp
->name
);
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
);
154 static void update_dr_priority(struct pim_neighbor
*neigh
,
155 pim_hello_options hello_options
,
156 uint32_t dr_priority
)
158 pim_hello_options will_set_pri
; /* boolean */
159 pim_hello_options bit_flip
; /* boolean */
160 pim_hello_options pri_change
; /* boolean */
162 will_set_pri
= PIM_OPTION_IS_SET(hello_options
,
163 PIM_OPTION_MASK_DR_PRIORITY
);
168 PIM_OPTION_IS_SET(neigh
->hello_options
, PIM_OPTION_MASK_DR_PRIORITY
)
172 struct pim_interface
*pim_ifp
= neigh
->interface
->info
;
174 /* update num. of neighbors without dr_pri */
177 --pim_ifp
->pim_dr_num_nondrpri_neighbors
;
180 ++pim_ifp
->pim_dr_num_nondrpri_neighbors
;
188 (neigh
->dr_priority
!= dr_priority
)
192 neigh
->dr_priority
= dr_priority
;
195 neigh
->dr_priority
= 0; /* cosmetic unset */
200 RFC 4601: 4.3.2. DR Election
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.
206 pim_if_dr_election(neigh
->interface
); // router's own DR Priority changes
210 static int on_neighbor_timer(struct thread
*t
)
212 struct pim_neighbor
*neigh
;
213 struct interface
*ifp
;
216 neigh
= THREAD_ARG(t
);
218 ifp
= neigh
->interface
;
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
);
227 snprintf(msg
, sizeof(msg
), "%d-sec holdtime expired", neigh
->holdtime
);
228 pim_neighbor_delete(ifp
, neigh
, msg
);
231 RFC 4601: 4.3.2. DR Election
233 A router's idea of the current DR on an interface can change when a
234 PIM Hello message is received, when a neighbor times out, or when a
235 router's own DR Priority changes.
237 pim_if_dr_election(ifp
); // neighbor times out
242 void pim_neighbor_timer_reset(struct pim_neighbor
*neigh
, uint16_t holdtime
)
244 neigh
->holdtime
= holdtime
;
246 THREAD_OFF(neigh
->t_expire_timer
);
249 0xFFFF is request for no holdtime
251 if (neigh
->holdtime
== 0xFFFF) {
255 if (PIM_DEBUG_PIM_TRACE_DETAIL
) {
256 char src_str
[INET_ADDRSTRLEN
];
257 pim_inet4_dump("<src?>", neigh
->source_addr
, src_str
, sizeof(src_str
));
258 zlog_debug("%s: starting %u sec timer for neighbor %s on %s",
260 neigh
->holdtime
, src_str
, neigh
->interface
->name
);
263 thread_add_timer(master
, on_neighbor_timer
, neigh
, neigh
->holdtime
,
264 &neigh
->t_expire_timer
);
268 on_neighbor_jp_timer (struct thread
*t
)
270 struct pim_neighbor
*neigh
= THREAD_ARG(t
);
273 if (PIM_DEBUG_PIM_TRACE
)
275 char src_str
[INET_ADDRSTRLEN
];
276 pim_inet4_dump("<src?>", neigh
->source_addr
, src_str
, sizeof(src_str
));
277 zlog_debug("%s:Sending JP Agg to %s on %s with %d groups", __PRETTY_FUNCTION__
,
278 src_str
, neigh
->interface
->name
, neigh
->upstream_jp_agg
->count
);
281 rpf
.source_nexthop
.interface
= neigh
->interface
;
282 rpf
.rpf_addr
.u
.prefix4
= neigh
->source_addr
;
283 pim_joinprune_send(&rpf
, neigh
->upstream_jp_agg
);
285 thread_add_timer(master
, on_neighbor_jp_timer
, neigh
, qpim_t_periodic
,
292 pim_neighbor_start_jp_timer (struct pim_neighbor
*neigh
)
294 THREAD_TIMER_OFF(neigh
->jp_timer
);
295 thread_add_timer(master
, on_neighbor_jp_timer
, neigh
, qpim_t_periodic
,
299 static struct pim_neighbor
*pim_neighbor_new(struct interface
*ifp
,
300 struct in_addr source_addr
,
301 pim_hello_options hello_options
,
303 uint16_t propagation_delay
,
304 uint16_t override_interval
,
305 uint32_t dr_priority
,
306 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 zlog_err("%s: PIM XCALLOC(%zu) failure",
320 __PRETTY_FUNCTION__
, sizeof(*neigh
));
324 neigh
->creation
= pim_time_monotonic_sec();
325 neigh
->source_addr
= source_addr
;
326 neigh
->hello_options
= hello_options
;
327 neigh
->propagation_delay_msec
= propagation_delay
;
328 neigh
->override_interval_msec
= override_interval
;
329 neigh
->dr_priority
= dr_priority
;
330 neigh
->generation_id
= generation_id
;
331 neigh
->prefix_list
= addr_list
;
332 neigh
->t_expire_timer
= NULL
;
333 neigh
->interface
= ifp
;
335 neigh
->upstream_jp_agg
= list_new();
336 neigh
->upstream_jp_agg
->cmp
= pim_jp_agg_group_list_cmp
;
337 neigh
->upstream_jp_agg
->del
= (void (*)(void *))pim_jp_agg_group_list_free
;
338 pim_neighbor_start_jp_timer(neigh
);
340 pim_neighbor_timer_reset(neigh
, holdtime
);
342 * The pim_ifstat_hello_sent variable is used to decide if
343 * we should expedite a hello out the interface. If we
344 * establish a new neighbor, we unfortunately need to
345 * reset the value so that we can know to hurry up and
348 pim_ifp
->pim_ifstat_hello_sent
= 0;
350 pim_inet4_dump("<src?>", source_addr
, src_str
, sizeof(src_str
));
352 if (PIM_DEBUG_PIM_EVENTS
) {
353 zlog_debug("%s: creating PIM neighbor %s on interface %s",
358 zlog_info("PIM NEIGHBOR UP: neighbor %s on interface %s",
361 if (neigh
->propagation_delay_msec
> pim_ifp
->pim_neighbors_highest_propagation_delay_msec
) {
362 pim_ifp
->pim_neighbors_highest_propagation_delay_msec
= neigh
->propagation_delay_msec
;
364 if (neigh
->override_interval_msec
> pim_ifp
->pim_neighbors_highest_override_interval_msec
) {
365 pim_ifp
->pim_neighbors_highest_override_interval_msec
= neigh
->override_interval_msec
;
368 if (!PIM_OPTION_IS_SET(neigh
->hello_options
,
369 PIM_OPTION_MASK_LAN_PRUNE_DELAY
)) {
370 /* update num. of neighbors without hello option lan_delay */
371 ++pim_ifp
->pim_number_of_nonlandelay_neighbors
;
374 if (!PIM_OPTION_IS_SET(neigh
->hello_options
,
375 PIM_OPTION_MASK_DR_PRIORITY
)) {
376 /* update num. of neighbors without hello option dr_pri */
377 ++pim_ifp
->pim_dr_num_nondrpri_neighbors
;
380 //Register PIM Neighbor with BFD
381 pim_bfd_trigger_event (pim_ifp
, neigh
, 1);
386 static void delete_prefix_list(struct pim_neighbor
*neigh
)
388 if (neigh
->prefix_list
) {
390 #ifdef DUMP_PREFIX_LIST
391 struct listnode
*p_node
;
394 int list_size
= neigh
->prefix_list
? (int) listcount(neigh
->prefix_list
) : -1;
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]",
400 (unsigned) neigh
, (unsigned) neigh
->prefix_list
, (unsigned) p
,
401 addr_str
, i
, list_size
);
406 list_delete(neigh
->prefix_list
);
407 neigh
->prefix_list
= 0;
411 void pim_neighbor_free(struct pim_neighbor
*neigh
)
413 zassert(!neigh
->t_expire_timer
);
415 delete_prefix_list(neigh
);
417 list_delete(neigh
->upstream_jp_agg
);
418 THREAD_OFF(neigh
->jp_timer
);
420 XFREE(MTYPE_PIM_NEIGHBOR
, neigh
);
423 struct pim_neighbor
*
424 pim_neighbor_find_by_secondary (struct interface
*ifp
,
427 struct pim_interface
*pim_ifp
;
428 struct listnode
*node
, *pnode
;
429 struct pim_neighbor
*neigh
;
436 for (ALL_LIST_ELEMENTS_RO(pim_ifp
->pim_neighbor_list
, node
, neigh
))
438 for (ALL_LIST_ELEMENTS_RO(neigh
->prefix_list
, pnode
, p
))
440 if (prefix_same (p
, src
))
448 struct pim_neighbor
*pim_neighbor_find(struct interface
*ifp
,
449 struct in_addr source_addr
)
451 struct pim_interface
*pim_ifp
;
452 struct listnode
*node
;
453 struct pim_neighbor
*neigh
;
462 for (ALL_LIST_ELEMENTS_RO(pim_ifp
->pim_neighbor_list
, node
, neigh
)) {
463 if (source_addr
.s_addr
== neigh
->source_addr
.s_addr
) {
472 * Find the *one* interface out
473 * this interface. If more than
476 struct pim_neighbor
*
477 pim_neighbor_find_if (struct interface
*ifp
)
479 struct pim_interface
*pim_ifp
= ifp
->info
;
481 if (!pim_ifp
|| pim_ifp
->pim_neighbor_list
->count
!= 1)
484 return listnode_head (pim_ifp
->pim_neighbor_list
);
487 /* rpf info associated with an upstream entry needs to be re-evaluated
488 * when an RPF neighbor comes or goes */
490 pim_neighbor_rpf_update(void)
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();
499 struct pim_neighbor
*pim_neighbor_add(struct interface
*ifp
,
500 struct in_addr source_addr
,
501 pim_hello_options hello_options
,
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
,
510 struct pim_interface
*pim_ifp
;
511 struct pim_neighbor
*neigh
;
513 neigh
= pim_neighbor_new(ifp
, source_addr
,
528 listnode_add(pim_ifp
->pim_neighbor_list
, neigh
);
530 if (PIM_DEBUG_PIM_TRACE_DETAIL
)
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
);
537 RFC 4601: 4.3.2. DR Election
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.
543 pim_if_dr_election(neigh
->interface
); // new neighbor -- should not trigger dr election...
546 RFC 4601: 4.3.1. Sending Hello Messages
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.
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
560 pim_hello_restart_now (ifp
);
562 pim_hello_restart_triggered(neigh
->interface
);
564 pim_upstream_find_new_rpf();
566 /* RNH can send nexthop update prior to PIM neibhor UP
567 in that case nexthop cache would not consider this neighbor
569 Upon PIM neighbor UP, iterate all RPs and update
570 nexthop cache with this neighbor.
572 pim_resolve_rp_nh ();
576 pim_neighbor_rpf_update();
581 find_neighbors_next_highest_propagation_delay_msec(struct interface
*ifp
,
582 struct pim_neighbor
*highest_neigh
)
584 struct pim_interface
*pim_ifp
;
585 struct listnode
*neigh_node
;
586 struct pim_neighbor
*neigh
;
587 uint16_t next_highest_delay_msec
;
592 next_highest_delay_msec
= pim_ifp
->pim_propagation_delay_msec
;
594 for (ALL_LIST_ELEMENTS_RO(pim_ifp
->pim_neighbor_list
, neigh_node
, neigh
)) {
595 if (neigh
== highest_neigh
)
597 if (neigh
->propagation_delay_msec
> next_highest_delay_msec
)
598 next_highest_delay_msec
= neigh
->propagation_delay_msec
;
601 return next_highest_delay_msec
;
605 find_neighbors_next_highest_override_interval_msec(struct interface
*ifp
,
606 struct pim_neighbor
*highest_neigh
)
608 struct pim_interface
*pim_ifp
;
609 struct listnode
*neigh_node
;
610 struct pim_neighbor
*neigh
;
611 uint16_t next_highest_interval_msec
;
616 next_highest_interval_msec
= pim_ifp
->pim_override_interval_msec
;
618 for (ALL_LIST_ELEMENTS_RO(pim_ifp
->pim_neighbor_list
, neigh_node
, neigh
)) {
619 if (neigh
== highest_neigh
)
621 if (neigh
->override_interval_msec
> next_highest_interval_msec
)
622 next_highest_interval_msec
= neigh
->override_interval_msec
;
625 return next_highest_interval_msec
;
628 void pim_neighbor_delete(struct interface
*ifp
,
629 struct pim_neighbor
*neigh
,
630 const char *delete_message
)
632 struct pim_interface
*pim_ifp
;
633 char src_str
[INET_ADDRSTRLEN
];
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
);
642 THREAD_OFF(neigh
->t_expire_timer
);
644 pim_if_assert_on_neighbor_down(ifp
, neigh
->source_addr
);
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 */
650 --pim_ifp
->pim_number_of_nonlandelay_neighbors
;
653 if (!PIM_OPTION_IS_SET(neigh
->hello_options
,
654 PIM_OPTION_MASK_DR_PRIORITY
)) {
655 /* update num. of neighbors without dr_pri */
657 --pim_ifp
->pim_dr_num_nondrpri_neighbors
;
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
);
663 if (pim_if_lan_delay_enabled(ifp
)) {
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
);
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
);
680 if (PIM_DEBUG_PIM_TRACE
) {
681 zlog_debug("%s: deleting PIM neighbor %s on interface %s",
686 //De-Register PIM Neighbor with BFD
687 pim_bfd_trigger_event (pim_ifp
, neigh
, 0);
689 listnode_delete(pim_ifp
->pim_neighbor_list
, neigh
);
691 pim_neighbor_free(neigh
);
693 pim_neighbor_rpf_update();
696 void pim_neighbor_delete_all(struct interface
*ifp
,
697 const char *delete_message
)
699 struct pim_interface
*pim_ifp
;
700 struct listnode
*neigh_node
;
701 struct listnode
*neigh_nextnode
;
702 struct pim_neighbor
*neigh
;
707 for (ALL_LIST_ELEMENTS(pim_ifp
->pim_neighbor_list
, neigh_node
,
708 neigh_nextnode
, neigh
)) {
709 pim_neighbor_delete(ifp
, neigh
, delete_message
);
713 struct prefix
*pim_neighbor_find_secondary(struct pim_neighbor
*neigh
,
716 struct listnode
*node
;
719 if (!neigh
->prefix_list
)
722 for (ALL_LIST_ELEMENTS_RO(neigh
->prefix_list
, node
, p
)) {
723 if (prefix_same (p
, addr
))
731 RFC 4601: 4.3.4. Maintaining Secondary Address Lists
733 All the advertised secondary addresses in received Hello messages
734 must be checked against those previously advertised by all other
735 PIM neighbors on that interface. If there is a conflict and the
736 same secondary address was previously advertised by another
737 neighbor, then only the most recently received mapping MUST be
738 maintained, and an error message SHOULD be logged to the
739 administrator in a rate-limited manner.
741 static void delete_from_neigh_addr(struct interface
*ifp
,
742 struct list
*addr_list
,
743 struct in_addr neigh_addr
)
745 struct listnode
*addr_node
;
747 struct pim_interface
*pim_ifp
;
755 Scan secondary address list
757 for (ALL_LIST_ELEMENTS_RO(addr_list
, addr_node
,
759 struct listnode
*neigh_node
;
760 struct pim_neighbor
*neigh
;
762 if (addr
->family
!= AF_INET
)
768 for (ALL_LIST_ELEMENTS_RO(pim_ifp
->pim_neighbor_list
, neigh_node
,
771 struct prefix
*p
= pim_neighbor_find_secondary(neigh
, addr
);
773 char addr_str
[INET_ADDRSTRLEN
];
774 char this_neigh_str
[INET_ADDRSTRLEN
];
775 char other_neigh_str
[INET_ADDRSTRLEN
];
777 pim_inet4_dump("<addr?>", addr
->u
.prefix4
, addr_str
, sizeof(addr_str
));
778 pim_inet4_dump("<neigh1?>", neigh_addr
, this_neigh_str
, sizeof(this_neigh_str
));
779 pim_inet4_dump("<neigh2?>", neigh
->source_addr
, other_neigh_str
, sizeof(other_neigh_str
));
781 zlog_info("secondary addr %s recvd from neigh %s deleted from neigh %s on %s",
782 addr_str
, this_neigh_str
, other_neigh_str
, ifp
->name
);
784 listnode_delete(neigh
->prefix_list
, p
);
789 } /* scan neighbors */
791 } /* scan addr list */
795 void pim_neighbor_update(struct pim_neighbor
*neigh
,
796 pim_hello_options hello_options
,
798 uint32_t dr_priority
,
799 struct list
*addr_list
)
801 struct pim_interface
*pim_ifp
= neigh
->interface
->info
;
803 /* Received holdtime ? */
804 if (PIM_OPTION_IS_SET(hello_options
, PIM_OPTION_MASK_HOLDTIME
)) {
805 pim_neighbor_timer_reset(neigh
, holdtime
);
808 pim_neighbor_timer_reset(neigh
, PIM_IF_DEFAULT_HOLDTIME(pim_ifp
));
811 #ifdef DUMP_PREFIX_LIST
812 zlog_debug("%s: DUMP_PREFIX_LIST old_prefix_list=%x old_size=%d new_prefix_list=%x new_size=%d",
814 (unsigned) neigh
->prefix_list
,
815 neigh
->prefix_list
? (int) listcount(neigh
->prefix_list
) : -1,
816 (unsigned) addr_list
,
817 addr_list
? (int) listcount(addr_list
) : -1);
820 if (neigh
->prefix_list
== addr_list
) {
822 zlog_err("%s: internal error: trying to replace same prefix list=%p",
823 __PRETTY_FUNCTION__
, (void *) addr_list
);
827 /* Delete existing secondary address list */
828 delete_prefix_list(neigh
);
832 delete_from_neigh_addr(neigh
->interface
, addr_list
, neigh
->source_addr
);
835 /* Replace secondary address list */
836 neigh
->prefix_list
= addr_list
;
838 update_dr_priority(neigh
,
844 neigh
->hello_options
= hello_options
;