blob: 9404cec131d33bd61dea080cefb05510a46705bb [file] [log] [blame]
Everton Marques871dbcf2009-08-11 15:43:05 -03001/*
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
20 $QuaggaId: $Format:%an, %ai, %h$ $
21*/
22
23#include <zebra.h>
24
25#include "log.h"
26#include "prefix.h"
27#include "memory.h"
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
Everton Marquese0b8b9b2009-11-17 10:17:21 -020049 if (PIM_DEBUG_PIM_TRACE) {
50 zlog_debug("%s: on interface %s",
51 __PRETTY_FUNCTION__,
52 ifp->name);
53 }
Leonard Herve236b0152009-08-11 15:51:52 -030054
Everton Marques871dbcf2009-08-11 15:43:05 -030055 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
Everton Marquese0b8b9b2009-11-17 10:17:21 -020075 if (PIM_DEBUG_PIM_TRACE) {
76 zlog_debug("%s: dr pri %u on interface %s",
77 __PRETTY_FUNCTION__,
78 dr_pri, ifp->name);
79 }
Leonard Herve236b0152009-08-11 15:51:52 -030080
Everton Marques871dbcf2009-08-11 15:43:05 -030081 for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, node, neigh)) {
Everton Marquese0b8b9b2009-11-17 10:17:21 -020082 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 }
Everton Marques871dbcf2009-08-11 15:43:05 -030089 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 */
109void pim_if_dr_election(struct interface *ifp)
110{
111 struct pim_interface *pim_ifp = ifp->info;
112 struct in_addr old_dr_addr;
113
Everton Marques871dbcf2009-08-11 15:43:05 -0300114 ++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
Leonard Herve236b0152009-08-11 15:51:52 -0300125 /* DR changed ? */
126 if (old_dr_addr.s_addr != pim_ifp->pim_dr_addr.s_addr) {
Everton Marquesc1b228c2014-08-27 15:27:26 -0300127
128 /* if (PIM_DEBUG_PIM_EVENTS) */ {
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 }
Everton Marques777fe1f2014-02-14 14:16:07 -0200137
Everton Marques82e6c732014-06-25 17:28:04 -0300138 pim_ifp->pim_dr_election_last = pim_time_monotonic_sec(); /* timestamp */
Everton Marques777fe1f2014-02-14 14:16:07 -0200139 ++pim_ifp->pim_dr_election_changes;
Everton Marques871dbcf2009-08-11 15:43:05 -0300140 pim_if_update_join_desired(pim_ifp);
141 pim_if_update_could_assert(ifp);
142 pim_if_update_assert_tracking_desired(ifp);
143 }
144}
145
146static void update_dr_priority(struct pim_neighbor *neigh,
147 pim_hello_options hello_options,
148 uint32_t dr_priority)
149{
150 pim_hello_options will_set_pri; /* boolean */
151 pim_hello_options bit_flip; /* boolean */
152 pim_hello_options pri_change; /* boolean */
153
154 will_set_pri = PIM_OPTION_IS_SET(hello_options,
155 PIM_OPTION_MASK_DR_PRIORITY);
156
157 bit_flip =
158 (
159 will_set_pri !=
160 PIM_OPTION_IS_SET(neigh->hello_options, PIM_OPTION_MASK_DR_PRIORITY)
161 );
162
163 if (bit_flip) {
164 struct pim_interface *pim_ifp = neigh->interface->info;
165
166 /* update num. of neighbors without dr_pri */
167
168 if (will_set_pri) {
169 --pim_ifp->pim_dr_num_nondrpri_neighbors;
170 }
171 else {
172 ++pim_ifp->pim_dr_num_nondrpri_neighbors;
173 }
174 }
175
176 pri_change =
177 (
178 bit_flip
179 ||
180 (neigh->dr_priority != dr_priority)
181 );
182
183 if (will_set_pri) {
184 neigh->dr_priority = dr_priority;
185 }
186 else {
187 neigh->dr_priority = 0; /* cosmetic unset */
188 }
189
190 if (pri_change) {
191 /*
192 RFC 4601: 4.3.2. DR Election
193
194 A router's idea of the current DR on an interface can change when a
195 PIM Hello message is received, when a neighbor times out, or when a
196 router's own DR Priority changes.
197 */
Everton Marques777fe1f2014-02-14 14:16:07 -0200198 pim_if_dr_election(neigh->interface); // router's own DR Priority changes
Everton Marques871dbcf2009-08-11 15:43:05 -0300199 }
200}
201
202static int on_neighbor_timer(struct thread *t)
203{
204 struct pim_neighbor *neigh;
205 struct interface *ifp;
206 char msg[100];
207
208 zassert(t);
209 neigh = THREAD_ARG(t);
210 zassert(neigh);
211
212 ifp = neigh->interface;
213
214 if (PIM_DEBUG_PIM_TRACE) {
215 char src_str[100];
216 pim_inet4_dump("<src?>", neigh->source_addr, src_str, sizeof(src_str));
217 zlog_debug("Expired %d sec holdtime for neighbor %s on interface %s",
218 neigh->holdtime, src_str, ifp->name);
219 }
220
221 neigh->t_expire_timer = 0;
222
223 snprintf(msg, sizeof(msg), "%d-sec holdtime expired", neigh->holdtime);
224 pim_neighbor_delete(ifp, neigh, msg);
225
226 /*
227 RFC 4601: 4.3.2. DR Election
228
229 A router's idea of the current DR on an interface can change when a
230 PIM Hello message is received, when a neighbor times out, or when a
231 router's own DR Priority changes.
232 */
Everton Marques777fe1f2014-02-14 14:16:07 -0200233 pim_if_dr_election(ifp); // neighbor times out
Everton Marques871dbcf2009-08-11 15:43:05 -0300234
235 return 0;
236}
237
238static void neighbor_timer_off(struct pim_neighbor *neigh)
239{
240 if (PIM_DEBUG_PIM_TRACE) {
241 if (neigh->t_expire_timer) {
242 char src_str[100];
243 pim_inet4_dump("<src?>", neigh->source_addr, src_str, sizeof(src_str));
244 zlog_debug("%s: cancelling timer for neighbor %s on %s",
245 __PRETTY_FUNCTION__,
246 src_str, neigh->interface->name);
247 }
248 }
249 THREAD_OFF(neigh->t_expire_timer);
250 zassert(!neigh->t_expire_timer);
251}
252
253void pim_neighbor_timer_reset(struct pim_neighbor *neigh, uint16_t holdtime)
254{
255 neigh->holdtime = holdtime;
256
257 neighbor_timer_off(neigh);
258
259 /*
260 0xFFFF is request for no holdtime
261 */
262 if (neigh->holdtime == 0xFFFF) {
263 return;
264 }
265
266 if (PIM_DEBUG_PIM_TRACE) {
267 char src_str[100];
268 pim_inet4_dump("<src?>", neigh->source_addr, src_str, sizeof(src_str));
269 zlog_debug("%s: starting %u sec timer for neighbor %s on %s",
270 __PRETTY_FUNCTION__,
271 neigh->holdtime, src_str, neigh->interface->name);
272 }
273
274 THREAD_TIMER_ON(master, neigh->t_expire_timer,
275 on_neighbor_timer,
276 neigh, neigh->holdtime);
277}
278
279static struct pim_neighbor *pim_neighbor_new(struct interface *ifp,
280 struct in_addr source_addr,
281 pim_hello_options hello_options,
282 uint16_t holdtime,
283 uint16_t propagation_delay,
284 uint16_t override_interval,
285 uint32_t dr_priority,
286 uint32_t generation_id,
287 struct list *addr_list)
288{
289 struct pim_interface *pim_ifp;
290 struct pim_neighbor *neigh;
291 char src_str[100];
292
293 zassert(ifp);
294 pim_ifp = ifp->info;
295 zassert(pim_ifp);
296
297 neigh = XMALLOC(MTYPE_PIM_NEIGHBOR, sizeof(*neigh));
298 if (!neigh) {
David Lamparter5c697982012-02-16 04:47:56 +0100299 zlog_err("%s: PIM XMALLOC(%zu) failure",
Everton Marques871dbcf2009-08-11 15:43:05 -0300300 __PRETTY_FUNCTION__, sizeof(*neigh));
301 return 0;
302 }
303
304 neigh->creation = pim_time_monotonic_sec();
305 neigh->source_addr = source_addr;
306 neigh->hello_options = hello_options;
307 neigh->propagation_delay_msec = propagation_delay;
308 neigh->override_interval_msec = override_interval;
309 neigh->dr_priority = dr_priority;
310 neigh->generation_id = generation_id;
311 neigh->prefix_list = addr_list;
312 neigh->t_expire_timer = 0;
313 neigh->interface = ifp;
314
315 pim_neighbor_timer_reset(neigh, holdtime);
316
317 pim_inet4_dump("<src?>", source_addr, src_str, sizeof(src_str));
318
319 if (PIM_DEBUG_PIM_EVENTS) {
320 zlog_debug("%s: creating PIM neighbor %s on interface %s",
321 __PRETTY_FUNCTION__,
322 src_str, ifp->name);
323 }
324
325 zlog_info("PIM NEIGHBOR UP: neighbor %s on interface %s",
326 src_str, ifp->name);
327
328 if (neigh->propagation_delay_msec > pim_ifp->pim_neighbors_highest_propagation_delay_msec) {
329 pim_ifp->pim_neighbors_highest_propagation_delay_msec = neigh->propagation_delay_msec;
330 }
331 if (neigh->override_interval_msec > pim_ifp->pim_neighbors_highest_override_interval_msec) {
332 pim_ifp->pim_neighbors_highest_override_interval_msec = neigh->override_interval_msec;
333 }
334
335 if (!PIM_OPTION_IS_SET(neigh->hello_options,
336 PIM_OPTION_MASK_LAN_PRUNE_DELAY)) {
337 /* update num. of neighbors without hello option lan_delay */
338 ++pim_ifp->pim_number_of_nonlandelay_neighbors;
339 }
340
341 if (!PIM_OPTION_IS_SET(neigh->hello_options,
342 PIM_OPTION_MASK_DR_PRIORITY)) {
343 /* update num. of neighbors without hello option dr_pri */
344 ++pim_ifp->pim_dr_num_nondrpri_neighbors;
345 }
346
347 /*
348 RFC 4601: 4.3.2. DR Election
349
350 A router's idea of the current DR on an interface can change when a
351 PIM Hello message is received, when a neighbor times out, or when a
352 router's own DR Priority changes.
353 */
Everton Marques777fe1f2014-02-14 14:16:07 -0200354 pim_if_dr_election(neigh->interface); // new neighbor -- should not trigger dr election...
Everton Marques871dbcf2009-08-11 15:43:05 -0300355
356 /*
357 RFC 4601: 4.3.1. Sending Hello Messages
358
359 To allow new or rebooting routers to learn of PIM neighbors quickly,
360 when a Hello message is received from a new neighbor, or a Hello
361 message with a new GenID is received from an existing neighbor, a
362 new Hello message should be sent on this interface after a
363 randomized delay between 0 and Triggered_Hello_Delay.
364 */
365 pim_hello_restart_triggered(neigh->interface);
366
367 return neigh;
368}
369
370static void delete_prefix_list(struct pim_neighbor *neigh)
371{
372 if (neigh->prefix_list) {
373
374#ifdef DUMP_PREFIX_LIST
375 struct listnode *p_node;
376 struct prefix *p;
377 char addr_str[10];
378 int list_size = neigh->prefix_list ? (int) listcount(neigh->prefix_list) : -1;
379 int i = 0;
380 for (ALL_LIST_ELEMENTS_RO(neigh->prefix_list, p_node, p)) {
381 pim_inet4_dump("<addr?>", p->u.prefix4, addr_str, sizeof(addr_str));
382 zlog_debug("%s: DUMP_PREFIX_LIST neigh=%x prefix_list=%x prefix=%x addr=%s [%d/%d]",
383 __PRETTY_FUNCTION__,
384 (unsigned) neigh, (unsigned) neigh->prefix_list, (unsigned) p,
385 addr_str, i, list_size);
386 ++i;
387 }
388#endif
389
390 list_delete(neigh->prefix_list);
391 neigh->prefix_list = 0;
392 }
393}
394
395void pim_neighbor_free(struct pim_neighbor *neigh)
396{
397 zassert(!neigh->t_expire_timer);
398
399 delete_prefix_list(neigh);
400
401 XFREE(MTYPE_PIM_NEIGHBOR, neigh);
402}
403
404struct pim_neighbor *pim_neighbor_find(struct interface *ifp,
405 struct in_addr source_addr)
406{
407 struct pim_interface *pim_ifp;
408 struct listnode *node;
409 struct pim_neighbor *neigh;
410
411 pim_ifp = ifp->info;
412 zassert(pim_ifp);
413
414 for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, node, neigh)) {
415 if (source_addr.s_addr == neigh->source_addr.s_addr) {
416 return neigh;
417 }
418 }
419
420 return 0;
421}
422
423struct pim_neighbor *pim_neighbor_add(struct interface *ifp,
424 struct in_addr source_addr,
425 pim_hello_options hello_options,
426 uint16_t holdtime,
427 uint16_t propagation_delay,
428 uint16_t override_interval,
429 uint32_t dr_priority,
430 uint32_t generation_id,
431 struct list *addr_list)
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
453 return neigh;
454}
455
456static uint16_t
457find_neighbors_next_highest_propagation_delay_msec(struct interface *ifp,
458 struct pim_neighbor *highest_neigh)
459{
460 struct pim_interface *pim_ifp;
461 struct listnode *neigh_node;
462 struct pim_neighbor *neigh;
463 uint16_t next_highest_delay_msec;
464
465 pim_ifp = ifp->info;
466 zassert(pim_ifp);
467
468 next_highest_delay_msec = pim_ifp->pim_propagation_delay_msec;
469
470 for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, neigh_node, neigh)) {
471 if (neigh == highest_neigh)
472 continue;
473 if (neigh->propagation_delay_msec > next_highest_delay_msec)
474 next_highest_delay_msec = neigh->propagation_delay_msec;
475 }
476
477 return next_highest_delay_msec;
478}
479
480static uint16_t
481find_neighbors_next_highest_override_interval_msec(struct interface *ifp,
482 struct pim_neighbor *highest_neigh)
483{
484 struct pim_interface *pim_ifp;
485 struct listnode *neigh_node;
486 struct pim_neighbor *neigh;
487 uint16_t next_highest_interval_msec;
488
489 pim_ifp = ifp->info;
490 zassert(pim_ifp);
491
492 next_highest_interval_msec = pim_ifp->pim_override_interval_msec;
493
494 for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, neigh_node, neigh)) {
495 if (neigh == highest_neigh)
496 continue;
497 if (neigh->override_interval_msec > next_highest_interval_msec)
498 next_highest_interval_msec = neigh->override_interval_msec;
499 }
500
501 return next_highest_interval_msec;
502}
503
504void pim_neighbor_delete(struct interface *ifp,
505 struct pim_neighbor *neigh,
506 const char *delete_message)
507{
508 struct pim_interface *pim_ifp;
509 char src_str[100];
510
511 pim_ifp = ifp->info;
512 zassert(pim_ifp);
513
514 pim_inet4_dump("<src?>", neigh->source_addr, src_str, sizeof(src_str));
515 zlog_info("PIM NEIGHBOR DOWN: neighbor %s on interface %s: %s",
516 src_str, ifp->name, delete_message);
517
518 neighbor_timer_off(neigh);
519
520 pim_if_assert_on_neighbor_down(ifp, neigh->source_addr);
521
522 if (!PIM_OPTION_IS_SET(neigh->hello_options,
523 PIM_OPTION_MASK_LAN_PRUNE_DELAY)) {
524 /* update num. of neighbors without hello option lan_delay */
525
526 --pim_ifp->pim_number_of_nonlandelay_neighbors;
527 }
528
529 if (!PIM_OPTION_IS_SET(neigh->hello_options,
530 PIM_OPTION_MASK_DR_PRIORITY)) {
531 /* update num. of neighbors without dr_pri */
532
533 --pim_ifp->pim_dr_num_nondrpri_neighbors;
534 }
535
536 zassert(neigh->propagation_delay_msec <= pim_ifp->pim_neighbors_highest_propagation_delay_msec);
537 zassert(neigh->override_interval_msec <= pim_ifp->pim_neighbors_highest_override_interval_msec);
538
539 if (pim_if_lan_delay_enabled(ifp)) {
540
541 /* will delete a neighbor with highest propagation delay? */
542 if (neigh->propagation_delay_msec == pim_ifp->pim_neighbors_highest_propagation_delay_msec) {
543 /* then find the next highest propagation delay */
544 pim_ifp->pim_neighbors_highest_propagation_delay_msec =
545 find_neighbors_next_highest_propagation_delay_msec(ifp, neigh);
546 }
547
548 /* will delete a neighbor with highest override interval? */
549 if (neigh->override_interval_msec == pim_ifp->pim_neighbors_highest_override_interval_msec) {
550 /* then find the next highest propagation delay */
551 pim_ifp->pim_neighbors_highest_override_interval_msec =
552 find_neighbors_next_highest_override_interval_msec(ifp, neigh);
553 }
554 }
555
556 if (PIM_DEBUG_PIM_TRACE) {
557 zlog_debug("%s: deleting PIM neighbor %s on interface %s",
558 __PRETTY_FUNCTION__,
559 src_str, ifp->name);
560 }
561
562 listnode_delete(pim_ifp->pim_neighbor_list, neigh);
563
564 pim_neighbor_free(neigh);
565}
566
567void pim_neighbor_delete_all(struct interface *ifp,
568 const char *delete_message)
569{
570 struct pim_interface *pim_ifp;
571 struct listnode *neigh_node;
572 struct listnode *neigh_nextnode;
573 struct pim_neighbor *neigh;
574
575 pim_ifp = ifp->info;
576 zassert(pim_ifp);
577
578 for (ALL_LIST_ELEMENTS(pim_ifp->pim_neighbor_list, neigh_node,
579 neigh_nextnode, neigh)) {
580 pim_neighbor_delete(ifp, neigh, delete_message);
581 }
582}
583
584struct prefix *pim_neighbor_find_secondary(struct pim_neighbor *neigh,
585 struct in_addr addr)
586{
587 struct listnode *node;
588 struct prefix *p;
589
590 if (!neigh->prefix_list)
591 return 0;
592
593 for (ALL_LIST_ELEMENTS_RO(neigh->prefix_list, node, p)) {
594 if (p->family == AF_INET) {
595 if (addr.s_addr == p->u.prefix4.s_addr) {
596 return p;
597 }
598 }
599 }
600
601 return 0;
602}
603
604/*
605 RFC 4601: 4.3.4. Maintaining Secondary Address Lists
606
607 All the advertised secondary addresses in received Hello messages
608 must be checked against those previously advertised by all other
609 PIM neighbors on that interface. If there is a conflict and the
610 same secondary address was previously advertised by another
611 neighbor, then only the most recently received mapping MUST be
612 maintained, and an error message SHOULD be logged to the
613 administrator in a rate-limited manner.
614*/
615static void delete_from_neigh_addr(struct interface *ifp,
616 struct list *addr_list,
617 struct in_addr neigh_addr)
618{
619 struct listnode *addr_node;
620 struct prefix *addr;
621 struct pim_interface *pim_ifp;
622
623 pim_ifp = ifp->info;
624 zassert(pim_ifp);
625
626 zassert(addr_list);
627
628 /*
629 Scan secondary address list
630 */
631 for (ALL_LIST_ELEMENTS_RO(addr_list, addr_node,
632 addr)) {
633 struct listnode *neigh_node;
634 struct pim_neighbor *neigh;
635
636 if (addr->family != AF_INET)
637 continue;
638
639 /*
640 Scan neighbors
641 */
642 for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, neigh_node,
643 neigh)) {
644 {
645 struct prefix *p = pim_neighbor_find_secondary(neigh, addr->u.prefix4);
646 if (p) {
647 char addr_str[100];
648 char this_neigh_str[100];
649 char other_neigh_str[100];
650
651 pim_inet4_dump("<addr?>", addr->u.prefix4, addr_str, sizeof(addr_str));
652 pim_inet4_dump("<neigh1?>", neigh_addr, this_neigh_str, sizeof(this_neigh_str));
653 pim_inet4_dump("<neigh2?>", neigh->source_addr, other_neigh_str, sizeof(other_neigh_str));
654
655 zlog_info("secondary addr %s recvd from neigh %s deleted from neigh %s on %s",
656 addr_str, this_neigh_str, other_neigh_str, ifp->name);
657
658 listnode_delete(neigh->prefix_list, p);
659 prefix_free(p);
660 }
661 }
662
663 } /* scan neighbors */
664
665 } /* scan addr list */
666
667}
668
669void pim_neighbor_update(struct pim_neighbor *neigh,
670 pim_hello_options hello_options,
671 uint16_t holdtime,
672 uint32_t dr_priority,
673 struct list *addr_list)
674{
675 struct pim_interface *pim_ifp = neigh->interface->info;
676
677 /* Received holdtime ? */
678 if (PIM_OPTION_IS_SET(hello_options, PIM_OPTION_MASK_HOLDTIME)) {
679 pim_neighbor_timer_reset(neigh, holdtime);
680 }
681 else {
682 pim_neighbor_timer_reset(neigh, PIM_IF_DEFAULT_HOLDTIME(pim_ifp));
683 }
684
685#ifdef DUMP_PREFIX_LIST
686 zlog_debug("%s: DUMP_PREFIX_LIST old_prefix_list=%x old_size=%d new_prefix_list=%x new_size=%d",
687 __PRETTY_FUNCTION__,
688 (unsigned) neigh->prefix_list,
689 neigh->prefix_list ? (int) listcount(neigh->prefix_list) : -1,
690 (unsigned) addr_list,
691 addr_list ? (int) listcount(addr_list) : -1);
692#endif
693
694 if (neigh->prefix_list == addr_list) {
695 if (addr_list) {
David Lamparter105ad862012-02-16 04:50:35 +0000696 zlog_err("%s: internal error: trying to replace same prefix list=%p",
697 __PRETTY_FUNCTION__, (void *) addr_list);
Everton Marques871dbcf2009-08-11 15:43:05 -0300698 }
699 }
700 else {
701 /* Delete existing secondary address list */
702 delete_prefix_list(neigh);
703 }
704
705 if (addr_list) {
706 delete_from_neigh_addr(neigh->interface, addr_list, neigh->source_addr);
707 }
708
709 /* Replace secondary address list */
710 neigh->prefix_list = addr_list;
711
712 update_dr_priority(neigh,
713 hello_options,
714 dr_priority);
715 /*
716 Copy flags
717 */
718 neigh->hello_options = hello_options;
719}