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
33 #include "pim_instance.h"
34 #include "pim_zebra.h"
35 #include "pim_iface.h"
37 #include "pim_mroute.h"
41 #include "pim_neighbor.h"
42 #include "pim_ifchannel.h"
45 #include "pim_ssmpingd.h"
48 #include "pim_jp_agg.h"
49 #include "pim_igmp_join.h"
50 #include "pim_vxlan.h"
52 static void pim_if_igmp_join_del_all(struct interface
*ifp
);
53 static int igmp_join_sock(const char *ifname
, ifindex_t ifindex
,
54 struct in_addr group_addr
,
55 struct in_addr source_addr
);
57 void pim_if_init(struct pim_instance
*pim
)
61 for (i
= 0; i
< MAXVIFS
; i
++)
62 pim
->iface_vif_index
[i
] = 0;
65 void pim_if_terminate(struct pim_instance
*pim
)
67 struct interface
*ifp
;
69 FOR_ALL_INTERFACES (pim
->vrf
, ifp
) {
70 struct pim_interface
*pim_ifp
= ifp
->info
;
80 static void pim_sec_addr_free(struct pim_secondary_addr
*sec_addr
)
82 XFREE(MTYPE_PIM_SEC_ADDR
, sec_addr
);
85 static int pim_sec_addr_comp(const void *p1
, const void *p2
)
87 const struct pim_secondary_addr
*sec1
= p1
;
88 const struct pim_secondary_addr
*sec2
= p2
;
90 if (sec1
->addr
.family
== AF_INET
&& sec2
->addr
.family
== AF_INET6
)
93 if (sec1
->addr
.family
== AF_INET6
&& sec2
->addr
.family
== AF_INET
)
96 if (sec1
->addr
.family
== AF_INET
) {
97 if (ntohl(sec1
->addr
.u
.prefix4
.s_addr
)
98 < ntohl(sec2
->addr
.u
.prefix4
.s_addr
))
101 if (ntohl(sec1
->addr
.u
.prefix4
.s_addr
)
102 > ntohl(sec2
->addr
.u
.prefix4
.s_addr
))
105 return memcmp(&sec1
->addr
.u
.prefix6
, &sec2
->addr
.u
.prefix6
,
106 sizeof(struct in6_addr
));
112 struct pim_interface
*pim_if_new(struct interface
*ifp
, bool igmp
, bool pim
,
113 bool ispimreg
, bool is_vxlan_term
)
115 struct pim_interface
*pim_ifp
;
120 pim_ifp
= XCALLOC(MTYPE_PIM_INTERFACE
, sizeof(*pim_ifp
));
122 pim_ifp
->options
= 0;
123 pim_ifp
->pim
= pim_get_pim_instance(vrf_to_id(ifp
->vrf
));
124 pim_ifp
->mroute_vif_index
= -1;
126 pim_ifp
->igmp_version
= IGMP_DEFAULT_VERSION
;
127 pim_ifp
->igmp_default_robustness_variable
=
128 IGMP_DEFAULT_ROBUSTNESS_VARIABLE
;
129 pim_ifp
->igmp_default_query_interval
= IGMP_GENERAL_QUERY_INTERVAL
;
130 pim_ifp
->igmp_query_max_response_time_dsec
=
131 IGMP_QUERY_MAX_RESPONSE_TIME_DSEC
;
132 pim_ifp
->igmp_specific_query_max_response_time_dsec
=
133 IGMP_SPECIFIC_QUERY_MAX_RESPONSE_TIME_DSEC
;
134 pim_ifp
->igmp_last_member_query_count
=
135 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;
142 RFC 3376: 8.3. Query Response Interval
143 The number of seconds represented by the [Query Response Interval]
144 must be less than the [Query Interval].
146 zassert(pim_ifp
->igmp_query_max_response_time_dsec
147 < pim_ifp
->igmp_default_query_interval
);
150 PIM_IF_DO_PIM(pim_ifp
->options
);
152 PIM_IF_DO_IGMP(pim_ifp
->options
);
154 PIM_IF_DO_IGMP_LISTEN_ALLROUTERS(pim_ifp
->options
);
156 pim_ifp
->igmp_join_list
= NULL
;
157 pim_ifp
->igmp_socket_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 igmp_sock */
163 pim_ifp
->igmp_socket_list
= list_new();
164 pim_ifp
->igmp_socket_list
->del
= (void (*)(void *))igmp_sock_free
;
166 /* list of struct pim_neighbor */
167 pim_ifp
->pim_neighbor_list
= list_new();
168 pim_ifp
->pim_neighbor_list
->del
= (void (*)(void *))pim_neighbor_free
;
170 pim_ifp
->upstream_switch_list
= list_new();
171 pim_ifp
->upstream_switch_list
->del
=
172 (void (*)(void *))pim_jp_agg_group_list_free
;
173 pim_ifp
->upstream_switch_list
->cmp
= pim_jp_agg_group_list_cmp
;
175 pim_ifp
->sec_addr_list
= list_new();
176 pim_ifp
->sec_addr_list
->del
= (void (*)(void *))pim_sec_addr_free
;
177 pim_ifp
->sec_addr_list
->cmp
=
178 (int (*)(void *, void *))pim_sec_addr_comp
;
180 pim_ifp
->activeactive
= false;
182 RB_INIT(pim_ifchannel_rb
, &pim_ifp
->ifchannel_rb
);
188 pim_if_add_vif(ifp
, ispimreg
, is_vxlan_term
);
193 void pim_if_delete(struct interface
*ifp
)
195 struct pim_interface
*pim_ifp
;
196 struct pim_ifchannel
*ch
;
202 if (pim_ifp
->igmp_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");
213 list_delete(&pim_ifp
->igmp_socket_list
);
214 list_delete(&pim_ifp
->pim_neighbor_list
);
215 list_delete(&pim_ifp
->upstream_switch_list
);
216 list_delete(&pim_ifp
->sec_addr_list
);
218 XFREE(MTYPE_PIM_INTERFACE
, pim_ifp
->boundary_oil_plist
);
220 while (!RB_EMPTY(pim_ifchannel_rb
, &pim_ifp
->ifchannel_rb
)) {
221 ch
= RB_ROOT(pim_ifchannel_rb
, &pim_ifp
->ifchannel_rb
);
223 pim_ifchannel_delete(ch
);
226 XFREE(MTYPE_PIM_INTERFACE
, pim_ifp
);
231 void pim_if_update_could_assert(struct interface
*ifp
)
233 struct pim_interface
*pim_ifp
;
234 struct pim_ifchannel
*ch
;
239 RB_FOREACH (ch
, pim_ifchannel_rb
, &pim_ifp
->ifchannel_rb
) {
240 pim_ifchannel_update_could_assert(ch
);
244 static void pim_if_update_my_assert_metric(struct interface
*ifp
)
246 struct pim_interface
*pim_ifp
;
247 struct pim_ifchannel
*ch
;
252 RB_FOREACH (ch
, pim_ifchannel_rb
, &pim_ifp
->ifchannel_rb
) {
253 pim_ifchannel_update_my_assert_metric(ch
);
257 static void pim_addr_change(struct interface
*ifp
)
259 struct pim_interface
*pim_ifp
;
264 pim_if_dr_election(ifp
); /* router's own DR Priority (addr) changes --
266 pim_if_update_join_desired(pim_ifp
); /* depends on DR */
267 pim_if_update_could_assert(ifp
); /* depends on DR */
268 pim_if_update_my_assert_metric(ifp
); /* depends on could_assert */
269 pim_if_update_assert_tracking_desired(
270 ifp
); /* depends on DR, join_desired */
273 RFC 4601: 4.3.1. Sending Hello Messages
275 1) Before an interface goes down or changes primary IP address, a
276 Hello message with a zero HoldTime should be sent immediately
277 (with the old IP address if the IP address changed).
278 -- FIXME See CAVEAT C13
280 2) After an interface has changed its IP address, it MUST send a
281 Hello message with its new IP address.
284 3) If an interface changes one of its secondary IP addresses, a
285 Hello message with an updated Address_List option and a non-zero
286 HoldTime should be sent immediately.
287 -- FIXME See TODO T31
289 pim_ifp
->pim_ifstat_hello_sent
= 0; /* reset hello counter */
290 if (pim_ifp
->pim_sock_fd
< 0)
292 pim_hello_restart_now(ifp
); /* send hello and restart timer */
295 static int detect_primary_address_change(struct interface
*ifp
,
296 int force_prim_as_any
,
299 struct pim_interface
*pim_ifp
= ifp
->info
;
300 struct in_addr new_prim_addr
;
303 if (force_prim_as_any
)
304 new_prim_addr
.s_addr
= INADDR_ANY
;
306 new_prim_addr
= pim_find_primary_addr(ifp
);
308 changed
= new_prim_addr
.s_addr
!= pim_ifp
->primary_address
.s_addr
;
310 if (PIM_DEBUG_ZEBRA
) {
311 char new_prim_str
[INET_ADDRSTRLEN
];
312 char old_prim_str
[INET_ADDRSTRLEN
];
313 pim_inet4_dump("<new?>", new_prim_addr
, new_prim_str
,
314 sizeof(new_prim_str
));
315 pim_inet4_dump("<old?>", pim_ifp
->primary_address
, old_prim_str
,
316 sizeof(old_prim_str
));
317 zlog_debug("%s: old=%s new=%s on interface %s: %s",
318 __PRETTY_FUNCTION__
, old_prim_str
, new_prim_str
,
319 ifp
->name
, changed
? "changed" : "unchanged");
323 pim_ifp
->primary_address
= new_prim_addr
;
329 static struct pim_secondary_addr
*
330 pim_sec_addr_find(struct pim_interface
*pim_ifp
, struct prefix
*addr
)
332 struct pim_secondary_addr
*sec_addr
;
333 struct listnode
*node
;
335 for (ALL_LIST_ELEMENTS_RO(pim_ifp
->sec_addr_list
, node
, sec_addr
)) {
336 if (prefix_cmp(&sec_addr
->addr
, addr
)) {
344 static void pim_sec_addr_del(struct pim_interface
*pim_ifp
,
345 struct pim_secondary_addr
*sec_addr
)
347 listnode_delete(pim_ifp
->sec_addr_list
, sec_addr
);
348 pim_sec_addr_free(sec_addr
);
351 static int pim_sec_addr_add(struct pim_interface
*pim_ifp
, struct prefix
*addr
)
354 struct pim_secondary_addr
*sec_addr
;
356 sec_addr
= pim_sec_addr_find(pim_ifp
, addr
);
358 sec_addr
->flags
&= ~PIM_SEC_ADDRF_STALE
;
362 sec_addr
= XCALLOC(MTYPE_PIM_SEC_ADDR
, sizeof(*sec_addr
));
365 sec_addr
->addr
= *addr
;
366 listnode_add_sort(pim_ifp
->sec_addr_list
, sec_addr
);
371 static int pim_sec_addr_del_all(struct pim_interface
*pim_ifp
)
375 if (!list_isempty(pim_ifp
->sec_addr_list
)) {
377 /* remove all nodes and free up the list itself */
378 list_delete_all_node(pim_ifp
->sec_addr_list
);
384 static int pim_sec_addr_update(struct interface
*ifp
)
386 struct pim_interface
*pim_ifp
= ifp
->info
;
387 struct connected
*ifc
;
388 struct listnode
*node
;
389 struct listnode
*nextnode
;
390 struct pim_secondary_addr
*sec_addr
;
393 for (ALL_LIST_ELEMENTS_RO(pim_ifp
->sec_addr_list
, node
, sec_addr
)) {
394 sec_addr
->flags
|= PIM_SEC_ADDRF_STALE
;
397 for (ALL_LIST_ELEMENTS_RO(ifp
->connected
, node
, ifc
)) {
398 struct prefix
*p
= ifc
->address
;
400 if (PIM_INADDR_IS_ANY(p
->u
.prefix4
)) {
404 if (pim_ifp
->primary_address
.s_addr
== p
->u
.prefix4
.s_addr
) {
405 /* don't add the primary address into the secondary
410 if (pim_sec_addr_add(pim_ifp
, p
)) {
415 /* Drop stale entries */
416 for (ALL_LIST_ELEMENTS(pim_ifp
->sec_addr_list
, node
, nextnode
,
418 if (sec_addr
->flags
& PIM_SEC_ADDRF_STALE
) {
419 pim_sec_addr_del(pim_ifp
, sec_addr
);
427 static int detect_secondary_address_change(struct interface
*ifp
,
428 int force_prim_as_any
,
431 struct pim_interface
*pim_ifp
= ifp
->info
;
434 if (force_prim_as_any
) {
435 /* if primary address is being forced to zero just flush the
436 * secondary address list */
437 changed
= pim_sec_addr_del_all(pim_ifp
);
439 /* re-evaluate the secondary address list */
440 changed
= pim_sec_addr_update(ifp
);
446 static void detect_address_change(struct interface
*ifp
, int force_prim_as_any
,
450 struct pim_interface
*pim_ifp
;
456 if (detect_primary_address_change(ifp
, force_prim_as_any
, caller
)) {
460 if (detect_secondary_address_change(ifp
, force_prim_as_any
, caller
)) {
466 if (!PIM_IF_TEST_PIM(pim_ifp
->options
)) {
470 pim_addr_change(ifp
);
473 /* XXX: if we have unnumbered interfaces we need to run detect address
474 * address change on all of them when the lo address changes */
477 int pim_update_source_set(struct interface
*ifp
, struct in_addr source
)
479 struct pim_interface
*pim_ifp
= ifp
->info
;
482 return PIM_IFACE_NOT_FOUND
;
485 if (pim_ifp
->update_source
.s_addr
== source
.s_addr
) {
486 return PIM_UPDATE_SOURCE_DUP
;
489 pim_ifp
->update_source
= source
;
490 detect_address_change(ifp
, 0 /* force_prim_as_any */,
491 __PRETTY_FUNCTION__
);
496 void pim_if_addr_add(struct connected
*ifc
)
498 struct pim_interface
*pim_ifp
;
499 struct interface
*ifp
;
500 struct in_addr ifaddr
;
510 if (!if_is_operative(ifp
))
513 if (PIM_DEBUG_ZEBRA
) {
515 prefix2str(ifc
->address
, buf
, BUFSIZ
);
516 zlog_debug("%s: %s ifindex=%d connected IP address %s %s",
517 __PRETTY_FUNCTION__
, ifp
->name
, ifp
->ifindex
, buf
,
518 CHECK_FLAG(ifc
->flags
, ZEBRA_IFA_SECONDARY
)
523 ifaddr
= ifc
->address
->u
.prefix4
;
525 detect_address_change(ifp
, 0, __PRETTY_FUNCTION__
);
527 // if (ifc->address->family != AF_INET)
530 if (PIM_IF_TEST_IGMP(pim_ifp
->options
)) {
531 struct igmp_sock
*igmp
;
533 /* lookup IGMP socket */
534 igmp
= pim_igmp_sock_lookup_ifaddr(pim_ifp
->igmp_socket_list
,
537 /* if addr new, add IGMP socket */
538 if (ifc
->address
->family
== AF_INET
)
539 pim_igmp_sock_add(pim_ifp
->igmp_socket_list
,
541 } else if (igmp
->mtrace_only
) {
542 igmp_sock_delete(igmp
);
543 pim_igmp_sock_add(pim_ifp
->igmp_socket_list
, ifaddr
,
547 /* Replay Static IGMP groups */
548 if (pim_ifp
->igmp_join_list
) {
549 struct listnode
*node
;
550 struct listnode
*nextnode
;
551 struct igmp_join
*ij
;
554 for (ALL_LIST_ELEMENTS(pim_ifp
->igmp_join_list
, node
,
556 /* Close socket and reopen with Source and Group
559 join_fd
= igmp_join_sock(
560 ifp
->name
, ifp
->ifindex
, ij
->group_addr
,
563 char group_str
[INET_ADDRSTRLEN
];
564 char source_str
[INET_ADDRSTRLEN
];
565 pim_inet4_dump("<grp?>", ij
->group_addr
,
569 "<src?>", ij
->source_addr
,
570 source_str
, sizeof(source_str
));
572 "%s: igmp_join_sock() failure for IGMP group %s source %s on interface %s",
573 __PRETTY_FUNCTION__
, group_str
,
574 source_str
, ifp
->name
);
577 ij
->sock_fd
= join_fd
;
582 struct igmp_sock
*igmp
;
584 /* lookup IGMP socket */
585 igmp
= pim_igmp_sock_lookup_ifaddr(pim_ifp
->igmp_socket_list
,
587 if (ifc
->address
->family
== AF_INET
) {
589 igmp_sock_delete(igmp
);
590 /* if addr new, add IGMP socket */
591 pim_igmp_sock_add(pim_ifp
->igmp_socket_list
, ifaddr
,
594 } /* igmp mtrace only */
596 if (PIM_IF_TEST_PIM(pim_ifp
->options
)) {
598 if (PIM_INADDR_ISNOT_ANY(pim_ifp
->primary_address
)) {
600 /* Interface has a valid socket ? */
601 if (pim_ifp
->pim_sock_fd
< 0) {
602 if (pim_sock_add(ifp
)) {
604 "Failure creating PIM socket for interface %s",
608 struct pim_nexthop_cache
*pnc
= NULL
;
610 struct zclient
*zclient
= NULL
;
612 zclient
= pim_zebra_zclient_get();
613 /* RP config might come prior to (local RP's interface)
615 In this case, pnc would not have pim enabled
617 Once Interface is UP and pim info is available,
619 with RNH address to receive update and add the
620 interface as nexthop. */
621 memset(&rpf
, 0, sizeof(struct pim_rpf
));
622 rpf
.rpf_addr
.family
= AF_INET
;
623 rpf
.rpf_addr
.prefixlen
= IPV4_MAX_BITLEN
;
624 rpf
.rpf_addr
.u
.prefix4
= ifc
->address
->u
.prefix4
;
625 pnc
= pim_nexthop_cache_find(pim_ifp
->pim
, &rpf
);
627 pim_sendmsg_zebra_rnh(pim_ifp
->pim
, zclient
,
629 ZEBRA_NEXTHOP_REGISTER
);
634 PIM or IGMP is enabled on interface, and there is at least one
635 address assigned, then try to create a vif_index.
637 if (pim_ifp
->mroute_vif_index
< 0) {
638 pim_if_add_vif(ifp
, false, false /*vxlan_term*/);
640 pim_ifchannel_scan_forward_start(ifp
);
643 static void pim_if_addr_del_igmp(struct connected
*ifc
)
645 struct pim_interface
*pim_ifp
= ifc
->ifp
->info
;
646 struct igmp_sock
*igmp
;
647 struct in_addr ifaddr
;
649 if (ifc
->address
->family
!= AF_INET
) {
650 /* non-IPv4 address */
655 /* IGMP not enabled on interface */
659 ifaddr
= ifc
->address
->u
.prefix4
;
661 /* lookup IGMP socket */
662 igmp
= pim_igmp_sock_lookup_ifaddr(pim_ifp
->igmp_socket_list
, ifaddr
);
664 /* if addr found, del IGMP socket */
665 igmp_sock_delete(igmp
);
669 static void pim_if_addr_del_pim(struct connected
*ifc
)
671 struct pim_interface
*pim_ifp
= ifc
->ifp
->info
;
673 if (ifc
->address
->family
!= AF_INET
) {
674 /* non-IPv4 address */
679 /* PIM not enabled on interface */
683 if (PIM_INADDR_ISNOT_ANY(pim_ifp
->primary_address
)) {
684 /* Interface keeps a valid primary address */
688 if (pim_ifp
->pim_sock_fd
< 0) {
689 /* Interface does not hold a valid socket any longer */
694 pim_sock_delete() closes the socket, stops read and timer threads,
695 and kills all neighbors.
697 pim_sock_delete(ifc
->ifp
,
698 "last address has been removed from interface");
701 void pim_if_addr_del(struct connected
*ifc
, int force_prim_as_any
)
703 struct interface
*ifp
;
709 if (PIM_DEBUG_ZEBRA
) {
711 prefix2str(ifc
->address
, buf
, BUFSIZ
);
712 zlog_debug("%s: %s ifindex=%d disconnected IP address %s %s",
713 __PRETTY_FUNCTION__
, ifp
->name
, ifp
->ifindex
, buf
,
714 CHECK_FLAG(ifc
->flags
, ZEBRA_IFA_SECONDARY
)
719 detect_address_change(ifp
, force_prim_as_any
, __PRETTY_FUNCTION__
);
721 pim_if_addr_del_igmp(ifc
);
722 pim_if_addr_del_pim(ifc
);
725 void pim_if_addr_add_all(struct interface
*ifp
)
727 struct connected
*ifc
;
728 struct listnode
*node
;
729 struct listnode
*nextnode
;
732 struct pim_interface
*pim_ifp
= ifp
->info
;
735 /* PIM/IGMP enabled ? */
739 for (ALL_LIST_ELEMENTS(ifp
->connected
, node
, nextnode
, ifc
)) {
740 struct prefix
*p
= ifc
->address
;
742 if (p
->family
!= AF_INET
)
746 pim_if_addr_add(ifc
);
749 if (!v4_addrs
&& v6_addrs
&& !if_is_loopback(ifp
)) {
750 if (PIM_IF_TEST_PIM(pim_ifp
->options
)) {
752 /* Interface has a valid primary address ? */
753 if (PIM_INADDR_ISNOT_ANY(pim_ifp
->primary_address
)) {
755 /* Interface has a valid socket ? */
756 if (pim_ifp
->pim_sock_fd
< 0) {
757 if (pim_sock_add(ifp
)) {
759 "Failure creating PIM socket for interface %s",
767 * PIM or IGMP is enabled on interface, and there is at least one
768 * address assigned, then try to create a vif_index.
770 if (pim_ifp
->mroute_vif_index
< 0) {
771 pim_if_add_vif(ifp
, false, false /*vxlan_term*/);
773 pim_ifchannel_scan_forward_start(ifp
);
775 pim_rp_setup(pim_ifp
->pim
);
776 pim_rp_check_on_if_add(pim_ifp
);
779 void pim_if_addr_del_all(struct interface
*ifp
)
781 struct connected
*ifc
;
782 struct listnode
*node
;
783 struct listnode
*nextnode
;
784 struct vrf
*vrf
= ifp
->vrf
;
785 struct pim_instance
*pim
;
791 /* PIM/IGMP enabled ? */
795 for (ALL_LIST_ELEMENTS(ifp
->connected
, node
, nextnode
, ifc
)) {
796 struct prefix
*p
= ifc
->address
;
798 if (p
->family
!= AF_INET
)
801 pim_if_addr_del(ifc
, 1 /* force_prim_as_any=true */);
805 pim_i_am_rp_re_evaluate(pim
);
808 void pim_if_addr_del_all_igmp(struct interface
*ifp
)
810 struct connected
*ifc
;
811 struct listnode
*node
;
812 struct listnode
*nextnode
;
814 /* PIM/IGMP enabled ? */
818 for (ALL_LIST_ELEMENTS(ifp
->connected
, node
, nextnode
, ifc
)) {
819 struct prefix
*p
= ifc
->address
;
821 if (p
->family
!= AF_INET
)
824 pim_if_addr_del_igmp(ifc
);
828 void pim_if_addr_del_all_pim(struct interface
*ifp
)
830 struct connected
*ifc
;
831 struct listnode
*node
;
832 struct listnode
*nextnode
;
834 /* PIM/IGMP enabled ? */
838 for (ALL_LIST_ELEMENTS(ifp
->connected
, node
, nextnode
, ifc
)) {
839 struct prefix
*p
= ifc
->address
;
841 if (p
->family
!= AF_INET
)
844 pim_if_addr_del_pim(ifc
);
848 struct in_addr
pim_find_primary_addr(struct interface
*ifp
)
850 struct connected
*ifc
;
851 struct listnode
*node
;
852 struct in_addr addr
= {0};
855 struct pim_interface
*pim_ifp
= ifp
->info
;
856 struct vrf
*vrf
= ifp
->vrf
;
861 if (pim_ifp
&& PIM_INADDR_ISNOT_ANY(pim_ifp
->update_source
)) {
862 return pim_ifp
->update_source
;
865 for (ALL_LIST_ELEMENTS_RO(ifp
->connected
, node
, ifc
)) {
866 struct prefix
*p
= ifc
->address
;
868 if (p
->family
!= AF_INET
) {
873 if (PIM_INADDR_IS_ANY(p
->u
.prefix4
)) {
875 "%s: null IPv4 address connected to interface %s",
876 __PRETTY_FUNCTION__
, ifp
->name
);
882 if (CHECK_FLAG(ifc
->flags
, ZEBRA_IFA_SECONDARY
))
889 * If we have no v4_addrs and v6 is configured
890 * We probably are using unnumbered
891 * So let's grab the loopbacks v4 address
892 * and use that as the primary address
894 if (!v4_addrs
&& v6_addrs
&& !if_is_loopback(ifp
)) {
895 struct interface
*lo_ifp
;
896 // DBS - Come back and check here
897 if (!ifp
->vrf
|| ifp
->vrf
->vrf_id
== VRF_DEFAULT
)
898 lo_ifp
= if_lookup_by_name("lo", vrf
);
900 lo_ifp
= if_lookup_by_name(vrf
->name
, vrf
);
903 return pim_find_primary_addr(lo_ifp
);
906 addr
.s_addr
= PIM_NET_INADDR_ANY
;
911 static int pim_iface_next_vif_index(struct interface
*ifp
)
913 struct pim_interface
*pim_ifp
= ifp
->info
;
914 struct pim_instance
*pim
= pim_ifp
->pim
;
918 * The pimreg vif is always going to be in index 0
921 if (ifp
->ifindex
== PIM_OIF_PIM_REGISTER_VIF
)
924 for (i
= 1; i
< MAXVIFS
; i
++) {
925 if (pim
->iface_vif_index
[i
] == 0)
932 pim_if_add_vif() uses ifindex as vif_index
934 see also pim_if_find_vifindex_by_ifindex()
936 int pim_if_add_vif(struct interface
*ifp
, bool ispimreg
, bool is_vxlan_term
)
938 struct pim_interface
*pim_ifp
= ifp
->info
;
939 struct in_addr ifaddr
;
940 unsigned char flags
= 0;
944 if (pim_ifp
->mroute_vif_index
> 0) {
945 zlog_warn("%s: vif_index=%d > 0 on interface %s ifindex=%d",
946 __PRETTY_FUNCTION__
, pim_ifp
->mroute_vif_index
,
947 ifp
->name
, ifp
->ifindex
);
951 if (ifp
->ifindex
< 0) {
952 zlog_warn("%s: ifindex=%d < 1 on interface %s",
953 __PRETTY_FUNCTION__
, ifp
->ifindex
, ifp
->name
);
957 ifaddr
= pim_ifp
->primary_address
;
958 if (!ispimreg
&& !is_vxlan_term
&& PIM_INADDR_IS_ANY(ifaddr
)) {
960 "%s: could not get address for interface %s ifindex=%d",
961 __PRETTY_FUNCTION__
, ifp
->name
, ifp
->ifindex
);
965 pim_ifp
->mroute_vif_index
= pim_iface_next_vif_index(ifp
);
967 if (pim_ifp
->mroute_vif_index
>= MAXVIFS
) {
969 "%s: Attempting to configure more than MAXVIFS=%d on pim enabled interface %s",
970 __PRETTY_FUNCTION__
, MAXVIFS
, ifp
->name
);
974 if (ifp
->ifindex
== PIM_OIF_PIM_REGISTER_VIF
)
975 flags
= VIFF_REGISTER
;
976 #ifdef VIFF_USE_IFINDEX
978 flags
= VIFF_USE_IFINDEX
;
981 if (pim_mroute_add_vif(ifp
, ifaddr
, flags
)) {
982 /* pim_mroute_add_vif reported error */
986 pim_ifp
->pim
->iface_vif_index
[pim_ifp
->mroute_vif_index
] = 1;
988 /* if the device qualifies as pim_vxlan iif/oif update vxlan entries */
989 pim_vxlan_add_vif(ifp
);
994 int pim_if_del_vif(struct interface
*ifp
)
996 struct pim_interface
*pim_ifp
= ifp
->info
;
998 if (pim_ifp
->mroute_vif_index
< 1) {
999 zlog_warn("%s: vif_index=%d < 1 on interface %s ifindex=%d",
1000 __PRETTY_FUNCTION__
, pim_ifp
->mroute_vif_index
,
1001 ifp
->name
, ifp
->ifindex
);
1005 /* if the device was a pim_vxlan iif/oif update vxlan mroute entries */
1006 pim_vxlan_del_vif(ifp
);
1008 pim_mroute_del_vif(ifp
);
1013 pim_ifp
->pim
->iface_vif_index
[pim_ifp
->mroute_vif_index
] = 0;
1015 pim_ifp
->mroute_vif_index
= -1;
1021 struct interface
*pim_if_find_by_vif_index(struct pim_instance
*pim
,
1022 ifindex_t vif_index
)
1024 struct interface
*ifp
;
1026 FOR_ALL_INTERFACES (pim
->vrf
, ifp
) {
1028 struct pim_interface
*pim_ifp
;
1029 pim_ifp
= ifp
->info
;
1031 if (vif_index
== pim_ifp
->mroute_vif_index
)
1040 pim_if_add_vif() uses ifindex as vif_index
1042 int pim_if_find_vifindex_by_ifindex(struct pim_instance
*pim
, ifindex_t ifindex
)
1044 struct pim_interface
*pim_ifp
;
1045 struct interface
*ifp
;
1047 ifp
= if_lookup_by_index(ifindex
, pim
->vrf_id
);
1048 if (!ifp
|| !ifp
->info
)
1050 pim_ifp
= ifp
->info
;
1052 return pim_ifp
->mroute_vif_index
;
1055 int pim_if_lan_delay_enabled(struct interface
*ifp
)
1057 struct pim_interface
*pim_ifp
;
1059 pim_ifp
= ifp
->info
;
1061 zassert(pim_ifp
->pim_number_of_nonlandelay_neighbors
>= 0);
1063 return pim_ifp
->pim_number_of_nonlandelay_neighbors
== 0;
1066 uint16_t pim_if_effective_propagation_delay_msec(struct interface
*ifp
)
1068 if (pim_if_lan_delay_enabled(ifp
)) {
1069 struct pim_interface
*pim_ifp
;
1070 pim_ifp
= ifp
->info
;
1071 return pim_ifp
->pim_neighbors_highest_propagation_delay_msec
;
1073 return PIM_DEFAULT_PROPAGATION_DELAY_MSEC
;
1077 uint16_t pim_if_effective_override_interval_msec(struct interface
*ifp
)
1079 if (pim_if_lan_delay_enabled(ifp
)) {
1080 struct pim_interface
*pim_ifp
;
1081 pim_ifp
= ifp
->info
;
1082 return pim_ifp
->pim_neighbors_highest_override_interval_msec
;
1084 return PIM_DEFAULT_OVERRIDE_INTERVAL_MSEC
;
1088 int pim_if_t_override_msec(struct interface
*ifp
)
1090 int effective_override_interval_msec
;
1091 int t_override_msec
;
1093 effective_override_interval_msec
=
1094 pim_if_effective_override_interval_msec(ifp
);
1096 t_override_msec
= random() % (effective_override_interval_msec
+ 1);
1098 return t_override_msec
;
1101 uint16_t pim_if_jp_override_interval_msec(struct interface
*ifp
)
1103 return pim_if_effective_propagation_delay_msec(ifp
)
1104 + pim_if_effective_override_interval_msec(ifp
);
1108 RFC 4601: 4.1.6. State Summarization Macros
1110 The function NBR( I, A ) uses information gathered through PIM Hello
1111 messages to map the IP address A of a directly connected PIM
1112 neighbor router on interface I to the primary IP address of the same
1113 router (Section 4.3.4). The primary IP address of a neighbor is the
1114 address that it uses as the source of its PIM Hello messages.
1116 struct pim_neighbor
*pim_if_find_neighbor(struct interface
*ifp
,
1117 struct in_addr addr
)
1119 struct listnode
*neighnode
;
1120 struct pim_neighbor
*neigh
;
1121 struct pim_interface
*pim_ifp
;
1126 pim_ifp
= ifp
->info
;
1128 zlog_warn("%s: multicast not enabled on interface %s",
1129 __PRETTY_FUNCTION__
, ifp
->name
);
1135 p
.prefixlen
= IPV4_MAX_PREFIXLEN
;
1137 for (ALL_LIST_ELEMENTS_RO(pim_ifp
->pim_neighbor_list
, neighnode
,
1140 /* primary address ? */
1141 if (neigh
->source_addr
.s_addr
== addr
.s_addr
)
1144 /* secondary address ? */
1145 if (pim_neighbor_find_secondary(neigh
, &p
))
1149 if (PIM_DEBUG_PIM_TRACE
) {
1150 char addr_str
[INET_ADDRSTRLEN
];
1151 pim_inet4_dump("<addr?>", addr
, addr_str
, sizeof(addr_str
));
1153 "%s: neighbor not found for address %s on interface %s",
1154 __PRETTY_FUNCTION__
, addr_str
, ifp
->name
);
1160 long pim_if_t_suppressed_msec(struct interface
*ifp
)
1162 struct pim_interface
*pim_ifp
;
1163 long t_suppressed_msec
;
1164 uint32_t ramount
= 0;
1166 pim_ifp
= ifp
->info
;
1169 /* join suppression disabled ? */
1170 if (PIM_IF_TEST_PIM_CAN_DISABLE_JOIN_SUPRESSION(pim_ifp
->options
))
1173 /* t_suppressed = t_periodic * rand(1.1, 1.4) */
1174 ramount
= 1100 + (random() % (1400 - 1100 + 1));
1175 t_suppressed_msec
= router
->t_periodic
* ramount
;
1177 return t_suppressed_msec
;
1180 static void igmp_join_free(struct igmp_join
*ij
)
1182 XFREE(MTYPE_PIM_IGMP_JOIN
, ij
);
1185 static struct igmp_join
*igmp_join_find(struct list
*join_list
,
1186 struct in_addr group_addr
,
1187 struct in_addr source_addr
)
1189 struct listnode
*node
;
1190 struct igmp_join
*ij
;
1194 for (ALL_LIST_ELEMENTS_RO(join_list
, node
, ij
)) {
1195 if ((group_addr
.s_addr
== ij
->group_addr
.s_addr
)
1196 && (source_addr
.s_addr
== ij
->source_addr
.s_addr
))
1203 static int igmp_join_sock(const char *ifname
, ifindex_t ifindex
,
1204 struct in_addr group_addr
, struct in_addr source_addr
)
1208 join_fd
= pim_socket_raw(IPPROTO_IGMP
);
1213 if (pim_igmp_join_source(join_fd
, ifindex
, group_addr
, source_addr
)) {
1214 char group_str
[INET_ADDRSTRLEN
];
1215 char source_str
[INET_ADDRSTRLEN
];
1216 pim_inet4_dump("<grp?>", group_addr
, group_str
,
1218 pim_inet4_dump("<src?>", source_addr
, source_str
,
1219 sizeof(source_str
));
1221 "%s: setsockopt(fd=%d) failure for IGMP group %s source %s ifindex %d on interface %s: errno=%d: %s",
1222 __PRETTY_FUNCTION__
, join_fd
, group_str
, source_str
,
1223 ifindex
, ifname
, errno
, safe_strerror(errno
));
1232 static struct igmp_join
*igmp_join_new(struct interface
*ifp
,
1233 struct in_addr group_addr
,
1234 struct in_addr source_addr
)
1236 struct pim_interface
*pim_ifp
;
1237 struct igmp_join
*ij
;
1240 pim_ifp
= ifp
->info
;
1243 join_fd
= igmp_join_sock(ifp
->name
, ifp
->ifindex
, group_addr
,
1246 char group_str
[INET_ADDRSTRLEN
];
1247 char source_str
[INET_ADDRSTRLEN
];
1249 pim_inet4_dump("<grp?>", group_addr
, group_str
,
1251 pim_inet4_dump("<src?>", source_addr
, source_str
,
1252 sizeof(source_str
));
1254 "%s: igmp_join_sock() failure for IGMP group %s source %s on interface %s",
1255 __PRETTY_FUNCTION__
, group_str
, source_str
, ifp
->name
);
1259 ij
= XCALLOC(MTYPE_PIM_IGMP_JOIN
, sizeof(*ij
));
1261 ij
->sock_fd
= join_fd
;
1262 ij
->group_addr
= group_addr
;
1263 ij
->source_addr
= source_addr
;
1264 ij
->sock_creation
= pim_time_monotonic_sec();
1266 listnode_add(pim_ifp
->igmp_join_list
, ij
);
1271 ferr_r
pim_if_igmp_join_add(struct interface
*ifp
, struct in_addr group_addr
,
1272 struct in_addr source_addr
)
1274 struct pim_interface
*pim_ifp
;
1275 struct igmp_join
*ij
;
1277 pim_ifp
= ifp
->info
;
1279 return ferr_cfg_invalid("multicast not enabled on interface %s",
1283 if (!pim_ifp
->igmp_join_list
) {
1284 pim_ifp
->igmp_join_list
= list_new();
1285 pim_ifp
->igmp_join_list
->del
= (void (*)(void *))igmp_join_free
;
1288 ij
= igmp_join_find(pim_ifp
->igmp_join_list
, group_addr
, source_addr
);
1290 /* This interface has already been configured to join this IGMP group
1296 ij
= igmp_join_new(ifp
, group_addr
, source_addr
);
1298 return ferr_cfg_invalid(
1299 "Failure to create new join data structure, see log file for more information");
1302 if (PIM_DEBUG_IGMP_EVENTS
) {
1303 char group_str
[INET_ADDRSTRLEN
];
1304 char source_str
[INET_ADDRSTRLEN
];
1305 pim_inet4_dump("<grp?>", group_addr
, group_str
,
1307 pim_inet4_dump("<src?>", source_addr
, source_str
,
1308 sizeof(source_str
));
1310 "%s: issued static igmp join for channel (S,G)=(%s,%s) on interface %s",
1311 __PRETTY_FUNCTION__
, source_str
, group_str
, ifp
->name
);
1318 int pim_if_igmp_join_del(struct interface
*ifp
, struct in_addr group_addr
,
1319 struct in_addr source_addr
)
1321 struct pim_interface
*pim_ifp
;
1322 struct igmp_join
*ij
;
1324 pim_ifp
= ifp
->info
;
1326 zlog_warn("%s: multicast not enabled on interface %s",
1327 __PRETTY_FUNCTION__
, ifp
->name
);
1331 if (!pim_ifp
->igmp_join_list
) {
1332 zlog_warn("%s: no IGMP join on interface %s",
1333 __PRETTY_FUNCTION__
, ifp
->name
);
1337 ij
= igmp_join_find(pim_ifp
->igmp_join_list
, group_addr
, source_addr
);
1339 char group_str
[INET_ADDRSTRLEN
];
1340 char source_str
[INET_ADDRSTRLEN
];
1341 pim_inet4_dump("<grp?>", group_addr
, group_str
,
1343 pim_inet4_dump("<src?>", source_addr
, source_str
,
1344 sizeof(source_str
));
1346 "%s: could not find IGMP group %s source %s on interface %s",
1347 __PRETTY_FUNCTION__
, group_str
, source_str
, ifp
->name
);
1351 if (close(ij
->sock_fd
)) {
1352 char group_str
[INET_ADDRSTRLEN
];
1353 char source_str
[INET_ADDRSTRLEN
];
1354 pim_inet4_dump("<grp?>", group_addr
, group_str
,
1356 pim_inet4_dump("<src?>", source_addr
, source_str
,
1357 sizeof(source_str
));
1359 "%s: failure closing sock_fd=%d for IGMP group %s source %s on interface %s: errno=%d: %s",
1360 __PRETTY_FUNCTION__
, ij
->sock_fd
, group_str
, source_str
,
1361 ifp
->name
, errno
, safe_strerror(errno
));
1364 listnode_delete(pim_ifp
->igmp_join_list
, ij
);
1366 if (listcount(pim_ifp
->igmp_join_list
) < 1) {
1367 list_delete(&pim_ifp
->igmp_join_list
);
1368 pim_ifp
->igmp_join_list
= 0;
1374 static void pim_if_igmp_join_del_all(struct interface
*ifp
)
1376 struct pim_interface
*pim_ifp
;
1377 struct listnode
*node
;
1378 struct listnode
*nextnode
;
1379 struct igmp_join
*ij
;
1381 pim_ifp
= ifp
->info
;
1383 zlog_warn("%s: multicast not enabled on interface %s",
1384 __PRETTY_FUNCTION__
, ifp
->name
);
1388 if (!pim_ifp
->igmp_join_list
)
1391 for (ALL_LIST_ELEMENTS(pim_ifp
->igmp_join_list
, node
, nextnode
, ij
))
1392 pim_if_igmp_join_del(ifp
, ij
->group_addr
, ij
->source_addr
);
1398 Transitions from "I am Assert Loser" State
1400 Current Winner's GenID Changes or NLT Expires
1402 The Neighbor Liveness Timer associated with the current winner
1403 expires or we receive a Hello message from the current winner
1404 reporting a different GenID from the one it previously reported.
1405 This indicates that the current winner's interface or router has
1406 gone down (and may have come back up), and so we must assume it no
1407 longer knows it was the winner.
1409 void pim_if_assert_on_neighbor_down(struct interface
*ifp
,
1410 struct in_addr neigh_addr
)
1412 struct pim_interface
*pim_ifp
;
1413 struct pim_ifchannel
*ch
;
1415 pim_ifp
= ifp
->info
;
1418 RB_FOREACH (ch
, pim_ifchannel_rb
, &pim_ifp
->ifchannel_rb
) {
1419 /* Is (S,G,I) assert loser ? */
1420 if (ch
->ifassert_state
!= PIM_IFASSERT_I_AM_LOSER
)
1422 /* Dead neighbor was winner ? */
1423 if (ch
->ifassert_winner
.s_addr
!= neigh_addr
.s_addr
)
1426 assert_action_a5(ch
);
1430 void pim_if_update_join_desired(struct pim_interface
*pim_ifp
)
1432 struct pim_ifchannel
*ch
;
1434 /* clear off flag from interface's upstreams */
1435 RB_FOREACH (ch
, pim_ifchannel_rb
, &pim_ifp
->ifchannel_rb
) {
1436 PIM_UPSTREAM_FLAG_UNSET_DR_JOIN_DESIRED_UPDATED(
1437 ch
->upstream
->flags
);
1440 /* scan per-interface (S,G,I) state on this I interface */
1441 RB_FOREACH (ch
, pim_ifchannel_rb
, &pim_ifp
->ifchannel_rb
) {
1442 struct pim_upstream
*up
= ch
->upstream
;
1444 if (PIM_UPSTREAM_FLAG_TEST_DR_JOIN_DESIRED_UPDATED(up
->flags
))
1447 /* update join_desired for the global (S,G) state */
1448 pim_upstream_update_join_desired(pim_ifp
->pim
, up
);
1449 PIM_UPSTREAM_FLAG_SET_DR_JOIN_DESIRED_UPDATED(up
->flags
);
1453 void pim_if_update_assert_tracking_desired(struct interface
*ifp
)
1455 struct pim_interface
*pim_ifp
;
1456 struct pim_ifchannel
*ch
;
1458 pim_ifp
= ifp
->info
;
1462 RB_FOREACH (ch
, pim_ifchannel_rb
, &pim_ifp
->ifchannel_rb
) {
1463 pim_ifchannel_update_assert_tracking_desired(ch
);
1468 * PIM wants to have an interface pointer for everything it does.
1469 * The pimreg is a special interface that we have that is not
1470 * quite an inteface but a VIF is created for it.
1472 void pim_if_create_pimreg(struct pim_instance
*pim
)
1474 char pimreg_name
[INTERFACE_NAMSIZ
];
1476 if (!pim
->regiface
) {
1477 if (pim
->vrf_id
== VRF_DEFAULT
)
1478 strlcpy(pimreg_name
, "pimreg", sizeof(pimreg_name
));
1480 snprintf(pimreg_name
, sizeof(pimreg_name
), "pimreg%u",
1481 pim
->vrf
->data
.l
.table_id
);
1483 pim
->regiface
= if_create(pimreg_name
, pim
->vrf
);
1484 pim
->regiface
->ifindex
= PIM_OIF_PIM_REGISTER_VIF
;
1486 pim_if_new(pim
->regiface
, false, false, true,
1487 false /*vxlan_term*/);
1491 int pim_if_connected_to_source(struct interface
*ifp
, struct in_addr src
)
1493 struct listnode
*cnode
;
1494 struct connected
*c
;
1502 p
.prefixlen
= IPV4_MAX_BITLEN
;
1504 for (ALL_LIST_ELEMENTS_RO(ifp
->connected
, cnode
, c
)) {
1505 if ((c
->address
->family
== AF_INET
)
1506 && prefix_match(CONNECTED_PREFIX(c
), &p
)) {
1514 bool pim_if_is_vrf_device(struct interface
*ifp
)
1522 int pim_if_ifchannel_count(struct pim_interface
*pim_ifp
)
1524 struct pim_ifchannel
*ch
;
1527 RB_FOREACH (ch
, pim_ifchannel_rb
, &pim_ifp
->ifchannel_rb
) {