]> git.proxmox.com Git - mirror_frr.git/blob - pimd/pim_iface.c
Revert "Ospf missing interface handling 2"
[mirror_frr.git] / pimd / pim_iface.c
1 /*
2 * PIM for Quagga
3 * Copyright (C) 2008 Everton da Silva Marques
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License along
15 * with this program; see the file COPYING; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17 */
18
19 #include <zebra.h>
20
21 #include "if.h"
22 #include "log.h"
23 #include "vty.h"
24 #include "memory.h"
25 #include "prefix.h"
26 #include "vrf.h"
27 #include "linklist.h"
28 #include "plist.h"
29 #include "hash.h"
30 #include "ferr.h"
31
32 #include "pimd.h"
33 #include "pim_instance.h"
34 #include "pim_zebra.h"
35 #include "pim_iface.h"
36 #include "pim_igmp.h"
37 #include "pim_mroute.h"
38 #include "pim_oil.h"
39 #include "pim_str.h"
40 #include "pim_pim.h"
41 #include "pim_neighbor.h"
42 #include "pim_ifchannel.h"
43 #include "pim_sock.h"
44 #include "pim_time.h"
45 #include "pim_ssmpingd.h"
46 #include "pim_rp.h"
47 #include "pim_nht.h"
48 #include "pim_jp_agg.h"
49 #include "pim_igmp_join.h"
50 #include "pim_vxlan.h"
51
52 static void pim_if_igmp_join_del_all(struct interface *ifp);
53 static int igmp_join_sock(const char *ifname, ifindex_t ifindex,
54 struct in_addr group_addr,
55 struct in_addr source_addr);
56
57 void pim_if_init(struct pim_instance *pim)
58 {
59 int i;
60
61 for (i = 0; i < MAXVIFS; i++)
62 pim->iface_vif_index[i] = 0;
63 }
64
65 void pim_if_terminate(struct pim_instance *pim)
66 {
67 struct interface *ifp;
68
69 FOR_ALL_INTERFACES (pim->vrf, ifp) {
70 struct pim_interface *pim_ifp = ifp->info;
71
72 if (!pim_ifp)
73 continue;
74
75 pim_if_delete(ifp);
76 }
77 return;
78 }
79
80 static void pim_sec_addr_free(struct pim_secondary_addr *sec_addr)
81 {
82 XFREE(MTYPE_PIM_SEC_ADDR, sec_addr);
83 }
84
85 static int pim_sec_addr_comp(const void *p1, const void *p2)
86 {
87 const struct pim_secondary_addr *sec1 = p1;
88 const struct pim_secondary_addr *sec2 = p2;
89
90 if (sec1->addr.family == AF_INET && sec2->addr.family == AF_INET6)
91 return -1;
92
93 if (sec1->addr.family == AF_INET6 && sec2->addr.family == AF_INET)
94 return 1;
95
96 if (sec1->addr.family == AF_INET) {
97 if (ntohl(sec1->addr.u.prefix4.s_addr)
98 < ntohl(sec2->addr.u.prefix4.s_addr))
99 return -1;
100
101 if (ntohl(sec1->addr.u.prefix4.s_addr)
102 > ntohl(sec2->addr.u.prefix4.s_addr))
103 return 1;
104 } else {
105 return memcmp(&sec1->addr.u.prefix6, &sec2->addr.u.prefix6,
106 sizeof(struct in6_addr));
107 }
108
109 return 0;
110 }
111
112 struct pim_interface *pim_if_new(struct interface *ifp, bool igmp, bool pim,
113 bool ispimreg, bool is_vxlan_term)
114 {
115 struct pim_interface *pim_ifp;
116
117 zassert(ifp);
118 zassert(!ifp->info);
119
120 pim_ifp = XCALLOC(MTYPE_PIM_INTERFACE, sizeof(*pim_ifp));
121
122 pim_ifp->options = 0;
123 pim_ifp->pim = pim_get_pim_instance(ifp->vrf_id);
124 pim_ifp->mroute_vif_index = -1;
125
126 pim_ifp->igmp_version = IGMP_DEFAULT_VERSION;
127 pim_ifp->igmp_default_robustness_variable =
128 IGMP_DEFAULT_ROBUSTNESS_VARIABLE;
129 pim_ifp->igmp_default_query_interval = IGMP_GENERAL_QUERY_INTERVAL;
130 pim_ifp->igmp_query_max_response_time_dsec =
131 IGMP_QUERY_MAX_RESPONSE_TIME_DSEC;
132 pim_ifp->igmp_specific_query_max_response_time_dsec =
133 IGMP_SPECIFIC_QUERY_MAX_RESPONSE_TIME_DSEC;
134 pim_ifp->igmp_last_member_query_count =
135 IGMP_DEFAULT_ROBUSTNESS_VARIABLE;
136
137 /* BSM config on interface: TRUE by default */
138 pim_ifp->bsm_enable = true;
139 pim_ifp->ucast_bsm_accept = true;
140
141 /*
142 RFC 3376: 8.3. Query Response Interval
143 The number of seconds represented by the [Query Response Interval]
144 must be less than the [Query Interval].
145 */
146 zassert(pim_ifp->igmp_query_max_response_time_dsec
147 < pim_ifp->igmp_default_query_interval);
148
149 if (pim)
150 PIM_IF_DO_PIM(pim_ifp->options);
151 if (igmp)
152 PIM_IF_DO_IGMP(pim_ifp->options);
153
154 PIM_IF_DO_IGMP_LISTEN_ALLROUTERS(pim_ifp->options);
155
156 pim_ifp->igmp_join_list = NULL;
157 pim_ifp->igmp_socket_list = NULL;
158 pim_ifp->pim_neighbor_list = NULL;
159 pim_ifp->upstream_switch_list = NULL;
160 pim_ifp->pim_generation_id = 0;
161
162 /* list of struct igmp_sock */
163 pim_ifp->igmp_socket_list = list_new();
164 pim_ifp->igmp_socket_list->del = (void (*)(void *))igmp_sock_free;
165
166 /* list of struct pim_neighbor */
167 pim_ifp->pim_neighbor_list = list_new();
168 pim_ifp->pim_neighbor_list->del = (void (*)(void *))pim_neighbor_free;
169
170 pim_ifp->upstream_switch_list = list_new();
171 pim_ifp->upstream_switch_list->del =
172 (void (*)(void *))pim_jp_agg_group_list_free;
173 pim_ifp->upstream_switch_list->cmp = pim_jp_agg_group_list_cmp;
174
175 pim_ifp->sec_addr_list = list_new();
176 pim_ifp->sec_addr_list->del = (void (*)(void *))pim_sec_addr_free;
177 pim_ifp->sec_addr_list->cmp =
178 (int (*)(void *, void *))pim_sec_addr_comp;
179
180 pim_ifp->activeactive = false;
181
182 RB_INIT(pim_ifchannel_rb, &pim_ifp->ifchannel_rb);
183
184 ifp->info = pim_ifp;
185
186 pim_sock_reset(ifp);
187
188 pim_if_add_vif(ifp, ispimreg, is_vxlan_term);
189
190 return pim_ifp;
191 }
192
193 void pim_if_delete(struct interface *ifp)
194 {
195 struct pim_interface *pim_ifp;
196 struct pim_ifchannel *ch;
197
198 zassert(ifp);
199 pim_ifp = ifp->info;
200 zassert(pim_ifp);
201
202 if (pim_ifp->igmp_join_list) {
203 pim_if_igmp_join_del_all(ifp);
204 }
205
206 pim_ifchannel_delete_all(ifp);
207 igmp_sock_delete_all(ifp);
208
209 pim_neighbor_delete_all(ifp, "Interface removed from configuration");
210
211 pim_if_del_vif(ifp);
212
213 list_delete(&pim_ifp->igmp_socket_list);
214 list_delete(&pim_ifp->pim_neighbor_list);
215 list_delete(&pim_ifp->upstream_switch_list);
216 list_delete(&pim_ifp->sec_addr_list);
217
218 XFREE(MTYPE_PIM_INTERFACE, pim_ifp->boundary_oil_plist);
219
220 while (!RB_EMPTY(pim_ifchannel_rb, &pim_ifp->ifchannel_rb)) {
221 ch = RB_ROOT(pim_ifchannel_rb, &pim_ifp->ifchannel_rb);
222
223 pim_ifchannel_delete(ch);
224 }
225
226 XFREE(MTYPE_PIM_INTERFACE, pim_ifp);
227
228 ifp->info = NULL;
229 }
230
231 void pim_if_update_could_assert(struct interface *ifp)
232 {
233 struct pim_interface *pim_ifp;
234 struct pim_ifchannel *ch;
235
236 pim_ifp = ifp->info;
237 zassert(pim_ifp);
238
239 RB_FOREACH (ch, pim_ifchannel_rb, &pim_ifp->ifchannel_rb) {
240 pim_ifchannel_update_could_assert(ch);
241 }
242 }
243
244 static void pim_if_update_my_assert_metric(struct interface *ifp)
245 {
246 struct pim_interface *pim_ifp;
247 struct pim_ifchannel *ch;
248
249 pim_ifp = ifp->info;
250 zassert(pim_ifp);
251
252 RB_FOREACH (ch, pim_ifchannel_rb, &pim_ifp->ifchannel_rb) {
253 pim_ifchannel_update_my_assert_metric(ch);
254 }
255 }
256
257 static void pim_addr_change(struct interface *ifp)
258 {
259 struct pim_interface *pim_ifp;
260
261 pim_ifp = ifp->info;
262 zassert(pim_ifp);
263
264 pim_if_dr_election(ifp); /* router's own DR Priority (addr) changes --
265 Done TODO T30 */
266 pim_if_update_join_desired(pim_ifp); /* depends on DR */
267 pim_if_update_could_assert(ifp); /* depends on DR */
268 pim_if_update_my_assert_metric(ifp); /* depends on could_assert */
269 pim_if_update_assert_tracking_desired(
270 ifp); /* depends on DR, join_desired */
271
272 /*
273 RFC 4601: 4.3.1. Sending Hello Messages
274
275 1) Before an interface goes down or changes primary IP address, a
276 Hello message with a zero HoldTime should be sent immediately
277 (with the old IP address if the IP address changed).
278 -- FIXME See CAVEAT C13
279
280 2) After an interface has changed its IP address, it MUST send a
281 Hello message with its new IP address.
282 -- DONE below
283
284 3) If an interface changes one of its secondary IP addresses, a
285 Hello message with an updated Address_List option and a non-zero
286 HoldTime should be sent immediately.
287 -- FIXME See TODO T31
288 */
289 pim_ifp->pim_ifstat_hello_sent = 0; /* reset hello counter */
290 if (pim_ifp->pim_sock_fd < 0)
291 return;
292 pim_hello_restart_now(ifp); /* send hello and restart timer */
293 }
294
295 static int detect_primary_address_change(struct interface *ifp,
296 int force_prim_as_any,
297 const char *caller)
298 {
299 struct pim_interface *pim_ifp = ifp->info;
300 struct in_addr new_prim_addr;
301 int changed;
302
303 if (force_prim_as_any)
304 new_prim_addr.s_addr = INADDR_ANY;
305 else
306 new_prim_addr = pim_find_primary_addr(ifp);
307
308 changed = new_prim_addr.s_addr != pim_ifp->primary_address.s_addr;
309
310 if (PIM_DEBUG_ZEBRA) {
311 char new_prim_str[INET_ADDRSTRLEN];
312 char old_prim_str[INET_ADDRSTRLEN];
313 pim_inet4_dump("<new?>", new_prim_addr, new_prim_str,
314 sizeof(new_prim_str));
315 pim_inet4_dump("<old?>", pim_ifp->primary_address, old_prim_str,
316 sizeof(old_prim_str));
317 zlog_debug("%s: old=%s new=%s on interface %s: %s",
318 __PRETTY_FUNCTION__, old_prim_str, new_prim_str,
319 ifp->name, changed ? "changed" : "unchanged");
320 }
321
322 if (changed) {
323 pim_ifp->primary_address = new_prim_addr;
324 }
325
326 return changed;
327 }
328
329 static struct pim_secondary_addr *
330 pim_sec_addr_find(struct pim_interface *pim_ifp, struct prefix *addr)
331 {
332 struct pim_secondary_addr *sec_addr;
333 struct listnode *node;
334
335 for (ALL_LIST_ELEMENTS_RO(pim_ifp->sec_addr_list, node, sec_addr)) {
336 if (prefix_cmp(&sec_addr->addr, addr)) {
337 return sec_addr;
338 }
339 }
340
341 return NULL;
342 }
343
344 static void pim_sec_addr_del(struct pim_interface *pim_ifp,
345 struct pim_secondary_addr *sec_addr)
346 {
347 listnode_delete(pim_ifp->sec_addr_list, sec_addr);
348 pim_sec_addr_free(sec_addr);
349 }
350
351 static int pim_sec_addr_add(struct pim_interface *pim_ifp, struct prefix *addr)
352 {
353 int changed = 0;
354 struct pim_secondary_addr *sec_addr;
355
356 sec_addr = pim_sec_addr_find(pim_ifp, addr);
357 if (sec_addr) {
358 sec_addr->flags &= ~PIM_SEC_ADDRF_STALE;
359 return changed;
360 }
361
362 sec_addr = XCALLOC(MTYPE_PIM_SEC_ADDR, sizeof(*sec_addr));
363
364 changed = 1;
365 sec_addr->addr = *addr;
366 listnode_add_sort(pim_ifp->sec_addr_list, sec_addr);
367
368 return changed;
369 }
370
371 static int pim_sec_addr_del_all(struct pim_interface *pim_ifp)
372 {
373 int changed = 0;
374
375 if (!list_isempty(pim_ifp->sec_addr_list)) {
376 changed = 1;
377 /* remove all nodes and free up the list itself */
378 list_delete_all_node(pim_ifp->sec_addr_list);
379 }
380
381 return changed;
382 }
383
384 static int pim_sec_addr_update(struct interface *ifp)
385 {
386 struct pim_interface *pim_ifp = ifp->info;
387 struct connected *ifc;
388 struct listnode *node;
389 struct listnode *nextnode;
390 struct pim_secondary_addr *sec_addr;
391 int changed = 0;
392
393 for (ALL_LIST_ELEMENTS_RO(pim_ifp->sec_addr_list, node, sec_addr)) {
394 sec_addr->flags |= PIM_SEC_ADDRF_STALE;
395 }
396
397 for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, ifc)) {
398 struct prefix *p = ifc->address;
399
400 if (PIM_INADDR_IS_ANY(p->u.prefix4)) {
401 continue;
402 }
403
404 if (pim_ifp->primary_address.s_addr == p->u.prefix4.s_addr) {
405 /* don't add the primary address into the secondary
406 * address list */
407 continue;
408 }
409
410 if (pim_sec_addr_add(pim_ifp, p)) {
411 changed = 1;
412 }
413 }
414
415 /* Drop stale entries */
416 for (ALL_LIST_ELEMENTS(pim_ifp->sec_addr_list, node, nextnode,
417 sec_addr)) {
418 if (sec_addr->flags & PIM_SEC_ADDRF_STALE) {
419 pim_sec_addr_del(pim_ifp, sec_addr);
420 changed = 1;
421 }
422 }
423
424 return changed;
425 }
426
427 static int detect_secondary_address_change(struct interface *ifp,
428 int force_prim_as_any,
429 const char *caller)
430 {
431 struct pim_interface *pim_ifp = ifp->info;
432 int changed = 0;
433
434 if (force_prim_as_any) {
435 /* if primary address is being forced to zero just flush the
436 * secondary address list */
437 changed = pim_sec_addr_del_all(pim_ifp);
438 } else {
439 /* re-evaluate the secondary address list */
440 changed = pim_sec_addr_update(ifp);
441 }
442
443 return changed;
444 }
445
446 static void detect_address_change(struct interface *ifp, int force_prim_as_any,
447 const char *caller)
448 {
449 int changed = 0;
450 struct pim_interface *pim_ifp;
451
452 pim_ifp = ifp->info;
453 if (!pim_ifp)
454 return;
455
456 if (detect_primary_address_change(ifp, force_prim_as_any, caller)) {
457 changed = 1;
458 }
459
460 if (detect_secondary_address_change(ifp, force_prim_as_any, caller)) {
461 changed = 1;
462 }
463
464
465 if (changed) {
466 if (!PIM_IF_TEST_PIM(pim_ifp->options)) {
467 return;
468 }
469
470 pim_addr_change(ifp);
471 }
472
473 /* XXX: if we have unnumbered interfaces we need to run detect address
474 * address change on all of them when the lo address changes */
475 }
476
477 int pim_update_source_set(struct interface *ifp, struct in_addr source)
478 {
479 struct pim_interface *pim_ifp = ifp->info;
480
481 if (!pim_ifp) {
482 return PIM_IFACE_NOT_FOUND;
483 }
484
485 if (pim_ifp->update_source.s_addr == source.s_addr) {
486 return PIM_UPDATE_SOURCE_DUP;
487 }
488
489 pim_ifp->update_source = source;
490 detect_address_change(ifp, 0 /* force_prim_as_any */,
491 __PRETTY_FUNCTION__);
492
493 return PIM_SUCCESS;
494 }
495
496 void pim_if_addr_add(struct connected *ifc)
497 {
498 struct pim_interface *pim_ifp;
499 struct interface *ifp;
500 struct in_addr ifaddr;
501
502 zassert(ifc);
503
504 ifp = ifc->ifp;
505 zassert(ifp);
506 pim_ifp = ifp->info;
507 if (!pim_ifp)
508 return;
509
510 if (!if_is_operative(ifp))
511 return;
512
513 if (PIM_DEBUG_ZEBRA) {
514 char buf[BUFSIZ];
515 prefix2str(ifc->address, buf, BUFSIZ);
516 zlog_debug("%s: %s ifindex=%d connected IP address %s %s",
517 __PRETTY_FUNCTION__, ifp->name, ifp->ifindex, buf,
518 CHECK_FLAG(ifc->flags, ZEBRA_IFA_SECONDARY)
519 ? "secondary"
520 : "primary");
521 }
522
523 ifaddr = ifc->address->u.prefix4;
524
525 detect_address_change(ifp, 0, __PRETTY_FUNCTION__);
526
527 // if (ifc->address->family != AF_INET)
528 // return;
529
530 if (PIM_IF_TEST_IGMP(pim_ifp->options)) {
531 struct igmp_sock *igmp;
532
533 /* lookup IGMP socket */
534 igmp = pim_igmp_sock_lookup_ifaddr(pim_ifp->igmp_socket_list,
535 ifaddr);
536 if (!igmp) {
537 /* if addr new, add IGMP socket */
538 if (ifc->address->family == AF_INET)
539 pim_igmp_sock_add(pim_ifp->igmp_socket_list,
540 ifaddr, ifp, false);
541 } else if (igmp->mtrace_only) {
542 igmp_sock_delete(igmp);
543 pim_igmp_sock_add(pim_ifp->igmp_socket_list, ifaddr,
544 ifp, false);
545 }
546
547 /* Replay Static IGMP groups */
548 if (pim_ifp->igmp_join_list) {
549 struct listnode *node;
550 struct listnode *nextnode;
551 struct igmp_join *ij;
552 int join_fd;
553
554 for (ALL_LIST_ELEMENTS(pim_ifp->igmp_join_list, node,
555 nextnode, ij)) {
556 /* Close socket and reopen with Source and Group
557 */
558 close(ij->sock_fd);
559 join_fd = igmp_join_sock(
560 ifp->name, ifp->ifindex, ij->group_addr,
561 ij->source_addr);
562 if (join_fd < 0) {
563 char group_str[INET_ADDRSTRLEN];
564 char source_str[INET_ADDRSTRLEN];
565 pim_inet4_dump("<grp?>", ij->group_addr,
566 group_str,
567 sizeof(group_str));
568 pim_inet4_dump(
569 "<src?>", ij->source_addr,
570 source_str, sizeof(source_str));
571 zlog_warn(
572 "%s: igmp_join_sock() failure for IGMP group %s source %s on interface %s",
573 __PRETTY_FUNCTION__, group_str,
574 source_str, ifp->name);
575 /* warning only */
576 } else
577 ij->sock_fd = join_fd;
578 }
579 }
580 } /* igmp */
581 else {
582 struct igmp_sock *igmp;
583
584 /* lookup IGMP socket */
585 igmp = pim_igmp_sock_lookup_ifaddr(pim_ifp->igmp_socket_list,
586 ifaddr);
587 if (ifc->address->family == AF_INET) {
588 if (igmp)
589 igmp_sock_delete(igmp);
590 /* if addr new, add IGMP socket */
591 pim_igmp_sock_add(pim_ifp->igmp_socket_list, ifaddr,
592 ifp, true);
593 }
594 } /* igmp mtrace only */
595
596 if (PIM_IF_TEST_PIM(pim_ifp->options)) {
597
598 if (PIM_INADDR_ISNOT_ANY(pim_ifp->primary_address)) {
599
600 /* Interface has a valid socket ? */
601 if (pim_ifp->pim_sock_fd < 0) {
602 if (pim_sock_add(ifp)) {
603 zlog_warn(
604 "Failure creating PIM socket for interface %s",
605 ifp->name);
606 }
607 }
608 struct pim_nexthop_cache *pnc = NULL;
609 struct pim_rpf rpf;
610 struct zclient *zclient = NULL;
611
612 zclient = pim_zebra_zclient_get();
613 /* RP config might come prior to (local RP's interface)
614 IF UP event.
615 In this case, pnc would not have pim enabled
616 nexthops.
617 Once Interface is UP and pim info is available,
618 reregister
619 with RNH address to receive update and add the
620 interface as nexthop. */
621 memset(&rpf, 0, sizeof(struct pim_rpf));
622 rpf.rpf_addr.family = AF_INET;
623 rpf.rpf_addr.prefixlen = IPV4_MAX_BITLEN;
624 rpf.rpf_addr.u.prefix4 = ifc->address->u.prefix4;
625 pnc = pim_nexthop_cache_find(pim_ifp->pim, &rpf);
626 if (pnc)
627 pim_sendmsg_zebra_rnh(pim_ifp->pim, zclient,
628 pnc,
629 ZEBRA_NEXTHOP_REGISTER);
630 }
631 } /* pim */
632
633 /*
634 PIM or IGMP is enabled on interface, and there is at least one
635 address assigned, then try to create a vif_index.
636 */
637 if (pim_ifp->mroute_vif_index < 0) {
638 pim_if_add_vif(ifp, false, false /*vxlan_term*/);
639 }
640 pim_ifchannel_scan_forward_start(ifp);
641 }
642
643 static void pim_if_addr_del_igmp(struct connected *ifc)
644 {
645 struct pim_interface *pim_ifp = ifc->ifp->info;
646 struct igmp_sock *igmp;
647 struct in_addr ifaddr;
648
649 if (ifc->address->family != AF_INET) {
650 /* non-IPv4 address */
651 return;
652 }
653
654 if (!pim_ifp) {
655 /* IGMP not enabled on interface */
656 return;
657 }
658
659 ifaddr = ifc->address->u.prefix4;
660
661 /* lookup IGMP socket */
662 igmp = pim_igmp_sock_lookup_ifaddr(pim_ifp->igmp_socket_list, ifaddr);
663 if (igmp) {
664 /* if addr found, del IGMP socket */
665 igmp_sock_delete(igmp);
666 }
667 }
668
669 static void pim_if_addr_del_pim(struct connected *ifc)
670 {
671 struct pim_interface *pim_ifp = ifc->ifp->info;
672
673 if (ifc->address->family != AF_INET) {
674 /* non-IPv4 address */
675 return;
676 }
677
678 if (!pim_ifp) {
679 /* PIM not enabled on interface */
680 return;
681 }
682
683 if (PIM_INADDR_ISNOT_ANY(pim_ifp->primary_address)) {
684 /* Interface keeps a valid primary address */
685 return;
686 }
687
688 if (pim_ifp->pim_sock_fd < 0) {
689 /* Interface does not hold a valid socket any longer */
690 return;
691 }
692
693 /*
694 pim_sock_delete() closes the socket, stops read and timer threads,
695 and kills all neighbors.
696 */
697 pim_sock_delete(ifc->ifp,
698 "last address has been removed from interface");
699 }
700
701 void pim_if_addr_del(struct connected *ifc, int force_prim_as_any)
702 {
703 struct interface *ifp;
704
705 zassert(ifc);
706 ifp = ifc->ifp;
707 zassert(ifp);
708
709 if (PIM_DEBUG_ZEBRA) {
710 char buf[BUFSIZ];
711 prefix2str(ifc->address, buf, BUFSIZ);
712 zlog_debug("%s: %s ifindex=%d disconnected IP address %s %s",
713 __PRETTY_FUNCTION__, ifp->name, ifp->ifindex, buf,
714 CHECK_FLAG(ifc->flags, ZEBRA_IFA_SECONDARY)
715 ? "secondary"
716 : "primary");
717 }
718
719 detect_address_change(ifp, force_prim_as_any, __PRETTY_FUNCTION__);
720
721 pim_if_addr_del_igmp(ifc);
722 pim_if_addr_del_pim(ifc);
723 }
724
725 void pim_if_addr_add_all(struct interface *ifp)
726 {
727 struct connected *ifc;
728 struct listnode *node;
729 struct listnode *nextnode;
730 int v4_addrs = 0;
731 int v6_addrs = 0;
732 struct pim_interface *pim_ifp = ifp->info;
733
734
735 /* PIM/IGMP enabled ? */
736 if (!pim_ifp)
737 return;
738
739 for (ALL_LIST_ELEMENTS(ifp->connected, node, nextnode, ifc)) {
740 struct prefix *p = ifc->address;
741
742 if (p->family != AF_INET)
743 v6_addrs++;
744 else
745 v4_addrs++;
746 pim_if_addr_add(ifc);
747 }
748
749 if (!v4_addrs && v6_addrs && !if_is_loopback(ifp)) {
750 if (PIM_IF_TEST_PIM(pim_ifp->options)) {
751
752 /* Interface has a valid primary address ? */
753 if (PIM_INADDR_ISNOT_ANY(pim_ifp->primary_address)) {
754
755 /* Interface has a valid socket ? */
756 if (pim_ifp->pim_sock_fd < 0) {
757 if (pim_sock_add(ifp)) {
758 zlog_warn(
759 "Failure creating PIM socket for interface %s",
760 ifp->name);
761 }
762 }
763 }
764 } /* pim */
765 }
766 /*
767 * PIM or IGMP is enabled on interface, and there is at least one
768 * address assigned, then try to create a vif_index.
769 */
770 if (pim_ifp->mroute_vif_index < 0) {
771 pim_if_add_vif(ifp, false, false /*vxlan_term*/);
772 }
773 pim_ifchannel_scan_forward_start(ifp);
774
775 pim_rp_setup(pim_ifp->pim);
776 pim_rp_check_on_if_add(pim_ifp);
777 }
778
779 void pim_if_addr_del_all(struct interface *ifp)
780 {
781 struct connected *ifc;
782 struct listnode *node;
783 struct listnode *nextnode;
784 struct vrf *vrf = vrf_lookup_by_id(ifp->vrf_id);
785 struct pim_instance *pim;
786
787 if (!vrf)
788 return;
789 pim = vrf->info;
790
791 /* PIM/IGMP enabled ? */
792 if (!ifp->info)
793 return;
794
795 for (ALL_LIST_ELEMENTS(ifp->connected, node, nextnode, ifc)) {
796 struct prefix *p = ifc->address;
797
798 if (p->family != AF_INET)
799 continue;
800
801 pim_if_addr_del(ifc, 1 /* force_prim_as_any=true */);
802 }
803
804 pim_rp_setup(pim);
805 pim_i_am_rp_re_evaluate(pim);
806 }
807
808 void pim_if_addr_del_all_igmp(struct interface *ifp)
809 {
810 struct connected *ifc;
811 struct listnode *node;
812 struct listnode *nextnode;
813
814 /* PIM/IGMP enabled ? */
815 if (!ifp->info)
816 return;
817
818 for (ALL_LIST_ELEMENTS(ifp->connected, node, nextnode, ifc)) {
819 struct prefix *p = ifc->address;
820
821 if (p->family != AF_INET)
822 continue;
823
824 pim_if_addr_del_igmp(ifc);
825 }
826 }
827
828 void pim_if_addr_del_all_pim(struct interface *ifp)
829 {
830 struct connected *ifc;
831 struct listnode *node;
832 struct listnode *nextnode;
833
834 /* PIM/IGMP enabled ? */
835 if (!ifp->info)
836 return;
837
838 for (ALL_LIST_ELEMENTS(ifp->connected, node, nextnode, ifc)) {
839 struct prefix *p = ifc->address;
840
841 if (p->family != AF_INET)
842 continue;
843
844 pim_if_addr_del_pim(ifc);
845 }
846 }
847
848 struct in_addr pim_find_primary_addr(struct interface *ifp)
849 {
850 struct connected *ifc;
851 struct listnode *node;
852 struct in_addr addr = {0};
853 int v4_addrs = 0;
854 int v6_addrs = 0;
855 struct pim_interface *pim_ifp = ifp->info;
856 struct vrf *vrf = vrf_lookup_by_id(ifp->vrf_id);
857
858 if (!vrf)
859 return addr;
860
861 if (pim_ifp && PIM_INADDR_ISNOT_ANY(pim_ifp->update_source)) {
862 return pim_ifp->update_source;
863 }
864
865 for (ALL_LIST_ELEMENTS_RO(ifp->connected, node, ifc)) {
866 struct prefix *p = ifc->address;
867
868 if (p->family != AF_INET) {
869 v6_addrs++;
870 continue;
871 }
872
873 if (PIM_INADDR_IS_ANY(p->u.prefix4)) {
874 zlog_warn(
875 "%s: null IPv4 address connected to interface %s",
876 __PRETTY_FUNCTION__, ifp->name);
877 continue;
878 }
879
880 v4_addrs++;
881
882 if (CHECK_FLAG(ifc->flags, ZEBRA_IFA_SECONDARY))
883 continue;
884
885 return p->u.prefix4;
886 }
887
888 /*
889 * If we have no v4_addrs and v6 is configured
890 * We probably are using unnumbered
891 * So let's grab the loopbacks v4 address
892 * and use that as the primary address
893 */
894 if (!v4_addrs && v6_addrs && !if_is_loopback(ifp)) {
895 struct interface *lo_ifp;
896 // DBS - Come back and check here
897 if (ifp->vrf_id == VRF_DEFAULT)
898 lo_ifp = if_lookup_by_name("lo", vrf->vrf_id);
899 else
900 lo_ifp = if_lookup_by_name(vrf->name, vrf->vrf_id);
901
902 if (lo_ifp)
903 return pim_find_primary_addr(lo_ifp);
904 }
905
906 addr.s_addr = PIM_NET_INADDR_ANY;
907
908 return addr;
909 }
910
911 static int pim_iface_next_vif_index(struct interface *ifp)
912 {
913 struct pim_interface *pim_ifp = ifp->info;
914 struct pim_instance *pim = pim_ifp->pim;
915 int i;
916
917 /*
918 * The pimreg vif is always going to be in index 0
919 * of the table.
920 */
921 if (ifp->ifindex == PIM_OIF_PIM_REGISTER_VIF)
922 return 0;
923
924 for (i = 1; i < MAXVIFS; i++) {
925 if (pim->iface_vif_index[i] == 0)
926 return i;
927 }
928 return MAXVIFS;
929 }
930
931 /*
932 pim_if_add_vif() uses ifindex as vif_index
933
934 see also pim_if_find_vifindex_by_ifindex()
935 */
936 int pim_if_add_vif(struct interface *ifp, bool ispimreg, bool is_vxlan_term)
937 {
938 struct pim_interface *pim_ifp = ifp->info;
939 struct in_addr ifaddr;
940 unsigned char flags = 0;
941
942 zassert(pim_ifp);
943
944 if (pim_ifp->mroute_vif_index > 0) {
945 zlog_warn("%s: vif_index=%d > 0 on interface %s ifindex=%d",
946 __PRETTY_FUNCTION__, pim_ifp->mroute_vif_index,
947 ifp->name, ifp->ifindex);
948 return -1;
949 }
950
951 if (ifp->ifindex < 0) {
952 zlog_warn("%s: ifindex=%d < 1 on interface %s",
953 __PRETTY_FUNCTION__, ifp->ifindex, ifp->name);
954 return -2;
955 }
956
957 ifaddr = pim_ifp->primary_address;
958 if (!ispimreg && !is_vxlan_term && PIM_INADDR_IS_ANY(ifaddr)) {
959 zlog_warn(
960 "%s: could not get address for interface %s ifindex=%d",
961 __PRETTY_FUNCTION__, ifp->name, ifp->ifindex);
962 return -4;
963 }
964
965 pim_ifp->mroute_vif_index = pim_iface_next_vif_index(ifp);
966
967 if (pim_ifp->mroute_vif_index >= MAXVIFS) {
968 zlog_warn(
969 "%s: Attempting to configure more than MAXVIFS=%d on pim enabled interface %s",
970 __PRETTY_FUNCTION__, MAXVIFS, ifp->name);
971 return -3;
972 }
973
974 if (ifp->ifindex == PIM_OIF_PIM_REGISTER_VIF)
975 flags = VIFF_REGISTER;
976 #ifdef VIFF_USE_IFINDEX
977 else
978 flags = VIFF_USE_IFINDEX;
979 #endif
980
981 if (pim_mroute_add_vif(ifp, ifaddr, flags)) {
982 /* pim_mroute_add_vif reported error */
983 return -5;
984 }
985
986 pim_ifp->pim->iface_vif_index[pim_ifp->mroute_vif_index] = 1;
987
988 /* if the device qualifies as pim_vxlan iif/oif update vxlan entries */
989 pim_vxlan_add_vif(ifp);
990
991 return 0;
992 }
993
994 int pim_if_del_vif(struct interface *ifp)
995 {
996 struct pim_interface *pim_ifp = ifp->info;
997
998 if (pim_ifp->mroute_vif_index < 1) {
999 zlog_warn("%s: vif_index=%d < 1 on interface %s ifindex=%d",
1000 __PRETTY_FUNCTION__, pim_ifp->mroute_vif_index,
1001 ifp->name, ifp->ifindex);
1002 return -1;
1003 }
1004
1005 /* if the device was a pim_vxlan iif/oif update vxlan mroute entries */
1006 pim_vxlan_del_vif(ifp);
1007
1008 pim_mroute_del_vif(ifp);
1009
1010 /*
1011 Update vif_index
1012 */
1013 pim_ifp->pim->iface_vif_index[pim_ifp->mroute_vif_index] = 0;
1014
1015 pim_ifp->mroute_vif_index = -1;
1016
1017 return 0;
1018 }
1019
1020 // DBS - VRF Revist
1021 struct interface *pim_if_find_by_vif_index(struct pim_instance *pim,
1022 ifindex_t vif_index)
1023 {
1024 struct interface *ifp;
1025
1026 FOR_ALL_INTERFACES (pim->vrf, ifp) {
1027 if (ifp->info) {
1028 struct pim_interface *pim_ifp;
1029 pim_ifp = ifp->info;
1030
1031 if (vif_index == pim_ifp->mroute_vif_index)
1032 return ifp;
1033 }
1034 }
1035
1036 return 0;
1037 }
1038
1039 /*
1040 pim_if_add_vif() uses ifindex as vif_index
1041 */
1042 int pim_if_find_vifindex_by_ifindex(struct pim_instance *pim, ifindex_t ifindex)
1043 {
1044 struct pim_interface *pim_ifp;
1045 struct interface *ifp;
1046
1047 ifp = if_lookup_by_index(ifindex, pim->vrf_id);
1048 if (!ifp || !ifp->info)
1049 return -1;
1050 pim_ifp = ifp->info;
1051
1052 return pim_ifp->mroute_vif_index;
1053 }
1054
1055 int pim_if_lan_delay_enabled(struct interface *ifp)
1056 {
1057 struct pim_interface *pim_ifp;
1058
1059 pim_ifp = ifp->info;
1060 zassert(pim_ifp);
1061 zassert(pim_ifp->pim_number_of_nonlandelay_neighbors >= 0);
1062
1063 return pim_ifp->pim_number_of_nonlandelay_neighbors == 0;
1064 }
1065
1066 uint16_t pim_if_effective_propagation_delay_msec(struct interface *ifp)
1067 {
1068 if (pim_if_lan_delay_enabled(ifp)) {
1069 struct pim_interface *pim_ifp;
1070 pim_ifp = ifp->info;
1071 return pim_ifp->pim_neighbors_highest_propagation_delay_msec;
1072 } else {
1073 return PIM_DEFAULT_PROPAGATION_DELAY_MSEC;
1074 }
1075 }
1076
1077 uint16_t pim_if_effective_override_interval_msec(struct interface *ifp)
1078 {
1079 if (pim_if_lan_delay_enabled(ifp)) {
1080 struct pim_interface *pim_ifp;
1081 pim_ifp = ifp->info;
1082 return pim_ifp->pim_neighbors_highest_override_interval_msec;
1083 } else {
1084 return PIM_DEFAULT_OVERRIDE_INTERVAL_MSEC;
1085 }
1086 }
1087
1088 int pim_if_t_override_msec(struct interface *ifp)
1089 {
1090 int effective_override_interval_msec;
1091 int t_override_msec;
1092
1093 effective_override_interval_msec =
1094 pim_if_effective_override_interval_msec(ifp);
1095
1096 t_override_msec = random() % (effective_override_interval_msec + 1);
1097
1098 return t_override_msec;
1099 }
1100
1101 uint16_t pim_if_jp_override_interval_msec(struct interface *ifp)
1102 {
1103 return pim_if_effective_propagation_delay_msec(ifp)
1104 + pim_if_effective_override_interval_msec(ifp);
1105 }
1106
1107 /*
1108 RFC 4601: 4.1.6. State Summarization Macros
1109
1110 The function NBR( I, A ) uses information gathered through PIM Hello
1111 messages to map the IP address A of a directly connected PIM
1112 neighbor router on interface I to the primary IP address of the same
1113 router (Section 4.3.4). The primary IP address of a neighbor is the
1114 address that it uses as the source of its PIM Hello messages.
1115 */
1116 struct pim_neighbor *pim_if_find_neighbor(struct interface *ifp,
1117 struct in_addr addr)
1118 {
1119 struct listnode *neighnode;
1120 struct pim_neighbor *neigh;
1121 struct pim_interface *pim_ifp;
1122 struct prefix p;
1123
1124 zassert(ifp);
1125
1126 pim_ifp = ifp->info;
1127 if (!pim_ifp) {
1128 zlog_warn("%s: multicast not enabled on interface %s",
1129 __PRETTY_FUNCTION__, ifp->name);
1130 return 0;
1131 }
1132
1133 p.family = AF_INET;
1134 p.u.prefix4 = addr;
1135 p.prefixlen = IPV4_MAX_PREFIXLEN;
1136
1137 for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, neighnode,
1138 neigh)) {
1139
1140 /* primary address ? */
1141 if (neigh->source_addr.s_addr == addr.s_addr)
1142 return neigh;
1143
1144 /* secondary address ? */
1145 if (pim_neighbor_find_secondary(neigh, &p))
1146 return neigh;
1147 }
1148
1149 if (PIM_DEBUG_PIM_TRACE) {
1150 char addr_str[INET_ADDRSTRLEN];
1151 pim_inet4_dump("<addr?>", addr, addr_str, sizeof(addr_str));
1152 zlog_debug(
1153 "%s: neighbor not found for address %s on interface %s",
1154 __PRETTY_FUNCTION__, addr_str, ifp->name);
1155 }
1156
1157 return NULL;
1158 }
1159
1160 long pim_if_t_suppressed_msec(struct interface *ifp)
1161 {
1162 struct pim_interface *pim_ifp;
1163 long t_suppressed_msec;
1164 uint32_t ramount = 0;
1165
1166 pim_ifp = ifp->info;
1167 zassert(pim_ifp);
1168
1169 /* join suppression disabled ? */
1170 if (PIM_IF_TEST_PIM_CAN_DISABLE_JOIN_SUPRESSION(pim_ifp->options))
1171 return 0;
1172
1173 /* t_suppressed = t_periodic * rand(1.1, 1.4) */
1174 ramount = 1100 + (random() % (1400 - 1100 + 1));
1175 t_suppressed_msec = router->t_periodic * ramount;
1176
1177 return t_suppressed_msec;
1178 }
1179
1180 static void igmp_join_free(struct igmp_join *ij)
1181 {
1182 XFREE(MTYPE_PIM_IGMP_JOIN, ij);
1183 }
1184
1185 static struct igmp_join *igmp_join_find(struct list *join_list,
1186 struct in_addr group_addr,
1187 struct in_addr source_addr)
1188 {
1189 struct listnode *node;
1190 struct igmp_join *ij;
1191
1192 zassert(join_list);
1193
1194 for (ALL_LIST_ELEMENTS_RO(join_list, node, ij)) {
1195 if ((group_addr.s_addr == ij->group_addr.s_addr)
1196 && (source_addr.s_addr == ij->source_addr.s_addr))
1197 return ij;
1198 }
1199
1200 return 0;
1201 }
1202
1203 static int igmp_join_sock(const char *ifname, ifindex_t ifindex,
1204 struct in_addr group_addr, struct in_addr source_addr)
1205 {
1206 int join_fd;
1207
1208 join_fd = pim_socket_raw(IPPROTO_IGMP);
1209 if (join_fd < 0) {
1210 return -1;
1211 }
1212
1213 if (pim_igmp_join_source(join_fd, ifindex, group_addr, source_addr)) {
1214 char group_str[INET_ADDRSTRLEN];
1215 char source_str[INET_ADDRSTRLEN];
1216 pim_inet4_dump("<grp?>", group_addr, group_str,
1217 sizeof(group_str));
1218 pim_inet4_dump("<src?>", source_addr, source_str,
1219 sizeof(source_str));
1220 zlog_warn(
1221 "%s: setsockopt(fd=%d) failure for IGMP group %s source %s ifindex %d on interface %s: errno=%d: %s",
1222 __PRETTY_FUNCTION__, join_fd, group_str, source_str,
1223 ifindex, ifname, errno, safe_strerror(errno));
1224
1225 close(join_fd);
1226 return -2;
1227 }
1228
1229 return join_fd;
1230 }
1231
1232 static struct igmp_join *igmp_join_new(struct interface *ifp,
1233 struct in_addr group_addr,
1234 struct in_addr source_addr)
1235 {
1236 struct pim_interface *pim_ifp;
1237 struct igmp_join *ij;
1238 int join_fd;
1239
1240 pim_ifp = ifp->info;
1241 zassert(pim_ifp);
1242
1243 join_fd = igmp_join_sock(ifp->name, ifp->ifindex, group_addr,
1244 source_addr);
1245 if (join_fd < 0) {
1246 char group_str[INET_ADDRSTRLEN];
1247 char source_str[INET_ADDRSTRLEN];
1248
1249 pim_inet4_dump("<grp?>", group_addr, group_str,
1250 sizeof(group_str));
1251 pim_inet4_dump("<src?>", source_addr, source_str,
1252 sizeof(source_str));
1253 zlog_warn(
1254 "%s: igmp_join_sock() failure for IGMP group %s source %s on interface %s",
1255 __PRETTY_FUNCTION__, group_str, source_str, ifp->name);
1256 return 0;
1257 }
1258
1259 ij = XCALLOC(MTYPE_PIM_IGMP_JOIN, sizeof(*ij));
1260
1261 ij->sock_fd = join_fd;
1262 ij->group_addr = group_addr;
1263 ij->source_addr = source_addr;
1264 ij->sock_creation = pim_time_monotonic_sec();
1265
1266 listnode_add(pim_ifp->igmp_join_list, ij);
1267
1268 return ij;
1269 }
1270
1271 ferr_r pim_if_igmp_join_add(struct interface *ifp, struct in_addr group_addr,
1272 struct in_addr source_addr)
1273 {
1274 struct pim_interface *pim_ifp;
1275 struct igmp_join *ij;
1276
1277 pim_ifp = ifp->info;
1278 if (!pim_ifp) {
1279 return ferr_cfg_invalid("multicast not enabled on interface %s",
1280 ifp->name);
1281 }
1282
1283 if (!pim_ifp->igmp_join_list) {
1284 pim_ifp->igmp_join_list = list_new();
1285 pim_ifp->igmp_join_list->del = (void (*)(void *))igmp_join_free;
1286 }
1287
1288 ij = igmp_join_find(pim_ifp->igmp_join_list, group_addr, source_addr);
1289
1290 /* This interface has already been configured to join this IGMP group
1291 */
1292 if (ij) {
1293 return ferr_ok();
1294 }
1295
1296 ij = igmp_join_new(ifp, group_addr, source_addr);
1297 if (!ij) {
1298 return ferr_cfg_invalid(
1299 "Failure to create new join data structure, see log file for more information");
1300 }
1301
1302 if (PIM_DEBUG_IGMP_EVENTS) {
1303 char group_str[INET_ADDRSTRLEN];
1304 char source_str[INET_ADDRSTRLEN];
1305 pim_inet4_dump("<grp?>", group_addr, group_str,
1306 sizeof(group_str));
1307 pim_inet4_dump("<src?>", source_addr, source_str,
1308 sizeof(source_str));
1309 zlog_debug(
1310 "%s: issued static igmp join for channel (S,G)=(%s,%s) on interface %s",
1311 __PRETTY_FUNCTION__, source_str, group_str, ifp->name);
1312 }
1313
1314 return ferr_ok();
1315 }
1316
1317
1318 int pim_if_igmp_join_del(struct interface *ifp, struct in_addr group_addr,
1319 struct in_addr source_addr)
1320 {
1321 struct pim_interface *pim_ifp;
1322 struct igmp_join *ij;
1323
1324 pim_ifp = ifp->info;
1325 if (!pim_ifp) {
1326 zlog_warn("%s: multicast not enabled on interface %s",
1327 __PRETTY_FUNCTION__, ifp->name);
1328 return -1;
1329 }
1330
1331 if (!pim_ifp->igmp_join_list) {
1332 zlog_warn("%s: no IGMP join on interface %s",
1333 __PRETTY_FUNCTION__, ifp->name);
1334 return -2;
1335 }
1336
1337 ij = igmp_join_find(pim_ifp->igmp_join_list, group_addr, source_addr);
1338 if (!ij) {
1339 char group_str[INET_ADDRSTRLEN];
1340 char source_str[INET_ADDRSTRLEN];
1341 pim_inet4_dump("<grp?>", group_addr, group_str,
1342 sizeof(group_str));
1343 pim_inet4_dump("<src?>", source_addr, source_str,
1344 sizeof(source_str));
1345 zlog_warn(
1346 "%s: could not find IGMP group %s source %s on interface %s",
1347 __PRETTY_FUNCTION__, group_str, source_str, ifp->name);
1348 return -3;
1349 }
1350
1351 if (close(ij->sock_fd)) {
1352 char group_str[INET_ADDRSTRLEN];
1353 char source_str[INET_ADDRSTRLEN];
1354 pim_inet4_dump("<grp?>", group_addr, group_str,
1355 sizeof(group_str));
1356 pim_inet4_dump("<src?>", source_addr, source_str,
1357 sizeof(source_str));
1358 zlog_warn(
1359 "%s: failure closing sock_fd=%d for IGMP group %s source %s on interface %s: errno=%d: %s",
1360 __PRETTY_FUNCTION__, ij->sock_fd, group_str, source_str,
1361 ifp->name, errno, safe_strerror(errno));
1362 /* warning only */
1363 }
1364 listnode_delete(pim_ifp->igmp_join_list, ij);
1365 igmp_join_free(ij);
1366 if (listcount(pim_ifp->igmp_join_list) < 1) {
1367 list_delete(&pim_ifp->igmp_join_list);
1368 pim_ifp->igmp_join_list = 0;
1369 }
1370
1371 return 0;
1372 }
1373
1374 static void pim_if_igmp_join_del_all(struct interface *ifp)
1375 {
1376 struct pim_interface *pim_ifp;
1377 struct listnode *node;
1378 struct listnode *nextnode;
1379 struct igmp_join *ij;
1380
1381 pim_ifp = ifp->info;
1382 if (!pim_ifp) {
1383 zlog_warn("%s: multicast not enabled on interface %s",
1384 __PRETTY_FUNCTION__, ifp->name);
1385 return;
1386 }
1387
1388 if (!pim_ifp->igmp_join_list)
1389 return;
1390
1391 for (ALL_LIST_ELEMENTS(pim_ifp->igmp_join_list, node, nextnode, ij))
1392 pim_if_igmp_join_del(ifp, ij->group_addr, ij->source_addr);
1393 }
1394
1395 /*
1396 RFC 4601
1397
1398 Transitions from "I am Assert Loser" State
1399
1400 Current Winner's GenID Changes or NLT Expires
1401
1402 The Neighbor Liveness Timer associated with the current winner
1403 expires or we receive a Hello message from the current winner
1404 reporting a different GenID from the one it previously reported.
1405 This indicates that the current winner's interface or router has
1406 gone down (and may have come back up), and so we must assume it no
1407 longer knows it was the winner.
1408 */
1409 void pim_if_assert_on_neighbor_down(struct interface *ifp,
1410 struct in_addr neigh_addr)
1411 {
1412 struct pim_interface *pim_ifp;
1413 struct pim_ifchannel *ch;
1414
1415 pim_ifp = ifp->info;
1416 zassert(pim_ifp);
1417
1418 RB_FOREACH (ch, pim_ifchannel_rb, &pim_ifp->ifchannel_rb) {
1419 /* Is (S,G,I) assert loser ? */
1420 if (ch->ifassert_state != PIM_IFASSERT_I_AM_LOSER)
1421 continue;
1422 /* Dead neighbor was winner ? */
1423 if (ch->ifassert_winner.s_addr != neigh_addr.s_addr)
1424 continue;
1425
1426 assert_action_a5(ch);
1427 }
1428 }
1429
1430 void pim_if_update_join_desired(struct pim_interface *pim_ifp)
1431 {
1432 struct pim_ifchannel *ch;
1433
1434 /* clear off flag from interface's upstreams */
1435 RB_FOREACH (ch, pim_ifchannel_rb, &pim_ifp->ifchannel_rb) {
1436 PIM_UPSTREAM_FLAG_UNSET_DR_JOIN_DESIRED_UPDATED(
1437 ch->upstream->flags);
1438 }
1439
1440 /* scan per-interface (S,G,I) state on this I interface */
1441 RB_FOREACH (ch, pim_ifchannel_rb, &pim_ifp->ifchannel_rb) {
1442 struct pim_upstream *up = ch->upstream;
1443
1444 if (PIM_UPSTREAM_FLAG_TEST_DR_JOIN_DESIRED_UPDATED(up->flags))
1445 continue;
1446
1447 /* update join_desired for the global (S,G) state */
1448 pim_upstream_update_join_desired(pim_ifp->pim, up);
1449 PIM_UPSTREAM_FLAG_SET_DR_JOIN_DESIRED_UPDATED(up->flags);
1450 }
1451 }
1452
1453 void pim_if_update_assert_tracking_desired(struct interface *ifp)
1454 {
1455 struct pim_interface *pim_ifp;
1456 struct pim_ifchannel *ch;
1457
1458 pim_ifp = ifp->info;
1459 if (!pim_ifp)
1460 return;
1461
1462 RB_FOREACH (ch, pim_ifchannel_rb, &pim_ifp->ifchannel_rb) {
1463 pim_ifchannel_update_assert_tracking_desired(ch);
1464 }
1465 }
1466
1467 /*
1468 * PIM wants to have an interface pointer for everything it does.
1469 * The pimreg is a special interface that we have that is not
1470 * quite an inteface but a VIF is created for it.
1471 */
1472 void pim_if_create_pimreg(struct pim_instance *pim)
1473 {
1474 char pimreg_name[INTERFACE_NAMSIZ];
1475
1476 if (!pim->regiface) {
1477 if (pim->vrf_id == VRF_DEFAULT)
1478 strlcpy(pimreg_name, "pimreg", sizeof(pimreg_name));
1479 else
1480 snprintf(pimreg_name, sizeof(pimreg_name), "pimreg%u",
1481 pim->vrf->data.l.table_id);
1482
1483 pim->regiface = if_create(pimreg_name, pim->vrf_id);
1484 pim->regiface->ifindex = PIM_OIF_PIM_REGISTER_VIF;
1485
1486 pim_if_new(pim->regiface, false, false, true,
1487 false /*vxlan_term*/);
1488 }
1489 }
1490
1491 int pim_if_connected_to_source(struct interface *ifp, struct in_addr src)
1492 {
1493 struct listnode *cnode;
1494 struct connected *c;
1495 struct prefix p;
1496
1497 if (!ifp)
1498 return 0;
1499
1500 p.family = AF_INET;
1501 p.u.prefix4 = src;
1502 p.prefixlen = IPV4_MAX_BITLEN;
1503
1504 for (ALL_LIST_ELEMENTS_RO(ifp->connected, cnode, c)) {
1505 if ((c->address->family == AF_INET)
1506 && prefix_match(CONNECTED_PREFIX(c), &p)) {
1507 return 1;
1508 }
1509 }
1510
1511 return 0;
1512 }
1513
1514 bool pim_if_is_vrf_device(struct interface *ifp)
1515 {
1516 if (if_is_vrf(ifp))
1517 return true;
1518
1519 return false;
1520 }
1521
1522 int pim_if_ifchannel_count(struct pim_interface *pim_ifp)
1523 {
1524 struct pim_ifchannel *ch;
1525 int count = 0;
1526
1527 RB_FOREACH (ch, pim_ifchannel_rb, &pim_ifp->ifchannel_rb) {
1528 count++;
1529 }
1530
1531 return count;
1532 }