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
= pim_get_pim_instance(ifp
->vrf_id
);
125 pim_ifp
->mroute_vif_index
= -1;
127 pim_ifp
->igmp_version
= IGMP_DEFAULT_VERSION
;
128 pim_ifp
->igmp_default_robustness_variable
=
129 IGMP_DEFAULT_ROBUSTNESS_VARIABLE
;
130 pim_ifp
->igmp_default_query_interval
= IGMP_GENERAL_QUERY_INTERVAL
;
131 pim_ifp
->igmp_query_max_response_time_dsec
=
132 IGMP_QUERY_MAX_RESPONSE_TIME_DSEC
;
133 pim_ifp
->igmp_specific_query_max_response_time_dsec
=
134 IGMP_SPECIFIC_QUERY_MAX_RESPONSE_TIME_DSEC
;
135 pim_ifp
->igmp_last_member_query_count
=
136 IGMP_DEFAULT_ROBUSTNESS_VARIABLE
;
138 /* BSM config on interface: true by default */
139 pim_ifp
->bsm_enable
= true;
140 pim_ifp
->ucast_bsm_accept
= true;
141 pim_ifp
->am_i_dr
= false;
144 RFC 3376: 8.3. Query Response Interval
145 The number of seconds represented by the [Query Response Interval]
146 must be less than the [Query Interval].
148 assert(pim_ifp
->igmp_query_max_response_time_dsec
149 < pim_ifp
->igmp_default_query_interval
);
152 PIM_IF_DO_PIM(pim_ifp
->options
);
154 PIM_IF_DO_IGMP(pim_ifp
->options
);
156 PIM_IF_DO_IGMP_LISTEN_ALLROUTERS(pim_ifp
->options
);
158 pim_ifp
->igmp_join_list
= NULL
;
159 pim_ifp
->igmp_socket_list
= NULL
;
160 pim_ifp
->pim_neighbor_list
= NULL
;
161 pim_ifp
->upstream_switch_list
= NULL
;
162 pim_ifp
->pim_generation_id
= 0;
164 /* list of struct igmp_sock */
165 pim_ifp
->igmp_socket_list
= list_new();
166 pim_ifp
->igmp_socket_list
->del
= (void (*)(void *))igmp_sock_free
;
168 /* list of struct pim_neighbor */
169 pim_ifp
->pim_neighbor_list
= list_new();
170 pim_ifp
->pim_neighbor_list
->del
= (void (*)(void *))pim_neighbor_free
;
172 pim_ifp
->upstream_switch_list
= list_new();
173 pim_ifp
->upstream_switch_list
->del
=
174 (void (*)(void *))pim_jp_agg_group_list_free
;
175 pim_ifp
->upstream_switch_list
->cmp
= pim_jp_agg_group_list_cmp
;
177 pim_ifp
->sec_addr_list
= list_new();
178 pim_ifp
->sec_addr_list
->del
= (void (*)(void *))pim_sec_addr_free
;
179 pim_ifp
->sec_addr_list
->cmp
=
180 (int (*)(void *, void *))pim_sec_addr_comp
;
182 pim_ifp
->activeactive
= false;
184 RB_INIT(pim_ifchannel_rb
, &pim_ifp
->ifchannel_rb
);
190 pim_if_add_vif(ifp
, ispimreg
, is_vxlan_term
);
191 pim_ifp
->pim
->mcast_if_count
++;
196 void pim_if_delete(struct interface
*ifp
)
198 struct pim_interface
*pim_ifp
;
199 struct pim_ifchannel
*ch
;
205 if (pim_ifp
->igmp_join_list
) {
206 pim_if_igmp_join_del_all(ifp
);
209 pim_ifchannel_delete_all(ifp
);
210 igmp_sock_delete_all(ifp
);
212 pim_neighbor_delete_all(ifp
, "Interface removed from configuration");
215 pim_ifp
->pim
->mcast_if_count
--;
217 list_delete(&pim_ifp
->igmp_socket_list
);
218 list_delete(&pim_ifp
->pim_neighbor_list
);
219 list_delete(&pim_ifp
->upstream_switch_list
);
220 list_delete(&pim_ifp
->sec_addr_list
);
222 XFREE(MTYPE_PIM_INTERFACE
, pim_ifp
->boundary_oil_plist
);
224 while (!RB_EMPTY(pim_ifchannel_rb
, &pim_ifp
->ifchannel_rb
)) {
225 ch
= RB_ROOT(pim_ifchannel_rb
, &pim_ifp
->ifchannel_rb
);
227 pim_ifchannel_delete(ch
);
230 XFREE(MTYPE_PIM_INTERFACE
, pim_ifp
);
235 void pim_if_update_could_assert(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_could_assert(ch
);
248 static void pim_if_update_my_assert_metric(struct interface
*ifp
)
250 struct pim_interface
*pim_ifp
;
251 struct pim_ifchannel
*ch
;
256 RB_FOREACH (ch
, pim_ifchannel_rb
, &pim_ifp
->ifchannel_rb
) {
257 pim_ifchannel_update_my_assert_metric(ch
);
261 static void pim_addr_change(struct interface
*ifp
)
263 struct pim_interface
*pim_ifp
;
268 pim_if_dr_election(ifp
); /* router's own DR Priority (addr) changes --
270 pim_if_update_join_desired(pim_ifp
); /* depends on DR */
271 pim_if_update_could_assert(ifp
); /* depends on DR */
272 pim_if_update_my_assert_metric(ifp
); /* depends on could_assert */
273 pim_if_update_assert_tracking_desired(
274 ifp
); /* depends on DR, join_desired */
277 RFC 4601: 4.3.1. Sending Hello Messages
279 1) Before an interface goes down or changes primary IP address, a
280 Hello message with a zero HoldTime should be sent immediately
281 (with the old IP address if the IP address changed).
282 -- Done at the caller of the function as new ip already updated here
284 2) After an interface has changed its IP address, it MUST send a
285 Hello message with its new IP address.
288 3) If an interface changes one of its secondary IP addresses, a
289 Hello message with an updated Address_List option and a non-zero
290 HoldTime should be sent immediately.
291 -- FIXME See TODO T31
293 pim_ifp
->pim_ifstat_hello_sent
= 0; /* reset hello counter */
294 if (pim_ifp
->pim_sock_fd
< 0)
296 pim_hello_restart_now(ifp
); /* send hello and restart timer */
299 static int detect_primary_address_change(struct interface
*ifp
,
300 int force_prim_as_any
,
303 struct pim_interface
*pim_ifp
= ifp
->info
;
304 struct in_addr new_prim_addr
;
307 if (force_prim_as_any
)
308 new_prim_addr
.s_addr
= INADDR_ANY
;
310 new_prim_addr
= pim_find_primary_addr(ifp
);
312 changed
= new_prim_addr
.s_addr
!= pim_ifp
->primary_address
.s_addr
;
314 if (PIM_DEBUG_ZEBRA
) {
315 char new_prim_str
[INET_ADDRSTRLEN
];
316 char old_prim_str
[INET_ADDRSTRLEN
];
317 pim_inet4_dump("<new?>", new_prim_addr
, new_prim_str
,
318 sizeof(new_prim_str
));
319 pim_inet4_dump("<old?>", pim_ifp
->primary_address
, old_prim_str
,
320 sizeof(old_prim_str
));
321 zlog_debug("%s: old=%s new=%s on interface %s: %s", __func__
,
322 old_prim_str
, new_prim_str
, ifp
->name
,
323 changed
? "changed" : "unchanged");
327 /* Before updating pim_ifp send Hello time with 0 hold time */
328 if (PIM_IF_TEST_PIM(pim_ifp
->options
)) {
329 pim_hello_send(ifp
, 0 /* zero-sec holdtime */);
331 pim_ifp
->primary_address
= new_prim_addr
;
337 static struct pim_secondary_addr
*
338 pim_sec_addr_find(struct pim_interface
*pim_ifp
, struct prefix
*addr
)
340 struct pim_secondary_addr
*sec_addr
;
341 struct listnode
*node
;
343 for (ALL_LIST_ELEMENTS_RO(pim_ifp
->sec_addr_list
, node
, sec_addr
)) {
344 if (prefix_cmp(&sec_addr
->addr
, addr
) == 0) {
352 static void pim_sec_addr_del(struct pim_interface
*pim_ifp
,
353 struct pim_secondary_addr
*sec_addr
)
355 listnode_delete(pim_ifp
->sec_addr_list
, sec_addr
);
356 pim_sec_addr_free(sec_addr
);
359 static int pim_sec_addr_add(struct pim_interface
*pim_ifp
, struct prefix
*addr
)
362 struct pim_secondary_addr
*sec_addr
;
364 sec_addr
= pim_sec_addr_find(pim_ifp
, addr
);
366 sec_addr
->flags
&= ~PIM_SEC_ADDRF_STALE
;
370 sec_addr
= XCALLOC(MTYPE_PIM_SEC_ADDR
, sizeof(*sec_addr
));
373 sec_addr
->addr
= *addr
;
374 listnode_add_sort(pim_ifp
->sec_addr_list
, sec_addr
);
379 static int pim_sec_addr_del_all(struct pim_interface
*pim_ifp
)
383 if (!list_isempty(pim_ifp
->sec_addr_list
)) {
385 /* remove all nodes and free up the list itself */
386 list_delete_all_node(pim_ifp
->sec_addr_list
);
392 static int pim_sec_addr_update(struct interface
*ifp
)
394 struct pim_interface
*pim_ifp
= ifp
->info
;
395 struct connected
*ifc
;
396 struct listnode
*node
;
397 struct listnode
*nextnode
;
398 struct pim_secondary_addr
*sec_addr
;
401 for (ALL_LIST_ELEMENTS_RO(pim_ifp
->sec_addr_list
, node
, sec_addr
)) {
402 sec_addr
->flags
|= PIM_SEC_ADDRF_STALE
;
405 for (ALL_LIST_ELEMENTS_RO(ifp
->connected
, node
, ifc
)) {
406 struct prefix
*p
= ifc
->address
;
408 if (PIM_INADDR_IS_ANY(p
->u
.prefix4
)) {
412 if (pim_ifp
->primary_address
.s_addr
== p
->u
.prefix4
.s_addr
) {
413 /* don't add the primary address into the secondary
418 if (pim_sec_addr_add(pim_ifp
, p
)) {
423 /* Drop stale entries */
424 for (ALL_LIST_ELEMENTS(pim_ifp
->sec_addr_list
, node
, nextnode
,
426 if (sec_addr
->flags
& PIM_SEC_ADDRF_STALE
) {
427 pim_sec_addr_del(pim_ifp
, sec_addr
);
435 static int detect_secondary_address_change(struct interface
*ifp
,
436 int force_prim_as_any
,
439 struct pim_interface
*pim_ifp
= ifp
->info
;
442 if (force_prim_as_any
) {
443 /* if primary address is being forced to zero just flush the
444 * secondary address list */
445 changed
= pim_sec_addr_del_all(pim_ifp
);
447 /* re-evaluate the secondary address list */
448 changed
= pim_sec_addr_update(ifp
);
454 static void detect_address_change(struct interface
*ifp
, int force_prim_as_any
,
458 struct pim_interface
*pim_ifp
;
464 if (detect_primary_address_change(ifp
, force_prim_as_any
, caller
)) {
468 if (detect_secondary_address_change(ifp
, force_prim_as_any
, caller
)) {
474 if (!PIM_IF_TEST_PIM(pim_ifp
->options
)) {
478 pim_addr_change(ifp
);
481 /* XXX: if we have unnumbered interfaces we need to run detect address
482 * address change on all of them when the lo address changes */
485 int pim_update_source_set(struct interface
*ifp
, struct in_addr source
)
487 struct pim_interface
*pim_ifp
= ifp
->info
;
490 return PIM_IFACE_NOT_FOUND
;
493 if (pim_ifp
->update_source
.s_addr
== source
.s_addr
) {
494 return PIM_UPDATE_SOURCE_DUP
;
497 pim_ifp
->update_source
= source
;
498 detect_address_change(ifp
, 0 /* force_prim_as_any */, __func__
);
503 void pim_if_addr_add(struct connected
*ifc
)
505 struct pim_interface
*pim_ifp
;
506 struct interface
*ifp
;
507 struct in_addr ifaddr
;
518 if (!if_is_operative(ifp
))
522 zlog_debug("%s: %s ifindex=%d connected IP address %pFX %s",
523 __func__
, ifp
->name
, ifp
->ifindex
, ifc
->address
,
524 CHECK_FLAG(ifc
->flags
, ZEBRA_IFA_SECONDARY
)
528 ifaddr
= ifc
->address
->u
.prefix4
;
530 detect_address_change(ifp
, 0, __func__
);
532 // if (ifc->address->family != AF_INET)
535 if (PIM_IF_TEST_IGMP(pim_ifp
->options
)) {
536 struct igmp_sock
*igmp
;
538 /* lookup IGMP socket */
539 igmp
= pim_igmp_sock_lookup_ifaddr(pim_ifp
->igmp_socket_list
,
542 /* if addr new, add IGMP socket */
543 if (ifc
->address
->family
== AF_INET
)
544 pim_igmp_sock_add(pim_ifp
->igmp_socket_list
,
546 } else if (igmp
->mtrace_only
) {
547 igmp_sock_delete(igmp
);
548 pim_igmp_sock_add(pim_ifp
->igmp_socket_list
, ifaddr
,
552 /* Replay Static IGMP groups */
553 if (pim_ifp
->igmp_join_list
) {
554 struct listnode
*node
;
555 struct listnode
*nextnode
;
556 struct igmp_join
*ij
;
559 for (ALL_LIST_ELEMENTS(pim_ifp
->igmp_join_list
, node
,
561 /* Close socket and reopen with Source and Group
564 join_fd
= igmp_join_sock(
565 ifp
->name
, ifp
->ifindex
, ij
->group_addr
,
568 char group_str
[INET_ADDRSTRLEN
];
569 char source_str
[INET_ADDRSTRLEN
];
570 pim_inet4_dump("<grp?>", ij
->group_addr
,
574 "<src?>", ij
->source_addr
,
575 source_str
, sizeof(source_str
));
577 "%s: igmp_join_sock() failure for IGMP group %s source %s on interface %s",
578 __func__
, group_str
, source_str
,
582 ij
->sock_fd
= join_fd
;
587 struct igmp_sock
*igmp
;
589 /* lookup IGMP socket */
590 igmp
= pim_igmp_sock_lookup_ifaddr(pim_ifp
->igmp_socket_list
,
592 if (ifc
->address
->family
== AF_INET
) {
594 igmp_sock_delete(igmp
);
595 /* if addr new, add IGMP socket */
596 pim_igmp_sock_add(pim_ifp
->igmp_socket_list
, ifaddr
,
599 } /* igmp mtrace only */
601 if (PIM_IF_TEST_PIM(pim_ifp
->options
)) {
603 if (PIM_INADDR_ISNOT_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
.family
= AF_INET
;
628 rpf
.rpf_addr
.prefixlen
= IPV4_MAX_BITLEN
;
629 rpf
.rpf_addr
.u
.prefix4
= ifc
->address
->u
.prefix4
;
630 pnc
= pim_nexthop_cache_find(pim_ifp
->pim
, &rpf
);
632 pim_sendmsg_zebra_rnh(pim_ifp
->pim
, zclient
,
634 ZEBRA_NEXTHOP_REGISTER
);
639 PIM or IGMP is enabled on interface, and there is at least one
640 address assigned, then try to create a vif_index.
642 if (pim_ifp
->mroute_vif_index
< 0) {
643 vxlan_term
= pim_vxlan_is_term_dev_cfg(pim_ifp
->pim
, ifp
);
644 pim_if_add_vif(ifp
, false, vxlan_term
);
646 pim_ifchannel_scan_forward_start(ifp
);
649 static void pim_if_addr_del_igmp(struct connected
*ifc
)
651 struct pim_interface
*pim_ifp
= ifc
->ifp
->info
;
652 struct igmp_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
->igmp_socket_list
, ifaddr
);
670 /* if addr found, del IGMP socket */
671 igmp_sock_delete(igmp
);
675 static void pim_if_addr_del_pim(struct connected
*ifc
)
677 struct pim_interface
*pim_ifp
= ifc
->ifp
->info
;
679 if (ifc
->address
->family
!= AF_INET
) {
680 /* non-IPv4 address */
685 /* PIM not enabled on interface */
689 if (PIM_INADDR_ISNOT_ANY(pim_ifp
->primary_address
)) {
690 /* Interface keeps a valid primary address */
694 if (pim_ifp
->pim_sock_fd
< 0) {
695 /* Interface does not hold a valid socket any longer */
700 pim_sock_delete() closes the socket, stops read and timer threads,
701 and kills all neighbors.
703 pim_sock_delete(ifc
->ifp
,
704 "last address has been removed from interface");
707 void pim_if_addr_del(struct connected
*ifc
, int force_prim_as_any
)
709 struct interface
*ifp
;
716 zlog_debug("%s: %s ifindex=%d disconnected IP address %pFX %s",
717 __func__
, ifp
->name
, ifp
->ifindex
, ifc
->address
,
718 CHECK_FLAG(ifc
->flags
, ZEBRA_IFA_SECONDARY
)
722 detect_address_change(ifp
, force_prim_as_any
, __func__
);
724 pim_if_addr_del_igmp(ifc
);
725 pim_if_addr_del_pim(ifc
);
728 void pim_if_addr_add_all(struct interface
*ifp
)
730 struct connected
*ifc
;
731 struct listnode
*node
;
732 struct listnode
*nextnode
;
735 struct pim_interface
*pim_ifp
= ifp
->info
;
739 /* PIM/IGMP enabled ? */
743 for (ALL_LIST_ELEMENTS(ifp
->connected
, node
, nextnode
, ifc
)) {
744 struct prefix
*p
= ifc
->address
;
746 if (p
->family
!= AF_INET
)
750 pim_if_addr_add(ifc
);
753 if (!v4_addrs
&& v6_addrs
&& !if_is_loopback(ifp
)) {
754 if (PIM_IF_TEST_PIM(pim_ifp
->options
)) {
756 /* Interface has a valid primary address ? */
757 if (PIM_INADDR_ISNOT_ANY(pim_ifp
->primary_address
)) {
759 /* Interface has a valid socket ? */
760 if (pim_ifp
->pim_sock_fd
< 0) {
761 if (pim_sock_add(ifp
)) {
763 "Failure creating PIM socket for interface %s",
771 * PIM or IGMP is enabled on interface, and there is at least one
772 * address assigned, then try to create a vif_index.
774 if (pim_ifp
->mroute_vif_index
< 0) {
775 vxlan_term
= pim_vxlan_is_term_dev_cfg(pim_ifp
->pim
, ifp
);
776 pim_if_add_vif(ifp
, false, vxlan_term
);
778 pim_ifchannel_scan_forward_start(ifp
);
780 pim_rp_setup(pim_ifp
->pim
);
781 pim_rp_check_on_if_add(pim_ifp
);
784 void pim_if_addr_del_all(struct interface
*ifp
)
786 struct connected
*ifc
;
787 struct listnode
*node
;
788 struct listnode
*nextnode
;
789 struct vrf
*vrf
= vrf_lookup_by_id(ifp
->vrf_id
);
790 struct pim_instance
*pim
;
796 /* PIM/IGMP enabled ? */
800 for (ALL_LIST_ELEMENTS(ifp
->connected
, node
, nextnode
, ifc
)) {
801 struct prefix
*p
= ifc
->address
;
803 if (p
->family
!= AF_INET
)
806 pim_if_addr_del(ifc
, 1 /* force_prim_as_any=true */);
810 pim_i_am_rp_re_evaluate(pim
);
813 void pim_if_addr_del_all_igmp(struct interface
*ifp
)
815 struct connected
*ifc
;
816 struct listnode
*node
;
817 struct listnode
*nextnode
;
819 /* PIM/IGMP enabled ? */
823 for (ALL_LIST_ELEMENTS(ifp
->connected
, node
, nextnode
, ifc
)) {
824 struct prefix
*p
= ifc
->address
;
826 if (p
->family
!= AF_INET
)
829 pim_if_addr_del_igmp(ifc
);
833 void pim_if_addr_del_all_pim(struct interface
*ifp
)
835 struct connected
*ifc
;
836 struct listnode
*node
;
837 struct listnode
*nextnode
;
839 /* PIM/IGMP enabled ? */
843 for (ALL_LIST_ELEMENTS(ifp
->connected
, node
, nextnode
, ifc
)) {
844 struct prefix
*p
= ifc
->address
;
846 if (p
->family
!= AF_INET
)
849 pim_if_addr_del_pim(ifc
);
853 struct in_addr
pim_find_primary_addr(struct interface
*ifp
)
855 struct connected
*ifc
;
856 struct listnode
*node
;
857 struct in_addr addr
= {0};
860 struct pim_interface
*pim_ifp
= ifp
->info
;
861 struct vrf
*vrf
= vrf_lookup_by_id(ifp
->vrf_id
);
866 if (pim_ifp
&& PIM_INADDR_ISNOT_ANY(pim_ifp
->update_source
)) {
867 return pim_ifp
->update_source
;
870 for (ALL_LIST_ELEMENTS_RO(ifp
->connected
, node
, ifc
)) {
871 struct prefix
*p
= ifc
->address
;
873 if (p
->family
!= AF_INET
) {
878 if (PIM_INADDR_IS_ANY(p
->u
.prefix4
)) {
880 "%s: null IPv4 address connected to interface %s",
881 __func__
, ifp
->name
);
887 if (CHECK_FLAG(ifc
->flags
, ZEBRA_IFA_SECONDARY
))
894 * If we have no v4_addrs and v6 is configured
895 * We probably are using unnumbered
896 * So let's grab the loopbacks v4 address
897 * and use that as the primary address
899 if (!v4_addrs
&& v6_addrs
) {
900 struct interface
*lo_ifp
;
902 // DBS - Come back and check here
903 if (ifp
->vrf_id
== VRF_DEFAULT
)
904 lo_ifp
= if_lookup_by_name("lo", vrf
->vrf_id
);
906 lo_ifp
= if_lookup_by_name(vrf
->name
, vrf
->vrf_id
);
908 if (lo_ifp
&& (lo_ifp
!= ifp
))
909 return pim_find_primary_addr(lo_ifp
);
912 addr
.s_addr
= PIM_NET_INADDR_ANY
;
917 static int pim_iface_next_vif_index(struct interface
*ifp
)
919 struct pim_interface
*pim_ifp
= ifp
->info
;
920 struct pim_instance
*pim
= pim_ifp
->pim
;
924 * The pimreg vif is always going to be in index 0
927 if (ifp
->ifindex
== PIM_OIF_PIM_REGISTER_VIF
)
930 for (i
= 1; i
< MAXVIFS
; i
++) {
931 if (pim
->iface_vif_index
[i
] == 0)
938 pim_if_add_vif() uses ifindex as vif_index
940 see also pim_if_find_vifindex_by_ifindex()
942 int pim_if_add_vif(struct interface
*ifp
, bool ispimreg
, bool is_vxlan_term
)
944 struct pim_interface
*pim_ifp
= ifp
->info
;
945 struct in_addr ifaddr
;
946 unsigned char flags
= 0;
950 if (pim_ifp
->mroute_vif_index
> 0) {
951 zlog_warn("%s: vif_index=%d > 0 on interface %s ifindex=%d",
952 __func__
, pim_ifp
->mroute_vif_index
, ifp
->name
,
957 if (ifp
->ifindex
< 0) {
958 zlog_warn("%s: ifindex=%d < 1 on interface %s", __func__
,
959 ifp
->ifindex
, ifp
->name
);
963 ifaddr
= pim_ifp
->primary_address
;
964 if (!ispimreg
&& !is_vxlan_term
&& PIM_INADDR_IS_ANY(ifaddr
)) {
966 "%s: could not get address for interface %s ifindex=%d",
967 __func__
, ifp
->name
, ifp
->ifindex
);
971 pim_ifp
->mroute_vif_index
= pim_iface_next_vif_index(ifp
);
973 if (pim_ifp
->mroute_vif_index
>= MAXVIFS
) {
975 "%s: Attempting to configure more than MAXVIFS=%d on pim enabled interface %s",
976 __func__
, MAXVIFS
, ifp
->name
);
980 if (ifp
->ifindex
== PIM_OIF_PIM_REGISTER_VIF
)
981 flags
= VIFF_REGISTER
;
982 #ifdef VIFF_USE_IFINDEX
984 flags
= VIFF_USE_IFINDEX
;
987 if (pim_mroute_add_vif(ifp
, ifaddr
, flags
)) {
988 /* pim_mroute_add_vif reported error */
992 pim_ifp
->pim
->iface_vif_index
[pim_ifp
->mroute_vif_index
] = 1;
994 /* if the device qualifies as pim_vxlan iif/oif update vxlan entries */
995 pim_vxlan_add_vif(ifp
);
1000 int pim_if_del_vif(struct interface
*ifp
)
1002 struct pim_interface
*pim_ifp
= ifp
->info
;
1004 if (pim_ifp
->mroute_vif_index
< 1) {
1005 zlog_warn("%s: vif_index=%d < 1 on interface %s ifindex=%d",
1006 __func__
, pim_ifp
->mroute_vif_index
, ifp
->name
,
1011 /* if the device was a pim_vxlan iif/oif update vxlan mroute entries */
1012 pim_vxlan_del_vif(ifp
);
1014 pim_mroute_del_vif(ifp
);
1019 pim_ifp
->pim
->iface_vif_index
[pim_ifp
->mroute_vif_index
] = 0;
1021 pim_ifp
->mroute_vif_index
= -1;
1027 struct interface
*pim_if_find_by_vif_index(struct pim_instance
*pim
,
1028 ifindex_t vif_index
)
1030 struct interface
*ifp
;
1032 FOR_ALL_INTERFACES (pim
->vrf
, ifp
) {
1034 struct pim_interface
*pim_ifp
;
1035 pim_ifp
= ifp
->info
;
1037 if (vif_index
== pim_ifp
->mroute_vif_index
)
1046 pim_if_add_vif() uses ifindex as vif_index
1048 int pim_if_find_vifindex_by_ifindex(struct pim_instance
*pim
, ifindex_t ifindex
)
1050 struct pim_interface
*pim_ifp
;
1051 struct interface
*ifp
;
1053 ifp
= if_lookup_by_index(ifindex
, pim
->vrf
->vrf_id
);
1054 if (!ifp
|| !ifp
->info
)
1056 pim_ifp
= ifp
->info
;
1058 return pim_ifp
->mroute_vif_index
;
1061 int pim_if_lan_delay_enabled(struct interface
*ifp
)
1063 struct pim_interface
*pim_ifp
;
1065 pim_ifp
= ifp
->info
;
1067 assert(pim_ifp
->pim_number_of_nonlandelay_neighbors
>= 0);
1069 return pim_ifp
->pim_number_of_nonlandelay_neighbors
== 0;
1072 uint16_t pim_if_effective_propagation_delay_msec(struct interface
*ifp
)
1074 if (pim_if_lan_delay_enabled(ifp
)) {
1075 struct pim_interface
*pim_ifp
;
1076 pim_ifp
= ifp
->info
;
1077 return pim_ifp
->pim_neighbors_highest_propagation_delay_msec
;
1079 return PIM_DEFAULT_PROPAGATION_DELAY_MSEC
;
1083 uint16_t pim_if_effective_override_interval_msec(struct interface
*ifp
)
1085 if (pim_if_lan_delay_enabled(ifp
)) {
1086 struct pim_interface
*pim_ifp
;
1087 pim_ifp
= ifp
->info
;
1088 return pim_ifp
->pim_neighbors_highest_override_interval_msec
;
1090 return PIM_DEFAULT_OVERRIDE_INTERVAL_MSEC
;
1094 int pim_if_t_override_msec(struct interface
*ifp
)
1096 int effective_override_interval_msec
;
1097 int t_override_msec
;
1099 effective_override_interval_msec
=
1100 pim_if_effective_override_interval_msec(ifp
);
1103 frr_weak_random() % (effective_override_interval_msec
+ 1);
1105 return t_override_msec
;
1108 uint16_t pim_if_jp_override_interval_msec(struct interface
*ifp
)
1110 return pim_if_effective_propagation_delay_msec(ifp
)
1111 + pim_if_effective_override_interval_msec(ifp
);
1115 RFC 4601: 4.1.6. State Summarization Macros
1117 The function NBR( I, A ) uses information gathered through PIM Hello
1118 messages to map the IP address A of a directly connected PIM
1119 neighbor router on interface I to the primary IP address of the same
1120 router (Section 4.3.4). The primary IP address of a neighbor is the
1121 address that it uses as the source of its PIM Hello messages.
1123 struct pim_neighbor
*pim_if_find_neighbor(struct interface
*ifp
,
1124 struct in_addr addr
)
1126 struct listnode
*neighnode
;
1127 struct pim_neighbor
*neigh
;
1128 struct pim_interface
*pim_ifp
;
1133 pim_ifp
= ifp
->info
;
1135 zlog_warn("%s: multicast not enabled on interface %s", __func__
,
1142 p
.prefixlen
= IPV4_MAX_BITLEN
;
1144 for (ALL_LIST_ELEMENTS_RO(pim_ifp
->pim_neighbor_list
, neighnode
,
1147 /* primary address ? */
1148 if (neigh
->source_addr
.s_addr
== addr
.s_addr
)
1151 /* secondary address ? */
1152 if (pim_neighbor_find_secondary(neigh
, &p
))
1156 if (PIM_DEBUG_PIM_TRACE
) {
1157 char addr_str
[INET_ADDRSTRLEN
];
1158 pim_inet4_dump("<addr?>", addr
, addr_str
, sizeof(addr_str
));
1160 "%s: neighbor not found for address %s on interface %s",
1161 __func__
, addr_str
, ifp
->name
);
1167 long pim_if_t_suppressed_msec(struct interface
*ifp
)
1169 struct pim_interface
*pim_ifp
;
1170 long t_suppressed_msec
;
1171 uint32_t ramount
= 0;
1173 pim_ifp
= ifp
->info
;
1176 /* join suppression disabled ? */
1177 if (PIM_IF_TEST_PIM_CAN_DISABLE_JOIN_SUPPRESSION(pim_ifp
->options
))
1180 /* t_suppressed = t_periodic * rand(1.1, 1.4) */
1181 ramount
= 1100 + (frr_weak_random() % (1400 - 1100 + 1));
1182 t_suppressed_msec
= router
->t_periodic
* ramount
;
1184 return t_suppressed_msec
;
1187 static void igmp_join_free(struct igmp_join
*ij
)
1189 XFREE(MTYPE_PIM_IGMP_JOIN
, ij
);
1192 static struct igmp_join
*igmp_join_find(struct list
*join_list
,
1193 struct in_addr group_addr
,
1194 struct in_addr source_addr
)
1196 struct listnode
*node
;
1197 struct igmp_join
*ij
;
1201 for (ALL_LIST_ELEMENTS_RO(join_list
, node
, ij
)) {
1202 if ((group_addr
.s_addr
== ij
->group_addr
.s_addr
)
1203 && (source_addr
.s_addr
== ij
->source_addr
.s_addr
))
1210 static int igmp_join_sock(const char *ifname
, ifindex_t ifindex
,
1211 struct in_addr group_addr
, struct in_addr source_addr
)
1215 join_fd
= pim_socket_raw(IPPROTO_IGMP
);
1220 if (pim_igmp_join_source(join_fd
, ifindex
, group_addr
, source_addr
)) {
1221 char group_str
[INET_ADDRSTRLEN
];
1222 char source_str
[INET_ADDRSTRLEN
];
1223 pim_inet4_dump("<grp?>", group_addr
, group_str
,
1225 pim_inet4_dump("<src?>", source_addr
, source_str
,
1226 sizeof(source_str
));
1228 "%s: setsockopt(fd=%d) failure for IGMP group %s source %s ifindex %d on interface %s: errno=%d: %s",
1229 __func__
, join_fd
, group_str
, source_str
, ifindex
,
1230 ifname
, errno
, safe_strerror(errno
));
1239 static struct igmp_join
*igmp_join_new(struct interface
*ifp
,
1240 struct in_addr group_addr
,
1241 struct in_addr source_addr
)
1243 struct pim_interface
*pim_ifp
;
1244 struct igmp_join
*ij
;
1247 pim_ifp
= ifp
->info
;
1250 join_fd
= igmp_join_sock(ifp
->name
, ifp
->ifindex
, group_addr
,
1253 char group_str
[INET_ADDRSTRLEN
];
1254 char source_str
[INET_ADDRSTRLEN
];
1256 pim_inet4_dump("<grp?>", group_addr
, group_str
,
1258 pim_inet4_dump("<src?>", source_addr
, source_str
,
1259 sizeof(source_str
));
1261 "%s: igmp_join_sock() failure for IGMP group %s source %s on interface %s",
1262 __func__
, group_str
, source_str
, ifp
->name
);
1266 ij
= XCALLOC(MTYPE_PIM_IGMP_JOIN
, sizeof(*ij
));
1268 ij
->sock_fd
= join_fd
;
1269 ij
->group_addr
= group_addr
;
1270 ij
->source_addr
= source_addr
;
1271 ij
->sock_creation
= pim_time_monotonic_sec();
1273 listnode_add(pim_ifp
->igmp_join_list
, ij
);
1278 ferr_r
pim_if_igmp_join_add(struct interface
*ifp
, struct in_addr group_addr
,
1279 struct in_addr source_addr
)
1281 struct pim_interface
*pim_ifp
;
1282 struct igmp_join
*ij
;
1284 pim_ifp
= ifp
->info
;
1286 return ferr_cfg_invalid("multicast not enabled on interface %s",
1290 if (!pim_ifp
->igmp_join_list
) {
1291 pim_ifp
->igmp_join_list
= list_new();
1292 pim_ifp
->igmp_join_list
->del
= (void (*)(void *))igmp_join_free
;
1295 ij
= igmp_join_find(pim_ifp
->igmp_join_list
, group_addr
, source_addr
);
1297 /* This interface has already been configured to join this IGMP group
1303 (void)igmp_join_new(ifp
, group_addr
, source_addr
);
1305 if (PIM_DEBUG_IGMP_EVENTS
) {
1306 char group_str
[INET_ADDRSTRLEN
];
1307 char source_str
[INET_ADDRSTRLEN
];
1308 pim_inet4_dump("<grp?>", group_addr
, group_str
,
1310 pim_inet4_dump("<src?>", source_addr
, source_str
,
1311 sizeof(source_str
));
1313 "%s: issued static igmp join for channel (S,G)=(%s,%s) on interface %s",
1314 __func__
, source_str
, group_str
, ifp
->name
);
1321 int pim_if_igmp_join_del(struct interface
*ifp
, struct in_addr group_addr
,
1322 struct in_addr source_addr
)
1324 struct pim_interface
*pim_ifp
;
1325 struct igmp_join
*ij
;
1327 pim_ifp
= ifp
->info
;
1329 zlog_warn("%s: multicast not enabled on interface %s", __func__
,
1334 if (!pim_ifp
->igmp_join_list
) {
1335 zlog_warn("%s: no IGMP join on interface %s", __func__
,
1340 ij
= igmp_join_find(pim_ifp
->igmp_join_list
, group_addr
, source_addr
);
1342 char group_str
[INET_ADDRSTRLEN
];
1343 char source_str
[INET_ADDRSTRLEN
];
1344 pim_inet4_dump("<grp?>", group_addr
, group_str
,
1346 pim_inet4_dump("<src?>", source_addr
, source_str
,
1347 sizeof(source_str
));
1349 "%s: could not find IGMP group %s source %s on interface %s",
1350 __func__
, group_str
, source_str
, ifp
->name
);
1354 if (close(ij
->sock_fd
)) {
1355 char group_str
[INET_ADDRSTRLEN
];
1356 char source_str
[INET_ADDRSTRLEN
];
1357 pim_inet4_dump("<grp?>", group_addr
, group_str
,
1359 pim_inet4_dump("<src?>", source_addr
, source_str
,
1360 sizeof(source_str
));
1362 "%s: failure closing sock_fd=%d for IGMP group %s source %s on interface %s: errno=%d: %s",
1363 __func__
, ij
->sock_fd
, group_str
, source_str
, ifp
->name
,
1364 errno
, safe_strerror(errno
));
1367 listnode_delete(pim_ifp
->igmp_join_list
, ij
);
1369 if (listcount(pim_ifp
->igmp_join_list
) < 1) {
1370 list_delete(&pim_ifp
->igmp_join_list
);
1371 pim_ifp
->igmp_join_list
= 0;
1377 static void pim_if_igmp_join_del_all(struct interface
*ifp
)
1379 struct pim_interface
*pim_ifp
;
1380 struct listnode
*node
;
1381 struct listnode
*nextnode
;
1382 struct igmp_join
*ij
;
1384 pim_ifp
= ifp
->info
;
1386 zlog_warn("%s: multicast not enabled on interface %s", __func__
,
1391 if (!pim_ifp
->igmp_join_list
)
1394 for (ALL_LIST_ELEMENTS(pim_ifp
->igmp_join_list
, node
, nextnode
, ij
))
1395 pim_if_igmp_join_del(ifp
, ij
->group_addr
, ij
->source_addr
);
1401 Transitions from "I am Assert Loser" State
1403 Current Winner's GenID Changes or NLT Expires
1405 The Neighbor Liveness Timer associated with the current winner
1406 expires or we receive a Hello message from the current winner
1407 reporting a different GenID from the one it previously reported.
1408 This indicates that the current winner's interface or router has
1409 gone down (and may have come back up), and so we must assume it no
1410 longer knows it was the winner.
1412 void pim_if_assert_on_neighbor_down(struct interface
*ifp
,
1413 struct in_addr neigh_addr
)
1415 struct pim_interface
*pim_ifp
;
1416 struct pim_ifchannel
*ch
;
1418 pim_ifp
= ifp
->info
;
1421 RB_FOREACH (ch
, pim_ifchannel_rb
, &pim_ifp
->ifchannel_rb
) {
1422 /* Is (S,G,I) assert loser ? */
1423 if (ch
->ifassert_state
!= PIM_IFASSERT_I_AM_LOSER
)
1425 /* Dead neighbor was winner ? */
1426 if (ch
->ifassert_winner
.s_addr
!= neigh_addr
.s_addr
)
1429 assert_action_a5(ch
);
1433 void pim_if_update_join_desired(struct pim_interface
*pim_ifp
)
1435 struct pim_ifchannel
*ch
;
1437 /* clear off flag from interface's upstreams */
1438 RB_FOREACH (ch
, pim_ifchannel_rb
, &pim_ifp
->ifchannel_rb
) {
1439 PIM_UPSTREAM_FLAG_UNSET_DR_JOIN_DESIRED_UPDATED(
1440 ch
->upstream
->flags
);
1443 /* scan per-interface (S,G,I) state on this I interface */
1444 RB_FOREACH (ch
, pim_ifchannel_rb
, &pim_ifp
->ifchannel_rb
) {
1445 struct pim_upstream
*up
= ch
->upstream
;
1447 if (PIM_UPSTREAM_FLAG_TEST_DR_JOIN_DESIRED_UPDATED(up
->flags
))
1450 /* update join_desired for the global (S,G) state */
1451 pim_upstream_update_join_desired(pim_ifp
->pim
, up
);
1452 PIM_UPSTREAM_FLAG_SET_DR_JOIN_DESIRED_UPDATED(up
->flags
);
1456 void pim_if_update_assert_tracking_desired(struct interface
*ifp
)
1458 struct pim_interface
*pim_ifp
;
1459 struct pim_ifchannel
*ch
;
1461 pim_ifp
= ifp
->info
;
1465 RB_FOREACH (ch
, pim_ifchannel_rb
, &pim_ifp
->ifchannel_rb
) {
1466 pim_ifchannel_update_assert_tracking_desired(ch
);
1471 * PIM wants to have an interface pointer for everything it does.
1472 * The pimreg is a special interface that we have that is not
1473 * quite an inteface but a VIF is created for it.
1475 void pim_if_create_pimreg(struct pim_instance
*pim
)
1477 char pimreg_name
[INTERFACE_NAMSIZ
];
1479 if (!pim
->regiface
) {
1480 if (pim
->vrf
->vrf_id
== VRF_DEFAULT
)
1481 strlcpy(pimreg_name
, "pimreg", sizeof(pimreg_name
));
1483 snprintf(pimreg_name
, sizeof(pimreg_name
), "pimreg%u",
1484 pim
->vrf
->data
.l
.table_id
);
1486 pim
->regiface
= if_create_name(pimreg_name
, pim
->vrf
->vrf_id
);
1487 pim
->regiface
->ifindex
= PIM_OIF_PIM_REGISTER_VIF
;
1489 pim_if_new(pim
->regiface
, false, false, true,
1490 false /*vxlan_term*/);
1492 * On vrf moves we delete the interface if there
1493 * is nothing going on with it. We cannot have
1494 * the pimregiface deleted.
1496 pim
->regiface
->configured
= true;
1501 struct prefix
*pim_if_connected_to_source(struct interface
*ifp
, struct in_addr src
)
1503 struct listnode
*cnode
;
1504 struct connected
*c
;
1512 p
.prefixlen
= IPV4_MAX_BITLEN
;
1514 for (ALL_LIST_ELEMENTS_RO(ifp
->connected
, cnode
, c
)) {
1515 if ((c
->address
->family
== AF_INET
)
1516 && prefix_match(CONNECTED_PREFIX(c
), &p
)) {
1517 return CONNECTED_PREFIX(c
);
1524 bool pim_if_is_vrf_device(struct interface
*ifp
)
1532 int pim_if_ifchannel_count(struct pim_interface
*pim_ifp
)
1534 struct pim_ifchannel
*ch
;
1537 RB_FOREACH (ch
, pim_ifchannel_rb
, &pim_ifp
->ifchannel_rb
) {
1544 int pim_ifp_create(struct interface
*ifp
)
1546 struct pim_instance
*pim
;
1548 pim
= pim_get_pim_instance(ifp
->vrf_id
);
1549 if (PIM_DEBUG_ZEBRA
) {
1551 "%s: %s index %d(%u) flags %ld metric %d mtu %d operative %d",
1552 __func__
, ifp
->name
, ifp
->ifindex
, ifp
->vrf_id
,
1553 (long)ifp
->flags
, ifp
->metric
, ifp
->mtu
,
1554 if_is_operative(ifp
));
1557 if (if_is_operative(ifp
)) {
1558 struct pim_interface
*pim_ifp
;
1560 pim_ifp
= ifp
->info
;
1562 * If we have a pim_ifp already and this is an if_add
1563 * that means that we probably have a vrf move event
1564 * If that is the case, set the proper vrfness.
1568 pim_if_addr_add_all(ifp
);
1571 * Due to ordering issues based upon when
1572 * a command is entered we should ensure that
1573 * the pim reg is created for this vrf if we
1574 * have configuration for it already.
1576 * this is a no-op if it's already been done.
1578 pim_if_create_pimreg(pim
);
1582 * If we are a vrf device that is up, open up the pim_socket for
1584 * to incoming pim messages irrelevant if the user has configured us
1587 if (pim_if_is_vrf_device(ifp
)) {
1588 struct pim_interface
*pim_ifp
;
1591 pim_ifp
= pim_if_new(ifp
, false, false, false,
1592 false /*vxlan_term*/);
1593 ifp
->info
= pim_ifp
;
1599 if (!strncmp(ifp
->name
, PIM_VXLAN_TERM_DEV_NAME
,
1600 sizeof(PIM_VXLAN_TERM_DEV_NAME
))) {
1601 if (pim
->mcast_if_count
< MAXVIFS
)
1602 pim_vxlan_add_term_dev(pim
, ifp
);
1605 "%s: Cannot enable pim on %s. MAXVIFS(%d) reached. Deleting and readding the vxlan termimation device after unconfiguring pim from other interfaces may succeed.",
1606 __func__
, ifp
->name
, MAXVIFS
);
1612 int pim_ifp_up(struct interface
*ifp
)
1614 struct pim_interface
*pim_ifp
;
1615 struct pim_instance
*pim
;
1618 if (PIM_DEBUG_ZEBRA
) {
1620 "%s: %s index %d(%u) flags %ld metric %d mtu %d operative %d",
1621 __func__
, ifp
->name
, ifp
->ifindex
, ifp
->vrf_id
,
1622 (long)ifp
->flags
, ifp
->metric
, ifp
->mtu
,
1623 if_is_operative(ifp
));
1626 pim
= pim_get_pim_instance(ifp
->vrf_id
);
1628 pim_ifp
= ifp
->info
;
1630 * If we have a pim_ifp already and this is an if_add
1631 * that means that we probably have a vrf move event
1632 * If that is the case, set the proper vrfness.
1638 pim_if_addr_add_all() suffices for bringing up both IGMP and
1641 pim_if_addr_add_all(ifp
);
1644 * If we have a pimreg device callback and it's for a specific
1645 * table set the master appropriately
1647 if (sscanf(ifp
->name
, "pimreg%" SCNu32
, &table_id
) == 1) {
1649 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
1650 if ((table_id
== vrf
->data
.l
.table_id
)
1651 && (ifp
->vrf_id
!= vrf
->vrf_id
)) {
1652 struct interface
*master
= if_lookup_by_name(
1653 vrf
->name
, vrf
->vrf_id
);
1657 "%s: Unable to find Master interface for %s",
1658 __func__
, vrf
->name
);
1661 pim_zebra_interface_set_master(master
, ifp
);
1668 int pim_ifp_down(struct interface
*ifp
)
1670 if (PIM_DEBUG_ZEBRA
) {
1672 "%s: %s index %d(%u) flags %ld metric %d mtu %d operative %d",
1673 __func__
, ifp
->name
, ifp
->ifindex
, ifp
->vrf_id
,
1674 (long)ifp
->flags
, ifp
->metric
, ifp
->mtu
,
1675 if_is_operative(ifp
));
1678 if (!if_is_operative(ifp
)) {
1679 pim_ifchannel_delete_all(ifp
);
1681 pim_if_addr_del_all() suffices for shutting down IGMP,
1682 but not for shutting down PIM
1684 pim_if_addr_del_all(ifp
);
1687 pim_sock_delete() closes the socket, stops read and timer
1689 and kills all neighbors.
1692 pim_sock_delete(ifp
, "link down");
1697 pim_if_del_vif(ifp
);
1702 int pim_ifp_destroy(struct interface
*ifp
)
1704 struct pim_instance
*pim
;
1706 if (PIM_DEBUG_ZEBRA
) {
1708 "%s: %s index %d(%u) flags %ld metric %d mtu %d operative %d",
1709 __func__
, ifp
->name
, ifp
->ifindex
, ifp
->vrf_id
,
1710 (long)ifp
->flags
, ifp
->metric
, ifp
->mtu
,
1711 if_is_operative(ifp
));
1714 if (!if_is_operative(ifp
))
1715 pim_if_addr_del_all(ifp
);
1717 pim
= pim_get_pim_instance(ifp
->vrf_id
);
1718 if (pim
&& pim
->vxlan
.term_if
== ifp
)
1719 pim_vxlan_del_term_dev(pim
);