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"
53 static void pim_if_igmp_join_del_all(struct interface
*ifp
);
54 static int igmp_join_sock(const char *ifname
, ifindex_t ifindex
,
55 struct in_addr group_addr
,
56 struct in_addr source_addr
);
58 void pim_if_init(struct pim_instance
*pim
)
62 for (i
= 0; i
< MAXVIFS
; i
++)
63 pim
->iface_vif_index
[i
] = 0;
66 void pim_if_terminate(struct pim_instance
*pim
)
68 struct interface
*ifp
;
70 FOR_ALL_INTERFACES (pim
->vrf
, ifp
) {
71 struct pim_interface
*pim_ifp
= ifp
->info
;
81 static void pim_sec_addr_free(struct pim_secondary_addr
*sec_addr
)
83 XFREE(MTYPE_PIM_SEC_ADDR
, sec_addr
);
86 static int pim_sec_addr_comp(const void *p1
, const void *p2
)
88 const struct pim_secondary_addr
*sec1
= p1
;
89 const struct pim_secondary_addr
*sec2
= p2
;
91 if (sec1
->addr
.family
== AF_INET
&& sec2
->addr
.family
== AF_INET6
)
94 if (sec1
->addr
.family
== AF_INET6
&& sec2
->addr
.family
== AF_INET
)
97 if (sec1
->addr
.family
== AF_INET
) {
98 if (ntohl(sec1
->addr
.u
.prefix4
.s_addr
)
99 < ntohl(sec2
->addr
.u
.prefix4
.s_addr
))
102 if (ntohl(sec1
->addr
.u
.prefix4
.s_addr
)
103 > ntohl(sec2
->addr
.u
.prefix4
.s_addr
))
106 return memcmp(&sec1
->addr
.u
.prefix6
, &sec2
->addr
.u
.prefix6
,
107 sizeof(struct in6_addr
));
113 struct pim_interface
*pim_if_new(struct interface
*ifp
, bool igmp
, bool pim
,
114 bool ispimreg
, bool is_vxlan_term
)
116 struct pim_interface
*pim_ifp
;
121 pim_ifp
= XCALLOC(MTYPE_PIM_INTERFACE
, sizeof(*pim_ifp
));
123 pim_ifp
->options
= 0;
124 pim_ifp
->pim
= ifp
->vrf
->info
;
125 pim_ifp
->mroute_vif_index
= -1;
127 pim_ifp
->igmp_version
= IGMP_DEFAULT_VERSION
;
128 pim_ifp
->gm_default_robustness_variable
=
129 IGMP_DEFAULT_ROBUSTNESS_VARIABLE
;
130 pim_ifp
->gm_default_query_interval
= IGMP_GENERAL_QUERY_INTERVAL
;
131 pim_ifp
->gm_query_max_response_time_dsec
=
132 IGMP_QUERY_MAX_RESPONSE_TIME_DSEC
;
133 pim_ifp
->gm_specific_query_max_response_time_dsec
=
134 IGMP_SPECIFIC_QUERY_MAX_RESPONSE_TIME_DSEC
;
135 pim_ifp
->gm_last_member_query_count
= IGMP_DEFAULT_ROBUSTNESS_VARIABLE
;
137 /* BSM config on interface: true by default */
138 pim_ifp
->bsm_enable
= true;
139 pim_ifp
->ucast_bsm_accept
= true;
140 pim_ifp
->am_i_dr
= false;
143 RFC 3376: 8.3. Query Response Interval
144 The number of seconds represented by the [Query Response Interval]
145 must be less than the [Query Interval].
147 assert(pim_ifp
->gm_query_max_response_time_dsec
<
148 pim_ifp
->gm_default_query_interval
);
151 PIM_IF_DO_PIM(pim_ifp
->options
);
153 PIM_IF_DO_IGMP(pim_ifp
->options
);
155 PIM_IF_DO_IGMP_LISTEN_ALLROUTERS(pim_ifp
->options
);
157 pim_ifp
->gm_join_list
= NULL
;
158 pim_ifp
->pim_neighbor_list
= NULL
;
159 pim_ifp
->upstream_switch_list
= NULL
;
160 pim_ifp
->pim_generation_id
= 0;
162 /* list of struct gm_sock */
163 pim_igmp_if_init(pim_ifp
, ifp
);
165 /* list of struct pim_neighbor */
166 pim_ifp
->pim_neighbor_list
= list_new();
167 pim_ifp
->pim_neighbor_list
->del
= (void (*)(void *))pim_neighbor_free
;
169 pim_ifp
->upstream_switch_list
= list_new();
170 pim_ifp
->upstream_switch_list
->del
=
171 (void (*)(void *))pim_jp_agg_group_list_free
;
172 pim_ifp
->upstream_switch_list
->cmp
= pim_jp_agg_group_list_cmp
;
174 pim_ifp
->sec_addr_list
= list_new();
175 pim_ifp
->sec_addr_list
->del
= (void (*)(void *))pim_sec_addr_free
;
176 pim_ifp
->sec_addr_list
->cmp
=
177 (int (*)(void *, void *))pim_sec_addr_comp
;
179 pim_ifp
->activeactive
= false;
181 RB_INIT(pim_ifchannel_rb
, &pim_ifp
->ifchannel_rb
);
187 pim_if_add_vif(ifp
, ispimreg
, is_vxlan_term
);
188 pim_ifp
->pim
->mcast_if_count
++;
193 void pim_if_delete(struct interface
*ifp
)
195 struct pim_interface
*pim_ifp
;
196 struct pim_ifchannel
*ch
;
202 if (pim_ifp
->gm_join_list
) {
203 pim_if_igmp_join_del_all(ifp
);
206 pim_ifchannel_delete_all(ifp
);
207 igmp_sock_delete_all(ifp
);
209 pim_neighbor_delete_all(ifp
, "Interface removed from configuration");
212 pim_ifp
->pim
->mcast_if_count
--;
214 pim_igmp_if_fini(pim_ifp
);
216 list_delete(&pim_ifp
->pim_neighbor_list
);
217 list_delete(&pim_ifp
->upstream_switch_list
);
218 list_delete(&pim_ifp
->sec_addr_list
);
220 XFREE(MTYPE_PIM_INTERFACE
, pim_ifp
->boundary_oil_plist
);
222 while (!RB_EMPTY(pim_ifchannel_rb
, &pim_ifp
->ifchannel_rb
)) {
223 ch
= RB_ROOT(pim_ifchannel_rb
, &pim_ifp
->ifchannel_rb
);
225 pim_ifchannel_delete(ch
);
228 XFREE(MTYPE_PIM_INTERFACE
, pim_ifp
);
233 void pim_if_update_could_assert(struct interface
*ifp
)
235 struct pim_interface
*pim_ifp
;
236 struct pim_ifchannel
*ch
;
241 RB_FOREACH (ch
, pim_ifchannel_rb
, &pim_ifp
->ifchannel_rb
) {
242 pim_ifchannel_update_could_assert(ch
);
246 static void pim_if_update_my_assert_metric(struct interface
*ifp
)
248 struct pim_interface
*pim_ifp
;
249 struct pim_ifchannel
*ch
;
254 RB_FOREACH (ch
, pim_ifchannel_rb
, &pim_ifp
->ifchannel_rb
) {
255 pim_ifchannel_update_my_assert_metric(ch
);
259 static void pim_addr_change(struct interface
*ifp
)
261 struct pim_interface
*pim_ifp
;
266 pim_if_dr_election(ifp
); /* router's own DR Priority (addr) changes --
268 pim_if_update_join_desired(pim_ifp
); /* depends on DR */
269 pim_if_update_could_assert(ifp
); /* depends on DR */
270 pim_if_update_my_assert_metric(ifp
); /* depends on could_assert */
271 pim_if_update_assert_tracking_desired(
272 ifp
); /* depends on DR, join_desired */
275 RFC 4601: 4.3.1. Sending Hello Messages
277 1) Before an interface goes down or changes primary IP address, a
278 Hello message with a zero HoldTime should be sent immediately
279 (with the old IP address if the IP address changed).
280 -- Done at the caller of the function as new ip already updated here
282 2) After an interface has changed its IP address, it MUST send a
283 Hello message with its new IP address.
286 3) If an interface changes one of its secondary IP addresses, a
287 Hello message with an updated Address_List option and a non-zero
288 HoldTime should be sent immediately.
289 -- FIXME See TODO T31
291 PIM_IF_FLAG_UNSET_HELLO_SENT(pim_ifp
->flags
);
292 if (pim_ifp
->pim_sock_fd
< 0)
294 pim_hello_restart_now(ifp
); /* send hello and restart timer */
297 static int detect_primary_address_change(struct interface
*ifp
,
298 int force_prim_as_any
,
301 struct pim_interface
*pim_ifp
= ifp
->info
;
302 struct in_addr new_prim_addr
;
305 if (force_prim_as_any
)
306 new_prim_addr
.s_addr
= INADDR_ANY
;
308 new_prim_addr
= pim_find_primary_addr(ifp
);
310 changed
= new_prim_addr
.s_addr
!= pim_ifp
->primary_address
.s_addr
;
312 if (PIM_DEBUG_ZEBRA
) {
313 char new_prim_str
[INET_ADDRSTRLEN
];
314 char old_prim_str
[INET_ADDRSTRLEN
];
315 pim_inet4_dump("<new?>", new_prim_addr
, new_prim_str
,
316 sizeof(new_prim_str
));
317 pim_inet4_dump("<old?>", pim_ifp
->primary_address
, old_prim_str
,
318 sizeof(old_prim_str
));
319 zlog_debug("%s: old=%s new=%s on interface %s: %s", __func__
,
320 old_prim_str
, new_prim_str
, ifp
->name
,
321 changed
? "changed" : "unchanged");
325 /* Before updating pim_ifp send Hello time with 0 hold time */
326 if (PIM_IF_TEST_PIM(pim_ifp
->options
)) {
327 pim_hello_send(ifp
, 0 /* zero-sec holdtime */);
329 pim_ifp
->primary_address
= new_prim_addr
;
335 static struct pim_secondary_addr
*
336 pim_sec_addr_find(struct pim_interface
*pim_ifp
, struct prefix
*addr
)
338 struct pim_secondary_addr
*sec_addr
;
339 struct listnode
*node
;
341 for (ALL_LIST_ELEMENTS_RO(pim_ifp
->sec_addr_list
, node
, sec_addr
)) {
342 if (prefix_cmp(&sec_addr
->addr
, addr
) == 0) {
350 static void pim_sec_addr_del(struct pim_interface
*pim_ifp
,
351 struct pim_secondary_addr
*sec_addr
)
353 listnode_delete(pim_ifp
->sec_addr_list
, sec_addr
);
354 pim_sec_addr_free(sec_addr
);
357 static int pim_sec_addr_add(struct pim_interface
*pim_ifp
, struct prefix
*addr
)
360 struct pim_secondary_addr
*sec_addr
;
362 sec_addr
= pim_sec_addr_find(pim_ifp
, addr
);
364 sec_addr
->flags
&= ~PIM_SEC_ADDRF_STALE
;
368 sec_addr
= XCALLOC(MTYPE_PIM_SEC_ADDR
, sizeof(*sec_addr
));
371 sec_addr
->addr
= *addr
;
372 listnode_add_sort(pim_ifp
->sec_addr_list
, sec_addr
);
377 static int pim_sec_addr_del_all(struct pim_interface
*pim_ifp
)
381 if (!list_isempty(pim_ifp
->sec_addr_list
)) {
383 /* remove all nodes and free up the list itself */
384 list_delete_all_node(pim_ifp
->sec_addr_list
);
390 static int pim_sec_addr_update(struct interface
*ifp
)
392 struct pim_interface
*pim_ifp
= ifp
->info
;
393 struct connected
*ifc
;
394 struct listnode
*node
;
395 struct listnode
*nextnode
;
396 struct pim_secondary_addr
*sec_addr
;
399 for (ALL_LIST_ELEMENTS_RO(pim_ifp
->sec_addr_list
, node
, sec_addr
)) {
400 sec_addr
->flags
|= PIM_SEC_ADDRF_STALE
;
403 for (ALL_LIST_ELEMENTS_RO(ifp
->connected
, node
, ifc
)) {
404 struct prefix
*p
= ifc
->address
;
406 if (PIM_INADDR_IS_ANY(p
->u
.prefix4
)) {
410 if (pim_ifp
->primary_address
.s_addr
== p
->u
.prefix4
.s_addr
) {
411 /* don't add the primary address into the secondary
416 if (pim_sec_addr_add(pim_ifp
, p
)) {
421 /* Drop stale entries */
422 for (ALL_LIST_ELEMENTS(pim_ifp
->sec_addr_list
, node
, nextnode
,
424 if (sec_addr
->flags
& PIM_SEC_ADDRF_STALE
) {
425 pim_sec_addr_del(pim_ifp
, sec_addr
);
433 static int detect_secondary_address_change(struct interface
*ifp
,
434 int force_prim_as_any
,
437 struct pim_interface
*pim_ifp
= ifp
->info
;
440 if (force_prim_as_any
) {
441 /* if primary address is being forced to zero just flush the
442 * secondary address list */
443 changed
= pim_sec_addr_del_all(pim_ifp
);
445 /* re-evaluate the secondary address list */
446 changed
= pim_sec_addr_update(ifp
);
452 static void detect_address_change(struct interface
*ifp
, int force_prim_as_any
,
456 struct pim_interface
*pim_ifp
;
462 if (detect_primary_address_change(ifp
, force_prim_as_any
, caller
)) {
466 if (detect_secondary_address_change(ifp
, force_prim_as_any
, caller
)) {
472 if (!PIM_IF_TEST_PIM(pim_ifp
->options
)) {
476 pim_addr_change(ifp
);
479 /* XXX: if we have unnumbered interfaces we need to run detect address
480 * address change on all of them when the lo address changes */
483 int pim_update_source_set(struct interface
*ifp
, struct in_addr source
)
485 struct pim_interface
*pim_ifp
= ifp
->info
;
488 return PIM_IFACE_NOT_FOUND
;
491 if (pim_ifp
->update_source
.s_addr
== source
.s_addr
) {
492 return PIM_UPDATE_SOURCE_DUP
;
495 pim_ifp
->update_source
= source
;
496 detect_address_change(ifp
, 0 /* force_prim_as_any */, __func__
);
501 void pim_if_addr_add(struct connected
*ifc
)
503 struct pim_interface
*pim_ifp
;
504 struct interface
*ifp
;
505 struct in_addr ifaddr
;
516 if (!if_is_operative(ifp
))
520 zlog_debug("%s: %s ifindex=%d connected IP address %pFX %s",
521 __func__
, ifp
->name
, ifp
->ifindex
, ifc
->address
,
522 CHECK_FLAG(ifc
->flags
, ZEBRA_IFA_SECONDARY
)
526 ifaddr
= ifc
->address
->u
.prefix4
;
528 detect_address_change(ifp
, 0, __func__
);
530 // if (ifc->address->family != AF_INET)
533 if (PIM_IF_TEST_IGMP(pim_ifp
->options
)) {
534 struct gm_sock
*igmp
;
536 /* lookup IGMP socket */
537 igmp
= pim_igmp_sock_lookup_ifaddr(pim_ifp
->gm_socket_list
,
540 /* if addr new, add IGMP socket */
541 if (ifc
->address
->family
== AF_INET
)
542 pim_igmp_sock_add(pim_ifp
->gm_socket_list
,
544 } else if (igmp
->mtrace_only
) {
545 igmp_sock_delete(igmp
);
546 pim_igmp_sock_add(pim_ifp
->gm_socket_list
, ifaddr
, ifp
,
550 /* Replay Static IGMP groups */
551 if (pim_ifp
->gm_join_list
) {
552 struct listnode
*node
;
553 struct listnode
*nextnode
;
557 for (ALL_LIST_ELEMENTS(pim_ifp
->gm_join_list
, node
,
559 /* Close socket and reopen with Source and Group
562 join_fd
= igmp_join_sock(
563 ifp
->name
, ifp
->ifindex
, ij
->group_addr
,
566 char group_str
[INET_ADDRSTRLEN
];
567 char source_str
[INET_ADDRSTRLEN
];
568 pim_inet4_dump("<grp?>", ij
->group_addr
,
572 "<src?>", ij
->source_addr
,
573 source_str
, sizeof(source_str
));
575 "%s: igmp_join_sock() failure for IGMP group %s source %s on interface %s",
576 __func__
, group_str
, source_str
,
580 ij
->sock_fd
= join_fd
;
585 struct gm_sock
*igmp
;
587 /* lookup IGMP socket */
588 igmp
= pim_igmp_sock_lookup_ifaddr(pim_ifp
->gm_socket_list
,
590 if (ifc
->address
->family
== AF_INET
) {
592 igmp_sock_delete(igmp
);
593 /* if addr new, add IGMP socket */
594 pim_igmp_sock_add(pim_ifp
->gm_socket_list
, ifaddr
, ifp
,
597 } /* igmp mtrace only */
599 if (PIM_IF_TEST_PIM(pim_ifp
->options
)) {
601 if (PIM_INADDR_ISNOT_ANY(pim_ifp
->primary_address
)) {
603 /* Interface has a valid socket ? */
604 if (pim_ifp
->pim_sock_fd
< 0) {
605 if (pim_sock_add(ifp
)) {
607 "Failure creating PIM socket for interface %s",
611 struct pim_nexthop_cache
*pnc
= NULL
;
613 struct zclient
*zclient
= NULL
;
615 zclient
= pim_zebra_zclient_get();
616 /* RP config might come prior to (local RP's interface)
618 In this case, pnc would not have pim enabled
620 Once Interface is UP and pim info is available,
622 with RNH address to receive update and add the
623 interface as nexthop. */
624 memset(&rpf
, 0, sizeof(struct pim_rpf
));
625 rpf
.rpf_addr
.family
= AF_INET
;
626 rpf
.rpf_addr
.prefixlen
= IPV4_MAX_BITLEN
;
627 rpf
.rpf_addr
.u
.prefix4
= ifc
->address
->u
.prefix4
;
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
);
644 pim_ifchannel_scan_forward_start(ifp
);
647 static void pim_if_addr_del_igmp(struct connected
*ifc
)
649 struct pim_interface
*pim_ifp
= ifc
->ifp
->info
;
650 struct gm_sock
*igmp
;
651 struct in_addr ifaddr
;
653 if (ifc
->address
->family
!= AF_INET
) {
654 /* non-IPv4 address */
659 /* IGMP not enabled on interface */
663 ifaddr
= ifc
->address
->u
.prefix4
;
665 /* lookup IGMP socket */
666 igmp
= pim_igmp_sock_lookup_ifaddr(pim_ifp
->gm_socket_list
, ifaddr
);
668 /* if addr found, del IGMP socket */
669 igmp_sock_delete(igmp
);
673 static void pim_if_addr_del_pim(struct connected
*ifc
)
675 struct pim_interface
*pim_ifp
= ifc
->ifp
->info
;
677 if (ifc
->address
->family
!= AF_INET
) {
678 /* non-IPv4 address */
683 /* PIM not enabled on interface */
687 if (PIM_INADDR_ISNOT_ANY(pim_ifp
->primary_address
)) {
688 /* Interface keeps a valid primary address */
692 if (pim_ifp
->pim_sock_fd
< 0) {
693 /* Interface does not hold a valid socket any longer */
698 pim_sock_delete() closes the socket, stops read and timer threads,
699 and kills all neighbors.
701 pim_sock_delete(ifc
->ifp
,
702 "last address has been removed from interface");
705 void pim_if_addr_del(struct connected
*ifc
, int force_prim_as_any
)
707 struct interface
*ifp
;
714 zlog_debug("%s: %s ifindex=%d disconnected IP address %pFX %s",
715 __func__
, ifp
->name
, ifp
->ifindex
, ifc
->address
,
716 CHECK_FLAG(ifc
->flags
, ZEBRA_IFA_SECONDARY
)
720 detect_address_change(ifp
, force_prim_as_any
, __func__
);
722 pim_if_addr_del_igmp(ifc
);
723 pim_if_addr_del_pim(ifc
);
726 void pim_if_addr_add_all(struct interface
*ifp
)
728 struct connected
*ifc
;
729 struct listnode
*node
;
730 struct listnode
*nextnode
;
733 struct pim_interface
*pim_ifp
= ifp
->info
;
737 /* PIM/IGMP enabled ? */
741 for (ALL_LIST_ELEMENTS(ifp
->connected
, node
, nextnode
, ifc
)) {
742 struct prefix
*p
= ifc
->address
;
744 if (p
->family
!= AF_INET
)
748 pim_if_addr_add(ifc
);
751 if (!v4_addrs
&& v6_addrs
&& !if_is_loopback(ifp
)) {
752 if (PIM_IF_TEST_PIM(pim_ifp
->options
)) {
754 /* Interface has a valid primary address ? */
755 if (PIM_INADDR_ISNOT_ANY(pim_ifp
->primary_address
)) {
757 /* Interface has a valid socket ? */
758 if (pim_ifp
->pim_sock_fd
< 0) {
759 if (pim_sock_add(ifp
)) {
761 "Failure creating PIM socket for interface %s",
769 * PIM or IGMP is enabled on interface, and there is at least one
770 * address assigned, then try to create a vif_index.
772 if (pim_ifp
->mroute_vif_index
< 0) {
773 vxlan_term
= pim_vxlan_is_term_dev_cfg(pim_ifp
->pim
, ifp
);
774 pim_if_add_vif(ifp
, false, vxlan_term
);
776 pim_ifchannel_scan_forward_start(ifp
);
778 pim_rp_setup(pim_ifp
->pim
);
779 pim_rp_check_on_if_add(pim_ifp
);
782 void pim_if_addr_del_all(struct interface
*ifp
)
784 struct connected
*ifc
;
785 struct listnode
*node
;
786 struct listnode
*nextnode
;
787 struct pim_instance
*pim
;
789 pim
= ifp
->vrf
->info
;
793 /* PIM/IGMP enabled ? */
797 for (ALL_LIST_ELEMENTS(ifp
->connected
, node
, nextnode
, ifc
)) {
798 struct prefix
*p
= ifc
->address
;
800 if (p
->family
!= AF_INET
)
803 pim_if_addr_del(ifc
, 1 /* force_prim_as_any=true */);
807 pim_i_am_rp_re_evaluate(pim
);
810 void pim_if_addr_del_all_igmp(struct interface
*ifp
)
812 struct connected
*ifc
;
813 struct listnode
*node
;
814 struct listnode
*nextnode
;
816 /* PIM/IGMP enabled ? */
820 for (ALL_LIST_ELEMENTS(ifp
->connected
, node
, nextnode
, ifc
)) {
821 struct prefix
*p
= ifc
->address
;
823 if (p
->family
!= AF_INET
)
826 pim_if_addr_del_igmp(ifc
);
830 struct in_addr
pim_find_primary_addr(struct interface
*ifp
)
832 struct connected
*ifc
;
833 struct listnode
*node
;
834 struct in_addr addr
= {0};
837 struct pim_interface
*pim_ifp
= ifp
->info
;
839 if (pim_ifp
&& PIM_INADDR_ISNOT_ANY(pim_ifp
->update_source
)) {
840 return pim_ifp
->update_source
;
843 for (ALL_LIST_ELEMENTS_RO(ifp
->connected
, node
, ifc
)) {
844 struct prefix
*p
= ifc
->address
;
846 if (p
->family
!= AF_INET
) {
851 if (PIM_INADDR_IS_ANY(p
->u
.prefix4
)) {
853 "%s: null IPv4 address connected to interface %s",
854 __func__
, ifp
->name
);
860 if (CHECK_FLAG(ifc
->flags
, ZEBRA_IFA_SECONDARY
))
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
);
886 addr
.s_addr
= PIM_NET_INADDR_ANY
;
891 static int pim_iface_next_vif_index(struct interface
*ifp
)
893 struct pim_interface
*pim_ifp
= ifp
->info
;
894 struct pim_instance
*pim
= pim_ifp
->pim
;
898 * The pimreg vif is always going to be in index 0
901 if (ifp
->ifindex
== PIM_OIF_PIM_REGISTER_VIF
)
904 for (i
= 1; i
< MAXVIFS
; i
++) {
905 if (pim
->iface_vif_index
[i
] == 0)
912 pim_if_add_vif() uses ifindex as vif_index
914 see also pim_if_find_vifindex_by_ifindex()
916 int pim_if_add_vif(struct interface
*ifp
, bool ispimreg
, bool is_vxlan_term
)
918 struct pim_interface
*pim_ifp
= ifp
->info
;
919 struct in_addr ifaddr
;
920 unsigned char flags
= 0;
924 if (pim_ifp
->mroute_vif_index
> 0) {
925 zlog_warn("%s: vif_index=%d > 0 on interface %s ifindex=%d",
926 __func__
, pim_ifp
->mroute_vif_index
, ifp
->name
,
931 if (ifp
->ifindex
< 0) {
932 zlog_warn("%s: ifindex=%d < 1 on interface %s", __func__
,
933 ifp
->ifindex
, ifp
->name
);
937 ifaddr
= pim_ifp
->primary_address
;
938 if (!ispimreg
&& !is_vxlan_term
&& PIM_INADDR_IS_ANY(ifaddr
)) {
940 "%s: could not get address for interface %s ifindex=%d",
941 __func__
, ifp
->name
, ifp
->ifindex
);
945 pim_ifp
->mroute_vif_index
= pim_iface_next_vif_index(ifp
);
947 if (pim_ifp
->mroute_vif_index
>= MAXVIFS
) {
949 "%s: Attempting to configure more than MAXVIFS=%d on pim enabled interface %s",
950 __func__
, MAXVIFS
, ifp
->name
);
954 if (ifp
->ifindex
== PIM_OIF_PIM_REGISTER_VIF
)
955 flags
= VIFF_REGISTER
;
956 #ifdef VIFF_USE_IFINDEX
958 flags
= VIFF_USE_IFINDEX
;
961 if (pim_mroute_add_vif(ifp
, ifaddr
, flags
)) {
962 /* pim_mroute_add_vif reported error */
966 pim_ifp
->pim
->iface_vif_index
[pim_ifp
->mroute_vif_index
] = 1;
968 /* if the device qualifies as pim_vxlan iif/oif update vxlan entries */
969 pim_vxlan_add_vif(ifp
);
974 int pim_if_del_vif(struct interface
*ifp
)
976 struct pim_interface
*pim_ifp
= ifp
->info
;
978 if (pim_ifp
->mroute_vif_index
< 1) {
979 zlog_warn("%s: vif_index=%d < 1 on interface %s ifindex=%d",
980 __func__
, pim_ifp
->mroute_vif_index
, ifp
->name
,
985 /* if the device was a pim_vxlan iif/oif update vxlan mroute entries */
986 pim_vxlan_del_vif(ifp
);
988 pim_mroute_del_vif(ifp
);
993 pim_ifp
->pim
->iface_vif_index
[pim_ifp
->mroute_vif_index
] = 0;
995 pim_ifp
->mroute_vif_index
= -1;
1001 struct interface
*pim_if_find_by_vif_index(struct pim_instance
*pim
,
1002 ifindex_t vif_index
)
1004 struct interface
*ifp
;
1006 FOR_ALL_INTERFACES (pim
->vrf
, ifp
) {
1008 struct pim_interface
*pim_ifp
;
1009 pim_ifp
= ifp
->info
;
1011 if (vif_index
== pim_ifp
->mroute_vif_index
)
1020 pim_if_add_vif() uses ifindex as vif_index
1022 int pim_if_find_vifindex_by_ifindex(struct pim_instance
*pim
, ifindex_t ifindex
)
1024 struct pim_interface
*pim_ifp
;
1025 struct interface
*ifp
;
1027 ifp
= if_lookup_by_index(ifindex
, pim
->vrf
->vrf_id
);
1028 if (!ifp
|| !ifp
->info
)
1030 pim_ifp
= ifp
->info
;
1032 return pim_ifp
->mroute_vif_index
;
1035 int pim_if_lan_delay_enabled(struct interface
*ifp
)
1037 struct pim_interface
*pim_ifp
;
1039 pim_ifp
= ifp
->info
;
1041 assert(pim_ifp
->pim_number_of_nonlandelay_neighbors
>= 0);
1043 return pim_ifp
->pim_number_of_nonlandelay_neighbors
== 0;
1046 uint16_t pim_if_effective_propagation_delay_msec(struct interface
*ifp
)
1048 if (pim_if_lan_delay_enabled(ifp
)) {
1049 struct pim_interface
*pim_ifp
;
1050 pim_ifp
= ifp
->info
;
1051 return pim_ifp
->pim_neighbors_highest_propagation_delay_msec
;
1053 return PIM_DEFAULT_PROPAGATION_DELAY_MSEC
;
1057 uint16_t pim_if_effective_override_interval_msec(struct interface
*ifp
)
1059 if (pim_if_lan_delay_enabled(ifp
)) {
1060 struct pim_interface
*pim_ifp
;
1061 pim_ifp
= ifp
->info
;
1062 return pim_ifp
->pim_neighbors_highest_override_interval_msec
;
1064 return PIM_DEFAULT_OVERRIDE_INTERVAL_MSEC
;
1068 int pim_if_t_override_msec(struct interface
*ifp
)
1070 int effective_override_interval_msec
;
1071 int t_override_msec
;
1073 effective_override_interval_msec
=
1074 pim_if_effective_override_interval_msec(ifp
);
1077 frr_weak_random() % (effective_override_interval_msec
+ 1);
1079 return t_override_msec
;
1082 uint16_t pim_if_jp_override_interval_msec(struct interface
*ifp
)
1084 return pim_if_effective_propagation_delay_msec(ifp
)
1085 + pim_if_effective_override_interval_msec(ifp
);
1089 RFC 4601: 4.1.6. State Summarization Macros
1091 The function NBR( I, A ) uses information gathered through PIM Hello
1092 messages to map the IP address A of a directly connected PIM
1093 neighbor router on interface I to the primary IP address of the same
1094 router (Section 4.3.4). The primary IP address of a neighbor is the
1095 address that it uses as the source of its PIM Hello messages.
1097 struct pim_neighbor
*pim_if_find_neighbor(struct interface
*ifp
,
1098 struct in_addr addr
)
1100 struct listnode
*neighnode
;
1101 struct pim_neighbor
*neigh
;
1102 struct pim_interface
*pim_ifp
;
1107 pim_ifp
= ifp
->info
;
1109 zlog_warn("%s: multicast not enabled on interface %s", __func__
,
1116 p
.prefixlen
= IPV4_MAX_BITLEN
;
1118 for (ALL_LIST_ELEMENTS_RO(pim_ifp
->pim_neighbor_list
, neighnode
,
1121 /* primary address ? */
1122 if (neigh
->source_addr
.s_addr
== addr
.s_addr
)
1125 /* secondary address ? */
1126 if (pim_neighbor_find_secondary(neigh
, &p
))
1130 if (PIM_DEBUG_PIM_TRACE
) {
1131 char addr_str
[INET_ADDRSTRLEN
];
1132 pim_inet4_dump("<addr?>", addr
, addr_str
, sizeof(addr_str
));
1134 "%s: neighbor not found for address %s on interface %s",
1135 __func__
, addr_str
, ifp
->name
);
1141 long pim_if_t_suppressed_msec(struct interface
*ifp
)
1143 struct pim_interface
*pim_ifp
;
1144 long t_suppressed_msec
;
1145 uint32_t ramount
= 0;
1147 pim_ifp
= ifp
->info
;
1150 /* join suppression disabled ? */
1151 if (PIM_IF_TEST_PIM_CAN_DISABLE_JOIN_SUPPRESSION(pim_ifp
->options
))
1154 /* t_suppressed = t_periodic * rand(1.1, 1.4) */
1155 ramount
= 1100 + (frr_weak_random() % (1400 - 1100 + 1));
1156 t_suppressed_msec
= router
->t_periodic
* ramount
;
1158 return t_suppressed_msec
;
1161 static void igmp_join_free(struct gm_join
*ij
)
1163 XFREE(MTYPE_PIM_IGMP_JOIN
, ij
);
1166 static struct gm_join
*igmp_join_find(struct list
*join_list
,
1167 struct in_addr group_addr
,
1168 struct in_addr source_addr
)
1170 struct listnode
*node
;
1175 for (ALL_LIST_ELEMENTS_RO(join_list
, node
, ij
)) {
1176 if ((group_addr
.s_addr
== ij
->group_addr
.s_addr
)
1177 && (source_addr
.s_addr
== ij
->source_addr
.s_addr
))
1184 static int igmp_join_sock(const char *ifname
, ifindex_t ifindex
,
1185 struct in_addr group_addr
, struct in_addr source_addr
)
1189 join_fd
= pim_socket_raw(IPPROTO_IGMP
);
1194 if (pim_igmp_join_source(join_fd
, ifindex
, group_addr
, source_addr
)) {
1195 char group_str
[INET_ADDRSTRLEN
];
1196 char source_str
[INET_ADDRSTRLEN
];
1197 pim_inet4_dump("<grp?>", group_addr
, group_str
,
1199 pim_inet4_dump("<src?>", source_addr
, source_str
,
1200 sizeof(source_str
));
1202 "%s: setsockopt(fd=%d) failure for IGMP group %s source %s ifindex %d on interface %s: errno=%d: %s",
1203 __func__
, join_fd
, group_str
, source_str
, ifindex
,
1204 ifname
, errno
, safe_strerror(errno
));
1213 static struct gm_join
*igmp_join_new(struct interface
*ifp
,
1214 struct in_addr group_addr
,
1215 struct in_addr source_addr
)
1217 struct pim_interface
*pim_ifp
;
1221 pim_ifp
= ifp
->info
;
1224 join_fd
= igmp_join_sock(ifp
->name
, ifp
->ifindex
, group_addr
,
1227 char group_str
[INET_ADDRSTRLEN
];
1228 char source_str
[INET_ADDRSTRLEN
];
1230 pim_inet4_dump("<grp?>", group_addr
, group_str
,
1232 pim_inet4_dump("<src?>", source_addr
, source_str
,
1233 sizeof(source_str
));
1235 "%s: igmp_join_sock() failure for IGMP group %s source %s on interface %s",
1236 __func__
, group_str
, source_str
, ifp
->name
);
1240 ij
= XCALLOC(MTYPE_PIM_IGMP_JOIN
, sizeof(*ij
));
1242 ij
->sock_fd
= join_fd
;
1243 ij
->group_addr
= group_addr
;
1244 ij
->source_addr
= source_addr
;
1245 ij
->sock_creation
= pim_time_monotonic_sec();
1247 listnode_add(pim_ifp
->gm_join_list
, ij
);
1252 ferr_r
pim_if_igmp_join_add(struct interface
*ifp
, struct in_addr group_addr
,
1253 struct in_addr source_addr
)
1255 struct pim_interface
*pim_ifp
;
1258 pim_ifp
= ifp
->info
;
1260 return ferr_cfg_invalid("multicast not enabled on interface %s",
1264 if (!pim_ifp
->gm_join_list
) {
1265 pim_ifp
->gm_join_list
= list_new();
1266 pim_ifp
->gm_join_list
->del
= (void (*)(void *))igmp_join_free
;
1269 ij
= igmp_join_find(pim_ifp
->gm_join_list
, group_addr
, source_addr
);
1271 /* This interface has already been configured to join this IGMP group
1277 (void)igmp_join_new(ifp
, group_addr
, source_addr
);
1279 if (PIM_DEBUG_IGMP_EVENTS
) {
1280 char group_str
[INET_ADDRSTRLEN
];
1281 char source_str
[INET_ADDRSTRLEN
];
1282 pim_inet4_dump("<grp?>", group_addr
, group_str
,
1284 pim_inet4_dump("<src?>", source_addr
, source_str
,
1285 sizeof(source_str
));
1287 "%s: issued static igmp join for channel (S,G)=(%s,%s) on interface %s",
1288 __func__
, source_str
, group_str
, ifp
->name
);
1295 int pim_if_igmp_join_del(struct interface
*ifp
, struct in_addr group_addr
,
1296 struct in_addr source_addr
)
1298 struct pim_interface
*pim_ifp
;
1301 pim_ifp
= ifp
->info
;
1303 zlog_warn("%s: multicast not enabled on interface %s", __func__
,
1308 if (!pim_ifp
->gm_join_list
) {
1309 zlog_warn("%s: no IGMP join on interface %s", __func__
,
1314 ij
= igmp_join_find(pim_ifp
->gm_join_list
, group_addr
, source_addr
);
1316 char group_str
[INET_ADDRSTRLEN
];
1317 char source_str
[INET_ADDRSTRLEN
];
1318 pim_inet4_dump("<grp?>", group_addr
, group_str
,
1320 pim_inet4_dump("<src?>", source_addr
, source_str
,
1321 sizeof(source_str
));
1323 "%s: could not find IGMP group %s source %s on interface %s",
1324 __func__
, group_str
, source_str
, ifp
->name
);
1328 if (close(ij
->sock_fd
)) {
1329 char group_str
[INET_ADDRSTRLEN
];
1330 char source_str
[INET_ADDRSTRLEN
];
1331 pim_inet4_dump("<grp?>", group_addr
, group_str
,
1333 pim_inet4_dump("<src?>", source_addr
, source_str
,
1334 sizeof(source_str
));
1336 "%s: failure closing sock_fd=%d for IGMP group %s source %s on interface %s: errno=%d: %s",
1337 __func__
, ij
->sock_fd
, group_str
, source_str
, ifp
->name
,
1338 errno
, safe_strerror(errno
));
1341 listnode_delete(pim_ifp
->gm_join_list
, ij
);
1343 if (listcount(pim_ifp
->gm_join_list
) < 1) {
1344 list_delete(&pim_ifp
->gm_join_list
);
1345 pim_ifp
->gm_join_list
= 0;
1351 static void pim_if_igmp_join_del_all(struct interface
*ifp
)
1353 struct pim_interface
*pim_ifp
;
1354 struct listnode
*node
;
1355 struct listnode
*nextnode
;
1358 pim_ifp
= ifp
->info
;
1360 zlog_warn("%s: multicast not enabled on interface %s", __func__
,
1365 if (!pim_ifp
->gm_join_list
)
1368 for (ALL_LIST_ELEMENTS(pim_ifp
->gm_join_list
, node
, nextnode
, ij
))
1369 pim_if_igmp_join_del(ifp
, ij
->group_addr
, ij
->source_addr
);
1375 Transitions from "I am Assert Loser" State
1377 Current Winner's GenID Changes or NLT Expires
1379 The Neighbor Liveness Timer associated with the current winner
1380 expires or we receive a Hello message from the current winner
1381 reporting a different GenID from the one it previously reported.
1382 This indicates that the current winner's interface or router has
1383 gone down (and may have come back up), and so we must assume it no
1384 longer knows it was the winner.
1386 void pim_if_assert_on_neighbor_down(struct interface
*ifp
,
1387 struct in_addr neigh_addr
)
1389 struct pim_interface
*pim_ifp
;
1390 struct pim_ifchannel
*ch
;
1392 pim_ifp
= ifp
->info
;
1395 RB_FOREACH (ch
, pim_ifchannel_rb
, &pim_ifp
->ifchannel_rb
) {
1396 /* Is (S,G,I) assert loser ? */
1397 if (ch
->ifassert_state
!= PIM_IFASSERT_I_AM_LOSER
)
1399 /* Dead neighbor was winner ? */
1400 if (ch
->ifassert_winner
.s_addr
!= neigh_addr
.s_addr
)
1403 assert_action_a5(ch
);
1407 void pim_if_update_join_desired(struct pim_interface
*pim_ifp
)
1409 struct pim_ifchannel
*ch
;
1411 /* clear off flag from interface's upstreams */
1412 RB_FOREACH (ch
, pim_ifchannel_rb
, &pim_ifp
->ifchannel_rb
) {
1413 PIM_UPSTREAM_FLAG_UNSET_DR_JOIN_DESIRED_UPDATED(
1414 ch
->upstream
->flags
);
1417 /* scan per-interface (S,G,I) state on this I interface */
1418 RB_FOREACH (ch
, pim_ifchannel_rb
, &pim_ifp
->ifchannel_rb
) {
1419 struct pim_upstream
*up
= ch
->upstream
;
1421 if (PIM_UPSTREAM_FLAG_TEST_DR_JOIN_DESIRED_UPDATED(up
->flags
))
1424 /* update join_desired for the global (S,G) state */
1425 pim_upstream_update_join_desired(pim_ifp
->pim
, up
);
1426 PIM_UPSTREAM_FLAG_SET_DR_JOIN_DESIRED_UPDATED(up
->flags
);
1430 void pim_if_update_assert_tracking_desired(struct interface
*ifp
)
1432 struct pim_interface
*pim_ifp
;
1433 struct pim_ifchannel
*ch
;
1435 pim_ifp
= ifp
->info
;
1439 RB_FOREACH (ch
, pim_ifchannel_rb
, &pim_ifp
->ifchannel_rb
) {
1440 pim_ifchannel_update_assert_tracking_desired(ch
);
1445 * PIM wants to have an interface pointer for everything it does.
1446 * The pimreg is a special interface that we have that is not
1447 * quite an inteface but a VIF is created for it.
1449 void pim_if_create_pimreg(struct pim_instance
*pim
)
1451 char pimreg_name
[INTERFACE_NAMSIZ
];
1453 if (!pim
->regiface
) {
1454 if (pim
->vrf
->vrf_id
== VRF_DEFAULT
)
1455 strlcpy(pimreg_name
, "pimreg", sizeof(pimreg_name
));
1457 snprintf(pimreg_name
, sizeof(pimreg_name
), "pimreg%u",
1458 pim
->vrf
->data
.l
.table_id
);
1460 pim
->regiface
= if_get_by_name(pimreg_name
, pim
->vrf
->vrf_id
,
1462 pim
->regiface
->ifindex
= PIM_OIF_PIM_REGISTER_VIF
;
1464 pim_if_new(pim
->regiface
, false, false, true,
1465 false /*vxlan_term*/);
1467 * On vrf moves we delete the interface if there
1468 * is nothing going on with it. We cannot have
1469 * the pimregiface deleted.
1471 pim
->regiface
->configured
= true;
1476 struct prefix
*pim_if_connected_to_source(struct interface
*ifp
, struct in_addr src
)
1478 struct listnode
*cnode
;
1479 struct connected
*c
;
1487 p
.prefixlen
= IPV4_MAX_BITLEN
;
1489 for (ALL_LIST_ELEMENTS_RO(ifp
->connected
, cnode
, c
)) {
1490 if (c
->address
->family
!= AF_INET
)
1492 if (prefix_match(c
->address
, &p
))
1494 if (CONNECTED_PEER(c
) && prefix_match(c
->destination
, &p
))
1495 /* this is not a typo, on PtP we need to return the
1496 * *local* address that lines up with src.
1504 bool pim_if_is_vrf_device(struct interface
*ifp
)
1512 int pim_if_ifchannel_count(struct pim_interface
*pim_ifp
)
1514 struct pim_ifchannel
*ch
;
1517 RB_FOREACH (ch
, pim_ifchannel_rb
, &pim_ifp
->ifchannel_rb
) {
1524 static int pim_ifp_create(struct interface
*ifp
)
1526 struct pim_instance
*pim
;
1528 pim
= ifp
->vrf
->info
;
1529 if (PIM_DEBUG_ZEBRA
) {
1531 "%s: %s index %d vrf %s(%u) flags %ld metric %d mtu %d operative %d",
1532 __func__
, ifp
->name
, ifp
->ifindex
, ifp
->vrf
->name
,
1533 ifp
->vrf
->vrf_id
, (long)ifp
->flags
, ifp
->metric
,
1534 ifp
->mtu
, if_is_operative(ifp
));
1537 if (if_is_operative(ifp
)) {
1538 struct pim_interface
*pim_ifp
;
1540 pim_ifp
= ifp
->info
;
1542 * If we have a pim_ifp already and this is an if_add
1543 * that means that we probably have a vrf move event
1544 * If that is the case, set the proper vrfness.
1548 pim_if_addr_add_all(ifp
);
1551 * Due to ordering issues based upon when
1552 * a command is entered we should ensure that
1553 * the pim reg is created for this vrf if we
1554 * have configuration for it already.
1556 * this is a no-op if it's already been done.
1558 pim_if_create_pimreg(pim
);
1562 * If we are a vrf device that is up, open up the pim_socket for
1564 * to incoming pim messages irrelevant if the user has configured us
1567 if (pim_if_is_vrf_device(ifp
)) {
1568 struct pim_interface
*pim_ifp
;
1571 pim_ifp
= pim_if_new(ifp
, false, false, false,
1572 false /*vxlan_term*/);
1573 ifp
->info
= pim_ifp
;
1579 if (!strncmp(ifp
->name
, PIM_VXLAN_TERM_DEV_NAME
,
1580 sizeof(PIM_VXLAN_TERM_DEV_NAME
))) {
1581 if (pim
->mcast_if_count
< MAXVIFS
)
1582 pim_vxlan_add_term_dev(pim
, ifp
);
1585 "%s: Cannot enable pim on %s. MAXVIFS(%d) reached. Deleting and readding the vxlan termimation device after unconfiguring pim from other interfaces may succeed.",
1586 __func__
, ifp
->name
, MAXVIFS
);
1592 static int pim_ifp_up(struct interface
*ifp
)
1594 struct pim_interface
*pim_ifp
;
1595 struct pim_instance
*pim
;
1598 if (PIM_DEBUG_ZEBRA
) {
1600 "%s: %s index %d vrf %s(%u) flags %ld metric %d mtu %d operative %d",
1601 __func__
, ifp
->name
, ifp
->ifindex
, ifp
->vrf
->name
,
1602 ifp
->vrf
->vrf_id
, (long)ifp
->flags
, ifp
->metric
,
1603 ifp
->mtu
, if_is_operative(ifp
));
1606 pim
= ifp
->vrf
->info
;
1608 pim_ifp
= ifp
->info
;
1610 * If we have a pim_ifp already and this is an if_add
1611 * that means that we probably have a vrf move event
1612 * If that is the case, set the proper vrfness.
1618 pim_if_addr_add_all() suffices for bringing up both IGMP and
1621 pim_if_addr_add_all(ifp
);
1624 * If we have a pimreg device callback and it's for a specific
1625 * table set the master appropriately
1627 if (sscanf(ifp
->name
, "pimreg%" SCNu32
, &table_id
) == 1) {
1629 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
1630 if ((table_id
== vrf
->data
.l
.table_id
)
1631 && (ifp
->vrf
->vrf_id
!= vrf
->vrf_id
)) {
1632 struct interface
*master
= if_lookup_by_name(
1633 vrf
->name
, vrf
->vrf_id
);
1637 "%s: Unable to find Master interface for %s",
1638 __func__
, vrf
->name
);
1641 pim_zebra_interface_set_master(master
, ifp
);
1648 static int pim_ifp_down(struct interface
*ifp
)
1650 if (PIM_DEBUG_ZEBRA
) {
1652 "%s: %s index %d vrf %s(%u) flags %ld metric %d mtu %d operative %d",
1653 __func__
, ifp
->name
, ifp
->ifindex
, ifp
->vrf
->name
,
1654 ifp
->vrf
->vrf_id
, (long)ifp
->flags
, ifp
->metric
,
1655 ifp
->mtu
, if_is_operative(ifp
));
1658 if (!if_is_operative(ifp
)) {
1659 pim_ifchannel_delete_all(ifp
);
1661 pim_if_addr_del_all() suffices for shutting down IGMP,
1662 but not for shutting down PIM
1664 pim_if_addr_del_all(ifp
);
1667 pim_sock_delete() closes the socket, stops read and timer
1669 and kills all neighbors.
1672 pim_sock_delete(ifp
, "link down");
1677 pim_if_del_vif(ifp
);
1678 pim_ifstat_reset(ifp
);
1684 static int pim_ifp_destroy(struct interface
*ifp
)
1686 struct pim_instance
*pim
;
1688 if (PIM_DEBUG_ZEBRA
) {
1690 "%s: %s index %d vrf %s(%u) flags %ld metric %d mtu %d operative %d",
1691 __func__
, ifp
->name
, ifp
->ifindex
, ifp
->vrf
->name
,
1692 ifp
->vrf
->vrf_id
, (long)ifp
->flags
, ifp
->metric
,
1693 ifp
->mtu
, if_is_operative(ifp
));
1696 if (!if_is_operative(ifp
))
1697 pim_if_addr_del_all(ifp
);
1699 pim
= ifp
->vrf
->info
;
1700 if (pim
&& pim
->vxlan
.term_if
== ifp
)
1701 pim_vxlan_del_term_dev(pim
);
1706 static int pim_if_new_hook(struct interface
*ifp
)
1711 static int pim_if_delete_hook(struct interface
*ifp
)
1719 void pim_iface_init(void)
1721 hook_register_prio(if_add
, 0, pim_if_new_hook
);
1722 hook_register_prio(if_del
, 0, pim_if_delete_hook
);
1724 if_zapi_callbacks(pim_ifp_create
, pim_ifp_up
, pim_ifp_down
,