Annotation of embedaddon/quagga/pimd/pim_neighbor.c, revision 1.1.1.1
1.1 misho 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:
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:
38: static 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:
62: static 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: */
109: int pim_if_dr_election(struct interface *ifp)
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:
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: }
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);
143: return 1;
144: }
145:
146: return 0;
147: }
148:
149: static 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:
205: static 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:
224: neigh->t_expire_timer = 0;
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:
241: static void neighbor_timer_off(struct pim_neighbor *neigh)
242: {
243: if (PIM_DEBUG_PIM_TRACE) {
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:
256: void 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:
269: if (PIM_DEBUG_PIM_TRACE) {
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:
282: static 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:
300: neigh = XMALLOC(MTYPE_PIM_NEIGHBOR, sizeof(*neigh));
301: if (!neigh) {
302: zlog_err("%s: PIM XMALLOC(%zu) failure",
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;
315: neigh->t_expire_timer = 0;
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:
350: return neigh;
351: }
352:
353: static 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:
378: void 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:
387: struct 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:
406: struct pim_neighbor *pim_neighbor_add(struct interface *ifp,
407: struct in_addr source_addr,
408: pim_hello_options hello_options,
409: uint16_t holdtime,
410: uint16_t propagation_delay,
411: uint16_t override_interval,
412: uint32_t dr_priority,
413: uint32_t generation_id,
414: struct list *addr_list)
415: {
416: struct pim_interface *pim_ifp;
417: struct pim_neighbor *neigh;
418:
419: neigh = pim_neighbor_new(ifp, source_addr,
420: hello_options,
421: holdtime,
422: propagation_delay,
423: override_interval,
424: dr_priority,
425: generation_id,
426: addr_list);
427: if (!neigh) {
428: return 0;
429: }
430:
431: pim_ifp = ifp->info;
432: zassert(pim_ifp);
433:
434: listnode_add(pim_ifp->pim_neighbor_list, neigh);
435:
436: /*
437: RFC 4601: 4.3.2. DR Election
438:
439: A router's idea of the current DR on an interface can change when a
440: PIM Hello message is received, when a neighbor times out, or when a
441: router's own DR Priority changes.
442: */
443: pim_if_dr_election(neigh->interface); // new neighbor -- should not trigger dr election...
444:
445: /*
446: RFC 4601: 4.3.1. Sending Hello Messages
447:
448: To allow new or rebooting routers to learn of PIM neighbors quickly,
449: when a Hello message is received from a new neighbor, or a Hello
450: message with a new GenID is received from an existing neighbor, a
451: new Hello message should be sent on this interface after a
452: randomized delay between 0 and Triggered_Hello_Delay.
453: */
454: pim_hello_restart_triggered(neigh->interface);
455:
456: return neigh;
457: }
458:
459: static uint16_t
460: find_neighbors_next_highest_propagation_delay_msec(struct interface *ifp,
461: struct pim_neighbor *highest_neigh)
462: {
463: struct pim_interface *pim_ifp;
464: struct listnode *neigh_node;
465: struct pim_neighbor *neigh;
466: uint16_t next_highest_delay_msec;
467:
468: pim_ifp = ifp->info;
469: zassert(pim_ifp);
470:
471: next_highest_delay_msec = pim_ifp->pim_propagation_delay_msec;
472:
473: for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, neigh_node, neigh)) {
474: if (neigh == highest_neigh)
475: continue;
476: if (neigh->propagation_delay_msec > next_highest_delay_msec)
477: next_highest_delay_msec = neigh->propagation_delay_msec;
478: }
479:
480: return next_highest_delay_msec;
481: }
482:
483: static uint16_t
484: find_neighbors_next_highest_override_interval_msec(struct interface *ifp,
485: struct pim_neighbor *highest_neigh)
486: {
487: struct pim_interface *pim_ifp;
488: struct listnode *neigh_node;
489: struct pim_neighbor *neigh;
490: uint16_t next_highest_interval_msec;
491:
492: pim_ifp = ifp->info;
493: zassert(pim_ifp);
494:
495: next_highest_interval_msec = pim_ifp->pim_override_interval_msec;
496:
497: for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, neigh_node, neigh)) {
498: if (neigh == highest_neigh)
499: continue;
500: if (neigh->override_interval_msec > next_highest_interval_msec)
501: next_highest_interval_msec = neigh->override_interval_msec;
502: }
503:
504: return next_highest_interval_msec;
505: }
506:
507: void pim_neighbor_delete(struct interface *ifp,
508: struct pim_neighbor *neigh,
509: const char *delete_message)
510: {
511: struct pim_interface *pim_ifp;
512: char src_str[100];
513:
514: pim_ifp = ifp->info;
515: zassert(pim_ifp);
516:
517: pim_inet4_dump("<src?>", neigh->source_addr, src_str, sizeof(src_str));
518: zlog_info("PIM NEIGHBOR DOWN: neighbor %s on interface %s: %s",
519: src_str, ifp->name, delete_message);
520:
521: neighbor_timer_off(neigh);
522:
523: pim_if_assert_on_neighbor_down(ifp, neigh->source_addr);
524:
525: if (!PIM_OPTION_IS_SET(neigh->hello_options,
526: PIM_OPTION_MASK_LAN_PRUNE_DELAY)) {
527: /* update num. of neighbors without hello option lan_delay */
528:
529: --pim_ifp->pim_number_of_nonlandelay_neighbors;
530: }
531:
532: if (!PIM_OPTION_IS_SET(neigh->hello_options,
533: PIM_OPTION_MASK_DR_PRIORITY)) {
534: /* update num. of neighbors without dr_pri */
535:
536: --pim_ifp->pim_dr_num_nondrpri_neighbors;
537: }
538:
539: zassert(neigh->propagation_delay_msec <= pim_ifp->pim_neighbors_highest_propagation_delay_msec);
540: zassert(neigh->override_interval_msec <= pim_ifp->pim_neighbors_highest_override_interval_msec);
541:
542: if (pim_if_lan_delay_enabled(ifp)) {
543:
544: /* will delete a neighbor with highest propagation delay? */
545: if (neigh->propagation_delay_msec == pim_ifp->pim_neighbors_highest_propagation_delay_msec) {
546: /* then find the next highest propagation delay */
547: pim_ifp->pim_neighbors_highest_propagation_delay_msec =
548: find_neighbors_next_highest_propagation_delay_msec(ifp, neigh);
549: }
550:
551: /* will delete a neighbor with highest override interval? */
552: if (neigh->override_interval_msec == pim_ifp->pim_neighbors_highest_override_interval_msec) {
553: /* then find the next highest propagation delay */
554: pim_ifp->pim_neighbors_highest_override_interval_msec =
555: find_neighbors_next_highest_override_interval_msec(ifp, neigh);
556: }
557: }
558:
559: if (PIM_DEBUG_PIM_TRACE) {
560: zlog_debug("%s: deleting PIM neighbor %s on interface %s",
561: __PRETTY_FUNCTION__,
562: src_str, ifp->name);
563: }
564:
565: listnode_delete(pim_ifp->pim_neighbor_list, neigh);
566:
567: pim_neighbor_free(neigh);
568: }
569:
570: void pim_neighbor_delete_all(struct interface *ifp,
571: const char *delete_message)
572: {
573: struct pim_interface *pim_ifp;
574: struct listnode *neigh_node;
575: struct listnode *neigh_nextnode;
576: struct pim_neighbor *neigh;
577:
578: pim_ifp = ifp->info;
579: zassert(pim_ifp);
580:
581: for (ALL_LIST_ELEMENTS(pim_ifp->pim_neighbor_list, neigh_node,
582: neigh_nextnode, neigh)) {
583: pim_neighbor_delete(ifp, neigh, delete_message);
584: }
585: }
586:
587: struct prefix *pim_neighbor_find_secondary(struct pim_neighbor *neigh,
588: struct in_addr addr)
589: {
590: struct listnode *node;
591: struct prefix *p;
592:
593: if (!neigh->prefix_list)
594: return 0;
595:
596: for (ALL_LIST_ELEMENTS_RO(neigh->prefix_list, node, p)) {
597: if (p->family == AF_INET) {
598: if (addr.s_addr == p->u.prefix4.s_addr) {
599: return p;
600: }
601: }
602: }
603:
604: return 0;
605: }
606:
607: /*
608: RFC 4601: 4.3.4. Maintaining Secondary Address Lists
609:
610: All the advertised secondary addresses in received Hello messages
611: must be checked against those previously advertised by all other
612: PIM neighbors on that interface. If there is a conflict and the
613: same secondary address was previously advertised by another
614: neighbor, then only the most recently received mapping MUST be
615: maintained, and an error message SHOULD be logged to the
616: administrator in a rate-limited manner.
617: */
618: static void delete_from_neigh_addr(struct interface *ifp,
619: struct list *addr_list,
620: struct in_addr neigh_addr)
621: {
622: struct listnode *addr_node;
623: struct prefix *addr;
624: struct pim_interface *pim_ifp;
625:
626: pim_ifp = ifp->info;
627: zassert(pim_ifp);
628:
629: zassert(addr_list);
630:
631: /*
632: Scan secondary address list
633: */
634: for (ALL_LIST_ELEMENTS_RO(addr_list, addr_node,
635: addr)) {
636: struct listnode *neigh_node;
637: struct pim_neighbor *neigh;
638:
639: if (addr->family != AF_INET)
640: continue;
641:
642: /*
643: Scan neighbors
644: */
645: for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, neigh_node,
646: neigh)) {
647: {
648: struct prefix *p = pim_neighbor_find_secondary(neigh, addr->u.prefix4);
649: if (p) {
650: char addr_str[100];
651: char this_neigh_str[100];
652: char other_neigh_str[100];
653:
654: pim_inet4_dump("<addr?>", addr->u.prefix4, addr_str, sizeof(addr_str));
655: pim_inet4_dump("<neigh1?>", neigh_addr, this_neigh_str, sizeof(this_neigh_str));
656: pim_inet4_dump("<neigh2?>", neigh->source_addr, other_neigh_str, sizeof(other_neigh_str));
657:
658: zlog_info("secondary addr %s recvd from neigh %s deleted from neigh %s on %s",
659: addr_str, this_neigh_str, other_neigh_str, ifp->name);
660:
661: listnode_delete(neigh->prefix_list, p);
662: prefix_free(p);
663: }
664: }
665:
666: } /* scan neighbors */
667:
668: } /* scan addr list */
669:
670: }
671:
672: void pim_neighbor_update(struct pim_neighbor *neigh,
673: pim_hello_options hello_options,
674: uint16_t holdtime,
675: uint32_t dr_priority,
676: struct list *addr_list)
677: {
678: struct pim_interface *pim_ifp = neigh->interface->info;
679:
680: /* Received holdtime ? */
681: if (PIM_OPTION_IS_SET(hello_options, PIM_OPTION_MASK_HOLDTIME)) {
682: pim_neighbor_timer_reset(neigh, holdtime);
683: }
684: else {
685: pim_neighbor_timer_reset(neigh, PIM_IF_DEFAULT_HOLDTIME(pim_ifp));
686: }
687:
688: #ifdef DUMP_PREFIX_LIST
689: zlog_debug("%s: DUMP_PREFIX_LIST old_prefix_list=%x old_size=%d new_prefix_list=%x new_size=%d",
690: __PRETTY_FUNCTION__,
691: (unsigned) neigh->prefix_list,
692: neigh->prefix_list ? (int) listcount(neigh->prefix_list) : -1,
693: (unsigned) addr_list,
694: addr_list ? (int) listcount(addr_list) : -1);
695: #endif
696:
697: if (neigh->prefix_list == addr_list) {
698: if (addr_list) {
699: zlog_err("%s: internal error: trying to replace same prefix list=%p",
700: __PRETTY_FUNCTION__, (void *) addr_list);
701: }
702: }
703: else {
704: /* Delete existing secondary address list */
705: delete_prefix_list(neigh);
706: }
707:
708: if (addr_list) {
709: delete_from_neigh_addr(neigh->interface, addr_list, neigh->source_addr);
710: }
711:
712: /* Replace secondary address list */
713: neigh->prefix_list = addr_list;
714:
715: update_dr_priority(neigh,
716: hello_options,
717: dr_priority);
718: /*
719: Copy flags
720: */
721: neigh->hello_options = hello_options;
722: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>