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"
56 static void pim_if_igmp_join_del_all(struct interface
*ifp
);
57 static int igmp_join_sock(const char *ifname
, ifindex_t ifindex
,
58 struct in_addr group_addr
, struct in_addr source_addr
,
59 struct pim_interface
*pim_ifp
);
62 void pim_if_init(struct pim_instance
*pim
)
66 for (i
= 0; i
< MAXVIFS
; i
++)
67 pim
->iface_vif_index
[i
] = 0;
70 void pim_if_terminate(struct pim_instance
*pim
)
72 struct interface
*ifp
;
74 FOR_ALL_INTERFACES (pim
->vrf
, ifp
) {
75 struct pim_interface
*pim_ifp
= ifp
->info
;
85 static void pim_sec_addr_free(struct pim_secondary_addr
*sec_addr
)
87 XFREE(MTYPE_PIM_SEC_ADDR
, sec_addr
);
90 __attribute__((unused
))
91 static int pim_sec_addr_comp(const void *p1
, const void *p2
)
93 const struct pim_secondary_addr
*sec1
= p1
;
94 const struct pim_secondary_addr
*sec2
= p2
;
96 if (sec1
->addr
.family
== AF_INET
&& sec2
->addr
.family
== AF_INET6
)
99 if (sec1
->addr
.family
== AF_INET6
&& sec2
->addr
.family
== AF_INET
)
102 if (sec1
->addr
.family
== AF_INET
) {
103 if (ntohl(sec1
->addr
.u
.prefix4
.s_addr
)
104 < ntohl(sec2
->addr
.u
.prefix4
.s_addr
))
107 if (ntohl(sec1
->addr
.u
.prefix4
.s_addr
)
108 > ntohl(sec2
->addr
.u
.prefix4
.s_addr
))
111 return memcmp(&sec1
->addr
.u
.prefix6
, &sec2
->addr
.u
.prefix6
,
112 sizeof(struct in6_addr
));
118 struct pim_interface
*pim_if_new(struct interface
*ifp
, bool igmp
, bool pim
,
119 bool ispimreg
, bool is_vxlan_term
)
121 struct pim_interface
*pim_ifp
;
126 pim_ifp
= XCALLOC(MTYPE_PIM_INTERFACE
, sizeof(*pim_ifp
));
128 pim_ifp
->pim
= ifp
->vrf
->info
;
129 pim_ifp
->mroute_vif_index
= -1;
131 pim_ifp
->igmp_version
= IGMP_DEFAULT_VERSION
;
132 pim_ifp
->mld_version
= MLD_DEFAULT_VERSION
;
133 pim_ifp
->gm_default_robustness_variable
=
134 IGMP_DEFAULT_ROBUSTNESS_VARIABLE
;
135 pim_ifp
->gm_default_query_interval
= IGMP_GENERAL_QUERY_INTERVAL
;
136 pim_ifp
->gm_query_max_response_time_dsec
=
137 IGMP_QUERY_MAX_RESPONSE_TIME_DSEC
;
138 pim_ifp
->gm_specific_query_max_response_time_dsec
=
139 IGMP_SPECIFIC_QUERY_MAX_RESPONSE_TIME_DSEC
;
140 pim_ifp
->gm_last_member_query_count
= IGMP_DEFAULT_ROBUSTNESS_VARIABLE
;
142 /* BSM config on interface: true by default */
143 pim_ifp
->bsm_enable
= true;
144 pim_ifp
->ucast_bsm_accept
= true;
145 pim_ifp
->am_i_dr
= false;
148 RFC 3376: 8.3. Query Response Interval
149 The number of seconds represented by the [Query Response Interval]
150 must be less than the [Query Interval].
152 assert(pim_ifp
->gm_query_max_response_time_dsec
<
153 pim_ifp
->gm_default_query_interval
);
155 pim_ifp
->pim_enable
= pim
;
156 pim_ifp
->pim_passive_enable
= false;
158 pim_ifp
->gm_enable
= igmp
;
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
);
192 pim_ifp
->pim
->mcast_if_count
++;
197 void pim_if_delete(struct interface
*ifp
)
199 struct pim_interface
*pim_ifp
;
205 pim_ifp
->pim
->mcast_if_count
--;
207 if (pim_ifp
->gm_join_list
) {
208 pim_if_igmp_join_del_all(ifp
);
212 pim_ifchannel_delete_all(ifp
);
214 igmp_sock_delete_all(ifp
);
216 if (pim_ifp
->pim_sock_fd
>= 0)
217 pim_sock_delete(ifp
, "Interface removed from configuration");
221 pim_igmp_if_fini(pim_ifp
);
223 list_delete(&pim_ifp
->pim_neighbor_list
);
224 list_delete(&pim_ifp
->upstream_switch_list
);
225 list_delete(&pim_ifp
->sec_addr_list
);
227 XFREE(MTYPE_PIM_INTERFACE
, pim_ifp
->boundary_oil_plist
);
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 pim_addr new_prim_addr
;
305 if (force_prim_as_any
)
306 new_prim_addr
= PIMADDR_ANY
;
308 new_prim_addr
= pim_find_primary_addr(ifp
);
310 changed
= pim_addr_cmp(new_prim_addr
, pim_ifp
->primary_address
);
313 zlog_debug("%s: old=%pPA new=%pPA on interface %s: %s",
314 __func__
, &pim_ifp
->primary_address
, &new_prim_addr
,
315 ifp
->name
, changed
? "changed" : "unchanged");
318 /* Before updating pim_ifp send Hello time with 0 hold time */
319 if (pim_ifp
->pim_enable
) {
320 pim_hello_send(ifp
, 0 /* zero-sec holdtime */);
322 pim_ifp
->primary_address
= new_prim_addr
;
328 static struct pim_secondary_addr
*
329 pim_sec_addr_find(struct pim_interface
*pim_ifp
, struct prefix
*addr
)
331 struct pim_secondary_addr
*sec_addr
;
332 struct listnode
*node
;
334 for (ALL_LIST_ELEMENTS_RO(pim_ifp
->sec_addr_list
, node
, sec_addr
)) {
335 if (prefix_cmp(&sec_addr
->addr
, addr
) == 0) {
343 static void pim_sec_addr_del(struct pim_interface
*pim_ifp
,
344 struct pim_secondary_addr
*sec_addr
)
346 listnode_delete(pim_ifp
->sec_addr_list
, sec_addr
);
347 pim_sec_addr_free(sec_addr
);
350 static int pim_sec_addr_add(struct pim_interface
*pim_ifp
, struct prefix
*addr
)
353 struct pim_secondary_addr
*sec_addr
;
355 sec_addr
= pim_sec_addr_find(pim_ifp
, addr
);
357 sec_addr
->flags
&= ~PIM_SEC_ADDRF_STALE
;
361 sec_addr
= XCALLOC(MTYPE_PIM_SEC_ADDR
, sizeof(*sec_addr
));
364 sec_addr
->addr
= *addr
;
365 listnode_add_sort(pim_ifp
->sec_addr_list
, sec_addr
);
370 static int pim_sec_addr_del_all(struct pim_interface
*pim_ifp
)
374 if (!list_isempty(pim_ifp
->sec_addr_list
)) {
376 /* remove all nodes and free up the list itself */
377 list_delete_all_node(pim_ifp
->sec_addr_list
);
383 static int pim_sec_addr_update(struct interface
*ifp
)
385 struct pim_interface
*pim_ifp
= ifp
->info
;
386 struct connected
*ifc
;
387 struct listnode
*node
;
388 struct listnode
*nextnode
;
389 struct pim_secondary_addr
*sec_addr
;
392 for (ALL_LIST_ELEMENTS_RO(pim_ifp
->sec_addr_list
, node
, sec_addr
)) {
393 sec_addr
->flags
|= PIM_SEC_ADDRF_STALE
;
396 for (ALL_LIST_ELEMENTS_RO(ifp
->connected
, node
, ifc
)) {
397 pim_addr addr
= pim_addr_from_prefix(ifc
->address
);
399 if (pim_addr_is_any(addr
))
402 if (!pim_addr_cmp(addr
, pim_ifp
->primary_address
)) {
403 /* don't add the primary address into the secondary
408 if (pim_sec_addr_add(pim_ifp
, ifc
->address
)) {
413 /* Drop stale entries */
414 for (ALL_LIST_ELEMENTS(pim_ifp
->sec_addr_list
, node
, nextnode
,
416 if (sec_addr
->flags
& PIM_SEC_ADDRF_STALE
) {
417 pim_sec_addr_del(pim_ifp
, sec_addr
);
425 static int detect_secondary_address_change(struct interface
*ifp
,
426 int force_prim_as_any
,
429 struct pim_interface
*pim_ifp
= ifp
->info
;
432 if (force_prim_as_any
) {
433 /* if primary address is being forced to zero just flush the
434 * secondary address list */
435 changed
= pim_sec_addr_del_all(pim_ifp
);
437 /* re-evaluate the secondary address list */
438 changed
= pim_sec_addr_update(ifp
);
444 static void detect_address_change(struct interface
*ifp
, int force_prim_as_any
,
448 struct pim_interface
*pim_ifp
;
454 if (detect_primary_address_change(ifp
, force_prim_as_any
, caller
)) {
458 if (detect_secondary_address_change(ifp
, force_prim_as_any
, caller
)) {
464 if (!pim_ifp
->pim_enable
) {
468 pim_addr_change(ifp
);
471 /* XXX: if we have unnumbered interfaces we need to run detect address
472 * address change on all of them when the lo address changes */
475 int pim_update_source_set(struct interface
*ifp
, pim_addr source
)
477 struct pim_interface
*pim_ifp
= ifp
->info
;
480 return PIM_IFACE_NOT_FOUND
;
483 if (!pim_addr_cmp(pim_ifp
->update_source
, source
)) {
484 return PIM_UPDATE_SOURCE_DUP
;
487 pim_ifp
->update_source
= source
;
488 detect_address_change(ifp
, 0 /* force_prim_as_any */, __func__
);
493 void pim_if_addr_add(struct connected
*ifc
)
495 struct pim_interface
*pim_ifp
;
496 struct interface
*ifp
;
507 if (!if_is_operative(ifp
))
511 zlog_debug("%s: %s ifindex=%d connected IP address %pFX %s",
512 __func__
, ifp
->name
, ifp
->ifindex
, ifc
->address
,
513 CHECK_FLAG(ifc
->flags
, ZEBRA_IFA_SECONDARY
)
517 if (IN6_IS_ADDR_LINKLOCAL(&ifc
->address
->u
.prefix6
) ||
518 IN6_IS_ADDR_LOOPBACK(&ifc
->address
->u
.prefix6
)) {
519 if (IN6_IS_ADDR_UNSPECIFIED(&pim_ifp
->ll_lowest
))
520 pim_ifp
->ll_lowest
= ifc
->address
->u
.prefix6
;
521 else if (IPV6_ADDR_CMP(&ifc
->address
->u
.prefix6
,
522 &pim_ifp
->ll_lowest
) < 0)
523 pim_ifp
->ll_lowest
= ifc
->address
->u
.prefix6
;
525 if (IPV6_ADDR_CMP(&ifc
->address
->u
.prefix6
,
526 &pim_ifp
->ll_highest
) > 0)
527 pim_ifp
->ll_highest
= ifc
->address
->u
.prefix6
;
531 "%s: new link-local %pI6, lowest now %pI6, highest %pI6",
532 ifc
->ifp
->name
, &ifc
->address
->u
.prefix6
,
533 &pim_ifp
->ll_lowest
, &pim_ifp
->ll_highest
);
537 detect_address_change(ifp
, 0, __func__
);
539 // if (ifc->address->family != AF_INET)
543 struct in_addr ifaddr
= ifc
->address
->u
.prefix4
;
545 if (pim_ifp
->gm_enable
) {
546 struct gm_sock
*igmp
;
548 /* lookup IGMP socket */
549 igmp
= pim_igmp_sock_lookup_ifaddr(pim_ifp
->gm_socket_list
,
552 /* if addr new, add IGMP socket */
553 if (ifc
->address
->family
== AF_INET
)
554 pim_igmp_sock_add(pim_ifp
->gm_socket_list
,
556 } else if (igmp
->mtrace_only
) {
557 igmp_sock_delete(igmp
);
558 pim_igmp_sock_add(pim_ifp
->gm_socket_list
, ifaddr
, ifp
,
562 /* Replay Static IGMP groups */
563 if (pim_ifp
->gm_join_list
) {
564 struct listnode
*node
;
565 struct listnode
*nextnode
;
569 for (ALL_LIST_ELEMENTS(pim_ifp
->gm_join_list
, node
,
571 /* Close socket and reopen with Source and Group
574 join_fd
= igmp_join_sock(
575 ifp
->name
, ifp
->ifindex
, ij
->group_addr
,
576 ij
->source_addr
, pim_ifp
);
578 char group_str
[INET_ADDRSTRLEN
];
579 char source_str
[INET_ADDRSTRLEN
];
580 pim_inet4_dump("<grp?>", ij
->group_addr
,
584 "<src?>", ij
->source_addr
,
585 source_str
, sizeof(source_str
));
587 "%s: igmp_join_sock() failure for IGMP group %s source %s on interface %s",
588 __func__
, group_str
, source_str
,
592 ij
->sock_fd
= join_fd
;
597 struct gm_sock
*igmp
;
599 /* lookup IGMP socket */
600 igmp
= pim_igmp_sock_lookup_ifaddr(pim_ifp
->gm_socket_list
,
602 if (ifc
->address
->family
== AF_INET
) {
604 igmp_sock_delete(igmp
);
605 /* if addr new, add IGMP socket */
606 pim_igmp_sock_add(pim_ifp
->gm_socket_list
, ifaddr
, ifp
,
609 } /* igmp mtrace only */
612 if (pim_ifp
->pim_enable
) {
614 if (!pim_addr_is_any(pim_ifp
->primary_address
)) {
616 /* Interface has a valid socket ? */
617 if (pim_ifp
->pim_sock_fd
< 0) {
618 if (pim_sock_add(ifp
)) {
620 "Failure creating PIM socket for interface %s",
624 struct pim_nexthop_cache
*pnc
= NULL
;
626 struct zclient
*zclient
= NULL
;
628 zclient
= pim_zebra_zclient_get();
629 /* RP config might come prior to (local RP's interface)
631 In this case, pnc would not have pim enabled
633 Once Interface is UP and pim info is available,
635 with RNH address to receive update and add the
636 interface as nexthop. */
637 memset(&rpf
, 0, sizeof(struct pim_rpf
));
638 rpf
.rpf_addr
= pim_addr_from_prefix(ifc
->address
);
639 pnc
= pim_nexthop_cache_find(pim_ifp
->pim
, &rpf
);
641 pim_sendmsg_zebra_rnh(pim_ifp
->pim
, zclient
,
643 ZEBRA_NEXTHOP_REGISTER
);
648 PIM or IGMP is enabled on interface, and there is at least one
649 address assigned, then try to create a vif_index.
651 if (pim_ifp
->mroute_vif_index
< 0) {
652 vxlan_term
= pim_vxlan_is_term_dev_cfg(pim_ifp
->pim
, ifp
);
653 pim_if_add_vif(ifp
, false, vxlan_term
);
656 pim_ifchannel_scan_forward_start(ifp
);
659 static void pim_if_addr_del_igmp(struct connected
*ifc
)
662 struct pim_interface
*pim_ifp
= ifc
->ifp
->info
;
663 struct gm_sock
*igmp
;
664 struct in_addr ifaddr
;
666 if (ifc
->address
->family
!= AF_INET
) {
667 /* non-IPv4 address */
672 /* IGMP not enabled on interface */
676 ifaddr
= ifc
->address
->u
.prefix4
;
678 /* lookup IGMP socket */
679 igmp
= pim_igmp_sock_lookup_ifaddr(pim_ifp
->gm_socket_list
, ifaddr
);
681 /* if addr found, del IGMP socket */
682 igmp_sock_delete(igmp
);
687 static void pim_if_addr_del_pim(struct connected
*ifc
)
689 struct pim_interface
*pim_ifp
= ifc
->ifp
->info
;
691 if (ifc
->address
->family
!= AF_INET
) {
692 /* non-IPv4 address */
697 /* PIM not enabled on interface */
701 if (!pim_addr_is_any(pim_ifp
->primary_address
)) {
702 /* Interface keeps a valid primary address */
706 if (pim_ifp
->pim_sock_fd
< 0) {
707 /* Interface does not hold a valid socket any longer */
712 pim_sock_delete() closes the socket, stops read and timer threads,
713 and kills all neighbors.
715 pim_sock_delete(ifc
->ifp
,
716 "last address has been removed from interface");
719 void pim_if_addr_del(struct connected
*ifc
, int force_prim_as_any
)
721 struct interface
*ifp
;
728 zlog_debug("%s: %s ifindex=%d disconnected IP address %pFX %s",
729 __func__
, ifp
->name
, ifp
->ifindex
, ifc
->address
,
730 CHECK_FLAG(ifc
->flags
, ZEBRA_IFA_SECONDARY
)
735 struct pim_interface
*pim_ifp
= ifc
->ifp
->info
;
738 (!IPV6_ADDR_CMP(&ifc
->address
->u
.prefix6
, &pim_ifp
->ll_lowest
) ||
739 !IPV6_ADDR_CMP(&ifc
->address
->u
.prefix6
, &pim_ifp
->ll_highest
))) {
740 struct listnode
*cnode
;
741 struct connected
*cc
;
743 memset(&pim_ifp
->ll_lowest
, 0xff, sizeof(pim_ifp
->ll_lowest
));
744 memset(&pim_ifp
->ll_highest
, 0, sizeof(pim_ifp
->ll_highest
));
746 for (ALL_LIST_ELEMENTS_RO(ifc
->ifp
->connected
, cnode
, cc
)) {
747 if (!IN6_IS_ADDR_LINKLOCAL(&cc
->address
->u
.prefix6
) &&
748 !IN6_IS_ADDR_LOOPBACK(&cc
->address
->u
.prefix6
))
751 if (IPV6_ADDR_CMP(&cc
->address
->u
.prefix6
,
752 &pim_ifp
->ll_lowest
) < 0)
753 pim_ifp
->ll_lowest
= cc
->address
->u
.prefix6
;
754 if (IPV6_ADDR_CMP(&cc
->address
->u
.prefix6
,
755 &pim_ifp
->ll_highest
) > 0)
756 pim_ifp
->ll_highest
= cc
->address
->u
.prefix6
;
759 if (pim_ifp
->ll_lowest
.s6_addr
[0] == 0xff)
760 memset(&pim_ifp
->ll_lowest
, 0,
761 sizeof(pim_ifp
->ll_lowest
));
765 "%s: removed link-local %pI6, lowest now %pI6, highest %pI6",
766 ifc
->ifp
->name
, &ifc
->address
->u
.prefix6
,
767 &pim_ifp
->ll_lowest
, &pim_ifp
->ll_highest
);
773 detect_address_change(ifp
, force_prim_as_any
, __func__
);
775 pim_if_addr_del_igmp(ifc
);
776 pim_if_addr_del_pim(ifc
);
779 void pim_if_addr_add_all(struct interface
*ifp
)
781 struct connected
*ifc
;
782 struct listnode
*node
;
783 struct listnode
*nextnode
;
786 struct pim_interface
*pim_ifp
= ifp
->info
;
790 /* PIM/IGMP enabled ? */
794 for (ALL_LIST_ELEMENTS(ifp
->connected
, node
, nextnode
, ifc
)) {
795 struct prefix
*p
= ifc
->address
;
797 if (p
->family
!= AF_INET
)
801 pim_if_addr_add(ifc
);
804 if (!v4_addrs
&& v6_addrs
&& !if_is_loopback(ifp
) &&
805 pim_ifp
->pim_enable
&& !pim_addr_is_any(pim_ifp
->primary_address
) &&
806 pim_ifp
->pim_sock_fd
< 0 && pim_sock_add(ifp
)) {
807 /* Interface has a valid primary address ? */
808 /* Interface has a valid socket ? */
809 zlog_warn("Failure creating PIM socket for interface %s",
813 * PIM or IGMP is enabled on interface, and there is at least one
814 * address assigned, then try to create a vif_index.
816 if (pim_ifp
->mroute_vif_index
< 0) {
817 vxlan_term
= pim_vxlan_is_term_dev_cfg(pim_ifp
->pim
, ifp
);
818 pim_if_add_vif(ifp
, false, vxlan_term
);
821 pim_ifchannel_scan_forward_start(ifp
);
823 pim_rp_setup(pim_ifp
->pim
);
824 pim_rp_check_on_if_add(pim_ifp
);
827 void pim_if_addr_del_all(struct interface
*ifp
)
829 struct connected
*ifc
;
830 struct listnode
*node
;
831 struct listnode
*nextnode
;
832 struct pim_instance
*pim
;
834 pim
= ifp
->vrf
->info
;
838 /* PIM/IGMP enabled ? */
842 for (ALL_LIST_ELEMENTS(ifp
->connected
, node
, nextnode
, ifc
)) {
843 struct prefix
*p
= ifc
->address
;
845 if (p
->family
!= AF_INET
)
848 pim_if_addr_del(ifc
, 1 /* force_prim_as_any=true */);
852 pim_i_am_rp_re_evaluate(pim
);
855 void pim_if_addr_del_all_igmp(struct interface
*ifp
)
857 struct connected
*ifc
;
858 struct listnode
*node
;
859 struct listnode
*nextnode
;
861 /* PIM/IGMP enabled ? */
865 for (ALL_LIST_ELEMENTS(ifp
->connected
, node
, nextnode
, ifc
)) {
866 struct prefix
*p
= ifc
->address
;
868 if (p
->family
!= AF_INET
)
871 pim_if_addr_del_igmp(ifc
);
875 pim_addr
pim_find_primary_addr(struct interface
*ifp
)
877 struct connected
*ifc
;
878 struct listnode
*node
;
879 struct pim_interface
*pim_ifp
= ifp
->info
;
881 if (pim_ifp
&& !pim_addr_is_any(pim_ifp
->update_source
))
882 return pim_ifp
->update_source
;
886 return pim_ifp
->ll_highest
;
888 pim_addr best_addr
= PIMADDR_ANY
;
890 for (ALL_LIST_ELEMENTS_RO(ifp
->connected
, node
, ifc
)) {
893 if (ifc
->address
->family
!= AF_INET6
)
896 addr
= pim_addr_from_prefix(ifc
->address
);
897 if (!IN6_IS_ADDR_LINKLOCAL(&addr
))
899 if (pim_addr_cmp(addr
, best_addr
) > 0)
908 for (ALL_LIST_ELEMENTS_RO(ifp
->connected
, node
, ifc
)) {
909 switch (ifc
->address
->family
) {
920 if (CHECK_FLAG(ifc
->flags
, ZEBRA_IFA_SECONDARY
))
923 if (ifc
->address
->family
!= PIM_AF
)
926 return pim_addr_from_prefix(ifc
->address
);
930 * If we have no v4_addrs and v6 is configured
931 * We probably are using unnumbered
932 * So let's grab the loopbacks v4 address
933 * and use that as the primary address
935 if (!v4_addrs
&& v6_addrs
) {
936 struct interface
*lo_ifp
;
938 // DBS - Come back and check here
939 if (ifp
->vrf
->vrf_id
== VRF_DEFAULT
)
940 lo_ifp
= if_lookup_by_name("lo", ifp
->vrf
->vrf_id
);
942 lo_ifp
= if_lookup_by_name(ifp
->vrf
->name
,
945 if (lo_ifp
&& (lo_ifp
!= ifp
))
946 return pim_find_primary_addr(lo_ifp
);
952 static int pim_iface_next_vif_index(struct interface
*ifp
)
954 struct pim_interface
*pim_ifp
= ifp
->info
;
955 struct pim_instance
*pim
= pim_ifp
->pim
;
959 * The pimreg vif is always going to be in index 0
962 if (ifp
->ifindex
== PIM_OIF_PIM_REGISTER_VIF
)
965 for (i
= 1; i
< MAXVIFS
; i
++) {
966 if (pim
->iface_vif_index
[i
] == 0)
973 pim_if_add_vif() uses ifindex as vif_index
975 see also pim_if_find_vifindex_by_ifindex()
977 int pim_if_add_vif(struct interface
*ifp
, bool ispimreg
, bool is_vxlan_term
)
979 struct pim_interface
*pim_ifp
= ifp
->info
;
981 unsigned char flags
= 0;
985 if (pim_ifp
->mroute_vif_index
> 0) {
986 zlog_warn("%s: vif_index=%d > 0 on interface %s ifindex=%d",
987 __func__
, pim_ifp
->mroute_vif_index
, ifp
->name
,
992 if (ifp
->ifindex
< 0) {
993 zlog_warn("%s: ifindex=%d < 1 on interface %s", __func__
,
994 ifp
->ifindex
, ifp
->name
);
998 ifaddr
= pim_ifp
->primary_address
;
1000 /* IPv6 API is always by interface index */
1001 if (!ispimreg
&& !is_vxlan_term
&& pim_addr_is_any(ifaddr
)) {
1003 "%s: could not get address for interface %s ifindex=%d",
1004 __func__
, ifp
->name
, ifp
->ifindex
);
1009 pim_ifp
->mroute_vif_index
= pim_iface_next_vif_index(ifp
);
1011 if (pim_ifp
->mroute_vif_index
>= MAXVIFS
) {
1013 "%s: Attempting to configure more than MAXVIFS=%d on pim enabled interface %s",
1014 __func__
, MAXVIFS
, ifp
->name
);
1018 if (ifp
->ifindex
== PIM_OIF_PIM_REGISTER_VIF
)
1019 flags
= VIFF_REGISTER
;
1020 #ifdef VIFF_USE_IFINDEX
1022 flags
= VIFF_USE_IFINDEX
;
1025 if (pim_mroute_add_vif(ifp
, ifaddr
, flags
)) {
1026 /* pim_mroute_add_vif reported error */
1030 pim_ifp
->pim
->iface_vif_index
[pim_ifp
->mroute_vif_index
] = 1;
1035 /* if the device qualifies as pim_vxlan iif/oif update vxlan entries */
1036 pim_vxlan_add_vif(ifp
);
1040 int pim_if_del_vif(struct interface
*ifp
)
1042 struct pim_interface
*pim_ifp
= ifp
->info
;
1044 if (pim_ifp
->mroute_vif_index
< 1) {
1045 zlog_warn("%s: vif_index=%d < 1 on interface %s ifindex=%d",
1046 __func__
, pim_ifp
->mroute_vif_index
, ifp
->name
,
1051 /* if the device was a pim_vxlan iif/oif update vxlan mroute entries */
1052 pim_vxlan_del_vif(ifp
);
1054 gm_ifp_teardown(ifp
);
1056 pim_mroute_del_vif(ifp
);
1061 pim_ifp
->pim
->iface_vif_index
[pim_ifp
->mroute_vif_index
] = 0;
1063 pim_ifp
->mroute_vif_index
= -1;
1068 struct interface
*pim_if_find_by_vif_index(struct pim_instance
*pim
,
1069 ifindex_t vif_index
)
1071 struct interface
*ifp
;
1073 FOR_ALL_INTERFACES (pim
->vrf
, ifp
) {
1075 struct pim_interface
*pim_ifp
;
1076 pim_ifp
= ifp
->info
;
1078 if (vif_index
== pim_ifp
->mroute_vif_index
)
1087 pim_if_add_vif() uses ifindex as vif_index
1089 int pim_if_find_vifindex_by_ifindex(struct pim_instance
*pim
, ifindex_t ifindex
)
1091 struct pim_interface
*pim_ifp
;
1092 struct interface
*ifp
;
1094 ifp
= if_lookup_by_index(ifindex
, pim
->vrf
->vrf_id
);
1095 if (!ifp
|| !ifp
->info
)
1097 pim_ifp
= ifp
->info
;
1099 return pim_ifp
->mroute_vif_index
;
1102 int pim_if_lan_delay_enabled(struct interface
*ifp
)
1104 struct pim_interface
*pim_ifp
;
1106 pim_ifp
= ifp
->info
;
1108 assert(pim_ifp
->pim_number_of_nonlandelay_neighbors
>= 0);
1110 return pim_ifp
->pim_number_of_nonlandelay_neighbors
== 0;
1113 uint16_t pim_if_effective_propagation_delay_msec(struct interface
*ifp
)
1115 if (pim_if_lan_delay_enabled(ifp
)) {
1116 struct pim_interface
*pim_ifp
;
1117 pim_ifp
= ifp
->info
;
1118 return pim_ifp
->pim_neighbors_highest_propagation_delay_msec
;
1120 return PIM_DEFAULT_PROPAGATION_DELAY_MSEC
;
1124 uint16_t pim_if_effective_override_interval_msec(struct interface
*ifp
)
1126 if (pim_if_lan_delay_enabled(ifp
)) {
1127 struct pim_interface
*pim_ifp
;
1128 pim_ifp
= ifp
->info
;
1129 return pim_ifp
->pim_neighbors_highest_override_interval_msec
;
1131 return PIM_DEFAULT_OVERRIDE_INTERVAL_MSEC
;
1135 int pim_if_t_override_msec(struct interface
*ifp
)
1137 int effective_override_interval_msec
;
1138 int t_override_msec
;
1140 effective_override_interval_msec
=
1141 pim_if_effective_override_interval_msec(ifp
);
1144 frr_weak_random() % (effective_override_interval_msec
+ 1);
1146 return t_override_msec
;
1149 uint16_t pim_if_jp_override_interval_msec(struct interface
*ifp
)
1151 return pim_if_effective_propagation_delay_msec(ifp
)
1152 + pim_if_effective_override_interval_msec(ifp
);
1156 RFC 4601: 4.1.6. State Summarization Macros
1158 The function NBR( I, A ) uses information gathered through PIM Hello
1159 messages to map the IP address A of a directly connected PIM
1160 neighbor router on interface I to the primary IP address of the same
1161 router (Section 4.3.4). The primary IP address of a neighbor is the
1162 address that it uses as the source of its PIM Hello messages.
1164 struct pim_neighbor
*pim_if_find_neighbor(struct interface
*ifp
, pim_addr addr
)
1166 struct listnode
*neighnode
;
1167 struct pim_neighbor
*neigh
;
1168 struct pim_interface
*pim_ifp
;
1173 pim_ifp
= ifp
->info
;
1175 zlog_warn("%s: multicast not enabled on interface %s", __func__
,
1180 pim_addr_to_prefix(&p
, addr
);
1182 for (ALL_LIST_ELEMENTS_RO(pim_ifp
->pim_neighbor_list
, neighnode
,
1185 /* primary address ? */
1186 if (!pim_addr_cmp(neigh
->source_addr
, addr
))
1189 /* secondary address ? */
1190 if (pim_neighbor_find_secondary(neigh
, &p
))
1194 if (PIM_DEBUG_PIM_TRACE
)
1196 "%s: neighbor not found for address %pPA on interface %s",
1197 __func__
, &addr
, ifp
->name
);
1202 long pim_if_t_suppressed_msec(struct interface
*ifp
)
1204 struct pim_interface
*pim_ifp
;
1205 long t_suppressed_msec
;
1206 uint32_t ramount
= 0;
1208 pim_ifp
= ifp
->info
;
1211 /* join suppression disabled ? */
1212 if (pim_ifp
->pim_can_disable_join_suppression
)
1215 /* t_suppressed = t_periodic * rand(1.1, 1.4) */
1216 ramount
= 1100 + (frr_weak_random() % (1400 - 1100 + 1));
1217 t_suppressed_msec
= router
->t_periodic
* ramount
;
1219 return t_suppressed_msec
;
1223 static void igmp_join_free(struct gm_join
*ij
)
1225 XFREE(MTYPE_PIM_IGMP_JOIN
, ij
);
1228 static struct gm_join
*igmp_join_find(struct list
*join_list
,
1229 struct in_addr group_addr
,
1230 struct in_addr source_addr
)
1232 struct listnode
*node
;
1237 for (ALL_LIST_ELEMENTS_RO(join_list
, node
, ij
)) {
1238 if ((group_addr
.s_addr
== ij
->group_addr
.s_addr
)
1239 && (source_addr
.s_addr
== ij
->source_addr
.s_addr
))
1246 static int igmp_join_sock(const char *ifname
, ifindex_t ifindex
,
1247 struct in_addr group_addr
, struct in_addr source_addr
,
1248 struct pim_interface
*pim_ifp
)
1252 pim_ifp
->igmp_ifstat_joins_sent
++;
1254 join_fd
= pim_socket_raw(IPPROTO_IGMP
);
1256 pim_ifp
->igmp_ifstat_joins_failed
++;
1260 if (pim_igmp_join_source(join_fd
, ifindex
, group_addr
, source_addr
)) {
1261 char group_str
[INET_ADDRSTRLEN
];
1262 char source_str
[INET_ADDRSTRLEN
];
1263 pim_inet4_dump("<grp?>", group_addr
, group_str
,
1265 pim_inet4_dump("<src?>", source_addr
, source_str
,
1266 sizeof(source_str
));
1268 "%s: setsockopt(fd=%d) failure for IGMP group %s source %s ifindex %d on interface %s: errno=%d: %s",
1269 __func__
, join_fd
, group_str
, source_str
, ifindex
,
1270 ifname
, errno
, safe_strerror(errno
));
1272 pim_ifp
->igmp_ifstat_joins_failed
++;
1282 static struct gm_join
*igmp_join_new(struct interface
*ifp
,
1283 struct in_addr group_addr
,
1284 struct in_addr source_addr
)
1286 struct pim_interface
*pim_ifp
;
1290 pim_ifp
= ifp
->info
;
1293 join_fd
= igmp_join_sock(ifp
->name
, ifp
->ifindex
, group_addr
,
1294 source_addr
, pim_ifp
);
1296 char group_str
[INET_ADDRSTRLEN
];
1297 char source_str
[INET_ADDRSTRLEN
];
1299 pim_inet4_dump("<grp?>", group_addr
, group_str
,
1301 pim_inet4_dump("<src?>", source_addr
, source_str
,
1302 sizeof(source_str
));
1304 "%s: igmp_join_sock() failure for IGMP group %s source %s on interface %s",
1305 __func__
, group_str
, source_str
, ifp
->name
);
1309 ij
= XCALLOC(MTYPE_PIM_IGMP_JOIN
, sizeof(*ij
));
1311 ij
->sock_fd
= join_fd
;
1312 ij
->group_addr
= group_addr
;
1313 ij
->source_addr
= source_addr
;
1314 ij
->sock_creation
= pim_time_monotonic_sec();
1316 listnode_add(pim_ifp
->gm_join_list
, ij
);
1320 #endif /* PIM_IPV == 4 */
1323 ferr_r
pim_if_igmp_join_add(struct interface
*ifp
, struct in_addr group_addr
,
1324 struct in_addr source_addr
)
1326 struct pim_interface
*pim_ifp
;
1329 pim_ifp
= ifp
->info
;
1331 return ferr_cfg_invalid("multicast not enabled on interface %s",
1335 if (!pim_ifp
->gm_join_list
) {
1336 pim_ifp
->gm_join_list
= list_new();
1337 pim_ifp
->gm_join_list
->del
= (void (*)(void *))igmp_join_free
;
1340 ij
= igmp_join_find(pim_ifp
->gm_join_list
, group_addr
, source_addr
);
1342 /* This interface has already been configured to join this IGMP group
1348 (void)igmp_join_new(ifp
, group_addr
, source_addr
);
1350 if (PIM_DEBUG_IGMP_EVENTS
) {
1351 char group_str
[INET_ADDRSTRLEN
];
1352 char source_str
[INET_ADDRSTRLEN
];
1353 pim_inet4_dump("<grp?>", group_addr
, group_str
,
1355 pim_inet4_dump("<src?>", source_addr
, source_str
,
1356 sizeof(source_str
));
1358 "%s: issued static igmp join for channel (S,G)=(%s,%s) on interface %s",
1359 __func__
, source_str
, group_str
, ifp
->name
);
1364 #endif /* PIM_IPV == 4 */
1366 int pim_if_igmp_join_del(struct interface
*ifp
, struct in_addr group_addr
,
1367 struct in_addr source_addr
)
1369 struct pim_interface
*pim_ifp
;
1372 pim_ifp
= ifp
->info
;
1374 zlog_warn("%s: multicast not enabled on interface %s", __func__
,
1379 if (!pim_ifp
->gm_join_list
) {
1380 zlog_warn("%s: no IGMP join on interface %s", __func__
,
1385 ij
= igmp_join_find(pim_ifp
->gm_join_list
, group_addr
, source_addr
);
1387 char group_str
[INET_ADDRSTRLEN
];
1388 char source_str
[INET_ADDRSTRLEN
];
1389 pim_inet4_dump("<grp?>", group_addr
, group_str
,
1391 pim_inet4_dump("<src?>", source_addr
, source_str
,
1392 sizeof(source_str
));
1394 "%s: could not find IGMP group %s source %s on interface %s",
1395 __func__
, group_str
, source_str
, ifp
->name
);
1399 if (close(ij
->sock_fd
)) {
1400 char group_str
[INET_ADDRSTRLEN
];
1401 char source_str
[INET_ADDRSTRLEN
];
1402 pim_inet4_dump("<grp?>", group_addr
, group_str
,
1404 pim_inet4_dump("<src?>", source_addr
, source_str
,
1405 sizeof(source_str
));
1407 "%s: failure closing sock_fd=%d for IGMP group %s source %s on interface %s: errno=%d: %s",
1408 __func__
, ij
->sock_fd
, group_str
, source_str
, ifp
->name
,
1409 errno
, safe_strerror(errno
));
1412 listnode_delete(pim_ifp
->gm_join_list
, ij
);
1414 if (listcount(pim_ifp
->gm_join_list
) < 1) {
1415 list_delete(&pim_ifp
->gm_join_list
);
1416 pim_ifp
->gm_join_list
= 0;
1422 __attribute__((unused
))
1423 static void pim_if_igmp_join_del_all(struct interface
*ifp
)
1425 struct pim_interface
*pim_ifp
;
1426 struct listnode
*node
;
1427 struct listnode
*nextnode
;
1430 pim_ifp
= ifp
->info
;
1432 zlog_warn("%s: multicast not enabled on interface %s", __func__
,
1437 if (!pim_ifp
->gm_join_list
)
1440 for (ALL_LIST_ELEMENTS(pim_ifp
->gm_join_list
, node
, nextnode
, ij
))
1441 pim_if_igmp_join_del(ifp
, ij
->group_addr
, ij
->source_addr
);
1443 #else /* PIM_IPV != 4 */
1444 ferr_r
pim_if_igmp_join_add(struct interface
*ifp
, struct in_addr group_addr
,
1445 struct in_addr source_addr
)
1450 int pim_if_igmp_join_del(struct interface
*ifp
, struct in_addr group_addr
,
1451 struct in_addr source_addr
)
1455 #endif /* PIM_IPV != 4 */
1460 Transitions from "I am Assert Loser" State
1462 Current Winner's GenID Changes or NLT Expires
1464 The Neighbor Liveness Timer associated with the current winner
1465 expires or we receive a Hello message from the current winner
1466 reporting a different GenID from the one it previously reported.
1467 This indicates that the current winner's interface or router has
1468 gone down (and may have come back up), and so we must assume it no
1469 longer knows it was the winner.
1471 void pim_if_assert_on_neighbor_down(struct interface
*ifp
, pim_addr neigh_addr
)
1473 struct pim_interface
*pim_ifp
;
1474 struct pim_ifchannel
*ch
;
1476 pim_ifp
= ifp
->info
;
1479 RB_FOREACH (ch
, pim_ifchannel_rb
, &pim_ifp
->ifchannel_rb
) {
1480 /* Is (S,G,I) assert loser ? */
1481 if (ch
->ifassert_state
!= PIM_IFASSERT_I_AM_LOSER
)
1483 /* Dead neighbor was winner ? */
1484 if (pim_addr_cmp(ch
->ifassert_winner
, neigh_addr
))
1487 assert_action_a5(ch
);
1491 void pim_if_update_join_desired(struct pim_interface
*pim_ifp
)
1493 struct pim_ifchannel
*ch
;
1495 /* clear off flag from interface's upstreams */
1496 RB_FOREACH (ch
, pim_ifchannel_rb
, &pim_ifp
->ifchannel_rb
) {
1497 PIM_UPSTREAM_FLAG_UNSET_DR_JOIN_DESIRED_UPDATED(
1498 ch
->upstream
->flags
);
1501 /* scan per-interface (S,G,I) state on this I interface */
1502 RB_FOREACH (ch
, pim_ifchannel_rb
, &pim_ifp
->ifchannel_rb
) {
1503 struct pim_upstream
*up
= ch
->upstream
;
1505 if (PIM_UPSTREAM_FLAG_TEST_DR_JOIN_DESIRED_UPDATED(up
->flags
))
1508 /* update join_desired for the global (S,G) state */
1509 pim_upstream_update_join_desired(pim_ifp
->pim
, up
);
1510 PIM_UPSTREAM_FLAG_SET_DR_JOIN_DESIRED_UPDATED(up
->flags
);
1514 void pim_if_update_assert_tracking_desired(struct interface
*ifp
)
1516 struct pim_interface
*pim_ifp
;
1517 struct pim_ifchannel
*ch
;
1519 pim_ifp
= ifp
->info
;
1523 RB_FOREACH (ch
, pim_ifchannel_rb
, &pim_ifp
->ifchannel_rb
) {
1524 pim_ifchannel_update_assert_tracking_desired(ch
);
1529 * PIM wants to have an interface pointer for everything it does.
1530 * The pimreg is a special interface that we have that is not
1531 * quite an interface but a VIF is created for it.
1533 void pim_if_create_pimreg(struct pim_instance
*pim
)
1535 char pimreg_name
[INTERFACE_NAMSIZ
];
1537 if (!pim
->regiface
) {
1538 if (pim
->vrf
->vrf_id
== VRF_DEFAULT
)
1539 strlcpy(pimreg_name
, PIMREG
, sizeof(pimreg_name
));
1541 snprintf(pimreg_name
, sizeof(pimreg_name
), PIMREG
"%u",
1542 pim
->vrf
->data
.l
.table_id
);
1544 pim
->regiface
= if_get_by_name(pimreg_name
, pim
->vrf
->vrf_id
,
1546 pim
->regiface
->ifindex
= PIM_OIF_PIM_REGISTER_VIF
;
1548 pim_if_new(pim
->regiface
, false, false, true,
1549 false /*vxlan_term*/);
1551 * On vrf moves we delete the interface if there
1552 * is nothing going on with it. We cannot have
1553 * the pimregiface deleted.
1555 pim
->regiface
->configured
= true;
1560 struct prefix
*pim_if_connected_to_source(struct interface
*ifp
, pim_addr src
)
1562 struct listnode
*cnode
;
1563 struct connected
*c
;
1569 pim_addr_to_prefix(&p
, src
);
1571 for (ALL_LIST_ELEMENTS_RO(ifp
->connected
, cnode
, c
)) {
1572 if (c
->address
->family
!= PIM_AF
)
1574 if (prefix_match(c
->address
, &p
))
1576 if (CONNECTED_PEER(c
) && prefix_match(c
->destination
, &p
))
1577 /* this is not a typo, on PtP we need to return the
1578 * *local* address that lines up with src.
1586 bool pim_if_is_vrf_device(struct interface
*ifp
)
1594 int pim_if_ifchannel_count(struct pim_interface
*pim_ifp
)
1596 struct pim_ifchannel
*ch
;
1599 RB_FOREACH (ch
, pim_ifchannel_rb
, &pim_ifp
->ifchannel_rb
) {
1606 static int pim_ifp_create(struct interface
*ifp
)
1608 struct pim_instance
*pim
;
1610 pim
= ifp
->vrf
->info
;
1611 if (PIM_DEBUG_ZEBRA
) {
1613 "%s: %s index %d vrf %s(%u) flags %ld metric %d mtu %d operative %d",
1614 __func__
, ifp
->name
, ifp
->ifindex
, ifp
->vrf
->name
,
1615 ifp
->vrf
->vrf_id
, (long)ifp
->flags
, ifp
->metric
,
1616 ifp
->mtu
, if_is_operative(ifp
));
1619 if (if_is_operative(ifp
)) {
1620 struct pim_interface
*pim_ifp
;
1622 pim_ifp
= ifp
->info
;
1624 * If we have a pim_ifp already and this is an if_add
1625 * that means that we probably have a vrf move event
1626 * If that is the case, set the proper vrfness.
1630 pim_if_addr_add_all(ifp
);
1633 * Due to ordering issues based upon when
1634 * a command is entered we should ensure that
1635 * the pim reg is created for this vrf if we
1636 * have configuration for it already.
1638 * this is a no-op if it's already been done.
1640 pim_if_create_pimreg(pim
);
1645 * If we are a vrf device that is up, open up the pim_socket for
1647 * to incoming pim messages irrelevant if the user has configured us
1650 if (pim_if_is_vrf_device(ifp
)) {
1651 struct pim_interface
*pim_ifp
;
1654 pim_ifp
= pim_if_new(ifp
, false, false, false,
1655 false /*vxlan_term*/);
1656 ifp
->info
= pim_ifp
;
1662 if (!strncmp(ifp
->name
, PIM_VXLAN_TERM_DEV_NAME
,
1663 sizeof(PIM_VXLAN_TERM_DEV_NAME
))) {
1664 if (pim
->mcast_if_count
< MAXVIFS
)
1665 pim_vxlan_add_term_dev(pim
, ifp
);
1668 "%s: Cannot enable pim on %s. MAXVIFS(%d) reached. Deleting and readding the vxlan termimation device after unconfiguring pim from other interfaces may succeed.",
1669 __func__
, ifp
->name
, MAXVIFS
);
1676 static int pim_ifp_up(struct interface
*ifp
)
1679 struct pim_interface
*pim_ifp
;
1680 struct pim_instance
*pim
;
1682 if (PIM_DEBUG_ZEBRA
) {
1684 "%s: %s index %d vrf %s(%u) flags %ld metric %d mtu %d operative %d",
1685 __func__
, ifp
->name
, ifp
->ifindex
, ifp
->vrf
->name
,
1686 ifp
->vrf
->vrf_id
, (long)ifp
->flags
, ifp
->metric
,
1687 ifp
->mtu
, if_is_operative(ifp
));
1690 pim
= ifp
->vrf
->info
;
1692 pim_ifp
= ifp
->info
;
1694 * If we have a pim_ifp already and this is an if_add
1695 * that means that we probably have a vrf move event
1696 * If that is the case, set the proper vrfness.
1702 pim_if_addr_add_all() suffices for bringing up both IGMP and
1705 pim_if_addr_add_all(ifp
);
1708 * If we have a pimreg device callback and it's for a specific
1709 * table set the master appropriately
1711 if (sscanf(ifp
->name
, "" PIMREG
"%" SCNu32
, &table_id
) == 1) {
1713 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
1714 if ((table_id
== vrf
->data
.l
.table_id
)
1715 && (ifp
->vrf
->vrf_id
!= vrf
->vrf_id
)) {
1716 struct interface
*master
= if_lookup_by_name(
1717 vrf
->name
, vrf
->vrf_id
);
1721 "%s: Unable to find Master interface for %s",
1722 __func__
, vrf
->name
);
1725 pim_zebra_interface_set_master(master
, ifp
);
1732 static int pim_ifp_down(struct interface
*ifp
)
1734 if (PIM_DEBUG_ZEBRA
) {
1736 "%s: %s index %d vrf %s(%u) flags %ld metric %d mtu %d operative %d",
1737 __func__
, ifp
->name
, ifp
->ifindex
, ifp
->vrf
->name
,
1738 ifp
->vrf
->vrf_id
, (long)ifp
->flags
, ifp
->metric
,
1739 ifp
->mtu
, if_is_operative(ifp
));
1742 if (!if_is_operative(ifp
)) {
1743 pim_ifchannel_delete_all(ifp
);
1745 pim_if_addr_del_all() suffices for shutting down IGMP,
1746 but not for shutting down PIM
1748 pim_if_addr_del_all(ifp
);
1751 pim_sock_delete() closes the socket, stops read and timer
1753 and kills all neighbors.
1756 pim_sock_delete(ifp
, "link down");
1761 pim_if_del_vif(ifp
);
1762 pim_ifstat_reset(ifp
);
1768 static int pim_ifp_destroy(struct interface
*ifp
)
1770 if (PIM_DEBUG_ZEBRA
) {
1772 "%s: %s index %d vrf %s(%u) flags %ld metric %d mtu %d operative %d",
1773 __func__
, ifp
->name
, ifp
->ifindex
, ifp
->vrf
->name
,
1774 ifp
->vrf
->vrf_id
, (long)ifp
->flags
, ifp
->metric
,
1775 ifp
->mtu
, if_is_operative(ifp
));
1778 if (!if_is_operative(ifp
))
1779 pim_if_addr_del_all(ifp
);
1782 struct pim_instance
*pim
;
1784 pim
= ifp
->vrf
->info
;
1785 if (pim
&& pim
->vxlan
.term_if
== ifp
)
1786 pim_vxlan_del_term_dev(pim
);
1792 static int pim_if_new_hook(struct interface
*ifp
)
1797 static int pim_if_delete_hook(struct interface
*ifp
)
1805 void pim_iface_init(void)
1807 hook_register_prio(if_add
, 0, pim_if_new_hook
);
1808 hook_register_prio(if_del
, 0, pim_if_delete_hook
);
1810 if_zapi_callbacks(pim_ifp_create
, pim_ifp_up
, pim_ifp_down
,