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