1 // SPDX-License-Identifier: GPL-2.0-or-later
4 * Copyright (C) 2008 Everton da Silva Marques
22 #include "pim_instance.h"
23 #include "pim_zebra.h"
24 #include "pim_iface.h"
26 #include "pim_mroute.h"
30 #include "pim_neighbor.h"
31 #include "pim_ifchannel.h"
34 #include "pim_ssmpingd.h"
37 #include "pim_jp_agg.h"
38 #include "pim_igmp_join.h"
39 #include "pim_vxlan.h"
44 static void pim_if_igmp_join_del_all(struct interface
*ifp
);
45 static int igmp_join_sock(const char *ifname
, ifindex_t ifindex
,
46 struct in_addr group_addr
, struct in_addr source_addr
,
47 struct pim_interface
*pim_ifp
);
50 void pim_if_init(struct pim_instance
*pim
)
54 for (i
= 0; i
< MAXVIFS
; i
++)
55 pim
->iface_vif_index
[i
] = 0;
58 void pim_if_terminate(struct pim_instance
*pim
)
60 struct interface
*ifp
;
62 FOR_ALL_INTERFACES (pim
->vrf
, ifp
) {
63 struct pim_interface
*pim_ifp
= ifp
->info
;
73 static void pim_sec_addr_free(struct pim_secondary_addr
*sec_addr
)
75 XFREE(MTYPE_PIM_SEC_ADDR
, sec_addr
);
78 __attribute__((unused
))
79 static int pim_sec_addr_comp(const void *p1
, const void *p2
)
81 const struct pim_secondary_addr
*sec1
= p1
;
82 const struct pim_secondary_addr
*sec2
= p2
;
84 if (sec1
->addr
.family
== AF_INET
&& sec2
->addr
.family
== AF_INET6
)
87 if (sec1
->addr
.family
== AF_INET6
&& sec2
->addr
.family
== AF_INET
)
90 if (sec1
->addr
.family
== AF_INET
) {
91 if (ntohl(sec1
->addr
.u
.prefix4
.s_addr
)
92 < ntohl(sec2
->addr
.u
.prefix4
.s_addr
))
95 if (ntohl(sec1
->addr
.u
.prefix4
.s_addr
)
96 > ntohl(sec2
->addr
.u
.prefix4
.s_addr
))
99 return memcmp(&sec1
->addr
.u
.prefix6
, &sec2
->addr
.u
.prefix6
,
100 sizeof(struct in6_addr
));
106 struct pim_interface
*pim_if_new(struct interface
*ifp
, bool gm
, bool pim
,
107 bool ispimreg
, bool is_vxlan_term
)
109 struct pim_interface
*pim_ifp
;
114 pim_ifp
= XCALLOC(MTYPE_PIM_INTERFACE
, sizeof(*pim_ifp
));
116 pim_ifp
->pim
= ifp
->vrf
->info
;
117 pim_ifp
->mroute_vif_index
= -1;
119 pim_ifp
->igmp_version
= IGMP_DEFAULT_VERSION
;
120 pim_ifp
->mld_version
= MLD_DEFAULT_VERSION
;
121 pim_ifp
->gm_default_robustness_variable
=
122 GM_DEFAULT_ROBUSTNESS_VARIABLE
;
123 pim_ifp
->gm_default_query_interval
= GM_GENERAL_QUERY_INTERVAL
;
124 pim_ifp
->gm_query_max_response_time_dsec
=
125 GM_QUERY_MAX_RESPONSE_TIME_DSEC
;
126 pim_ifp
->gm_specific_query_max_response_time_dsec
=
127 GM_SPECIFIC_QUERY_MAX_RESPONSE_TIME_DSEC
;
128 pim_ifp
->gm_last_member_query_count
= GM_DEFAULT_ROBUSTNESS_VARIABLE
;
130 /* BSM config on interface: true by default */
131 pim_ifp
->bsm_enable
= true;
132 pim_ifp
->ucast_bsm_accept
= true;
133 pim_ifp
->am_i_dr
= false;
136 RFC 3376: 8.3. Query Response Interval
137 The number of seconds represented by the [Query Response Interval]
138 must be less than the [Query Interval].
140 assert(pim_ifp
->gm_query_max_response_time_dsec
<
141 pim_ifp
->gm_default_query_interval
);
143 pim_ifp
->pim_enable
= pim
;
144 pim_ifp
->pim_passive_enable
= false;
145 pim_ifp
->gm_enable
= gm
;
147 pim_ifp
->gm_join_list
= NULL
;
148 pim_ifp
->pim_neighbor_list
= NULL
;
149 pim_ifp
->upstream_switch_list
= NULL
;
150 pim_ifp
->pim_generation_id
= 0;
152 /* list of struct gm_sock */
153 pim_igmp_if_init(pim_ifp
, ifp
);
155 /* list of struct pim_neighbor */
156 pim_ifp
->pim_neighbor_list
= list_new();
157 pim_ifp
->pim_neighbor_list
->del
= (void (*)(void *))pim_neighbor_free
;
159 pim_ifp
->upstream_switch_list
= list_new();
160 pim_ifp
->upstream_switch_list
->del
=
161 (void (*)(void *))pim_jp_agg_group_list_free
;
162 pim_ifp
->upstream_switch_list
->cmp
= pim_jp_agg_group_list_cmp
;
164 pim_ifp
->sec_addr_list
= list_new();
165 pim_ifp
->sec_addr_list
->del
= (void (*)(void *))pim_sec_addr_free
;
166 pim_ifp
->sec_addr_list
->cmp
=
167 (int (*)(void *, void *))pim_sec_addr_comp
;
169 pim_ifp
->activeactive
= false;
171 RB_INIT(pim_ifchannel_rb
, &pim_ifp
->ifchannel_rb
);
177 pim_if_add_vif(ifp
, ispimreg
, is_vxlan_term
);
178 pim_ifp
->pim
->mcast_if_count
++;
183 void pim_if_delete(struct interface
*ifp
)
185 struct pim_interface
*pim_ifp
;
191 pim_ifp
->pim
->mcast_if_count
--;
193 if (pim_ifp
->gm_join_list
) {
194 pim_if_igmp_join_del_all(ifp
);
198 pim_ifchannel_delete_all(ifp
);
200 igmp_sock_delete_all(ifp
);
202 if (pim_ifp
->pim_sock_fd
>= 0)
203 pim_sock_delete(ifp
, "Interface removed from configuration");
207 pim_igmp_if_fini(pim_ifp
);
209 list_delete(&pim_ifp
->pim_neighbor_list
);
210 list_delete(&pim_ifp
->upstream_switch_list
);
211 list_delete(&pim_ifp
->sec_addr_list
);
213 if (pim_ifp
->bfd_config
.profile
)
214 XFREE(MTYPE_TMP
, pim_ifp
->bfd_config
.profile
);
216 XFREE(MTYPE_PIM_INTERFACE
, pim_ifp
->boundary_oil_plist
);
217 XFREE(MTYPE_PIM_INTERFACE
, pim_ifp
);
222 void pim_if_update_could_assert(struct interface
*ifp
)
224 struct pim_interface
*pim_ifp
;
225 struct pim_ifchannel
*ch
;
230 RB_FOREACH (ch
, pim_ifchannel_rb
, &pim_ifp
->ifchannel_rb
) {
231 pim_ifchannel_update_could_assert(ch
);
235 static void pim_if_update_my_assert_metric(struct interface
*ifp
)
237 struct pim_interface
*pim_ifp
;
238 struct pim_ifchannel
*ch
;
243 RB_FOREACH (ch
, pim_ifchannel_rb
, &pim_ifp
->ifchannel_rb
) {
244 pim_ifchannel_update_my_assert_metric(ch
);
248 static void pim_addr_change(struct interface
*ifp
)
250 struct pim_interface
*pim_ifp
;
255 pim_if_dr_election(ifp
); /* router's own DR Priority (addr) changes --
257 pim_if_update_join_desired(pim_ifp
); /* depends on DR */
258 pim_if_update_could_assert(ifp
); /* depends on DR */
259 pim_if_update_my_assert_metric(ifp
); /* depends on could_assert */
260 pim_if_update_assert_tracking_desired(
261 ifp
); /* depends on DR, join_desired */
264 RFC 4601: 4.3.1. Sending Hello Messages
266 1) Before an interface goes down or changes primary IP address, a
267 Hello message with a zero HoldTime should be sent immediately
268 (with the old IP address if the IP address changed).
269 -- Done at the caller of the function as new ip already updated here
271 2) After an interface has changed its IP address, it MUST send a
272 Hello message with its new IP address.
275 3) If an interface changes one of its secondary IP addresses, a
276 Hello message with an updated Address_List option and a non-zero
277 HoldTime should be sent immediately.
278 -- FIXME See TODO T31
280 PIM_IF_FLAG_UNSET_HELLO_SENT(pim_ifp
->flags
);
281 if (pim_ifp
->pim_sock_fd
< 0)
283 pim_hello_restart_now(ifp
); /* send hello and restart timer */
286 static int detect_primary_address_change(struct interface
*ifp
,
287 int force_prim_as_any
,
290 struct pim_interface
*pim_ifp
= ifp
->info
;
291 pim_addr new_prim_addr
;
294 if (force_prim_as_any
)
295 new_prim_addr
= PIMADDR_ANY
;
297 new_prim_addr
= pim_find_primary_addr(ifp
);
299 changed
= pim_addr_cmp(new_prim_addr
, pim_ifp
->primary_address
);
302 zlog_debug("%s: old=%pPA new=%pPA on interface %s: %s",
303 __func__
, &pim_ifp
->primary_address
, &new_prim_addr
,
304 ifp
->name
, changed
? "changed" : "unchanged");
307 /* Before updating pim_ifp send Hello time with 0 hold time */
308 if (pim_ifp
->pim_enable
) {
309 pim_hello_send(ifp
, 0 /* zero-sec holdtime */);
311 pim_ifp
->primary_address
= new_prim_addr
;
317 static struct pim_secondary_addr
*
318 pim_sec_addr_find(struct pim_interface
*pim_ifp
, struct prefix
*addr
)
320 struct pim_secondary_addr
*sec_addr
;
321 struct listnode
*node
;
323 for (ALL_LIST_ELEMENTS_RO(pim_ifp
->sec_addr_list
, node
, sec_addr
)) {
324 if (prefix_cmp(&sec_addr
->addr
, addr
) == 0) {
332 static void pim_sec_addr_del(struct pim_interface
*pim_ifp
,
333 struct pim_secondary_addr
*sec_addr
)
335 listnode_delete(pim_ifp
->sec_addr_list
, sec_addr
);
336 pim_sec_addr_free(sec_addr
);
339 static int pim_sec_addr_add(struct pim_interface
*pim_ifp
, struct prefix
*addr
)
342 struct pim_secondary_addr
*sec_addr
;
344 sec_addr
= pim_sec_addr_find(pim_ifp
, addr
);
346 sec_addr
->flags
&= ~PIM_SEC_ADDRF_STALE
;
350 sec_addr
= XCALLOC(MTYPE_PIM_SEC_ADDR
, sizeof(*sec_addr
));
353 sec_addr
->addr
= *addr
;
354 listnode_add_sort(pim_ifp
->sec_addr_list
, sec_addr
);
359 static int pim_sec_addr_del_all(struct pim_interface
*pim_ifp
)
363 if (!list_isempty(pim_ifp
->sec_addr_list
)) {
365 /* remove all nodes and free up the list itself */
366 list_delete_all_node(pim_ifp
->sec_addr_list
);
372 static int pim_sec_addr_update(struct interface
*ifp
)
374 struct pim_interface
*pim_ifp
= ifp
->info
;
375 struct connected
*ifc
;
376 struct listnode
*node
;
377 struct listnode
*nextnode
;
378 struct pim_secondary_addr
*sec_addr
;
381 for (ALL_LIST_ELEMENTS_RO(pim_ifp
->sec_addr_list
, node
, sec_addr
)) {
382 sec_addr
->flags
|= PIM_SEC_ADDRF_STALE
;
385 for (ALL_LIST_ELEMENTS_RO(ifp
->connected
, node
, ifc
)) {
386 pim_addr addr
= pim_addr_from_prefix(ifc
->address
);
388 if (pim_addr_is_any(addr
))
391 if (!pim_addr_cmp(addr
, pim_ifp
->primary_address
)) {
392 /* don't add the primary address into the secondary
397 if (pim_sec_addr_add(pim_ifp
, ifc
->address
)) {
402 /* Drop stale entries */
403 for (ALL_LIST_ELEMENTS(pim_ifp
->sec_addr_list
, node
, nextnode
,
405 if (sec_addr
->flags
& PIM_SEC_ADDRF_STALE
) {
406 pim_sec_addr_del(pim_ifp
, sec_addr
);
414 static int detect_secondary_address_change(struct interface
*ifp
,
415 int force_prim_as_any
,
418 struct pim_interface
*pim_ifp
= ifp
->info
;
421 if (force_prim_as_any
) {
422 /* if primary address is being forced to zero just flush the
423 * secondary address list */
424 changed
= pim_sec_addr_del_all(pim_ifp
);
426 /* re-evaluate the secondary address list */
427 changed
= pim_sec_addr_update(ifp
);
433 static void detect_address_change(struct interface
*ifp
, int force_prim_as_any
,
437 struct pim_interface
*pim_ifp
;
443 if (detect_primary_address_change(ifp
, force_prim_as_any
, caller
)) {
447 if (detect_secondary_address_change(ifp
, force_prim_as_any
, caller
)) {
453 if (!pim_ifp
->pim_enable
) {
457 pim_addr_change(ifp
);
460 /* XXX: if we have unnumbered interfaces we need to run detect address
461 * address change on all of them when the lo address changes */
464 int pim_update_source_set(struct interface
*ifp
, pim_addr source
)
466 struct pim_interface
*pim_ifp
= ifp
->info
;
469 return PIM_IFACE_NOT_FOUND
;
472 if (!pim_addr_cmp(pim_ifp
->update_source
, source
)) {
473 return PIM_UPDATE_SOURCE_DUP
;
476 pim_ifp
->update_source
= source
;
477 detect_address_change(ifp
, 0 /* force_prim_as_any */, __func__
);
482 void pim_if_addr_add(struct connected
*ifc
)
484 struct pim_interface
*pim_ifp
;
485 struct interface
*ifp
;
496 if (!if_is_operative(ifp
))
500 zlog_debug("%s: %s ifindex=%d connected IP address %pFX %s",
501 __func__
, ifp
->name
, ifp
->ifindex
, ifc
->address
,
502 CHECK_FLAG(ifc
->flags
, ZEBRA_IFA_SECONDARY
)
506 if (IN6_IS_ADDR_LINKLOCAL(&ifc
->address
->u
.prefix6
) ||
507 IN6_IS_ADDR_LOOPBACK(&ifc
->address
->u
.prefix6
)) {
508 if (IN6_IS_ADDR_UNSPECIFIED(&pim_ifp
->ll_lowest
))
509 pim_ifp
->ll_lowest
= ifc
->address
->u
.prefix6
;
510 else if (IPV6_ADDR_CMP(&ifc
->address
->u
.prefix6
,
511 &pim_ifp
->ll_lowest
) < 0)
512 pim_ifp
->ll_lowest
= ifc
->address
->u
.prefix6
;
514 if (IPV6_ADDR_CMP(&ifc
->address
->u
.prefix6
,
515 &pim_ifp
->ll_highest
) > 0)
516 pim_ifp
->ll_highest
= ifc
->address
->u
.prefix6
;
520 "%s: new link-local %pI6, lowest now %pI6, highest %pI6",
521 ifc
->ifp
->name
, &ifc
->address
->u
.prefix6
,
522 &pim_ifp
->ll_lowest
, &pim_ifp
->ll_highest
);
526 detect_address_change(ifp
, 0, __func__
);
528 // if (ifc->address->family != AF_INET)
532 struct in_addr ifaddr
= ifc
->address
->u
.prefix4
;
534 if (pim_ifp
->gm_enable
) {
535 struct gm_sock
*igmp
;
537 /* lookup IGMP socket */
538 igmp
= pim_igmp_sock_lookup_ifaddr(pim_ifp
->gm_socket_list
,
541 /* if addr new, add IGMP socket */
542 if (ifc
->address
->family
== AF_INET
)
543 pim_igmp_sock_add(pim_ifp
->gm_socket_list
,
545 } else if (igmp
->mtrace_only
) {
546 igmp_sock_delete(igmp
);
547 pim_igmp_sock_add(pim_ifp
->gm_socket_list
, ifaddr
, ifp
,
551 /* Replay Static IGMP groups */
552 if (pim_ifp
->gm_join_list
) {
553 struct listnode
*node
;
554 struct listnode
*nextnode
;
558 for (ALL_LIST_ELEMENTS(pim_ifp
->gm_join_list
, node
,
560 /* Close socket and reopen with Source and Group
563 join_fd
= igmp_join_sock(
564 ifp
->name
, ifp
->ifindex
, ij
->group_addr
,
565 ij
->source_addr
, pim_ifp
);
567 char group_str
[INET_ADDRSTRLEN
];
568 char source_str
[INET_ADDRSTRLEN
];
569 pim_inet4_dump("<grp?>", ij
->group_addr
,
573 "<src?>", ij
->source_addr
,
574 source_str
, sizeof(source_str
));
576 "%s: igmp_join_sock() failure for IGMP group %s source %s on interface %s",
577 __func__
, group_str
, source_str
,
581 ij
->sock_fd
= join_fd
;
586 struct gm_sock
*igmp
;
588 /* lookup IGMP socket */
589 igmp
= pim_igmp_sock_lookup_ifaddr(pim_ifp
->gm_socket_list
,
591 if (ifc
->address
->family
== AF_INET
) {
593 igmp_sock_delete(igmp
);
594 /* if addr new, add IGMP socket */
595 pim_igmp_sock_add(pim_ifp
->gm_socket_list
, ifaddr
, ifp
,
598 } /* igmp mtrace only */
601 if (pim_ifp
->pim_enable
) {
603 if (!pim_addr_is_any(pim_ifp
->primary_address
)) {
605 /* Interface has a valid socket ? */
606 if (pim_ifp
->pim_sock_fd
< 0) {
607 if (pim_sock_add(ifp
)) {
609 "Failure creating PIM socket for interface %s",
613 struct pim_nexthop_cache
*pnc
= NULL
;
615 struct zclient
*zclient
= NULL
;
617 zclient
= pim_zebra_zclient_get();
618 /* RP config might come prior to (local RP's interface)
620 In this case, pnc would not have pim enabled
622 Once Interface is UP and pim info is available,
624 with RNH address to receive update and add the
625 interface as nexthop. */
626 memset(&rpf
, 0, sizeof(struct pim_rpf
));
627 rpf
.rpf_addr
= pim_addr_from_prefix(ifc
->address
);
628 pnc
= pim_nexthop_cache_find(pim_ifp
->pim
, &rpf
);
630 pim_sendmsg_zebra_rnh(pim_ifp
->pim
, zclient
,
632 ZEBRA_NEXTHOP_REGISTER
);
637 PIM or IGMP is enabled on interface, and there is at least one
638 address assigned, then try to create a vif_index.
640 if (pim_ifp
->mroute_vif_index
< 0) {
641 vxlan_term
= pim_vxlan_is_term_dev_cfg(pim_ifp
->pim
, ifp
);
642 pim_if_add_vif(ifp
, false, vxlan_term
);
645 pim_ifchannel_scan_forward_start(ifp
);
648 static void pim_if_addr_del_igmp(struct connected
*ifc
)
651 struct pim_interface
*pim_ifp
= ifc
->ifp
->info
;
652 struct gm_sock
*igmp
;
653 struct in_addr ifaddr
;
655 if (ifc
->address
->family
!= AF_INET
) {
656 /* non-IPv4 address */
661 /* IGMP not enabled on interface */
665 ifaddr
= ifc
->address
->u
.prefix4
;
667 /* lookup IGMP socket */
668 igmp
= pim_igmp_sock_lookup_ifaddr(pim_ifp
->gm_socket_list
, ifaddr
);
670 /* if addr found, del IGMP socket */
671 igmp_sock_delete(igmp
);
676 static void pim_if_addr_del_pim(struct connected
*ifc
)
678 struct pim_interface
*pim_ifp
= ifc
->ifp
->info
;
680 if (ifc
->address
->family
!= PIM_AF
) {
681 /* non-IPv4 address */
686 /* PIM not enabled on interface */
690 if (!pim_addr_is_any(pim_ifp
->primary_address
)) {
691 /* Interface keeps a valid primary address */
695 if (pim_ifp
->pim_sock_fd
< 0) {
696 /* Interface does not hold a valid socket any longer */
701 pim_sock_delete() closes the socket, stops read and timer threads,
702 and kills all neighbors.
704 pim_sock_delete(ifc
->ifp
,
705 "last address has been removed from interface");
708 void pim_if_addr_del(struct connected
*ifc
, int force_prim_as_any
)
710 struct interface
*ifp
;
717 zlog_debug("%s: %s ifindex=%d disconnected IP address %pFX %s",
718 __func__
, ifp
->name
, ifp
->ifindex
, ifc
->address
,
719 CHECK_FLAG(ifc
->flags
, ZEBRA_IFA_SECONDARY
)
724 struct pim_interface
*pim_ifp
= ifc
->ifp
->info
;
727 (!IPV6_ADDR_CMP(&ifc
->address
->u
.prefix6
, &pim_ifp
->ll_lowest
) ||
728 !IPV6_ADDR_CMP(&ifc
->address
->u
.prefix6
, &pim_ifp
->ll_highest
))) {
729 struct listnode
*cnode
;
730 struct connected
*cc
;
732 memset(&pim_ifp
->ll_lowest
, 0xff, sizeof(pim_ifp
->ll_lowest
));
733 memset(&pim_ifp
->ll_highest
, 0, sizeof(pim_ifp
->ll_highest
));
735 for (ALL_LIST_ELEMENTS_RO(ifc
->ifp
->connected
, cnode
, cc
)) {
736 if (!IN6_IS_ADDR_LINKLOCAL(&cc
->address
->u
.prefix6
) &&
737 !IN6_IS_ADDR_LOOPBACK(&cc
->address
->u
.prefix6
))
740 if (IPV6_ADDR_CMP(&cc
->address
->u
.prefix6
,
741 &pim_ifp
->ll_lowest
) < 0)
742 pim_ifp
->ll_lowest
= cc
->address
->u
.prefix6
;
743 if (IPV6_ADDR_CMP(&cc
->address
->u
.prefix6
,
744 &pim_ifp
->ll_highest
) > 0)
745 pim_ifp
->ll_highest
= cc
->address
->u
.prefix6
;
748 if (pim_ifp
->ll_lowest
.s6_addr
[0] == 0xff)
749 memset(&pim_ifp
->ll_lowest
, 0,
750 sizeof(pim_ifp
->ll_lowest
));
754 "%s: removed link-local %pI6, lowest now %pI6, highest %pI6",
755 ifc
->ifp
->name
, &ifc
->address
->u
.prefix6
,
756 &pim_ifp
->ll_lowest
, &pim_ifp
->ll_highest
);
762 detect_address_change(ifp
, force_prim_as_any
, __func__
);
764 pim_if_addr_del_igmp(ifc
);
765 pim_if_addr_del_pim(ifc
);
768 void pim_if_addr_add_all(struct interface
*ifp
)
770 struct connected
*ifc
;
771 struct listnode
*node
;
772 struct listnode
*nextnode
;
775 struct pim_interface
*pim_ifp
= ifp
->info
;
779 /* PIM/IGMP enabled ? */
783 for (ALL_LIST_ELEMENTS(ifp
->connected
, node
, nextnode
, ifc
)) {
784 struct prefix
*p
= ifc
->address
;
786 if (p
->family
!= AF_INET
)
790 pim_if_addr_add(ifc
);
793 if (!v4_addrs
&& v6_addrs
&& !if_is_loopback(ifp
) &&
794 pim_ifp
->pim_enable
&& !pim_addr_is_any(pim_ifp
->primary_address
) &&
795 pim_ifp
->pim_sock_fd
< 0 && pim_sock_add(ifp
)) {
796 /* Interface has a valid primary address ? */
797 /* Interface has a valid socket ? */
798 zlog_warn("Failure creating PIM socket for interface %s",
802 * PIM or IGMP/MLD is enabled on interface, and there is at least one
803 * address assigned, then try to create a vif_index.
805 if (pim_ifp
->mroute_vif_index
< 0) {
806 vxlan_term
= pim_vxlan_is_term_dev_cfg(pim_ifp
->pim
, ifp
);
807 pim_if_add_vif(ifp
, false, vxlan_term
);
810 pim_ifchannel_scan_forward_start(ifp
);
812 pim_rp_setup(pim_ifp
->pim
);
813 pim_rp_check_on_if_add(pim_ifp
);
816 void pim_if_addr_del_all(struct interface
*ifp
)
818 struct connected
*ifc
;
819 struct listnode
*node
;
820 struct listnode
*nextnode
;
821 struct pim_instance
*pim
;
823 pim
= ifp
->vrf
->info
;
827 /* PIM/IGMP enabled ? */
831 for (ALL_LIST_ELEMENTS(ifp
->connected
, node
, nextnode
, ifc
)) {
832 struct prefix
*p
= ifc
->address
;
834 if (p
->family
!= PIM_AF
)
837 pim_if_addr_del(ifc
, 1 /* force_prim_as_any=true */);
841 pim_i_am_rp_re_evaluate(pim
);
844 void pim_if_addr_del_all_igmp(struct interface
*ifp
)
846 struct connected
*ifc
;
847 struct listnode
*node
;
848 struct listnode
*nextnode
;
850 /* PIM/IGMP enabled ? */
854 for (ALL_LIST_ELEMENTS(ifp
->connected
, node
, nextnode
, ifc
)) {
855 struct prefix
*p
= ifc
->address
;
857 if (p
->family
!= AF_INET
)
860 pim_if_addr_del_igmp(ifc
);
864 pim_addr
pim_find_primary_addr(struct interface
*ifp
)
866 struct connected
*ifc
;
867 struct listnode
*node
;
868 struct pim_interface
*pim_ifp
= ifp
->info
;
870 if (pim_ifp
&& !pim_addr_is_any(pim_ifp
->update_source
))
871 return pim_ifp
->update_source
;
874 if (pim_ifp
&& !pim_addr_is_any(pim_ifp
->ll_highest
))
875 return pim_ifp
->ll_highest
;
877 pim_addr best_addr
= PIMADDR_ANY
;
879 for (ALL_LIST_ELEMENTS_RO(ifp
->connected
, node
, ifc
)) {
882 if (ifc
->address
->family
!= AF_INET6
)
885 addr
= pim_addr_from_prefix(ifc
->address
);
886 if (!IN6_IS_ADDR_LINKLOCAL(&addr
))
888 if (pim_addr_cmp(addr
, best_addr
) > 0)
897 for (ALL_LIST_ELEMENTS_RO(ifp
->connected
, node
, ifc
)) {
898 switch (ifc
->address
->family
) {
909 if (CHECK_FLAG(ifc
->flags
, ZEBRA_IFA_SECONDARY
))
912 if (ifc
->address
->family
!= PIM_AF
)
915 return pim_addr_from_prefix(ifc
->address
);
919 * If we have no v4_addrs and v6 is configured
920 * We probably are using unnumbered
921 * So let's grab the loopbacks v4 address
922 * and use that as the primary address
924 if (!v4_addrs
&& v6_addrs
) {
925 struct interface
*lo_ifp
;
927 // DBS - Come back and check here
928 if (ifp
->vrf
->vrf_id
== VRF_DEFAULT
)
929 lo_ifp
= if_lookup_by_name("lo", ifp
->vrf
->vrf_id
);
931 lo_ifp
= if_lookup_by_name(ifp
->vrf
->name
,
934 if (lo_ifp
&& (lo_ifp
!= ifp
))
935 return pim_find_primary_addr(lo_ifp
);
941 static int pim_iface_next_vif_index(struct interface
*ifp
)
943 struct pim_interface
*pim_ifp
= ifp
->info
;
944 struct pim_instance
*pim
= pim_ifp
->pim
;
948 * The pimreg vif is always going to be in index 0
951 if (ifp
->ifindex
== PIM_OIF_PIM_REGISTER_VIF
)
954 for (i
= 1; i
< MAXVIFS
; i
++) {
955 if (pim
->iface_vif_index
[i
] == 0)
962 pim_if_add_vif() uses ifindex as vif_index
964 see also pim_if_find_vifindex_by_ifindex()
966 int pim_if_add_vif(struct interface
*ifp
, bool ispimreg
, bool is_vxlan_term
)
968 struct pim_interface
*pim_ifp
= ifp
->info
;
970 unsigned char flags
= 0;
974 if (pim_ifp
->mroute_vif_index
> 0) {
975 zlog_warn("%s: vif_index=%d > 0 on interface %s ifindex=%d",
976 __func__
, pim_ifp
->mroute_vif_index
, ifp
->name
,
981 if (ifp
->ifindex
< 0) {
982 zlog_warn("%s: ifindex=%d < 1 on interface %s", __func__
,
983 ifp
->ifindex
, ifp
->name
);
985 } else if ((ifp
->ifindex
== 0) &&
986 ((strncmp(ifp
->name
, "pimreg", 6)) &&
987 (strncmp(ifp
->name
, "pim6reg", 7)))) {
988 zlog_warn("%s: ifindex=%d == 0 on interface %s", __func__
,
989 ifp
->ifindex
, ifp
->name
);
993 ifaddr
= pim_ifp
->primary_address
;
995 /* IPv6 API is always by interface index */
996 if (!ispimreg
&& !is_vxlan_term
&& pim_addr_is_any(ifaddr
)) {
998 "%s: could not get address for interface %s ifindex=%d",
999 __func__
, ifp
->name
, ifp
->ifindex
);
1004 pim_ifp
->mroute_vif_index
= pim_iface_next_vif_index(ifp
);
1006 if (pim_ifp
->mroute_vif_index
>= MAXVIFS
) {
1008 "%s: Attempting to configure more than MAXVIFS=%d on pim enabled interface %s",
1009 __func__
, MAXVIFS
, ifp
->name
);
1013 if (ifp
->ifindex
== PIM_OIF_PIM_REGISTER_VIF
)
1014 flags
= VIFF_REGISTER
;
1015 #ifdef VIFF_USE_IFINDEX
1017 flags
= VIFF_USE_IFINDEX
;
1020 if (pim_mroute_add_vif(ifp
, ifaddr
, flags
)) {
1021 /* pim_mroute_add_vif reported error */
1025 pim_ifp
->pim
->iface_vif_index
[pim_ifp
->mroute_vif_index
] = 1;
1030 /* if the device qualifies as pim_vxlan iif/oif update vxlan entries */
1031 pim_vxlan_add_vif(ifp
);
1035 int pim_if_del_vif(struct interface
*ifp
)
1037 struct pim_interface
*pim_ifp
= ifp
->info
;
1039 if (pim_ifp
->mroute_vif_index
< 1) {
1040 zlog_warn("%s: vif_index=%d < 1 on interface %s ifindex=%d",
1041 __func__
, pim_ifp
->mroute_vif_index
, ifp
->name
,
1046 /* if the device was a pim_vxlan iif/oif update vxlan mroute entries */
1047 pim_vxlan_del_vif(ifp
);
1049 gm_ifp_teardown(ifp
);
1051 pim_mroute_del_vif(ifp
);
1056 pim_ifp
->pim
->iface_vif_index
[pim_ifp
->mroute_vif_index
] = 0;
1058 pim_ifp
->mroute_vif_index
= -1;
1063 struct interface
*pim_if_find_by_vif_index(struct pim_instance
*pim
,
1064 ifindex_t vif_index
)
1066 struct interface
*ifp
;
1068 FOR_ALL_INTERFACES (pim
->vrf
, ifp
) {
1070 struct pim_interface
*pim_ifp
;
1071 pim_ifp
= ifp
->info
;
1073 if (vif_index
== pim_ifp
->mroute_vif_index
)
1082 pim_if_add_vif() uses ifindex as vif_index
1084 int pim_if_find_vifindex_by_ifindex(struct pim_instance
*pim
, ifindex_t ifindex
)
1086 struct pim_interface
*pim_ifp
;
1087 struct interface
*ifp
;
1089 ifp
= if_lookup_by_index(ifindex
, pim
->vrf
->vrf_id
);
1090 if (!ifp
|| !ifp
->info
)
1092 pim_ifp
= ifp
->info
;
1094 return pim_ifp
->mroute_vif_index
;
1097 int pim_if_lan_delay_enabled(struct interface
*ifp
)
1099 struct pim_interface
*pim_ifp
;
1101 pim_ifp
= ifp
->info
;
1103 assert(pim_ifp
->pim_number_of_nonlandelay_neighbors
>= 0);
1105 return pim_ifp
->pim_number_of_nonlandelay_neighbors
== 0;
1108 uint16_t pim_if_effective_propagation_delay_msec(struct interface
*ifp
)
1110 if (pim_if_lan_delay_enabled(ifp
)) {
1111 struct pim_interface
*pim_ifp
;
1112 pim_ifp
= ifp
->info
;
1113 return pim_ifp
->pim_neighbors_highest_propagation_delay_msec
;
1115 return PIM_DEFAULT_PROPAGATION_DELAY_MSEC
;
1119 uint16_t pim_if_effective_override_interval_msec(struct interface
*ifp
)
1121 if (pim_if_lan_delay_enabled(ifp
)) {
1122 struct pim_interface
*pim_ifp
;
1123 pim_ifp
= ifp
->info
;
1124 return pim_ifp
->pim_neighbors_highest_override_interval_msec
;
1126 return PIM_DEFAULT_OVERRIDE_INTERVAL_MSEC
;
1130 int pim_if_t_override_msec(struct interface
*ifp
)
1132 int effective_override_interval_msec
;
1133 int t_override_msec
;
1135 effective_override_interval_msec
=
1136 pim_if_effective_override_interval_msec(ifp
);
1139 frr_weak_random() % (effective_override_interval_msec
+ 1);
1141 return t_override_msec
;
1144 uint16_t pim_if_jp_override_interval_msec(struct interface
*ifp
)
1146 return pim_if_effective_propagation_delay_msec(ifp
)
1147 + pim_if_effective_override_interval_msec(ifp
);
1151 RFC 4601: 4.1.6. State Summarization Macros
1153 The function NBR( I, A ) uses information gathered through PIM Hello
1154 messages to map the IP address A of a directly connected PIM
1155 neighbor router on interface I to the primary IP address of the same
1156 router (Section 4.3.4). The primary IP address of a neighbor is the
1157 address that it uses as the source of its PIM Hello messages.
1159 struct pim_neighbor
*pim_if_find_neighbor(struct interface
*ifp
, pim_addr addr
)
1161 struct listnode
*neighnode
;
1162 struct pim_neighbor
*neigh
;
1163 struct pim_interface
*pim_ifp
;
1168 pim_ifp
= ifp
->info
;
1170 zlog_warn("%s: multicast not enabled on interface %s", __func__
,
1175 pim_addr_to_prefix(&p
, addr
);
1177 for (ALL_LIST_ELEMENTS_RO(pim_ifp
->pim_neighbor_list
, neighnode
,
1180 /* primary address ? */
1181 if (!pim_addr_cmp(neigh
->source_addr
, addr
))
1184 /* secondary address ? */
1185 if (pim_neighbor_find_secondary(neigh
, &p
))
1189 if (PIM_DEBUG_PIM_TRACE
)
1191 "%s: neighbor not found for address %pPA on interface %s",
1192 __func__
, &addr
, ifp
->name
);
1197 long pim_if_t_suppressed_msec(struct interface
*ifp
)
1199 struct pim_interface
*pim_ifp
;
1200 long t_suppressed_msec
;
1201 uint32_t ramount
= 0;
1203 pim_ifp
= ifp
->info
;
1206 /* join suppression disabled ? */
1207 if (pim_ifp
->pim_can_disable_join_suppression
)
1210 /* t_suppressed = t_periodic * rand(1.1, 1.4) */
1211 ramount
= 1100 + (frr_weak_random() % (1400 - 1100 + 1));
1212 t_suppressed_msec
= router
->t_periodic
* ramount
;
1214 return t_suppressed_msec
;
1218 static void igmp_join_free(struct gm_join
*ij
)
1220 XFREE(MTYPE_PIM_IGMP_JOIN
, ij
);
1223 static struct gm_join
*igmp_join_find(struct list
*join_list
,
1224 struct in_addr group_addr
,
1225 struct in_addr source_addr
)
1227 struct listnode
*node
;
1232 for (ALL_LIST_ELEMENTS_RO(join_list
, node
, ij
)) {
1233 if ((group_addr
.s_addr
== ij
->group_addr
.s_addr
)
1234 && (source_addr
.s_addr
== ij
->source_addr
.s_addr
))
1241 static int igmp_join_sock(const char *ifname
, ifindex_t ifindex
,
1242 struct in_addr group_addr
, struct in_addr source_addr
,
1243 struct pim_interface
*pim_ifp
)
1247 pim_ifp
->igmp_ifstat_joins_sent
++;
1249 join_fd
= pim_socket_raw(IPPROTO_IGMP
);
1251 pim_ifp
->igmp_ifstat_joins_failed
++;
1255 if (pim_igmp_join_source(join_fd
, ifindex
, group_addr
, source_addr
)) {
1256 char group_str
[INET_ADDRSTRLEN
];
1257 char source_str
[INET_ADDRSTRLEN
];
1258 pim_inet4_dump("<grp?>", group_addr
, group_str
,
1260 pim_inet4_dump("<src?>", source_addr
, source_str
,
1261 sizeof(source_str
));
1263 "%s: setsockopt(fd=%d) failure for IGMP group %s source %s ifindex %d on interface %s: errno=%d: %s",
1264 __func__
, join_fd
, group_str
, source_str
, ifindex
,
1265 ifname
, errno
, safe_strerror(errno
));
1267 pim_ifp
->igmp_ifstat_joins_failed
++;
1277 static struct gm_join
*igmp_join_new(struct interface
*ifp
,
1278 struct in_addr group_addr
,
1279 struct in_addr source_addr
)
1281 struct pim_interface
*pim_ifp
;
1285 pim_ifp
= ifp
->info
;
1288 join_fd
= igmp_join_sock(ifp
->name
, ifp
->ifindex
, group_addr
,
1289 source_addr
, pim_ifp
);
1291 char group_str
[INET_ADDRSTRLEN
];
1292 char source_str
[INET_ADDRSTRLEN
];
1294 pim_inet4_dump("<grp?>", group_addr
, group_str
,
1296 pim_inet4_dump("<src?>", source_addr
, source_str
,
1297 sizeof(source_str
));
1299 "%s: igmp_join_sock() failure for IGMP group %s source %s on interface %s",
1300 __func__
, group_str
, source_str
, ifp
->name
);
1304 ij
= XCALLOC(MTYPE_PIM_IGMP_JOIN
, sizeof(*ij
));
1306 ij
->sock_fd
= join_fd
;
1307 ij
->group_addr
= group_addr
;
1308 ij
->source_addr
= source_addr
;
1309 ij
->sock_creation
= pim_time_monotonic_sec();
1311 listnode_add(pim_ifp
->gm_join_list
, ij
);
1315 #endif /* PIM_IPV == 4 */
1318 ferr_r
pim_if_igmp_join_add(struct interface
*ifp
, struct in_addr group_addr
,
1319 struct in_addr source_addr
)
1321 struct pim_interface
*pim_ifp
;
1324 pim_ifp
= ifp
->info
;
1326 return ferr_cfg_invalid("multicast not enabled on interface %s",
1330 if (!pim_ifp
->gm_join_list
) {
1331 pim_ifp
->gm_join_list
= list_new();
1332 pim_ifp
->gm_join_list
->del
= (void (*)(void *))igmp_join_free
;
1335 ij
= igmp_join_find(pim_ifp
->gm_join_list
, group_addr
, source_addr
);
1337 /* This interface has already been configured to join this IGMP group
1343 (void)igmp_join_new(ifp
, group_addr
, source_addr
);
1345 if (PIM_DEBUG_GM_EVENTS
) {
1346 char group_str
[INET_ADDRSTRLEN
];
1347 char source_str
[INET_ADDRSTRLEN
];
1348 pim_inet4_dump("<grp?>", group_addr
, group_str
,
1350 pim_inet4_dump("<src?>", source_addr
, source_str
,
1351 sizeof(source_str
));
1353 "%s: issued static igmp join for channel (S,G)=(%s,%s) on interface %s",
1354 __func__
, source_str
, group_str
, ifp
->name
);
1359 #endif /* PIM_IPV == 4 */
1361 int pim_if_igmp_join_del(struct interface
*ifp
, struct in_addr group_addr
,
1362 struct in_addr source_addr
)
1364 struct pim_interface
*pim_ifp
;
1367 pim_ifp
= ifp
->info
;
1369 zlog_warn("%s: multicast not enabled on interface %s", __func__
,
1374 if (!pim_ifp
->gm_join_list
) {
1375 zlog_warn("%s: no IGMP join on interface %s", __func__
,
1380 ij
= igmp_join_find(pim_ifp
->gm_join_list
, group_addr
, source_addr
);
1382 char group_str
[INET_ADDRSTRLEN
];
1383 char source_str
[INET_ADDRSTRLEN
];
1384 pim_inet4_dump("<grp?>", group_addr
, group_str
,
1386 pim_inet4_dump("<src?>", source_addr
, source_str
,
1387 sizeof(source_str
));
1389 "%s: could not find IGMP group %s source %s on interface %s",
1390 __func__
, group_str
, source_str
, ifp
->name
);
1394 if (close(ij
->sock_fd
)) {
1395 char group_str
[INET_ADDRSTRLEN
];
1396 char source_str
[INET_ADDRSTRLEN
];
1397 pim_inet4_dump("<grp?>", group_addr
, group_str
,
1399 pim_inet4_dump("<src?>", source_addr
, source_str
,
1400 sizeof(source_str
));
1402 "%s: failure closing sock_fd=%d for IGMP group %s source %s on interface %s: errno=%d: %s",
1403 __func__
, ij
->sock_fd
, group_str
, source_str
, ifp
->name
,
1404 errno
, safe_strerror(errno
));
1407 listnode_delete(pim_ifp
->gm_join_list
, ij
);
1409 if (listcount(pim_ifp
->gm_join_list
) < 1) {
1410 list_delete(&pim_ifp
->gm_join_list
);
1411 pim_ifp
->gm_join_list
= 0;
1417 __attribute__((unused
))
1418 static void pim_if_igmp_join_del_all(struct interface
*ifp
)
1420 struct pim_interface
*pim_ifp
;
1421 struct listnode
*node
;
1422 struct listnode
*nextnode
;
1425 pim_ifp
= ifp
->info
;
1427 zlog_warn("%s: multicast not enabled on interface %s", __func__
,
1432 if (!pim_ifp
->gm_join_list
)
1435 for (ALL_LIST_ELEMENTS(pim_ifp
->gm_join_list
, node
, nextnode
, ij
))
1436 pim_if_igmp_join_del(ifp
, ij
->group_addr
, ij
->source_addr
);
1438 #else /* PIM_IPV != 4 */
1439 ferr_r
pim_if_igmp_join_add(struct interface
*ifp
, struct in_addr group_addr
,
1440 struct in_addr source_addr
)
1445 int pim_if_igmp_join_del(struct interface
*ifp
, struct in_addr group_addr
,
1446 struct in_addr source_addr
)
1450 #endif /* PIM_IPV != 4 */
1455 Transitions from "I am Assert Loser" State
1457 Current Winner's GenID Changes or NLT Expires
1459 The Neighbor Liveness Timer associated with the current winner
1460 expires or we receive a Hello message from the current winner
1461 reporting a different GenID from the one it previously reported.
1462 This indicates that the current winner's interface or router has
1463 gone down (and may have come back up), and so we must assume it no
1464 longer knows it was the winner.
1466 void pim_if_assert_on_neighbor_down(struct interface
*ifp
, pim_addr neigh_addr
)
1468 struct pim_interface
*pim_ifp
;
1469 struct pim_ifchannel
*ch
;
1471 pim_ifp
= ifp
->info
;
1474 RB_FOREACH (ch
, pim_ifchannel_rb
, &pim_ifp
->ifchannel_rb
) {
1475 /* Is (S,G,I) assert loser ? */
1476 if (ch
->ifassert_state
!= PIM_IFASSERT_I_AM_LOSER
)
1478 /* Dead neighbor was winner ? */
1479 if (pim_addr_cmp(ch
->ifassert_winner
, neigh_addr
))
1482 assert_action_a5(ch
);
1486 void pim_if_update_join_desired(struct pim_interface
*pim_ifp
)
1488 struct pim_ifchannel
*ch
;
1490 /* clear off flag from interface's upstreams */
1491 RB_FOREACH (ch
, pim_ifchannel_rb
, &pim_ifp
->ifchannel_rb
) {
1492 PIM_UPSTREAM_FLAG_UNSET_DR_JOIN_DESIRED_UPDATED(
1493 ch
->upstream
->flags
);
1496 /* scan per-interface (S,G,I) state on this I interface */
1497 RB_FOREACH (ch
, pim_ifchannel_rb
, &pim_ifp
->ifchannel_rb
) {
1498 struct pim_upstream
*up
= ch
->upstream
;
1500 if (PIM_UPSTREAM_FLAG_TEST_DR_JOIN_DESIRED_UPDATED(up
->flags
))
1503 /* update join_desired for the global (S,G) state */
1504 pim_upstream_update_join_desired(pim_ifp
->pim
, up
);
1505 PIM_UPSTREAM_FLAG_SET_DR_JOIN_DESIRED_UPDATED(up
->flags
);
1509 void pim_if_update_assert_tracking_desired(struct interface
*ifp
)
1511 struct pim_interface
*pim_ifp
;
1512 struct pim_ifchannel
*ch
;
1514 pim_ifp
= ifp
->info
;
1518 RB_FOREACH (ch
, pim_ifchannel_rb
, &pim_ifp
->ifchannel_rb
) {
1519 pim_ifchannel_update_assert_tracking_desired(ch
);
1524 * PIM wants to have an interface pointer for everything it does.
1525 * The pimreg is a special interface that we have that is not
1526 * quite an interface but a VIF is created for it.
1528 void pim_if_create_pimreg(struct pim_instance
*pim
)
1530 char pimreg_name
[INTERFACE_NAMSIZ
];
1532 if (!pim
->regiface
) {
1533 if (pim
->vrf
->vrf_id
== VRF_DEFAULT
)
1534 strlcpy(pimreg_name
, PIMREG
, sizeof(pimreg_name
));
1536 snprintf(pimreg_name
, sizeof(pimreg_name
), PIMREG
"%u",
1537 pim
->vrf
->data
.l
.table_id
);
1539 pim
->regiface
= if_get_by_name(pimreg_name
, pim
->vrf
->vrf_id
,
1541 pim
->regiface
->ifindex
= PIM_OIF_PIM_REGISTER_VIF
;
1543 if (!pim
->regiface
->info
)
1544 pim_if_new(pim
->regiface
, false, false, true,
1545 false /*vxlan_term*/);
1548 * On vrf moves we delete the interface if there
1549 * is nothing going on with it. We cannot have
1550 * the pimregiface deleted.
1552 pim
->regiface
->configured
= true;
1557 struct prefix
*pim_if_connected_to_source(struct interface
*ifp
, pim_addr src
)
1559 struct listnode
*cnode
;
1560 struct connected
*c
;
1566 pim_addr_to_prefix(&p
, src
);
1568 for (ALL_LIST_ELEMENTS_RO(ifp
->connected
, cnode
, c
)) {
1569 if (c
->address
->family
!= PIM_AF
)
1571 if (prefix_match(c
->address
, &p
))
1573 if (CONNECTED_PEER(c
) && prefix_match(c
->destination
, &p
))
1574 /* this is not a typo, on PtP we need to return the
1575 * *local* address that lines up with src.
1583 bool pim_if_is_vrf_device(struct interface
*ifp
)
1591 int pim_if_ifchannel_count(struct pim_interface
*pim_ifp
)
1593 struct pim_ifchannel
*ch
;
1596 RB_FOREACH (ch
, pim_ifchannel_rb
, &pim_ifp
->ifchannel_rb
) {
1603 static int pim_ifp_create(struct interface
*ifp
)
1605 struct pim_instance
*pim
;
1607 pim
= ifp
->vrf
->info
;
1608 if (PIM_DEBUG_ZEBRA
) {
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
));
1616 if (if_is_operative(ifp
)) {
1617 struct pim_interface
*pim_ifp
;
1619 pim_ifp
= ifp
->info
;
1621 * If we have a pim_ifp already and this is an if_add
1622 * that means that we probably have a vrf move event
1623 * If that is the case, set the proper vrfness.
1627 pim_if_addr_add_all(ifp
);
1630 * Due to ordering issues based upon when
1631 * a command is entered we should ensure that
1632 * the pim reg is created for this vrf if we
1633 * have configuration for it already.
1635 * this is a no-op if it's already been done.
1637 pim_if_create_pimreg(pim
);
1642 * If we are a vrf device that is up, open up the pim_socket for
1644 * to incoming pim messages irrelevant if the user has configured us
1647 if (pim_if_is_vrf_device(ifp
)) {
1648 struct pim_interface
*pim_ifp
;
1651 pim_ifp
= pim_if_new(ifp
, false, false, false,
1652 false /*vxlan_term*/);
1653 ifp
->info
= pim_ifp
;
1659 if (!strncmp(ifp
->name
, PIM_VXLAN_TERM_DEV_NAME
,
1660 sizeof(PIM_VXLAN_TERM_DEV_NAME
))) {
1661 if (pim
->mcast_if_count
< MAXVIFS
)
1662 pim_vxlan_add_term_dev(pim
, ifp
);
1665 "%s: Cannot enable pim on %s. MAXVIFS(%d) reached. Deleting and readding the vxlan termimation device after unconfiguring pim from other interfaces may succeed.",
1666 __func__
, ifp
->name
, MAXVIFS
);
1673 static int pim_ifp_up(struct interface
*ifp
)
1676 struct pim_interface
*pim_ifp
;
1677 struct pim_instance
*pim
;
1679 if (PIM_DEBUG_ZEBRA
) {
1681 "%s: %s index %d vrf %s(%u) flags %ld metric %d mtu %d operative %d",
1682 __func__
, ifp
->name
, ifp
->ifindex
, ifp
->vrf
->name
,
1683 ifp
->vrf
->vrf_id
, (long)ifp
->flags
, ifp
->metric
,
1684 ifp
->mtu
, if_is_operative(ifp
));
1687 pim
= ifp
->vrf
->info
;
1689 pim_ifp
= ifp
->info
;
1691 * If we have a pim_ifp already and this is an if_add
1692 * that means that we probably have a vrf move event
1693 * If that is the case, set the proper vrfness.
1699 pim_if_addr_add_all() suffices for bringing up both IGMP and
1702 pim_if_addr_add_all(ifp
);
1705 * If we have a pimreg device callback and it's for a specific
1706 * table set the master appropriately
1708 if (sscanf(ifp
->name
, "" PIMREG
"%" SCNu32
, &table_id
) == 1) {
1710 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
1711 if ((table_id
== vrf
->data
.l
.table_id
)
1712 && (ifp
->vrf
->vrf_id
!= vrf
->vrf_id
)) {
1713 struct interface
*master
= if_lookup_by_name(
1714 vrf
->name
, vrf
->vrf_id
);
1718 "%s: Unable to find Master interface for %s",
1719 __func__
, vrf
->name
);
1722 pim_zebra_interface_set_master(master
, ifp
);
1729 static int pim_ifp_down(struct interface
*ifp
)
1731 if (PIM_DEBUG_ZEBRA
) {
1733 "%s: %s index %d vrf %s(%u) flags %ld metric %d mtu %d operative %d",
1734 __func__
, ifp
->name
, ifp
->ifindex
, ifp
->vrf
->name
,
1735 ifp
->vrf
->vrf_id
, (long)ifp
->flags
, ifp
->metric
,
1736 ifp
->mtu
, if_is_operative(ifp
));
1739 if (!if_is_operative(ifp
)) {
1740 pim_ifchannel_delete_all(ifp
);
1742 pim_if_addr_del_all() suffices for shutting down IGMP,
1743 but not for shutting down PIM
1745 pim_if_addr_del_all(ifp
);
1748 pim_sock_delete() closes the socket, stops read and timer
1750 and kills all neighbors.
1753 pim_sock_delete(ifp
, "link down");
1758 pim_if_del_vif(ifp
);
1759 pim_ifstat_reset(ifp
);
1765 static int pim_ifp_destroy(struct interface
*ifp
)
1767 if (PIM_DEBUG_ZEBRA
) {
1769 "%s: %s index %d vrf %s(%u) flags %ld metric %d mtu %d operative %d",
1770 __func__
, ifp
->name
, ifp
->ifindex
, ifp
->vrf
->name
,
1771 ifp
->vrf
->vrf_id
, (long)ifp
->flags
, ifp
->metric
,
1772 ifp
->mtu
, if_is_operative(ifp
));
1775 if (!if_is_operative(ifp
))
1776 pim_if_addr_del_all(ifp
);
1779 struct pim_instance
*pim
;
1781 pim
= ifp
->vrf
->info
;
1782 if (pim
&& pim
->vxlan
.term_if
== ifp
)
1783 pim_vxlan_del_term_dev(pim
);
1789 static int pim_if_new_hook(struct interface
*ifp
)
1794 static int pim_if_delete_hook(struct interface
*ifp
)
1802 void pim_iface_init(void)
1804 hook_register_prio(if_add
, 0, pim_if_new_hook
);
1805 hook_register_prio(if_del
, 0, pim_if_delete_hook
);
1807 if_zapi_callbacks(pim_ifp_create
, pim_ifp_up
, pim_ifp_down
,