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_ifp
->pim_ifstat_hello_sent
= 0;
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_info("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_trigger_event(pim_ifp
, neigh
, 1);
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 zassert(!neigh
->t_expire_timer
);
417 delete_prefix_list(neigh
);
419 list_delete(&neigh
->upstream_jp_agg
);
420 THREAD_OFF(neigh
->jp_timer
);
423 pim_bfd_info_free(&neigh
->bfd_info
);
425 XFREE(MTYPE_PIM_NEIGHBOR
, neigh
);
428 struct pim_neighbor
*pim_neighbor_find_by_secondary(struct interface
*ifp
,
431 struct pim_interface
*pim_ifp
;
432 struct listnode
*node
, *pnode
;
433 struct pim_neighbor
*neigh
;
436 if (!ifp
|| !ifp
->info
)
441 for (ALL_LIST_ELEMENTS_RO(pim_ifp
->pim_neighbor_list
, node
, neigh
)) {
442 for (ALL_LIST_ELEMENTS_RO(neigh
->prefix_list
, pnode
, p
)) {
443 if (prefix_same(p
, src
))
451 struct pim_neighbor
*pim_neighbor_find(struct interface
*ifp
,
452 struct in_addr source_addr
)
454 struct pim_interface
*pim_ifp
;
455 struct listnode
*node
;
456 struct pim_neighbor
*neigh
;
465 for (ALL_LIST_ELEMENTS_RO(pim_ifp
->pim_neighbor_list
, node
, neigh
)) {
466 if (source_addr
.s_addr
== neigh
->source_addr
.s_addr
) {
475 * Find the *one* interface out
476 * this interface. If more than
479 struct pim_neighbor
*pim_neighbor_find_if(struct interface
*ifp
)
481 struct pim_interface
*pim_ifp
= ifp
->info
;
483 if (!pim_ifp
|| pim_ifp
->pim_neighbor_list
->count
!= 1)
486 return listnode_head(pim_ifp
->pim_neighbor_list
);
489 struct pim_neighbor
*
490 pim_neighbor_add(struct interface
*ifp
, struct in_addr source_addr
,
491 pim_hello_options hello_options
, uint16_t holdtime
,
492 uint16_t propagation_delay
, uint16_t override_interval
,
493 uint32_t dr_priority
, uint32_t generation_id
,
494 struct list
*addr_list
, int send_hello_now
)
496 struct pim_interface
*pim_ifp
;
497 struct pim_neighbor
*neigh
;
499 neigh
= pim_neighbor_new(ifp
, source_addr
, hello_options
, holdtime
,
500 propagation_delay
, override_interval
,
501 dr_priority
, generation_id
, addr_list
);
509 listnode_add(pim_ifp
->pim_neighbor_list
, neigh
);
511 if (PIM_DEBUG_PIM_TRACE_DETAIL
) {
512 char str
[INET_ADDRSTRLEN
];
513 pim_inet4_dump("<nht_nbr?>", source_addr
, str
, sizeof(str
));
514 zlog_debug("%s: neighbor %s added ", __func__
, str
);
517 RFC 4601: 4.3.2. DR Election
519 A router's idea of the current DR on an interface can change when a
520 PIM Hello message is received, when a neighbor times out, or when a
521 router's own DR Priority changes.
523 pim_if_dr_election(neigh
->interface
); // new neighbor -- should not
524 // trigger dr election...
527 RFC 4601: 4.3.1. Sending Hello Messages
529 To allow new or rebooting routers to learn of PIM neighbors quickly,
530 when a Hello message is received from a new neighbor, or a Hello
531 message with a new GenID is received from an existing neighbor, a
532 new Hello message should be sent on this interface after a
533 randomized delay between 0 and Triggered_Hello_Delay.
535 This is a bit silly to do it that way. If I get a new
536 genid we need to send the hello *now* because we've
537 lined up a bunch of join/prune messages to go out the
541 pim_hello_restart_now(ifp
);
543 pim_hello_restart_triggered(neigh
->interface
);
545 pim_upstream_find_new_rpf(pim_ifp
->pim
);
547 /* RNH can send nexthop update prior to PIM neibhor UP
548 in that case nexthop cache would not consider this neighbor
550 Upon PIM neighbor UP, iterate all RPs and update
551 nexthop cache with this neighbor.
553 pim_resolve_rp_nh(pim_ifp
->pim
, neigh
);
555 pim_rp_setup(pim_ifp
->pim
);
557 sched_rpf_cache_refresh(pim_ifp
->pim
);
561 static uint16_t find_neighbors_next_highest_propagation_delay_msec(
562 struct interface
*ifp
, struct pim_neighbor
*highest_neigh
)
564 struct pim_interface
*pim_ifp
;
565 struct listnode
*neigh_node
;
566 struct pim_neighbor
*neigh
;
567 uint16_t next_highest_delay_msec
;
572 next_highest_delay_msec
= pim_ifp
->pim_propagation_delay_msec
;
574 for (ALL_LIST_ELEMENTS_RO(pim_ifp
->pim_neighbor_list
, neigh_node
,
576 if (neigh
== highest_neigh
)
578 if (neigh
->propagation_delay_msec
> next_highest_delay_msec
)
579 next_highest_delay_msec
= neigh
->propagation_delay_msec
;
582 return next_highest_delay_msec
;
585 static uint16_t find_neighbors_next_highest_override_interval_msec(
586 struct interface
*ifp
, struct pim_neighbor
*highest_neigh
)
588 struct pim_interface
*pim_ifp
;
589 struct listnode
*neigh_node
;
590 struct pim_neighbor
*neigh
;
591 uint16_t next_highest_interval_msec
;
596 next_highest_interval_msec
= pim_ifp
->pim_override_interval_msec
;
598 for (ALL_LIST_ELEMENTS_RO(pim_ifp
->pim_neighbor_list
, neigh_node
,
600 if (neigh
== highest_neigh
)
602 if (neigh
->override_interval_msec
> next_highest_interval_msec
)
603 next_highest_interval_msec
=
604 neigh
->override_interval_msec
;
607 return next_highest_interval_msec
;
610 void pim_neighbor_delete(struct interface
*ifp
, struct pim_neighbor
*neigh
,
611 const char *delete_message
)
613 struct pim_interface
*pim_ifp
;
614 char src_str
[INET_ADDRSTRLEN
];
619 pim_inet4_dump("<src?>", neigh
->source_addr
, src_str
, sizeof(src_str
));
620 zlog_info("PIM NEIGHBOR DOWN: neighbor %s on interface %s: %s", src_str
,
621 ifp
->name
, delete_message
);
623 THREAD_OFF(neigh
->t_expire_timer
);
625 pim_if_assert_on_neighbor_down(ifp
, neigh
->source_addr
);
627 if (!PIM_OPTION_IS_SET(neigh
->hello_options
,
628 PIM_OPTION_MASK_LAN_PRUNE_DELAY
)) {
629 /* update num. of neighbors without hello option lan_delay */
631 --pim_ifp
->pim_number_of_nonlandelay_neighbors
;
634 if (!PIM_OPTION_IS_SET(neigh
->hello_options
,
635 PIM_OPTION_MASK_DR_PRIORITY
)) {
636 /* update num. of neighbors without dr_pri */
638 --pim_ifp
->pim_dr_num_nondrpri_neighbors
;
641 zassert(neigh
->propagation_delay_msec
642 <= pim_ifp
->pim_neighbors_highest_propagation_delay_msec
);
643 zassert(neigh
->override_interval_msec
644 <= pim_ifp
->pim_neighbors_highest_override_interval_msec
);
646 if (pim_if_lan_delay_enabled(ifp
)) {
648 /* will delete a neighbor with highest propagation delay? */
649 if (neigh
->propagation_delay_msec
650 == pim_ifp
->pim_neighbors_highest_propagation_delay_msec
) {
651 /* then find the next highest propagation delay */
652 pim_ifp
->pim_neighbors_highest_propagation_delay_msec
=
653 find_neighbors_next_highest_propagation_delay_msec(
657 /* will delete a neighbor with highest override interval? */
658 if (neigh
->override_interval_msec
659 == pim_ifp
->pim_neighbors_highest_override_interval_msec
) {
660 /* then find the next highest propagation delay */
661 pim_ifp
->pim_neighbors_highest_override_interval_msec
=
662 find_neighbors_next_highest_override_interval_msec(
667 if (PIM_DEBUG_PIM_TRACE
) {
668 zlog_debug("%s: deleting PIM neighbor %s on interface %s",
669 __func__
, src_str
, ifp
->name
);
672 // De-Register PIM Neighbor with BFD
673 pim_bfd_trigger_event(pim_ifp
, neigh
, 0);
675 listnode_delete(pim_ifp
->pim_neighbor_list
, neigh
);
677 pim_neighbor_free(neigh
);
679 sched_rpf_cache_refresh(pim_ifp
->pim
);
682 void pim_neighbor_delete_all(struct interface
*ifp
, const char *delete_message
)
684 struct pim_interface
*pim_ifp
;
685 struct listnode
*neigh_node
;
686 struct listnode
*neigh_nextnode
;
687 struct pim_neighbor
*neigh
;
692 for (ALL_LIST_ELEMENTS(pim_ifp
->pim_neighbor_list
, neigh_node
,
693 neigh_nextnode
, neigh
)) {
694 pim_neighbor_delete(ifp
, neigh
, delete_message
);
698 struct prefix
*pim_neighbor_find_secondary(struct pim_neighbor
*neigh
,
701 struct listnode
*node
;
704 if (!neigh
->prefix_list
)
707 for (ALL_LIST_ELEMENTS_RO(neigh
->prefix_list
, node
, p
)) {
708 if (prefix_same(p
, addr
))
716 RFC 4601: 4.3.4. Maintaining Secondary Address Lists
718 All the advertised secondary addresses in received Hello messages
719 must be checked against those previously advertised by all other
720 PIM neighbors on that interface. If there is a conflict and the
721 same secondary address was previously advertised by another
722 neighbor, then only the most recently received mapping MUST be
723 maintained, and an error message SHOULD be logged to the
724 administrator in a rate-limited manner.
726 static void delete_from_neigh_addr(struct interface
*ifp
,
727 struct list
*addr_list
,
728 struct in_addr neigh_addr
)
730 struct listnode
*addr_node
;
732 struct pim_interface
*pim_ifp
;
740 Scan secondary address list
742 for (ALL_LIST_ELEMENTS_RO(addr_list
, addr_node
, addr
)) {
743 struct listnode
*neigh_node
;
744 struct pim_neighbor
*neigh
;
746 if (addr
->family
!= AF_INET
)
752 for (ALL_LIST_ELEMENTS_RO(pim_ifp
->pim_neighbor_list
,
753 neigh_node
, neigh
)) {
755 struct prefix
*p
= pim_neighbor_find_secondary(
758 char addr_str
[INET_ADDRSTRLEN
];
759 char this_neigh_str
[INET_ADDRSTRLEN
];
760 char other_neigh_str
[INET_ADDRSTRLEN
];
763 "<addr?>", addr
->u
.prefix4
,
764 addr_str
, sizeof(addr_str
));
765 pim_inet4_dump("<neigh1?>", neigh_addr
,
767 sizeof(this_neigh_str
));
768 pim_inet4_dump("<neigh2?>",
771 sizeof(other_neigh_str
));
774 "secondary addr %s recvd from neigh %s deleted from neigh %s on %s",
775 addr_str
, this_neigh_str
,
776 other_neigh_str
, ifp
->name
);
778 listnode_delete(neigh
->prefix_list
, p
);
783 } /* scan neighbors */
785 } /* scan addr list */
788 void pim_neighbor_update(struct pim_neighbor
*neigh
,
789 pim_hello_options hello_options
, uint16_t holdtime
,
790 uint32_t dr_priority
, struct list
*addr_list
)
792 struct pim_interface
*pim_ifp
= neigh
->interface
->info
;
795 /* Received holdtime ? */
796 if (PIM_OPTION_IS_SET(hello_options
, PIM_OPTION_MASK_HOLDTIME
)) {
797 pim_neighbor_timer_reset(neigh
, holdtime
);
799 pim_neighbor_timer_reset(neigh
,
800 PIM_IF_DEFAULT_HOLDTIME(pim_ifp
));
803 #ifdef DUMP_PREFIX_LIST
805 "%s: DUMP_PREFIX_LIST old_prefix_list=%x old_size=%d new_prefix_list=%x new_size=%d",
806 __func__
, (unsigned)neigh
->prefix_list
,
807 neigh
->prefix_list
? (int)listcount(neigh
->prefix_list
) : -1,
809 addr_list
? (int)listcount(addr_list
) : -1);
812 if (neigh
->prefix_list
== addr_list
) {
816 "%s: internal error: trying to replace same prefix list=%p",
817 __func__
, (void *)addr_list
);
820 /* Delete existing secondary address list */
821 delete_prefix_list(neigh
);
825 delete_from_neigh_addr(neigh
->interface
, addr_list
,
829 /* Replace secondary address list */
830 neigh
->prefix_list
= addr_list
;
832 update_dr_priority(neigh
, hello_options
, dr_priority
);
833 new = PIM_OPTION_IS_SET(hello_options
, PIM_OPTION_MASK_LAN_PRUNE_DELAY
);
834 old
= PIM_OPTION_IS_SET(neigh
->hello_options
,
835 PIM_OPTION_MASK_LAN_PRUNE_DELAY
);
839 ++pim_ifp
->pim_number_of_nonlandelay_neighbors
;
841 --pim_ifp
->pim_number_of_nonlandelay_neighbors
;
846 neigh
->hello_options
= hello_options
;