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.
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.
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
34 #include "pim_instance.h"
35 #include "pim_zebra.h"
36 #include "pim_iface.h"
38 #include "pim_mroute.h"
42 #include "pim_neighbor.h"
43 #include "pim_ifchannel.h"
46 #include "pim_ssmpingd.h"
49 #include "pim_jp_agg.h"
50 #include "pim_igmp_join.h"
51 #include "pim_vxlan.h"
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
);
60 void pim_if_init(struct pim_instance
*pim
)
64 for (i
= 0; i
< MAXVIFS
; i
++)
65 pim
->iface_vif_index
[i
] = 0;
68 void pim_if_terminate(struct pim_instance
*pim
)
70 struct interface
*ifp
;
72 FOR_ALL_INTERFACES (pim
->vrf
, ifp
) {
73 struct pim_interface
*pim_ifp
= ifp
->info
;
83 static void pim_sec_addr_free(struct pim_secondary_addr
*sec_addr
)
85 XFREE(MTYPE_PIM_SEC_ADDR
, sec_addr
);
88 __attribute__((unused
))
89 static int pim_sec_addr_comp(const void *p1
, const void *p2
)
91 const struct pim_secondary_addr
*sec1
= p1
;
92 const struct pim_secondary_addr
*sec2
= p2
;
94 if (sec1
->addr
.family
== AF_INET
&& sec2
->addr
.family
== AF_INET6
)
97 if (sec1
->addr
.family
== AF_INET6
&& sec2
->addr
.family
== AF_INET
)
100 if (sec1
->addr
.family
== AF_INET
) {
101 if (ntohl(sec1
->addr
.u
.prefix4
.s_addr
)
102 < ntohl(sec2
->addr
.u
.prefix4
.s_addr
))
105 if (ntohl(sec1
->addr
.u
.prefix4
.s_addr
)
106 > ntohl(sec2
->addr
.u
.prefix4
.s_addr
))
109 return memcmp(&sec1
->addr
.u
.prefix6
, &sec2
->addr
.u
.prefix6
,
110 sizeof(struct in6_addr
));
116 struct pim_interface
*pim_if_new(struct interface
*ifp
, bool igmp
, bool pim
,
117 bool ispimreg
, bool is_vxlan_term
)
119 struct pim_interface
*pim_ifp
;
124 pim_ifp
= XCALLOC(MTYPE_PIM_INTERFACE
, sizeof(*pim_ifp
));
126 pim_ifp
->options
= 0;
127 pim_ifp
->pim
= ifp
->vrf
->info
;
128 pim_ifp
->mroute_vif_index
= -1;
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
;
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;
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].
151 assert(pim_ifp
->gm_query_max_response_time_dsec
<
152 pim_ifp
->gm_default_query_interval
);
155 PIM_IF_DO_PIM(pim_ifp
->options
);
157 PIM_IF_DO_IGMP(pim_ifp
->options
);
159 PIM_IF_DO_IGMP_LISTEN_ALLROUTERS(pim_ifp
->options
);
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;
166 /* list of struct gm_sock */
167 pim_igmp_if_init(pim_ifp
, ifp
);
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
;
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
;
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
;
183 pim_ifp
->activeactive
= false;
185 RB_INIT(pim_ifchannel_rb
, &pim_ifp
->ifchannel_rb
);
191 pim_if_add_vif(ifp
, ispimreg
, is_vxlan_term
);
193 pim_ifp
->pim
->mcast_if_count
++;
198 void pim_if_delete(struct interface
*ifp
)
200 struct pim_interface
*pim_ifp
;
206 pim_ifp
->pim
->mcast_if_count
--;
208 if (pim_ifp
->gm_join_list
) {
209 pim_if_igmp_join_del_all(ifp
);
212 pim_ifchannel_delete_all(ifp
);
213 igmp_sock_delete_all(ifp
);
215 pim_neighbor_delete_all(ifp
, "Interface removed from configuration");
219 pim_igmp_if_fini(pim_ifp
);
221 list_delete(&pim_ifp
->pim_neighbor_list
);
222 list_delete(&pim_ifp
->upstream_switch_list
);
223 list_delete(&pim_ifp
->sec_addr_list
);
225 XFREE(MTYPE_PIM_INTERFACE
, pim_ifp
->boundary_oil_plist
);
226 XFREE(MTYPE_PIM_INTERFACE
, pim_ifp
);
232 void pim_if_update_could_assert(struct interface
*ifp
)
234 struct pim_interface
*pim_ifp
;
235 struct pim_ifchannel
*ch
;
240 RB_FOREACH (ch
, pim_ifchannel_rb
, &pim_ifp
->ifchannel_rb
) {
241 pim_ifchannel_update_could_assert(ch
);
245 static void pim_if_update_my_assert_metric(struct interface
*ifp
)
247 struct pim_interface
*pim_ifp
;
248 struct pim_ifchannel
*ch
;
253 RB_FOREACH (ch
, pim_ifchannel_rb
, &pim_ifp
->ifchannel_rb
) {
254 pim_ifchannel_update_my_assert_metric(ch
);
258 static void pim_addr_change(struct interface
*ifp
)
260 struct pim_interface
*pim_ifp
;
265 pim_if_dr_election(ifp
); /* router's own DR Priority (addr) changes --
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 */
274 RFC 4601: 4.3.1. Sending Hello Messages
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
281 2) After an interface has changed its IP address, it MUST send a
282 Hello message with its new IP address.
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
290 PIM_IF_FLAG_UNSET_HELLO_SENT(pim_ifp
->flags
);
291 if (pim_ifp
->pim_sock_fd
< 0)
293 pim_hello_restart_now(ifp
); /* send hello and restart timer */
296 static int detect_primary_address_change(struct interface
*ifp
,
297 int force_prim_as_any
,
300 struct pim_interface
*pim_ifp
= ifp
->info
;
301 pim_addr new_prim_addr
;
304 if (force_prim_as_any
)
305 new_prim_addr
= PIMADDR_ANY
;
307 new_prim_addr
= pim_find_primary_addr(ifp
);
309 changed
= pim_addr_cmp(new_prim_addr
, pim_ifp
->primary_address
);
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");
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 */);
321 pim_ifp
->primary_address
= new_prim_addr
;
327 static struct pim_secondary_addr
*
328 pim_sec_addr_find(struct pim_interface
*pim_ifp
, struct prefix
*addr
)
330 struct pim_secondary_addr
*sec_addr
;
331 struct listnode
*node
;
333 for (ALL_LIST_ELEMENTS_RO(pim_ifp
->sec_addr_list
, node
, sec_addr
)) {
334 if (prefix_cmp(&sec_addr
->addr
, addr
) == 0) {
342 static void pim_sec_addr_del(struct pim_interface
*pim_ifp
,
343 struct pim_secondary_addr
*sec_addr
)
345 listnode_delete(pim_ifp
->sec_addr_list
, sec_addr
);
346 pim_sec_addr_free(sec_addr
);
349 static int pim_sec_addr_add(struct pim_interface
*pim_ifp
, struct prefix
*addr
)
352 struct pim_secondary_addr
*sec_addr
;
354 sec_addr
= pim_sec_addr_find(pim_ifp
, addr
);
356 sec_addr
->flags
&= ~PIM_SEC_ADDRF_STALE
;
360 sec_addr
= XCALLOC(MTYPE_PIM_SEC_ADDR
, sizeof(*sec_addr
));
363 sec_addr
->addr
= *addr
;
364 listnode_add_sort(pim_ifp
->sec_addr_list
, sec_addr
);
369 static int pim_sec_addr_del_all(struct pim_interface
*pim_ifp
)
373 if (!list_isempty(pim_ifp
->sec_addr_list
)) {
375 /* remove all nodes and free up the list itself */
376 list_delete_all_node(pim_ifp
->sec_addr_list
);
382 static int pim_sec_addr_update(struct interface
*ifp
)
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
;
391 for (ALL_LIST_ELEMENTS_RO(pim_ifp
->sec_addr_list
, node
, sec_addr
)) {
392 sec_addr
->flags
|= PIM_SEC_ADDRF_STALE
;
395 for (ALL_LIST_ELEMENTS_RO(ifp
->connected
, node
, ifc
)) {
396 pim_addr addr
= pim_addr_from_prefix(ifc
->address
);
398 if (pim_addr_is_any(addr
))
401 if (!pim_addr_cmp(addr
, pim_ifp
->primary_address
)) {
402 /* don't add the primary address into the secondary
407 if (pim_sec_addr_add(pim_ifp
, ifc
->address
)) {
412 /* Drop stale entries */
413 for (ALL_LIST_ELEMENTS(pim_ifp
->sec_addr_list
, node
, nextnode
,
415 if (sec_addr
->flags
& PIM_SEC_ADDRF_STALE
) {
416 pim_sec_addr_del(pim_ifp
, sec_addr
);
424 static int detect_secondary_address_change(struct interface
*ifp
,
425 int force_prim_as_any
,
428 struct pim_interface
*pim_ifp
= ifp
->info
;
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
);
436 /* re-evaluate the secondary address list */
437 changed
= pim_sec_addr_update(ifp
);
443 static void detect_address_change(struct interface
*ifp
, int force_prim_as_any
,
447 struct pim_interface
*pim_ifp
;
453 if (detect_primary_address_change(ifp
, force_prim_as_any
, caller
)) {
457 if (detect_secondary_address_change(ifp
, force_prim_as_any
, caller
)) {
463 if (!PIM_IF_TEST_PIM(pim_ifp
->options
)) {
467 pim_addr_change(ifp
);
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 */
474 int pim_update_source_set(struct interface
*ifp
, pim_addr source
)
476 struct pim_interface
*pim_ifp
= ifp
->info
;
479 return PIM_IFACE_NOT_FOUND
;
482 if (!pim_addr_cmp(pim_ifp
->update_source
, source
)) {
483 return PIM_UPDATE_SOURCE_DUP
;
486 pim_ifp
->update_source
= source
;
487 detect_address_change(ifp
, 0 /* force_prim_as_any */, __func__
);
492 void pim_if_addr_add(struct connected
*ifc
)
494 struct pim_interface
*pim_ifp
;
495 struct interface
*ifp
;
506 if (!if_is_operative(ifp
))
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
)
516 detect_address_change(ifp
, 0, __func__
);
518 // if (ifc->address->family != AF_INET)
522 struct in_addr ifaddr
= ifc
->address
->u
.prefix4
;
524 if (PIM_IF_TEST_IGMP(pim_ifp
->options
)) {
525 struct gm_sock
*igmp
;
527 /* lookup IGMP socket */
528 igmp
= pim_igmp_sock_lookup_ifaddr(pim_ifp
->gm_socket_list
,
531 /* if addr new, add IGMP socket */
532 if (ifc
->address
->family
== AF_INET
)
533 pim_igmp_sock_add(pim_ifp
->gm_socket_list
,
535 } else if (igmp
->mtrace_only
) {
536 igmp_sock_delete(igmp
);
537 pim_igmp_sock_add(pim_ifp
->gm_socket_list
, ifaddr
, ifp
,
541 /* Replay Static IGMP groups */
542 if (pim_ifp
->gm_join_list
) {
543 struct listnode
*node
;
544 struct listnode
*nextnode
;
548 for (ALL_LIST_ELEMENTS(pim_ifp
->gm_join_list
, node
,
550 /* Close socket and reopen with Source and Group
553 join_fd
= igmp_join_sock(
554 ifp
->name
, ifp
->ifindex
, ij
->group_addr
,
557 char group_str
[INET_ADDRSTRLEN
];
558 char source_str
[INET_ADDRSTRLEN
];
559 pim_inet4_dump("<grp?>", ij
->group_addr
,
563 "<src?>", ij
->source_addr
,
564 source_str
, sizeof(source_str
));
566 "%s: igmp_join_sock() failure for IGMP group %s source %s on interface %s",
567 __func__
, group_str
, source_str
,
571 ij
->sock_fd
= join_fd
;
576 struct gm_sock
*igmp
;
578 /* lookup IGMP socket */
579 igmp
= pim_igmp_sock_lookup_ifaddr(pim_ifp
->gm_socket_list
,
581 if (ifc
->address
->family
== AF_INET
) {
583 igmp_sock_delete(igmp
);
584 /* if addr new, add IGMP socket */
585 pim_igmp_sock_add(pim_ifp
->gm_socket_list
, ifaddr
, ifp
,
588 } /* igmp mtrace only */
591 if (PIM_IF_TEST_PIM(pim_ifp
->options
)) {
593 if (!pim_addr_is_any(pim_ifp
->primary_address
)) {
595 /* Interface has a valid socket ? */
596 if (pim_ifp
->pim_sock_fd
< 0) {
597 if (pim_sock_add(ifp
)) {
599 "Failure creating PIM socket for interface %s",
603 struct pim_nexthop_cache
*pnc
= NULL
;
605 struct zclient
*zclient
= NULL
;
607 zclient
= pim_zebra_zclient_get();
608 /* RP config might come prior to (local RP's interface)
610 In this case, pnc would not have pim enabled
612 Once Interface is UP and pim info is available,
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
);
622 pim_sendmsg_zebra_rnh(pim_ifp
->pim
, zclient
,
624 ZEBRA_NEXTHOP_REGISTER
);
629 PIM or IGMP is enabled on interface, and there is at least one
630 address assigned, then try to create a vif_index.
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
);
636 pim_ifchannel_scan_forward_start(ifp
);
639 static void pim_if_addr_del_igmp(struct connected
*ifc
)
642 struct pim_interface
*pim_ifp
= ifc
->ifp
->info
;
643 struct gm_sock
*igmp
;
644 struct in_addr ifaddr
;
646 if (ifc
->address
->family
!= AF_INET
) {
647 /* non-IPv4 address */
652 /* IGMP not enabled on interface */
656 ifaddr
= ifc
->address
->u
.prefix4
;
658 /* lookup IGMP socket */
659 igmp
= pim_igmp_sock_lookup_ifaddr(pim_ifp
->gm_socket_list
, ifaddr
);
661 /* if addr found, del IGMP socket */
662 igmp_sock_delete(igmp
);
667 static void pim_if_addr_del_pim(struct connected
*ifc
)
669 struct pim_interface
*pim_ifp
= ifc
->ifp
->info
;
671 if (ifc
->address
->family
!= AF_INET
) {
672 /* non-IPv4 address */
677 /* PIM not enabled on interface */
681 if (!pim_addr_is_any(pim_ifp
->primary_address
)) {
682 /* Interface keeps a valid primary address */
686 if (pim_ifp
->pim_sock_fd
< 0) {
687 /* Interface does not hold a valid socket any longer */
692 pim_sock_delete() closes the socket, stops read and timer threads,
693 and kills all neighbors.
695 pim_sock_delete(ifc
->ifp
,
696 "last address has been removed from interface");
699 void pim_if_addr_del(struct connected
*ifc
, int force_prim_as_any
)
701 struct interface
*ifp
;
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
)
714 detect_address_change(ifp
, force_prim_as_any
, __func__
);
716 pim_if_addr_del_igmp(ifc
);
717 pim_if_addr_del_pim(ifc
);
720 void pim_if_addr_add_all(struct interface
*ifp
)
722 struct connected
*ifc
;
723 struct listnode
*node
;
724 struct listnode
*nextnode
;
727 struct pim_interface
*pim_ifp
= ifp
->info
;
731 /* PIM/IGMP enabled ? */
735 for (ALL_LIST_ELEMENTS(ifp
->connected
, node
, nextnode
, ifc
)) {
736 struct prefix
*p
= ifc
->address
;
738 if (p
->family
!= AF_INET
)
742 pim_if_addr_add(ifc
);
745 if (!v4_addrs
&& v6_addrs
&& !if_is_loopback(ifp
)) {
746 if (PIM_IF_TEST_PIM(pim_ifp
->options
)) {
748 /* Interface has a valid primary address ? */
749 if (!pim_addr_is_any(pim_ifp
->primary_address
)) {
751 /* Interface has a valid socket ? */
752 if (pim_ifp
->pim_sock_fd
< 0) {
753 if (pim_sock_add(ifp
)) {
755 "Failure creating PIM socket for interface %s",
763 * PIM or IGMP is enabled on interface, and there is at least one
764 * address assigned, then try to create a vif_index.
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
);
770 pim_ifchannel_scan_forward_start(ifp
);
772 pim_rp_setup(pim_ifp
->pim
);
773 pim_rp_check_on_if_add(pim_ifp
);
776 void pim_if_addr_del_all(struct interface
*ifp
)
778 struct connected
*ifc
;
779 struct listnode
*node
;
780 struct listnode
*nextnode
;
781 struct pim_instance
*pim
;
783 pim
= ifp
->vrf
->info
;
787 /* PIM/IGMP enabled ? */
791 for (ALL_LIST_ELEMENTS(ifp
->connected
, node
, nextnode
, ifc
)) {
792 struct prefix
*p
= ifc
->address
;
794 if (p
->family
!= AF_INET
)
797 pim_if_addr_del(ifc
, 1 /* force_prim_as_any=true */);
801 pim_i_am_rp_re_evaluate(pim
);
804 void pim_if_addr_del_all_igmp(struct interface
*ifp
)
806 struct connected
*ifc
;
807 struct listnode
*node
;
808 struct listnode
*nextnode
;
810 /* PIM/IGMP enabled ? */
814 for (ALL_LIST_ELEMENTS(ifp
->connected
, node
, nextnode
, ifc
)) {
815 struct prefix
*p
= ifc
->address
;
817 if (p
->family
!= AF_INET
)
820 pim_if_addr_del_igmp(ifc
);
824 pim_addr
pim_find_primary_addr(struct interface
*ifp
)
826 struct connected
*ifc
;
827 struct listnode
*node
;
830 struct pim_interface
*pim_ifp
= ifp
->info
;
832 if (pim_ifp
&& !pim_addr_is_any(pim_ifp
->update_source
)) {
833 return pim_ifp
->update_source
;
836 for (ALL_LIST_ELEMENTS_RO(ifp
->connected
, node
, ifc
)) {
839 switch (ifc
->address
->family
) {
850 if (CHECK_FLAG(ifc
->flags
, ZEBRA_IFA_SECONDARY
))
853 if (ifc
->address
->family
!= PIM_AF
)
856 addr
= pim_addr_from_prefix(ifc
->address
);
859 if (!IN6_IS_ADDR_LINKLOCAL(&addr
))
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
872 if (!v4_addrs
&& v6_addrs
) {
873 struct interface
*lo_ifp
;
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
);
879 lo_ifp
= if_lookup_by_name(ifp
->vrf
->name
,
882 if (lo_ifp
&& (lo_ifp
!= ifp
))
883 return pim_find_primary_addr(lo_ifp
);
889 static int pim_iface_next_vif_index(struct interface
*ifp
)
891 struct pim_interface
*pim_ifp
= ifp
->info
;
892 struct pim_instance
*pim
= pim_ifp
->pim
;
896 * The pimreg vif is always going to be in index 0
899 if (ifp
->ifindex
== PIM_OIF_PIM_REGISTER_VIF
)
902 for (i
= 1; i
< MAXVIFS
; i
++) {
903 if (pim
->iface_vif_index
[i
] == 0)
910 pim_if_add_vif() uses ifindex as vif_index
912 see also pim_if_find_vifindex_by_ifindex()
914 int pim_if_add_vif(struct interface
*ifp
, bool ispimreg
, bool is_vxlan_term
)
916 struct pim_interface
*pim_ifp
= ifp
->info
;
918 unsigned char flags
= 0;
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
,
929 if (ifp
->ifindex
< 0) {
930 zlog_warn("%s: ifindex=%d < 1 on interface %s", __func__
,
931 ifp
->ifindex
, ifp
->name
);
935 ifaddr
= pim_ifp
->primary_address
;
936 if (!ispimreg
&& !is_vxlan_term
&& pim_addr_is_any(ifaddr
)) {
938 "%s: could not get address for interface %s ifindex=%d",
939 __func__
, ifp
->name
, ifp
->ifindex
);
943 pim_ifp
->mroute_vif_index
= pim_iface_next_vif_index(ifp
);
945 if (pim_ifp
->mroute_vif_index
>= MAXVIFS
) {
947 "%s: Attempting to configure more than MAXVIFS=%d on pim enabled interface %s",
948 __func__
, MAXVIFS
, ifp
->name
);
952 if (ifp
->ifindex
== PIM_OIF_PIM_REGISTER_VIF
)
953 flags
= VIFF_REGISTER
;
954 #ifdef VIFF_USE_IFINDEX
956 flags
= VIFF_USE_IFINDEX
;
959 if (pim_mroute_add_vif(ifp
, ifaddr
, flags
)) {
960 /* pim_mroute_add_vif reported error */
964 pim_ifp
->pim
->iface_vif_index
[pim_ifp
->mroute_vif_index
] = 1;
966 /* if the device qualifies as pim_vxlan iif/oif update vxlan entries */
967 pim_vxlan_add_vif(ifp
);
972 int pim_if_del_vif(struct interface
*ifp
)
974 struct pim_interface
*pim_ifp
= ifp
->info
;
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
,
983 /* if the device was a pim_vxlan iif/oif update vxlan mroute entries */
984 pim_vxlan_del_vif(ifp
);
986 pim_mroute_del_vif(ifp
);
991 pim_ifp
->pim
->iface_vif_index
[pim_ifp
->mroute_vif_index
] = 0;
993 pim_ifp
->mroute_vif_index
= -1;
999 struct interface
*pim_if_find_by_vif_index(struct pim_instance
*pim
,
1000 ifindex_t vif_index
)
1002 struct interface
*ifp
;
1004 FOR_ALL_INTERFACES (pim
->vrf
, ifp
) {
1006 struct pim_interface
*pim_ifp
;
1007 pim_ifp
= ifp
->info
;
1009 if (vif_index
== pim_ifp
->mroute_vif_index
)
1018 pim_if_add_vif() uses ifindex as vif_index
1020 int pim_if_find_vifindex_by_ifindex(struct pim_instance
*pim
, ifindex_t ifindex
)
1022 struct pim_interface
*pim_ifp
;
1023 struct interface
*ifp
;
1025 ifp
= if_lookup_by_index(ifindex
, pim
->vrf
->vrf_id
);
1026 if (!ifp
|| !ifp
->info
)
1028 pim_ifp
= ifp
->info
;
1030 return pim_ifp
->mroute_vif_index
;
1033 int pim_if_lan_delay_enabled(struct interface
*ifp
)
1035 struct pim_interface
*pim_ifp
;
1037 pim_ifp
= ifp
->info
;
1039 assert(pim_ifp
->pim_number_of_nonlandelay_neighbors
>= 0);
1041 return pim_ifp
->pim_number_of_nonlandelay_neighbors
== 0;
1044 uint16_t pim_if_effective_propagation_delay_msec(struct interface
*ifp
)
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
;
1051 return PIM_DEFAULT_PROPAGATION_DELAY_MSEC
;
1055 uint16_t pim_if_effective_override_interval_msec(struct interface
*ifp
)
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
;
1062 return PIM_DEFAULT_OVERRIDE_INTERVAL_MSEC
;
1066 int pim_if_t_override_msec(struct interface
*ifp
)
1068 int effective_override_interval_msec
;
1069 int t_override_msec
;
1071 effective_override_interval_msec
=
1072 pim_if_effective_override_interval_msec(ifp
);
1075 frr_weak_random() % (effective_override_interval_msec
+ 1);
1077 return t_override_msec
;
1080 uint16_t pim_if_jp_override_interval_msec(struct interface
*ifp
)
1082 return pim_if_effective_propagation_delay_msec(ifp
)
1083 + pim_if_effective_override_interval_msec(ifp
);
1087 RFC 4601: 4.1.6. State Summarization Macros
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.
1095 struct pim_neighbor
*pim_if_find_neighbor(struct interface
*ifp
, pim_addr addr
)
1097 struct listnode
*neighnode
;
1098 struct pim_neighbor
*neigh
;
1099 struct pim_interface
*pim_ifp
;
1104 pim_ifp
= ifp
->info
;
1106 zlog_warn("%s: multicast not enabled on interface %s", __func__
,
1111 pim_addr_to_prefix(&p
, addr
);
1113 for (ALL_LIST_ELEMENTS_RO(pim_ifp
->pim_neighbor_list
, neighnode
,
1116 /* primary address ? */
1117 if (!pim_addr_cmp(neigh
->source_addr
, addr
))
1120 /* secondary address ? */
1121 if (pim_neighbor_find_secondary(neigh
, &p
))
1125 if (PIM_DEBUG_PIM_TRACE
)
1127 "%s: neighbor not found for address %pPA on interface %s",
1128 __func__
, &addr
, ifp
->name
);
1133 long pim_if_t_suppressed_msec(struct interface
*ifp
)
1135 struct pim_interface
*pim_ifp
;
1136 long t_suppressed_msec
;
1137 uint32_t ramount
= 0;
1139 pim_ifp
= ifp
->info
;
1142 /* join suppression disabled ? */
1143 if (PIM_IF_TEST_PIM_CAN_DISABLE_JOIN_SUPPRESSION(pim_ifp
->options
))
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
;
1150 return t_suppressed_msec
;
1154 static void igmp_join_free(struct gm_join
*ij
)
1156 XFREE(MTYPE_PIM_IGMP_JOIN
, ij
);
1159 static struct gm_join
*igmp_join_find(struct list
*join_list
,
1160 struct in_addr group_addr
,
1161 struct in_addr source_addr
)
1163 struct listnode
*node
;
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
))
1177 static int igmp_join_sock(const char *ifname
, ifindex_t ifindex
,
1178 struct in_addr group_addr
, struct in_addr source_addr
)
1182 join_fd
= pim_socket_raw(IPPROTO_IGMP
);
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
,
1192 pim_inet4_dump("<src?>", source_addr
, source_str
,
1193 sizeof(source_str
));
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
));
1207 static struct gm_join
*igmp_join_new(struct interface
*ifp
,
1208 struct in_addr group_addr
,
1209 struct in_addr source_addr
)
1211 struct pim_interface
*pim_ifp
;
1215 pim_ifp
= ifp
->info
;
1218 join_fd
= igmp_join_sock(ifp
->name
, ifp
->ifindex
, group_addr
,
1221 char group_str
[INET_ADDRSTRLEN
];
1222 char source_str
[INET_ADDRSTRLEN
];
1224 pim_inet4_dump("<grp?>", group_addr
, group_str
,
1226 pim_inet4_dump("<src?>", source_addr
, source_str
,
1227 sizeof(source_str
));
1229 "%s: igmp_join_sock() failure for IGMP group %s source %s on interface %s",
1230 __func__
, group_str
, source_str
, ifp
->name
);
1234 ij
= XCALLOC(MTYPE_PIM_IGMP_JOIN
, sizeof(*ij
));
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();
1241 listnode_add(pim_ifp
->gm_join_list
, ij
);
1245 #endif /* 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
)
1251 struct pim_interface
*pim_ifp
;
1254 pim_ifp
= ifp
->info
;
1256 return ferr_cfg_invalid("multicast not enabled on interface %s",
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
;
1265 ij
= igmp_join_find(pim_ifp
->gm_join_list
, group_addr
, source_addr
);
1267 /* This interface has already been configured to join this IGMP group
1273 (void)igmp_join_new(ifp
, group_addr
, source_addr
);
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
,
1280 pim_inet4_dump("<src?>", source_addr
, source_str
,
1281 sizeof(source_str
));
1283 "%s: issued static igmp join for channel (S,G)=(%s,%s) on interface %s",
1284 __func__
, source_str
, group_str
, ifp
->name
);
1289 #endif /* PIM_IPV == 4 */
1291 int pim_if_igmp_join_del(struct interface
*ifp
, struct in_addr group_addr
,
1292 struct in_addr source_addr
)
1294 struct pim_interface
*pim_ifp
;
1297 pim_ifp
= ifp
->info
;
1299 zlog_warn("%s: multicast not enabled on interface %s", __func__
,
1304 if (!pim_ifp
->gm_join_list
) {
1305 zlog_warn("%s: no IGMP join on interface %s", __func__
,
1310 ij
= igmp_join_find(pim_ifp
->gm_join_list
, group_addr
, source_addr
);
1312 char group_str
[INET_ADDRSTRLEN
];
1313 char source_str
[INET_ADDRSTRLEN
];
1314 pim_inet4_dump("<grp?>", group_addr
, group_str
,
1316 pim_inet4_dump("<src?>", source_addr
, source_str
,
1317 sizeof(source_str
));
1319 "%s: could not find IGMP group %s source %s on interface %s",
1320 __func__
, group_str
, source_str
, ifp
->name
);
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
,
1329 pim_inet4_dump("<src?>", source_addr
, source_str
,
1330 sizeof(source_str
));
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
));
1337 listnode_delete(pim_ifp
->gm_join_list
, 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;
1347 __attribute__((unused
))
1348 static void pim_if_igmp_join_del_all(struct interface
*ifp
)
1350 struct pim_interface
*pim_ifp
;
1351 struct listnode
*node
;
1352 struct listnode
*nextnode
;
1355 pim_ifp
= ifp
->info
;
1357 zlog_warn("%s: multicast not enabled on interface %s", __func__
,
1362 if (!pim_ifp
->gm_join_list
)
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
);
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
)
1375 int pim_if_igmp_join_del(struct interface
*ifp
, struct in_addr group_addr
,
1376 struct in_addr source_addr
)
1380 #endif /* PIM_IPV != 4 */
1385 Transitions from "I am Assert Loser" State
1387 Current Winner's GenID Changes or NLT Expires
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.
1396 void pim_if_assert_on_neighbor_down(struct interface
*ifp
, pim_addr neigh_addr
)
1398 struct pim_interface
*pim_ifp
;
1399 struct pim_ifchannel
*ch
;
1401 pim_ifp
= ifp
->info
;
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
)
1408 /* Dead neighbor was winner ? */
1409 if (pim_addr_cmp(ch
->ifassert_winner
, neigh_addr
))
1412 assert_action_a5(ch
);
1416 void pim_if_update_join_desired(struct pim_interface
*pim_ifp
)
1418 struct pim_ifchannel
*ch
;
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
);
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
;
1430 if (PIM_UPSTREAM_FLAG_TEST_DR_JOIN_DESIRED_UPDATED(up
->flags
))
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
);
1439 void pim_if_update_assert_tracking_desired(struct interface
*ifp
)
1441 struct pim_interface
*pim_ifp
;
1442 struct pim_ifchannel
*ch
;
1444 pim_ifp
= ifp
->info
;
1448 RB_FOREACH (ch
, pim_ifchannel_rb
, &pim_ifp
->ifchannel_rb
) {
1449 pim_ifchannel_update_assert_tracking_desired(ch
);
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.
1458 void pim_if_create_pimreg(struct pim_instance
*pim
)
1460 char pimreg_name
[INTERFACE_NAMSIZ
];
1462 if (!pim
->regiface
) {
1463 if (pim
->vrf
->vrf_id
== VRF_DEFAULT
)
1464 strlcpy(pimreg_name
, "pimreg", sizeof(pimreg_name
));
1466 snprintf(pimreg_name
, sizeof(pimreg_name
), "pimreg%u",
1467 pim
->vrf
->data
.l
.table_id
);
1469 pim
->regiface
= if_get_by_name(pimreg_name
, pim
->vrf
->vrf_id
,
1471 pim
->regiface
->ifindex
= PIM_OIF_PIM_REGISTER_VIF
;
1473 pim_if_new(pim
->regiface
, false, false, true,
1474 false /*vxlan_term*/);
1476 * On vrf moves we delete the interface if there
1477 * is nothing going on with it. We cannot have
1478 * the pimregiface deleted.
1480 pim
->regiface
->configured
= true;
1485 struct prefix
*pim_if_connected_to_source(struct interface
*ifp
, pim_addr src
)
1487 struct listnode
*cnode
;
1488 struct connected
*c
;
1494 pim_addr_to_prefix(&p
, src
);
1496 for (ALL_LIST_ELEMENTS_RO(ifp
->connected
, cnode
, c
)) {
1497 if (c
->address
->family
!= PIM_AF
)
1499 if (prefix_match(c
->address
, &p
))
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.
1511 bool pim_if_is_vrf_device(struct interface
*ifp
)
1519 int pim_if_ifchannel_count(struct pim_interface
*pim_ifp
)
1521 struct pim_ifchannel
*ch
;
1524 RB_FOREACH (ch
, pim_ifchannel_rb
, &pim_ifp
->ifchannel_rb
) {
1531 static int pim_ifp_create(struct interface
*ifp
)
1533 struct pim_instance
*pim
;
1535 pim
= ifp
->vrf
->info
;
1536 if (PIM_DEBUG_ZEBRA
) {
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
));
1544 if (if_is_operative(ifp
)) {
1545 struct pim_interface
*pim_ifp
;
1547 pim_ifp
= ifp
->info
;
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.
1556 pim_if_addr_add_all(ifp
);
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.
1564 * this is a no-op if it's already been done.
1566 pim_if_create_pimreg(pim
);
1572 * If we are a vrf device that is up, open up the pim_socket for
1574 * to incoming pim messages irrelevant if the user has configured us
1577 if (pim_if_is_vrf_device(ifp
)) {
1578 struct pim_interface
*pim_ifp
;
1581 pim_ifp
= pim_if_new(ifp
, false, false, false,
1582 false /*vxlan_term*/);
1583 ifp
->info
= pim_ifp
;
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
);
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
);
1603 static int pim_ifp_up(struct interface
*ifp
)
1605 struct pim_interface
*pim_ifp
;
1606 struct pim_instance
*pim
;
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 pim
= ifp
->vrf
->info
;
1618 pim_ifp
= ifp
->info
;
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.
1631 pim_if_addr_add_all() suffices for bringing up both IGMP and
1634 pim_if_addr_add_all(ifp
);
1637 * If we have a pimreg device callback and it's for a specific
1638 * table set the master appropriately
1640 if (sscanf(ifp
->name
, "pimreg%" SCNu32
, &table_id
) == 1) {
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
);
1650 "%s: Unable to find Master interface for %s",
1651 __func__
, vrf
->name
);
1654 pim_zebra_interface_set_master(master
, ifp
);
1662 static int pim_ifp_down(struct interface
*ifp
)
1664 if (PIM_DEBUG_ZEBRA
) {
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
));
1673 if (!if_is_operative(ifp
)) {
1674 pim_ifchannel_delete_all(ifp
);
1676 pim_if_addr_del_all() suffices for shutting down IGMP,
1677 but not for shutting down PIM
1679 pim_if_addr_del_all(ifp
);
1682 pim_sock_delete() closes the socket, stops read and timer
1684 and kills all neighbors.
1687 pim_sock_delete(ifp
, "link down");
1692 pim_if_del_vif(ifp
);
1693 pim_ifstat_reset(ifp
);
1700 static int pim_ifp_destroy(struct interface
*ifp
)
1702 if (PIM_DEBUG_ZEBRA
) {
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
));
1711 struct pim_instance
*pim
;
1713 if (!if_is_operative(ifp
))
1714 pim_if_addr_del_all(ifp
);
1716 pim
= ifp
->vrf
->info
;
1717 if (pim
&& pim
->vxlan
.term_if
== ifp
)
1718 pim_vxlan_del_term_dev(pim
);
1724 static int pim_if_new_hook(struct interface
*ifp
)
1729 static int pim_if_delete_hook(struct interface
*ifp
)
1737 void pim_iface_init(void)
1739 hook_register_prio(if_add
, 0, pim_if_new_hook
);
1740 hook_register_prio(if_del
, 0, pim_if_delete_hook
);
1742 if_zapi_callbacks(pim_ifp_create
, pim_ifp_up
, pim_ifp_down
,