]> git.proxmox.com Git - mirror_frr.git/blame - pimd/pim_neighbor.c
pimd, zebra: Pass the ifindex for NEXTHOP_TYPE_IPV4
[mirror_frr.git] / pimd / pim_neighbor.c
CommitLineData
12e41d03
DL
1/*
2 PIM for Quagga
3 Copyright (C) 2008 Everton da Silva Marques
4
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.
9
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.
14
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,
18 MA 02110-1301 USA
19
12e41d03
DL
20*/
21
22#include <zebra.h>
23
24#include "log.h"
25#include "prefix.h"
26#include "memory.h"
744d91b3 27#include "if.h"
12e41d03
DL
28
29#include "pimd.h"
30#include "pim_neighbor.h"
31#include "pim_time.h"
32#include "pim_str.h"
33#include "pim_iface.h"
34#include "pim_pim.h"
35#include "pim_upstream.h"
36#include "pim_ifchannel.h"
37
38static void dr_election_by_addr(struct interface *ifp)
39{
40 struct pim_interface *pim_ifp;
41 struct listnode *node;
42 struct pim_neighbor *neigh;
43
44 pim_ifp = ifp->info;
45 zassert(pim_ifp);
46
47 pim_ifp->pim_dr_addr = pim_ifp->primary_address;
48
49 if (PIM_DEBUG_PIM_TRACE) {
50 zlog_debug("%s: on interface %s",
51 __PRETTY_FUNCTION__,
52 ifp->name);
53 }
54
55 for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, node, neigh)) {
56 if (ntohl(neigh->source_addr.s_addr) > ntohl(pim_ifp->pim_dr_addr.s_addr)) {
57 pim_ifp->pim_dr_addr = neigh->source_addr;
58 }
59 }
60}
61
62static void dr_election_by_pri(struct interface *ifp)
63{
64 struct pim_interface *pim_ifp;
65 struct listnode *node;
66 struct pim_neighbor *neigh;
67 uint32_t dr_pri;
68
69 pim_ifp = ifp->info;
70 zassert(pim_ifp);
71
72 pim_ifp->pim_dr_addr = pim_ifp->primary_address;
73 dr_pri = pim_ifp->pim_dr_priority;
74
75 if (PIM_DEBUG_PIM_TRACE) {
76 zlog_debug("%s: dr pri %u on interface %s",
77 __PRETTY_FUNCTION__,
78 dr_pri, ifp->name);
79 }
80
81 for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, node, neigh)) {
82 if (PIM_DEBUG_PIM_TRACE) {
83 zlog_info("%s: neigh pri %u addr %x if dr addr %x",
84 __PRETTY_FUNCTION__,
85 neigh->dr_priority,
86 ntohl(neigh->source_addr.s_addr),
87 ntohl(pim_ifp->pim_dr_addr.s_addr));
88 }
89 if (
90 (neigh->dr_priority > dr_pri) ||
91 (
92 (neigh->dr_priority == dr_pri) &&
93 (ntohl(neigh->source_addr.s_addr) > ntohl(pim_ifp->pim_dr_addr.s_addr))
94 )
95 ) {
96 pim_ifp->pim_dr_addr = neigh->source_addr;
97 dr_pri = neigh->dr_priority;
98 }
99 }
100}
101
102/*
103 RFC 4601: 4.3.2. DR Election
104
105 A router's idea of the current DR on an interface can change when a
106 PIM Hello message is received, when a neighbor times out, or when a
107 router's own DR Priority changes.
108 */
dedccda6 109int pim_if_dr_election(struct interface *ifp)
12e41d03
DL
110{
111 struct pim_interface *pim_ifp = ifp->info;
112 struct in_addr old_dr_addr;
113
114 ++pim_ifp->pim_dr_election_count;
115
116 old_dr_addr = pim_ifp->pim_dr_addr;
117
118 if (pim_ifp->pim_dr_num_nondrpri_neighbors) {
119 dr_election_by_addr(ifp);
120 }
121 else {
122 dr_election_by_pri(ifp);
123 }
124
125 /* DR changed ? */
126 if (old_dr_addr.s_addr != pim_ifp->pim_dr_addr.s_addr) {
127
7adf0260 128 if (PIM_DEBUG_PIM_EVENTS) {
12e41d03
DL
129 char dr_old_str[100];
130 char dr_new_str[100];
131 pim_inet4_dump("<old_dr?>", old_dr_addr, dr_old_str, sizeof(dr_old_str));
132 pim_inet4_dump("<new_dr?>", pim_ifp->pim_dr_addr, dr_new_str, sizeof(dr_new_str));
133 zlog_debug("%s: DR was %s now is %s on interface %s",
134 __PRETTY_FUNCTION__,
135 dr_old_str, dr_new_str, ifp->name);
136 }
137
138 pim_ifp->pim_dr_election_last = pim_time_monotonic_sec(); /* timestamp */
139 ++pim_ifp->pim_dr_election_changes;
140 pim_if_update_join_desired(pim_ifp);
141 pim_if_update_could_assert(ifp);
142 pim_if_update_assert_tracking_desired(ifp);
dedccda6 143 return 1;
12e41d03 144 }
dedccda6
DS
145
146 return 0;
12e41d03
DL
147}
148
149static void update_dr_priority(struct pim_neighbor *neigh,
150 pim_hello_options hello_options,
151 uint32_t dr_priority)
152{
153 pim_hello_options will_set_pri; /* boolean */
154 pim_hello_options bit_flip; /* boolean */
155 pim_hello_options pri_change; /* boolean */
156
157 will_set_pri = PIM_OPTION_IS_SET(hello_options,
158 PIM_OPTION_MASK_DR_PRIORITY);
159
160 bit_flip =
161 (
162 will_set_pri !=
163 PIM_OPTION_IS_SET(neigh->hello_options, PIM_OPTION_MASK_DR_PRIORITY)
164 );
165
166 if (bit_flip) {
167 struct pim_interface *pim_ifp = neigh->interface->info;
168
169 /* update num. of neighbors without dr_pri */
170
171 if (will_set_pri) {
172 --pim_ifp->pim_dr_num_nondrpri_neighbors;
173 }
174 else {
175 ++pim_ifp->pim_dr_num_nondrpri_neighbors;
176 }
177 }
178
179 pri_change =
180 (
181 bit_flip
182 ||
183 (neigh->dr_priority != dr_priority)
184 );
185
186 if (will_set_pri) {
187 neigh->dr_priority = dr_priority;
188 }
189 else {
190 neigh->dr_priority = 0; /* cosmetic unset */
191 }
192
193 if (pri_change) {
194 /*
195 RFC 4601: 4.3.2. DR Election
196
197 A router's idea of the current DR on an interface can change when a
198 PIM Hello message is received, when a neighbor times out, or when a
199 router's own DR Priority changes.
200 */
201 pim_if_dr_election(neigh->interface); // router's own DR Priority changes
202 }
203}
204
205static int on_neighbor_timer(struct thread *t)
206{
207 struct pim_neighbor *neigh;
208 struct interface *ifp;
209 char msg[100];
210
211 zassert(t);
212 neigh = THREAD_ARG(t);
213 zassert(neigh);
214
215 ifp = neigh->interface;
216
217 if (PIM_DEBUG_PIM_TRACE) {
218 char src_str[100];
219 pim_inet4_dump("<src?>", neigh->source_addr, src_str, sizeof(src_str));
220 zlog_debug("Expired %d sec holdtime for neighbor %s on interface %s",
221 neigh->holdtime, src_str, ifp->name);
222 }
223
59ba0ac3 224 neigh->t_expire_timer = NULL;
12e41d03
DL
225
226 snprintf(msg, sizeof(msg), "%d-sec holdtime expired", neigh->holdtime);
227 pim_neighbor_delete(ifp, neigh, msg);
228
229 /*
230 RFC 4601: 4.3.2. DR Election
231
232 A router's idea of the current DR on an interface can change when a
233 PIM Hello message is received, when a neighbor times out, or when a
234 router's own DR Priority changes.
235 */
236 pim_if_dr_election(ifp); // neighbor times out
237
238 return 0;
239}
240
241static void neighbor_timer_off(struct pim_neighbor *neigh)
242{
169edb7f 243 if (PIM_DEBUG_PIM_TRACE_DETAIL) {
12e41d03
DL
244 if (neigh->t_expire_timer) {
245 char src_str[100];
246 pim_inet4_dump("<src?>", neigh->source_addr, src_str, sizeof(src_str));
247 zlog_debug("%s: cancelling timer for neighbor %s on %s",
248 __PRETTY_FUNCTION__,
249 src_str, neigh->interface->name);
250 }
251 }
252 THREAD_OFF(neigh->t_expire_timer);
253 zassert(!neigh->t_expire_timer);
254}
255
256void pim_neighbor_timer_reset(struct pim_neighbor *neigh, uint16_t holdtime)
257{
258 neigh->holdtime = holdtime;
259
260 neighbor_timer_off(neigh);
261
262 /*
263 0xFFFF is request for no holdtime
264 */
265 if (neigh->holdtime == 0xFFFF) {
266 return;
267 }
268
ce9a0643 269 if (PIM_DEBUG_PIM_TRACE_DETAIL) {
12e41d03
DL
270 char src_str[100];
271 pim_inet4_dump("<src?>", neigh->source_addr, src_str, sizeof(src_str));
272 zlog_debug("%s: starting %u sec timer for neighbor %s on %s",
273 __PRETTY_FUNCTION__,
274 neigh->holdtime, src_str, neigh->interface->name);
275 }
276
277 THREAD_TIMER_ON(master, neigh->t_expire_timer,
278 on_neighbor_timer,
279 neigh, neigh->holdtime);
280}
281
282static struct pim_neighbor *pim_neighbor_new(struct interface *ifp,
283 struct in_addr source_addr,
284 pim_hello_options hello_options,
285 uint16_t holdtime,
286 uint16_t propagation_delay,
287 uint16_t override_interval,
288 uint32_t dr_priority,
289 uint32_t generation_id,
290 struct list *addr_list)
291{
292 struct pim_interface *pim_ifp;
293 struct pim_neighbor *neigh;
294 char src_str[100];
295
296 zassert(ifp);
297 pim_ifp = ifp->info;
298 zassert(pim_ifp);
299
36d9e7dc 300 neigh = XCALLOC(MTYPE_PIM_NEIGHBOR, sizeof(*neigh));
12e41d03 301 if (!neigh) {
36d9e7dc 302 zlog_err("%s: PIM XCALLOC(%zu) failure",
12e41d03
DL
303 __PRETTY_FUNCTION__, sizeof(*neigh));
304 return 0;
305 }
306
307 neigh->creation = pim_time_monotonic_sec();
308 neigh->source_addr = source_addr;
309 neigh->hello_options = hello_options;
310 neigh->propagation_delay_msec = propagation_delay;
311 neigh->override_interval_msec = override_interval;
312 neigh->dr_priority = dr_priority;
313 neigh->generation_id = generation_id;
314 neigh->prefix_list = addr_list;
59ba0ac3 315 neigh->t_expire_timer = NULL;
12e41d03
DL
316 neigh->interface = ifp;
317
318 pim_neighbor_timer_reset(neigh, holdtime);
319
320 pim_inet4_dump("<src?>", source_addr, src_str, sizeof(src_str));
321
322 if (PIM_DEBUG_PIM_EVENTS) {
323 zlog_debug("%s: creating PIM neighbor %s on interface %s",
324 __PRETTY_FUNCTION__,
325 src_str, ifp->name);
326 }
327
328 zlog_info("PIM NEIGHBOR UP: neighbor %s on interface %s",
329 src_str, ifp->name);
330
331 if (neigh->propagation_delay_msec > pim_ifp->pim_neighbors_highest_propagation_delay_msec) {
332 pim_ifp->pim_neighbors_highest_propagation_delay_msec = neigh->propagation_delay_msec;
333 }
334 if (neigh->override_interval_msec > pim_ifp->pim_neighbors_highest_override_interval_msec) {
335 pim_ifp->pim_neighbors_highest_override_interval_msec = neigh->override_interval_msec;
336 }
337
338 if (!PIM_OPTION_IS_SET(neigh->hello_options,
339 PIM_OPTION_MASK_LAN_PRUNE_DELAY)) {
340 /* update num. of neighbors without hello option lan_delay */
341 ++pim_ifp->pim_number_of_nonlandelay_neighbors;
342 }
343
344 if (!PIM_OPTION_IS_SET(neigh->hello_options,
345 PIM_OPTION_MASK_DR_PRIORITY)) {
346 /* update num. of neighbors without hello option dr_pri */
347 ++pim_ifp->pim_dr_num_nondrpri_neighbors;
348 }
349
12e41d03
DL
350 return neigh;
351}
352
353static void delete_prefix_list(struct pim_neighbor *neigh)
354{
355 if (neigh->prefix_list) {
356
357#ifdef DUMP_PREFIX_LIST
358 struct listnode *p_node;
359 struct prefix *p;
360 char addr_str[10];
361 int list_size = neigh->prefix_list ? (int) listcount(neigh->prefix_list) : -1;
362 int i = 0;
363 for (ALL_LIST_ELEMENTS_RO(neigh->prefix_list, p_node, p)) {
364 pim_inet4_dump("<addr?>", p->u.prefix4, addr_str, sizeof(addr_str));
365 zlog_debug("%s: DUMP_PREFIX_LIST neigh=%x prefix_list=%x prefix=%x addr=%s [%d/%d]",
366 __PRETTY_FUNCTION__,
367 (unsigned) neigh, (unsigned) neigh->prefix_list, (unsigned) p,
368 addr_str, i, list_size);
369 ++i;
370 }
371#endif
372
373 list_delete(neigh->prefix_list);
374 neigh->prefix_list = 0;
375 }
376}
377
378void pim_neighbor_free(struct pim_neighbor *neigh)
379{
380 zassert(!neigh->t_expire_timer);
381
382 delete_prefix_list(neigh);
383
384 XFREE(MTYPE_PIM_NEIGHBOR, neigh);
385}
386
387struct pim_neighbor *pim_neighbor_find(struct interface *ifp,
388 struct in_addr source_addr)
389{
390 struct pim_interface *pim_ifp;
391 struct listnode *node;
392 struct pim_neighbor *neigh;
393
394 pim_ifp = ifp->info;
395 zassert(pim_ifp);
396
397 for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, node, neigh)) {
398 if (source_addr.s_addr == neigh->source_addr.s_addr) {
399 return neigh;
400 }
401 }
402
403 return 0;
404}
405
99deb321
DS
406/*
407 * Find the *one* interface out
408 * this interface. If more than
409 * one return NULL
410 */
411struct pim_neighbor *
412pim_neighbor_find_if (struct interface *ifp)
413{
414 struct pim_interface *pim_ifp = ifp->info;
415
416 if (pim_ifp->pim_neighbor_list->count != 1)
417 return NULL;
418
419 return listnode_head (pim_ifp->pim_neighbor_list);
420}
421
12e41d03
DL
422struct pim_neighbor *pim_neighbor_add(struct interface *ifp,
423 struct in_addr source_addr,
424 pim_hello_options hello_options,
425 uint16_t holdtime,
426 uint16_t propagation_delay,
427 uint16_t override_interval,
428 uint32_t dr_priority,
429 uint32_t generation_id,
1148de0a
DS
430 struct list *addr_list,
431 int send_hello_now)
12e41d03
DL
432{
433 struct pim_interface *pim_ifp;
434 struct pim_neighbor *neigh;
435
436 neigh = pim_neighbor_new(ifp, source_addr,
437 hello_options,
438 holdtime,
439 propagation_delay,
440 override_interval,
441 dr_priority,
442 generation_id,
443 addr_list);
444 if (!neigh) {
445 return 0;
446 }
447
448 pim_ifp = ifp->info;
449 zassert(pim_ifp);
450
451 listnode_add(pim_ifp->pim_neighbor_list, neigh);
452
818a327c
DS
453 /*
454 RFC 4601: 4.3.2. DR Election
455
456 A router's idea of the current DR on an interface can change when a
457 PIM Hello message is received, when a neighbor times out, or when a
458 router's own DR Priority changes.
459 */
460 pim_if_dr_election(neigh->interface); // new neighbor -- should not trigger dr election...
461
462 /*
463 RFC 4601: 4.3.1. Sending Hello Messages
464
465 To allow new or rebooting routers to learn of PIM neighbors quickly,
466 when a Hello message is received from a new neighbor, or a Hello
467 message with a new GenID is received from an existing neighbor, a
468 new Hello message should be sent on this interface after a
469 randomized delay between 0 and Triggered_Hello_Delay.
1148de0a
DS
470
471 This is a bit silly to do it that way. If I get a new
472 genid we need to send the hello *now* because we've
473 lined up a bunch of join/prune messages to go out the
474 interface.
818a327c 475 */
1148de0a
DS
476 if (send_hello_now)
477 pim_hello_restart_now (ifp);
478 else
479 pim_hello_restart_triggered(neigh->interface);
818a327c 480
d3dd1804
DS
481 pim_upstream_find_new_rpf();
482
12e41d03
DL
483 return neigh;
484}
485
486static uint16_t
487find_neighbors_next_highest_propagation_delay_msec(struct interface *ifp,
488 struct pim_neighbor *highest_neigh)
489{
490 struct pim_interface *pim_ifp;
491 struct listnode *neigh_node;
492 struct pim_neighbor *neigh;
493 uint16_t next_highest_delay_msec;
494
495 pim_ifp = ifp->info;
496 zassert(pim_ifp);
497
498 next_highest_delay_msec = pim_ifp->pim_propagation_delay_msec;
499
500 for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, neigh_node, neigh)) {
501 if (neigh == highest_neigh)
502 continue;
503 if (neigh->propagation_delay_msec > next_highest_delay_msec)
504 next_highest_delay_msec = neigh->propagation_delay_msec;
505 }
506
507 return next_highest_delay_msec;
508}
509
510static uint16_t
511find_neighbors_next_highest_override_interval_msec(struct interface *ifp,
512 struct pim_neighbor *highest_neigh)
513{
514 struct pim_interface *pim_ifp;
515 struct listnode *neigh_node;
516 struct pim_neighbor *neigh;
517 uint16_t next_highest_interval_msec;
518
519 pim_ifp = ifp->info;
520 zassert(pim_ifp);
521
522 next_highest_interval_msec = pim_ifp->pim_override_interval_msec;
523
524 for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, neigh_node, neigh)) {
525 if (neigh == highest_neigh)
526 continue;
527 if (neigh->override_interval_msec > next_highest_interval_msec)
528 next_highest_interval_msec = neigh->override_interval_msec;
529 }
530
531 return next_highest_interval_msec;
532}
533
534void pim_neighbor_delete(struct interface *ifp,
535 struct pim_neighbor *neigh,
536 const char *delete_message)
537{
538 struct pim_interface *pim_ifp;
539 char src_str[100];
540
541 pim_ifp = ifp->info;
542 zassert(pim_ifp);
543
544 pim_inet4_dump("<src?>", neigh->source_addr, src_str, sizeof(src_str));
545 zlog_info("PIM NEIGHBOR DOWN: neighbor %s on interface %s: %s",
546 src_str, ifp->name, delete_message);
547
548 neighbor_timer_off(neigh);
549
550 pim_if_assert_on_neighbor_down(ifp, neigh->source_addr);
551
552 if (!PIM_OPTION_IS_SET(neigh->hello_options,
553 PIM_OPTION_MASK_LAN_PRUNE_DELAY)) {
554 /* update num. of neighbors without hello option lan_delay */
555
556 --pim_ifp->pim_number_of_nonlandelay_neighbors;
557 }
558
559 if (!PIM_OPTION_IS_SET(neigh->hello_options,
560 PIM_OPTION_MASK_DR_PRIORITY)) {
561 /* update num. of neighbors without dr_pri */
562
563 --pim_ifp->pim_dr_num_nondrpri_neighbors;
564 }
565
566 zassert(neigh->propagation_delay_msec <= pim_ifp->pim_neighbors_highest_propagation_delay_msec);
567 zassert(neigh->override_interval_msec <= pim_ifp->pim_neighbors_highest_override_interval_msec);
568
569 if (pim_if_lan_delay_enabled(ifp)) {
570
571 /* will delete a neighbor with highest propagation delay? */
572 if (neigh->propagation_delay_msec == pim_ifp->pim_neighbors_highest_propagation_delay_msec) {
573 /* then find the next highest propagation delay */
574 pim_ifp->pim_neighbors_highest_propagation_delay_msec =
575 find_neighbors_next_highest_propagation_delay_msec(ifp, neigh);
576 }
577
578 /* will delete a neighbor with highest override interval? */
579 if (neigh->override_interval_msec == pim_ifp->pim_neighbors_highest_override_interval_msec) {
580 /* then find the next highest propagation delay */
581 pim_ifp->pim_neighbors_highest_override_interval_msec =
582 find_neighbors_next_highest_override_interval_msec(ifp, neigh);
583 }
584 }
585
586 if (PIM_DEBUG_PIM_TRACE) {
587 zlog_debug("%s: deleting PIM neighbor %s on interface %s",
588 __PRETTY_FUNCTION__,
589 src_str, ifp->name);
590 }
591
592 listnode_delete(pim_ifp->pim_neighbor_list, neigh);
593
594 pim_neighbor_free(neigh);
595}
596
597void pim_neighbor_delete_all(struct interface *ifp,
598 const char *delete_message)
599{
600 struct pim_interface *pim_ifp;
601 struct listnode *neigh_node;
602 struct listnode *neigh_nextnode;
603 struct pim_neighbor *neigh;
604
605 pim_ifp = ifp->info;
606 zassert(pim_ifp);
607
608 for (ALL_LIST_ELEMENTS(pim_ifp->pim_neighbor_list, neigh_node,
609 neigh_nextnode, neigh)) {
610 pim_neighbor_delete(ifp, neigh, delete_message);
611 }
612}
613
614struct prefix *pim_neighbor_find_secondary(struct pim_neighbor *neigh,
615 struct in_addr addr)
616{
617 struct listnode *node;
618 struct prefix *p;
619
620 if (!neigh->prefix_list)
621 return 0;
622
623 for (ALL_LIST_ELEMENTS_RO(neigh->prefix_list, node, p)) {
624 if (p->family == AF_INET) {
625 if (addr.s_addr == p->u.prefix4.s_addr) {
626 return p;
627 }
628 }
629 }
630
631 return 0;
632}
633
634/*
635 RFC 4601: 4.3.4. Maintaining Secondary Address Lists
636
637 All the advertised secondary addresses in received Hello messages
638 must be checked against those previously advertised by all other
639 PIM neighbors on that interface. If there is a conflict and the
640 same secondary address was previously advertised by another
641 neighbor, then only the most recently received mapping MUST be
642 maintained, and an error message SHOULD be logged to the
643 administrator in a rate-limited manner.
644*/
645static void delete_from_neigh_addr(struct interface *ifp,
646 struct list *addr_list,
647 struct in_addr neigh_addr)
648{
649 struct listnode *addr_node;
650 struct prefix *addr;
651 struct pim_interface *pim_ifp;
652
653 pim_ifp = ifp->info;
654 zassert(pim_ifp);
655
656 zassert(addr_list);
657
658 /*
659 Scan secondary address list
660 */
661 for (ALL_LIST_ELEMENTS_RO(addr_list, addr_node,
662 addr)) {
663 struct listnode *neigh_node;
664 struct pim_neighbor *neigh;
665
666 if (addr->family != AF_INET)
667 continue;
668
669 /*
670 Scan neighbors
671 */
672 for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, neigh_node,
673 neigh)) {
674 {
675 struct prefix *p = pim_neighbor_find_secondary(neigh, addr->u.prefix4);
676 if (p) {
677 char addr_str[100];
678 char this_neigh_str[100];
679 char other_neigh_str[100];
680
681 pim_inet4_dump("<addr?>", addr->u.prefix4, addr_str, sizeof(addr_str));
682 pim_inet4_dump("<neigh1?>", neigh_addr, this_neigh_str, sizeof(this_neigh_str));
683 pim_inet4_dump("<neigh2?>", neigh->source_addr, other_neigh_str, sizeof(other_neigh_str));
684
685 zlog_info("secondary addr %s recvd from neigh %s deleted from neigh %s on %s",
686 addr_str, this_neigh_str, other_neigh_str, ifp->name);
687
688 listnode_delete(neigh->prefix_list, p);
689 prefix_free(p);
690 }
691 }
692
693 } /* scan neighbors */
694
695 } /* scan addr list */
696
697}
698
699void pim_neighbor_update(struct pim_neighbor *neigh,
700 pim_hello_options hello_options,
701 uint16_t holdtime,
702 uint32_t dr_priority,
703 struct list *addr_list)
704{
705 struct pim_interface *pim_ifp = neigh->interface->info;
706
707 /* Received holdtime ? */
708 if (PIM_OPTION_IS_SET(hello_options, PIM_OPTION_MASK_HOLDTIME)) {
709 pim_neighbor_timer_reset(neigh, holdtime);
710 }
711 else {
712 pim_neighbor_timer_reset(neigh, PIM_IF_DEFAULT_HOLDTIME(pim_ifp));
713 }
714
715#ifdef DUMP_PREFIX_LIST
716 zlog_debug("%s: DUMP_PREFIX_LIST old_prefix_list=%x old_size=%d new_prefix_list=%x new_size=%d",
717 __PRETTY_FUNCTION__,
718 (unsigned) neigh->prefix_list,
719 neigh->prefix_list ? (int) listcount(neigh->prefix_list) : -1,
720 (unsigned) addr_list,
721 addr_list ? (int) listcount(addr_list) : -1);
722#endif
723
724 if (neigh->prefix_list == addr_list) {
725 if (addr_list) {
726 zlog_err("%s: internal error: trying to replace same prefix list=%p",
727 __PRETTY_FUNCTION__, (void *) addr_list);
728 }
729 }
730 else {
731 /* Delete existing secondary address list */
732 delete_prefix_list(neigh);
733 }
734
735 if (addr_list) {
736 delete_from_neigh_addr(neigh->interface, addr_list, neigh->source_addr);
737 }
738
739 /* Replace secondary address list */
740 neigh->prefix_list = addr_list;
741
742 update_dr_priority(neigh,
743 hello_options,
744 dr_priority);
745 /*
746 Copy flags
747 */
748 neigh->hello_options = hello_options;
749}