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
16 along with this program; see the file COPYING; if not, write to the
17 Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
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 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 neigh
->t_expire_timer
= NULL
;
229 snprintf(msg
, sizeof(msg
), "%d-sec holdtime expired", neigh
->holdtime
);
230 pim_neighbor_delete(ifp
, neigh
, msg
);
233 RFC 4601: 4.3.2. DR Election
235 A router's idea of the current DR on an interface can change when a
236 PIM Hello message is received, when a neighbor times out, or when a
237 router's own DR Priority changes.
239 pim_if_dr_election(ifp
); // neighbor times out
244 void pim_neighbor_timer_reset(struct pim_neighbor
*neigh
, uint16_t holdtime
)
246 neigh
->holdtime
= holdtime
;
248 THREAD_OFF(neigh
->t_expire_timer
);
251 0xFFFF is request for no holdtime
253 if (neigh
->holdtime
== 0xFFFF) {
257 if (PIM_DEBUG_PIM_TRACE_DETAIL
) {
258 char src_str
[INET_ADDRSTRLEN
];
259 pim_inet4_dump("<src?>", neigh
->source_addr
, src_str
, sizeof(src_str
));
260 zlog_debug("%s: starting %u sec timer for neighbor %s on %s",
262 neigh
->holdtime
, src_str
, neigh
->interface
->name
);
265 THREAD_TIMER_ON(master
, neigh
->t_expire_timer
,
267 neigh
, neigh
->holdtime
);
271 on_neighbor_jp_timer (struct thread
*t
)
273 struct pim_neighbor
*neigh
= THREAD_ARG(t
);
276 if (PIM_DEBUG_PIM_TRACE
)
278 char src_str
[INET_ADDRSTRLEN
];
279 pim_inet4_dump("<src?>", neigh
->source_addr
, src_str
, sizeof(src_str
));
280 zlog_debug("%s:Sending JP Agg to %s on %s with %d groups", __PRETTY_FUNCTION__
,
281 src_str
, neigh
->interface
->name
, neigh
->upstream_jp_agg
->count
);
283 neigh
->jp_timer
= NULL
;
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_TIMER_ON(master
, neigh
->jp_timer
,
290 on_neighbor_jp_timer
,
291 neigh
, qpim_t_periodic
);
297 pim_neighbor_start_jp_timer (struct pim_neighbor
*neigh
)
299 THREAD_TIMER_OFF(neigh
->jp_timer
);
300 THREAD_TIMER_ON(master
, neigh
->jp_timer
,
301 on_neighbor_jp_timer
,
302 neigh
, qpim_t_periodic
);
305 static struct pim_neighbor
*pim_neighbor_new(struct interface
*ifp
,
306 struct in_addr source_addr
,
307 pim_hello_options hello_options
,
309 uint16_t propagation_delay
,
310 uint16_t override_interval
,
311 uint32_t dr_priority
,
312 uint32_t generation_id
,
313 struct list
*addr_list
)
315 struct pim_interface
*pim_ifp
;
316 struct pim_neighbor
*neigh
;
317 char src_str
[INET_ADDRSTRLEN
];
323 neigh
= XCALLOC(MTYPE_PIM_NEIGHBOR
, sizeof(*neigh
));
325 zlog_err("%s: PIM XCALLOC(%zu) failure",
326 __PRETTY_FUNCTION__
, sizeof(*neigh
));
330 neigh
->creation
= pim_time_monotonic_sec();
331 neigh
->source_addr
= source_addr
;
332 neigh
->hello_options
= hello_options
;
333 neigh
->propagation_delay_msec
= propagation_delay
;
334 neigh
->override_interval_msec
= override_interval
;
335 neigh
->dr_priority
= dr_priority
;
336 neigh
->generation_id
= generation_id
;
337 neigh
->prefix_list
= addr_list
;
338 neigh
->t_expire_timer
= NULL
;
339 neigh
->interface
= ifp
;
341 neigh
->upstream_jp_agg
= list_new();
342 neigh
->upstream_jp_agg
->cmp
= pim_jp_agg_group_list_cmp
;
343 neigh
->upstream_jp_agg
->del
= (void (*)(void *))pim_jp_agg_group_list_free
;
344 pim_neighbor_start_jp_timer(neigh
);
346 pim_neighbor_timer_reset(neigh
, holdtime
);
348 * The pim_ifstat_hello_sent variable is used to decide if
349 * we should expedite a hello out the interface. If we
350 * establish a new neighbor, we unfortunately need to
351 * reset the value so that we can know to hurry up and
354 pim_ifp
->pim_ifstat_hello_sent
= 0;
356 pim_inet4_dump("<src?>", source_addr
, src_str
, sizeof(src_str
));
358 if (PIM_DEBUG_PIM_EVENTS
) {
359 zlog_debug("%s: creating PIM neighbor %s on interface %s",
364 zlog_info("PIM NEIGHBOR UP: neighbor %s on interface %s",
367 if (neigh
->propagation_delay_msec
> pim_ifp
->pim_neighbors_highest_propagation_delay_msec
) {
368 pim_ifp
->pim_neighbors_highest_propagation_delay_msec
= neigh
->propagation_delay_msec
;
370 if (neigh
->override_interval_msec
> pim_ifp
->pim_neighbors_highest_override_interval_msec
) {
371 pim_ifp
->pim_neighbors_highest_override_interval_msec
= neigh
->override_interval_msec
;
374 if (!PIM_OPTION_IS_SET(neigh
->hello_options
,
375 PIM_OPTION_MASK_LAN_PRUNE_DELAY
)) {
376 /* update num. of neighbors without hello option lan_delay */
377 ++pim_ifp
->pim_number_of_nonlandelay_neighbors
;
380 if (!PIM_OPTION_IS_SET(neigh
->hello_options
,
381 PIM_OPTION_MASK_DR_PRIORITY
)) {
382 /* update num. of neighbors without hello option dr_pri */
383 ++pim_ifp
->pim_dr_num_nondrpri_neighbors
;
389 static void delete_prefix_list(struct pim_neighbor
*neigh
)
391 if (neigh
->prefix_list
) {
393 #ifdef DUMP_PREFIX_LIST
394 struct listnode
*p_node
;
397 int list_size
= neigh
->prefix_list
? (int) listcount(neigh
->prefix_list
) : -1;
399 for (ALL_LIST_ELEMENTS_RO(neigh
->prefix_list
, p_node
, p
)) {
400 pim_inet4_dump("<addr?>", p
->u
.prefix4
, addr_str
, sizeof(addr_str
));
401 zlog_debug("%s: DUMP_PREFIX_LIST neigh=%x prefix_list=%x prefix=%x addr=%s [%d/%d]",
403 (unsigned) neigh
, (unsigned) neigh
->prefix_list
, (unsigned) p
,
404 addr_str
, i
, list_size
);
409 list_delete(neigh
->prefix_list
);
410 neigh
->prefix_list
= 0;
414 void pim_neighbor_free(struct pim_neighbor
*neigh
)
416 zassert(!neigh
->t_expire_timer
);
418 delete_prefix_list(neigh
);
420 list_delete(neigh
->upstream_jp_agg
);
421 THREAD_OFF(neigh
->jp_timer
);
423 XFREE(MTYPE_PIM_NEIGHBOR
, neigh
);
426 struct pim_neighbor
*pim_neighbor_find(struct interface
*ifp
,
427 struct in_addr source_addr
)
429 struct pim_interface
*pim_ifp
;
430 struct listnode
*node
;
431 struct pim_neighbor
*neigh
;
437 for (ALL_LIST_ELEMENTS_RO(pim_ifp
->pim_neighbor_list
, node
, neigh
)) {
438 if (source_addr
.s_addr
== neigh
->source_addr
.s_addr
) {
447 * Find the *one* interface out
448 * this interface. If more than
451 struct pim_neighbor
*
452 pim_neighbor_find_if (struct interface
*ifp
)
454 struct pim_interface
*pim_ifp
= ifp
->info
;
456 if (!pim_ifp
|| pim_ifp
->pim_neighbor_list
->count
!= 1)
459 return listnode_head (pim_ifp
->pim_neighbor_list
);
462 /* rpf info associated with an upstream entry needs to be re-evaluated
463 * when an RPF neighbor comes or goes */
465 pim_neighbor_rpf_update(void)
467 /* XXX: for the time being piggyback on the timer used on rib changes
468 * to scan and update the rpf nexthop. This is expensive processing
469 * and we should be able to optimize neighbor changes differently than
470 * nexthop changes. */
471 sched_rpf_cache_refresh();
474 struct pim_neighbor
*pim_neighbor_add(struct interface
*ifp
,
475 struct in_addr source_addr
,
476 pim_hello_options hello_options
,
478 uint16_t propagation_delay
,
479 uint16_t override_interval
,
480 uint32_t dr_priority
,
481 uint32_t generation_id
,
482 struct list
*addr_list
,
485 struct pim_interface
*pim_ifp
;
486 struct pim_neighbor
*neigh
;
488 neigh
= pim_neighbor_new(ifp
, source_addr
,
503 listnode_add(pim_ifp
->pim_neighbor_list
, neigh
);
506 RFC 4601: 4.3.2. DR Election
508 A router's idea of the current DR on an interface can change when a
509 PIM Hello message is received, when a neighbor times out, or when a
510 router's own DR Priority changes.
512 pim_if_dr_election(neigh
->interface
); // new neighbor -- should not trigger dr election...
515 RFC 4601: 4.3.1. Sending Hello Messages
517 To allow new or rebooting routers to learn of PIM neighbors quickly,
518 when a Hello message is received from a new neighbor, or a Hello
519 message with a new GenID is received from an existing neighbor, a
520 new Hello message should be sent on this interface after a
521 randomized delay between 0 and Triggered_Hello_Delay.
523 This is a bit silly to do it that way. If I get a new
524 genid we need to send the hello *now* because we've
525 lined up a bunch of join/prune messages to go out the
529 pim_hello_restart_now (ifp
);
531 pim_hello_restart_triggered(neigh
->interface
);
533 pim_upstream_find_new_rpf();
537 pim_neighbor_rpf_update();
542 find_neighbors_next_highest_propagation_delay_msec(struct interface
*ifp
,
543 struct pim_neighbor
*highest_neigh
)
545 struct pim_interface
*pim_ifp
;
546 struct listnode
*neigh_node
;
547 struct pim_neighbor
*neigh
;
548 uint16_t next_highest_delay_msec
;
553 next_highest_delay_msec
= pim_ifp
->pim_propagation_delay_msec
;
555 for (ALL_LIST_ELEMENTS_RO(pim_ifp
->pim_neighbor_list
, neigh_node
, neigh
)) {
556 if (neigh
== highest_neigh
)
558 if (neigh
->propagation_delay_msec
> next_highest_delay_msec
)
559 next_highest_delay_msec
= neigh
->propagation_delay_msec
;
562 return next_highest_delay_msec
;
566 find_neighbors_next_highest_override_interval_msec(struct interface
*ifp
,
567 struct pim_neighbor
*highest_neigh
)
569 struct pim_interface
*pim_ifp
;
570 struct listnode
*neigh_node
;
571 struct pim_neighbor
*neigh
;
572 uint16_t next_highest_interval_msec
;
577 next_highest_interval_msec
= pim_ifp
->pim_override_interval_msec
;
579 for (ALL_LIST_ELEMENTS_RO(pim_ifp
->pim_neighbor_list
, neigh_node
, neigh
)) {
580 if (neigh
== highest_neigh
)
582 if (neigh
->override_interval_msec
> next_highest_interval_msec
)
583 next_highest_interval_msec
= neigh
->override_interval_msec
;
586 return next_highest_interval_msec
;
589 void pim_neighbor_delete(struct interface
*ifp
,
590 struct pim_neighbor
*neigh
,
591 const char *delete_message
)
593 struct pim_interface
*pim_ifp
;
594 char src_str
[INET_ADDRSTRLEN
];
599 pim_inet4_dump("<src?>", neigh
->source_addr
, src_str
, sizeof(src_str
));
600 zlog_info("PIM NEIGHBOR DOWN: neighbor %s on interface %s: %s",
601 src_str
, ifp
->name
, delete_message
);
603 THREAD_OFF(neigh
->t_expire_timer
);
605 pim_if_assert_on_neighbor_down(ifp
, neigh
->source_addr
);
607 if (!PIM_OPTION_IS_SET(neigh
->hello_options
,
608 PIM_OPTION_MASK_LAN_PRUNE_DELAY
)) {
609 /* update num. of neighbors without hello option lan_delay */
611 --pim_ifp
->pim_number_of_nonlandelay_neighbors
;
614 if (!PIM_OPTION_IS_SET(neigh
->hello_options
,
615 PIM_OPTION_MASK_DR_PRIORITY
)) {
616 /* update num. of neighbors without dr_pri */
618 --pim_ifp
->pim_dr_num_nondrpri_neighbors
;
621 zassert(neigh
->propagation_delay_msec
<= pim_ifp
->pim_neighbors_highest_propagation_delay_msec
);
622 zassert(neigh
->override_interval_msec
<= pim_ifp
->pim_neighbors_highest_override_interval_msec
);
624 if (pim_if_lan_delay_enabled(ifp
)) {
626 /* will delete a neighbor with highest propagation delay? */
627 if (neigh
->propagation_delay_msec
== pim_ifp
->pim_neighbors_highest_propagation_delay_msec
) {
628 /* then find the next highest propagation delay */
629 pim_ifp
->pim_neighbors_highest_propagation_delay_msec
=
630 find_neighbors_next_highest_propagation_delay_msec(ifp
, neigh
);
633 /* will delete a neighbor with highest override interval? */
634 if (neigh
->override_interval_msec
== pim_ifp
->pim_neighbors_highest_override_interval_msec
) {
635 /* then find the next highest propagation delay */
636 pim_ifp
->pim_neighbors_highest_override_interval_msec
=
637 find_neighbors_next_highest_override_interval_msec(ifp
, neigh
);
641 if (PIM_DEBUG_PIM_TRACE
) {
642 zlog_debug("%s: deleting PIM neighbor %s on interface %s",
647 listnode_delete(pim_ifp
->pim_neighbor_list
, neigh
);
649 pim_neighbor_free(neigh
);
651 pim_neighbor_rpf_update();
654 void pim_neighbor_delete_all(struct interface
*ifp
,
655 const char *delete_message
)
657 struct pim_interface
*pim_ifp
;
658 struct listnode
*neigh_node
;
659 struct listnode
*neigh_nextnode
;
660 struct pim_neighbor
*neigh
;
665 for (ALL_LIST_ELEMENTS(pim_ifp
->pim_neighbor_list
, neigh_node
,
666 neigh_nextnode
, neigh
)) {
667 pim_neighbor_delete(ifp
, neigh
, delete_message
);
671 struct prefix
*pim_neighbor_find_secondary(struct pim_neighbor
*neigh
,
674 struct listnode
*node
;
677 if (!neigh
->prefix_list
)
680 for (ALL_LIST_ELEMENTS_RO(neigh
->prefix_list
, node
, p
)) {
681 if (p
->family
== AF_INET
) {
682 if (addr
.s_addr
== p
->u
.prefix4
.s_addr
) {
692 RFC 4601: 4.3.4. Maintaining Secondary Address Lists
694 All the advertised secondary addresses in received Hello messages
695 must be checked against those previously advertised by all other
696 PIM neighbors on that interface. If there is a conflict and the
697 same secondary address was previously advertised by another
698 neighbor, then only the most recently received mapping MUST be
699 maintained, and an error message SHOULD be logged to the
700 administrator in a rate-limited manner.
702 static void delete_from_neigh_addr(struct interface
*ifp
,
703 struct list
*addr_list
,
704 struct in_addr neigh_addr
)
706 struct listnode
*addr_node
;
708 struct pim_interface
*pim_ifp
;
716 Scan secondary address list
718 for (ALL_LIST_ELEMENTS_RO(addr_list
, addr_node
,
720 struct listnode
*neigh_node
;
721 struct pim_neighbor
*neigh
;
723 if (addr
->family
!= AF_INET
)
729 for (ALL_LIST_ELEMENTS_RO(pim_ifp
->pim_neighbor_list
, neigh_node
,
732 struct prefix
*p
= pim_neighbor_find_secondary(neigh
, addr
->u
.prefix4
);
734 char addr_str
[INET_ADDRSTRLEN
];
735 char this_neigh_str
[INET_ADDRSTRLEN
];
736 char other_neigh_str
[INET_ADDRSTRLEN
];
738 pim_inet4_dump("<addr?>", addr
->u
.prefix4
, addr_str
, sizeof(addr_str
));
739 pim_inet4_dump("<neigh1?>", neigh_addr
, this_neigh_str
, sizeof(this_neigh_str
));
740 pim_inet4_dump("<neigh2?>", neigh
->source_addr
, other_neigh_str
, sizeof(other_neigh_str
));
742 zlog_info("secondary addr %s recvd from neigh %s deleted from neigh %s on %s",
743 addr_str
, this_neigh_str
, other_neigh_str
, ifp
->name
);
745 listnode_delete(neigh
->prefix_list
, p
);
750 } /* scan neighbors */
752 } /* scan addr list */
756 void pim_neighbor_update(struct pim_neighbor
*neigh
,
757 pim_hello_options hello_options
,
759 uint32_t dr_priority
,
760 struct list
*addr_list
)
762 struct pim_interface
*pim_ifp
= neigh
->interface
->info
;
764 /* Received holdtime ? */
765 if (PIM_OPTION_IS_SET(hello_options
, PIM_OPTION_MASK_HOLDTIME
)) {
766 pim_neighbor_timer_reset(neigh
, holdtime
);
769 pim_neighbor_timer_reset(neigh
, PIM_IF_DEFAULT_HOLDTIME(pim_ifp
));
772 #ifdef DUMP_PREFIX_LIST
773 zlog_debug("%s: DUMP_PREFIX_LIST old_prefix_list=%x old_size=%d new_prefix_list=%x new_size=%d",
775 (unsigned) neigh
->prefix_list
,
776 neigh
->prefix_list
? (int) listcount(neigh
->prefix_list
) : -1,
777 (unsigned) addr_list
,
778 addr_list
? (int) listcount(addr_list
) : -1);
781 if (neigh
->prefix_list
== addr_list
) {
783 zlog_err("%s: internal error: trying to replace same prefix list=%p",
784 __PRETTY_FUNCTION__
, (void *) addr_list
);
788 /* Delete existing secondary address list */
789 delete_prefix_list(neigh
);
793 delete_from_neigh_addr(neigh
->interface
, addr_list
, neigh
->source_addr
);
796 /* Replace secondary address list */
797 neigh
->prefix_list
= addr_list
;
799 update_dr_priority(neigh
,
805 neigh
->hello_options
= hello_options
;