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(ifp
->vrf_id
);
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
;
135 /* BSM config on interface: TRUE by default */
136 pim_ifp
->bsm_enable
= true;
137 pim_ifp
->ucast_bsm_accept
= true;
140 RFC 3376: 8.3. Query Response Interval
141 The number of seconds represented by the [Query Response Interval]
142 must be less than the [Query Interval].
144 zassert(pim_ifp
->igmp_query_max_response_time_dsec
145 < pim_ifp
->igmp_default_query_interval
);
148 PIM_IF_DO_PIM(pim_ifp
->options
);
150 PIM_IF_DO_IGMP(pim_ifp
->options
);
152 PIM_IF_DO_IGMP_LISTEN_ALLROUTERS(pim_ifp
->options
);
154 pim_ifp
->igmp_join_list
= NULL
;
155 pim_ifp
->igmp_socket_list
= NULL
;
156 pim_ifp
->pim_neighbor_list
= NULL
;
157 pim_ifp
->upstream_switch_list
= NULL
;
158 pim_ifp
->pim_generation_id
= 0;
160 /* list of struct igmp_sock */
161 pim_ifp
->igmp_socket_list
= list_new();
162 pim_ifp
->igmp_socket_list
->del
= (void (*)(void *))igmp_sock_free
;
164 /* list of struct pim_neighbor */
165 pim_ifp
->pim_neighbor_list
= list_new();
166 pim_ifp
->pim_neighbor_list
->del
= (void (*)(void *))pim_neighbor_free
;
168 pim_ifp
->upstream_switch_list
= list_new();
169 pim_ifp
->upstream_switch_list
->del
=
170 (void (*)(void *))pim_jp_agg_group_list_free
;
171 pim_ifp
->upstream_switch_list
->cmp
= pim_jp_agg_group_list_cmp
;
173 pim_ifp
->sec_addr_list
= list_new();
174 pim_ifp
->sec_addr_list
->del
= (void (*)(void *))pim_sec_addr_free
;
175 pim_ifp
->sec_addr_list
->cmp
=
176 (int (*)(void *, void *))pim_sec_addr_comp
;
178 pim_ifp
->activeactive
= false;
180 RB_INIT(pim_ifchannel_rb
, &pim_ifp
->ifchannel_rb
);
186 pim_if_add_vif(ifp
, ispimreg
, is_vxlan_term
);
191 void pim_if_delete(struct interface
*ifp
)
193 struct pim_interface
*pim_ifp
;
194 struct pim_ifchannel
*ch
;
200 if (pim_ifp
->igmp_join_list
) {
201 pim_if_igmp_join_del_all(ifp
);
204 pim_ifchannel_delete_all(ifp
);
205 igmp_sock_delete_all(ifp
);
207 pim_neighbor_delete_all(ifp
, "Interface removed from configuration");
211 list_delete(&pim_ifp
->igmp_socket_list
);
212 list_delete(&pim_ifp
->pim_neighbor_list
);
213 list_delete(&pim_ifp
->upstream_switch_list
);
214 list_delete(&pim_ifp
->sec_addr_list
);
216 XFREE(MTYPE_PIM_INTERFACE
, pim_ifp
->boundary_oil_plist
);
218 while (!RB_EMPTY(pim_ifchannel_rb
, &pim_ifp
->ifchannel_rb
)) {
219 ch
= RB_ROOT(pim_ifchannel_rb
, &pim_ifp
->ifchannel_rb
);
221 pim_ifchannel_delete(ch
);
224 XFREE(MTYPE_PIM_INTERFACE
, pim_ifp
);
229 void pim_if_update_could_assert(struct interface
*ifp
)
231 struct pim_interface
*pim_ifp
;
232 struct pim_ifchannel
*ch
;
237 RB_FOREACH (ch
, pim_ifchannel_rb
, &pim_ifp
->ifchannel_rb
) {
238 pim_ifchannel_update_could_assert(ch
);
242 static void pim_if_update_my_assert_metric(struct interface
*ifp
)
244 struct pim_interface
*pim_ifp
;
245 struct pim_ifchannel
*ch
;
250 RB_FOREACH (ch
, pim_ifchannel_rb
, &pim_ifp
->ifchannel_rb
) {
251 pim_ifchannel_update_my_assert_metric(ch
);
255 static void pim_addr_change(struct interface
*ifp
)
257 struct pim_interface
*pim_ifp
;
262 pim_if_dr_election(ifp
); /* router's own DR Priority (addr) changes --
264 pim_if_update_join_desired(pim_ifp
); /* depends on DR */
265 pim_if_update_could_assert(ifp
); /* depends on DR */
266 pim_if_update_my_assert_metric(ifp
); /* depends on could_assert */
267 pim_if_update_assert_tracking_desired(
268 ifp
); /* depends on DR, join_desired */
271 RFC 4601: 4.3.1. Sending Hello Messages
273 1) Before an interface goes down or changes primary IP address, a
274 Hello message with a zero HoldTime should be sent immediately
275 (with the old IP address if the IP address changed).
276 -- FIXME See CAVEAT C13
278 2) After an interface has changed its IP address, it MUST send a
279 Hello message with its new IP address.
282 3) If an interface changes one of its secondary IP addresses, a
283 Hello message with an updated Address_List option and a non-zero
284 HoldTime should be sent immediately.
285 -- FIXME See TODO T31
287 pim_ifp
->pim_ifstat_hello_sent
= 0; /* reset hello counter */
288 if (pim_ifp
->pim_sock_fd
< 0)
290 pim_hello_restart_now(ifp
); /* send hello and restart timer */
293 static int detect_primary_address_change(struct interface
*ifp
,
294 int force_prim_as_any
,
297 struct pim_interface
*pim_ifp
= ifp
->info
;
298 struct in_addr new_prim_addr
;
301 if (force_prim_as_any
)
302 new_prim_addr
.s_addr
= INADDR_ANY
;
304 new_prim_addr
= pim_find_primary_addr(ifp
);
306 changed
= new_prim_addr
.s_addr
!= pim_ifp
->primary_address
.s_addr
;
308 if (PIM_DEBUG_ZEBRA
) {
309 char new_prim_str
[INET_ADDRSTRLEN
];
310 char old_prim_str
[INET_ADDRSTRLEN
];
311 pim_inet4_dump("<new?>", new_prim_addr
, new_prim_str
,
312 sizeof(new_prim_str
));
313 pim_inet4_dump("<old?>", pim_ifp
->primary_address
, old_prim_str
,
314 sizeof(old_prim_str
));
315 zlog_debug("%s: old=%s new=%s on interface %s: %s",
316 __PRETTY_FUNCTION__
, old_prim_str
, new_prim_str
,
317 ifp
->name
, changed
? "changed" : "unchanged");
321 pim_ifp
->primary_address
= new_prim_addr
;
327 static struct pim_secondary_addr
*
328 pim_sec_addr_find(struct pim_interface
*pim_ifp
, struct prefix
*addr
)
330 struct pim_secondary_addr
*sec_addr
;
331 struct listnode
*node
;
333 for (ALL_LIST_ELEMENTS_RO(pim_ifp
->sec_addr_list
, node
, sec_addr
)) {
334 if (prefix_cmp(&sec_addr
->addr
, addr
)) {
342 static void pim_sec_addr_del(struct pim_interface
*pim_ifp
,
343 struct pim_secondary_addr
*sec_addr
)
345 listnode_delete(pim_ifp
->sec_addr_list
, sec_addr
);
346 pim_sec_addr_free(sec_addr
);
349 static int pim_sec_addr_add(struct pim_interface
*pim_ifp
, struct prefix
*addr
)
352 struct pim_secondary_addr
*sec_addr
;
354 sec_addr
= pim_sec_addr_find(pim_ifp
, addr
);
356 sec_addr
->flags
&= ~PIM_SEC_ADDRF_STALE
;
360 sec_addr
= XCALLOC(MTYPE_PIM_SEC_ADDR
, sizeof(*sec_addr
));
363 sec_addr
->addr
= *addr
;
364 listnode_add_sort(pim_ifp
->sec_addr_list
, sec_addr
);
369 static int pim_sec_addr_del_all(struct pim_interface
*pim_ifp
)
373 if (!list_isempty(pim_ifp
->sec_addr_list
)) {
375 /* remove all nodes and free up the list itself */
376 list_delete_all_node(pim_ifp
->sec_addr_list
);
382 static int pim_sec_addr_update(struct interface
*ifp
)
384 struct pim_interface
*pim_ifp
= ifp
->info
;
385 struct connected
*ifc
;
386 struct listnode
*node
;
387 struct listnode
*nextnode
;
388 struct pim_secondary_addr
*sec_addr
;
391 for (ALL_LIST_ELEMENTS_RO(pim_ifp
->sec_addr_list
, node
, sec_addr
)) {
392 sec_addr
->flags
|= PIM_SEC_ADDRF_STALE
;
395 for (ALL_LIST_ELEMENTS_RO(ifp
->connected
, node
, ifc
)) {
396 struct prefix
*p
= ifc
->address
;
398 if (PIM_INADDR_IS_ANY(p
->u
.prefix4
)) {
402 if (pim_ifp
->primary_address
.s_addr
== p
->u
.prefix4
.s_addr
) {
403 /* don't add the primary address into the secondary
408 if (pim_sec_addr_add(pim_ifp
, p
)) {
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_IF_TEST_PIM(pim_ifp
->options
)) {
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
, struct in_addr source
)
477 struct pim_interface
*pim_ifp
= ifp
->info
;
480 return PIM_IFACE_NOT_FOUND
;
483 if (pim_ifp
->update_source
.s_addr
== source
.s_addr
) {
484 return PIM_UPDATE_SOURCE_DUP
;
487 pim_ifp
->update_source
= source
;
488 detect_address_change(ifp
, 0 /* force_prim_as_any */,
489 __PRETTY_FUNCTION__
);
494 void pim_if_addr_add(struct connected
*ifc
)
496 struct pim_interface
*pim_ifp
;
497 struct interface
*ifp
;
498 struct in_addr ifaddr
;
508 if (!if_is_operative(ifp
))
511 if (PIM_DEBUG_ZEBRA
) {
513 prefix2str(ifc
->address
, buf
, BUFSIZ
);
514 zlog_debug("%s: %s ifindex=%d connected IP address %s %s",
515 __PRETTY_FUNCTION__
, ifp
->name
, ifp
->ifindex
, buf
,
516 CHECK_FLAG(ifc
->flags
, ZEBRA_IFA_SECONDARY
)
521 ifaddr
= ifc
->address
->u
.prefix4
;
523 detect_address_change(ifp
, 0, __PRETTY_FUNCTION__
);
525 // if (ifc->address->family != AF_INET)
528 if (PIM_IF_TEST_IGMP(pim_ifp
->options
)) {
529 struct igmp_sock
*igmp
;
531 /* lookup IGMP socket */
532 igmp
= pim_igmp_sock_lookup_ifaddr(pim_ifp
->igmp_socket_list
,
535 /* if addr new, add IGMP socket */
536 if (ifc
->address
->family
== AF_INET
)
537 pim_igmp_sock_add(pim_ifp
->igmp_socket_list
,
539 } else if (igmp
->mtrace_only
) {
540 igmp_sock_delete(igmp
);
541 pim_igmp_sock_add(pim_ifp
->igmp_socket_list
, ifaddr
,
545 /* Replay Static IGMP groups */
546 if (pim_ifp
->igmp_join_list
) {
547 struct listnode
*node
;
548 struct listnode
*nextnode
;
549 struct igmp_join
*ij
;
552 for (ALL_LIST_ELEMENTS(pim_ifp
->igmp_join_list
, node
,
554 /* Close socket and reopen with Source and Group
557 join_fd
= igmp_join_sock(
558 ifp
->name
, ifp
->ifindex
, ij
->group_addr
,
561 char group_str
[INET_ADDRSTRLEN
];
562 char source_str
[INET_ADDRSTRLEN
];
563 pim_inet4_dump("<grp?>", ij
->group_addr
,
567 "<src?>", ij
->source_addr
,
568 source_str
, sizeof(source_str
));
570 "%s: igmp_join_sock() failure for IGMP group %s source %s on interface %s",
571 __PRETTY_FUNCTION__
, group_str
,
572 source_str
, ifp
->name
);
575 ij
->sock_fd
= join_fd
;
580 struct igmp_sock
*igmp
;
582 /* lookup IGMP socket */
583 igmp
= pim_igmp_sock_lookup_ifaddr(pim_ifp
->igmp_socket_list
,
585 if (ifc
->address
->family
== AF_INET
) {
587 igmp_sock_delete(igmp
);
588 /* if addr new, add IGMP socket */
589 pim_igmp_sock_add(pim_ifp
->igmp_socket_list
, ifaddr
,
592 } /* igmp mtrace only */
594 if (PIM_IF_TEST_PIM(pim_ifp
->options
)) {
596 if (PIM_INADDR_ISNOT_ANY(pim_ifp
->primary_address
)) {
598 /* Interface has a valid socket ? */
599 if (pim_ifp
->pim_sock_fd
< 0) {
600 if (pim_sock_add(ifp
)) {
602 "Failure creating PIM socket for interface %s",
606 struct pim_nexthop_cache
*pnc
= NULL
;
608 struct zclient
*zclient
= NULL
;
610 zclient
= pim_zebra_zclient_get();
611 /* RP config might come prior to (local RP's interface)
613 In this case, pnc would not have pim enabled
615 Once Interface is UP and pim info is available,
617 with RNH address to receive update and add the
618 interface as nexthop. */
619 memset(&rpf
, 0, sizeof(struct pim_rpf
));
620 rpf
.rpf_addr
.family
= AF_INET
;
621 rpf
.rpf_addr
.prefixlen
= IPV4_MAX_BITLEN
;
622 rpf
.rpf_addr
.u
.prefix4
= ifc
->address
->u
.prefix4
;
623 pnc
= pim_nexthop_cache_find(pim_ifp
->pim
, &rpf
);
625 pim_sendmsg_zebra_rnh(pim_ifp
->pim
, zclient
,
627 ZEBRA_NEXTHOP_REGISTER
);
632 PIM or IGMP is enabled on interface, and there is at least one
633 address assigned, then try to create a vif_index.
635 if (pim_ifp
->mroute_vif_index
< 0) {
636 pim_if_add_vif(ifp
, false, false /*vxlan_term*/);
638 pim_ifchannel_scan_forward_start(ifp
);
641 static void pim_if_addr_del_igmp(struct connected
*ifc
)
643 struct pim_interface
*pim_ifp
= ifc
->ifp
->info
;
644 struct igmp_sock
*igmp
;
645 struct in_addr ifaddr
;
647 if (ifc
->address
->family
!= AF_INET
) {
648 /* non-IPv4 address */
653 /* IGMP not enabled on interface */
657 ifaddr
= ifc
->address
->u
.prefix4
;
659 /* lookup IGMP socket */
660 igmp
= pim_igmp_sock_lookup_ifaddr(pim_ifp
->igmp_socket_list
, ifaddr
);
662 /* if addr found, del IGMP socket */
663 igmp_sock_delete(igmp
);
667 static void pim_if_addr_del_pim(struct connected
*ifc
)
669 struct pim_interface
*pim_ifp
= ifc
->ifp
->info
;
671 if (ifc
->address
->family
!= AF_INET
) {
672 /* non-IPv4 address */
677 /* PIM not enabled on interface */
681 if (PIM_INADDR_ISNOT_ANY(pim_ifp
->primary_address
)) {
682 /* Interface keeps a valid primary address */
686 if (pim_ifp
->pim_sock_fd
< 0) {
687 /* Interface does not hold a valid socket any longer */
692 pim_sock_delete() closes the socket, stops read and timer threads,
693 and kills all neighbors.
695 pim_sock_delete(ifc
->ifp
,
696 "last address has been removed from interface");
699 void pim_if_addr_del(struct connected
*ifc
, int force_prim_as_any
)
701 struct interface
*ifp
;
707 if (PIM_DEBUG_ZEBRA
) {
709 prefix2str(ifc
->address
, buf
, BUFSIZ
);
710 zlog_debug("%s: %s ifindex=%d disconnected IP address %s %s",
711 __PRETTY_FUNCTION__
, ifp
->name
, ifp
->ifindex
, buf
,
712 CHECK_FLAG(ifc
->flags
, ZEBRA_IFA_SECONDARY
)
717 detect_address_change(ifp
, force_prim_as_any
, __PRETTY_FUNCTION__
);
719 pim_if_addr_del_igmp(ifc
);
720 pim_if_addr_del_pim(ifc
);
723 void pim_if_addr_add_all(struct interface
*ifp
)
725 struct connected
*ifc
;
726 struct listnode
*node
;
727 struct listnode
*nextnode
;
730 struct pim_interface
*pim_ifp
= ifp
->info
;
733 /* PIM/IGMP enabled ? */
737 for (ALL_LIST_ELEMENTS(ifp
->connected
, node
, nextnode
, ifc
)) {
738 struct prefix
*p
= ifc
->address
;
740 if (p
->family
!= AF_INET
)
744 pim_if_addr_add(ifc
);
747 if (!v4_addrs
&& v6_addrs
&& !if_is_loopback(ifp
)) {
748 if (PIM_IF_TEST_PIM(pim_ifp
->options
)) {
750 /* Interface has a valid primary address ? */
751 if (PIM_INADDR_ISNOT_ANY(pim_ifp
->primary_address
)) {
753 /* Interface has a valid socket ? */
754 if (pim_ifp
->pim_sock_fd
< 0) {
755 if (pim_sock_add(ifp
)) {
757 "Failure creating PIM socket for interface %s",
765 * PIM or IGMP is enabled on interface, and there is at least one
766 * address assigned, then try to create a vif_index.
768 if (pim_ifp
->mroute_vif_index
< 0) {
769 pim_if_add_vif(ifp
, false, false /*vxlan_term*/);
771 pim_ifchannel_scan_forward_start(ifp
);
773 pim_rp_setup(pim_ifp
->pim
);
774 pim_rp_check_on_if_add(pim_ifp
);
777 void pim_if_addr_del_all(struct interface
*ifp
)
779 struct connected
*ifc
;
780 struct listnode
*node
;
781 struct listnode
*nextnode
;
782 struct vrf
*vrf
= vrf_lookup_by_id(ifp
->vrf_id
);
783 struct pim_instance
*pim
;
789 /* PIM/IGMP enabled ? */
793 for (ALL_LIST_ELEMENTS(ifp
->connected
, node
, nextnode
, ifc
)) {
794 struct prefix
*p
= ifc
->address
;
796 if (p
->family
!= AF_INET
)
799 pim_if_addr_del(ifc
, 1 /* force_prim_as_any=true */);
803 pim_i_am_rp_re_evaluate(pim
);
806 void pim_if_addr_del_all_igmp(struct interface
*ifp
)
808 struct connected
*ifc
;
809 struct listnode
*node
;
810 struct listnode
*nextnode
;
812 /* PIM/IGMP enabled ? */
816 for (ALL_LIST_ELEMENTS(ifp
->connected
, node
, nextnode
, ifc
)) {
817 struct prefix
*p
= ifc
->address
;
819 if (p
->family
!= AF_INET
)
822 pim_if_addr_del_igmp(ifc
);
826 void pim_if_addr_del_all_pim(struct interface
*ifp
)
828 struct connected
*ifc
;
829 struct listnode
*node
;
830 struct listnode
*nextnode
;
832 /* PIM/IGMP enabled ? */
836 for (ALL_LIST_ELEMENTS(ifp
->connected
, node
, nextnode
, ifc
)) {
837 struct prefix
*p
= ifc
->address
;
839 if (p
->family
!= AF_INET
)
842 pim_if_addr_del_pim(ifc
);
846 struct in_addr
pim_find_primary_addr(struct interface
*ifp
)
848 struct connected
*ifc
;
849 struct listnode
*node
;
850 struct in_addr addr
= {0};
853 struct pim_interface
*pim_ifp
= ifp
->info
;
854 struct vrf
*vrf
= vrf_lookup_by_id(ifp
->vrf_id
);
859 if (pim_ifp
&& PIM_INADDR_ISNOT_ANY(pim_ifp
->update_source
)) {
860 return pim_ifp
->update_source
;
863 for (ALL_LIST_ELEMENTS_RO(ifp
->connected
, node
, ifc
)) {
864 struct prefix
*p
= ifc
->address
;
866 if (p
->family
!= AF_INET
) {
871 if (PIM_INADDR_IS_ANY(p
->u
.prefix4
)) {
873 "%s: null IPv4 address connected to interface %s",
874 __PRETTY_FUNCTION__
, ifp
->name
);
880 if (CHECK_FLAG(ifc
->flags
, ZEBRA_IFA_SECONDARY
))
887 * If we have no v4_addrs and v6 is configured
888 * We probably are using unnumbered
889 * So let's grab the loopbacks v4 address
890 * and use that as the primary address
892 if (!v4_addrs
&& v6_addrs
&& !if_is_loopback(ifp
)) {
893 struct interface
*lo_ifp
;
894 // DBS - Come back and check here
895 if (ifp
->vrf_id
== VRF_DEFAULT
)
896 lo_ifp
= if_lookup_by_name("lo", vrf
->vrf_id
);
898 lo_ifp
= if_lookup_by_name(vrf
->name
, vrf
->vrf_id
);
901 return pim_find_primary_addr(lo_ifp
);
904 addr
.s_addr
= PIM_NET_INADDR_ANY
;
909 static int pim_iface_next_vif_index(struct interface
*ifp
)
911 struct pim_interface
*pim_ifp
= ifp
->info
;
912 struct pim_instance
*pim
= pim_ifp
->pim
;
916 * The pimreg vif is always going to be in index 0
919 if (ifp
->ifindex
== PIM_OIF_PIM_REGISTER_VIF
)
922 for (i
= 1; i
< MAXVIFS
; i
++) {
923 if (pim
->iface_vif_index
[i
] == 0)
930 pim_if_add_vif() uses ifindex as vif_index
932 see also pim_if_find_vifindex_by_ifindex()
934 int pim_if_add_vif(struct interface
*ifp
, bool ispimreg
, bool is_vxlan_term
)
936 struct pim_interface
*pim_ifp
= ifp
->info
;
937 struct in_addr ifaddr
;
938 unsigned char flags
= 0;
942 if (pim_ifp
->mroute_vif_index
> 0) {
943 zlog_warn("%s: vif_index=%d > 0 on interface %s ifindex=%d",
944 __PRETTY_FUNCTION__
, pim_ifp
->mroute_vif_index
,
945 ifp
->name
, ifp
->ifindex
);
949 if (ifp
->ifindex
< 0) {
950 zlog_warn("%s: ifindex=%d < 1 on interface %s",
951 __PRETTY_FUNCTION__
, ifp
->ifindex
, ifp
->name
);
955 ifaddr
= pim_ifp
->primary_address
;
956 if (!ispimreg
&& !is_vxlan_term
&& PIM_INADDR_IS_ANY(ifaddr
)) {
958 "%s: could not get address for interface %s ifindex=%d",
959 __PRETTY_FUNCTION__
, ifp
->name
, ifp
->ifindex
);
963 pim_ifp
->mroute_vif_index
= pim_iface_next_vif_index(ifp
);
965 if (pim_ifp
->mroute_vif_index
>= MAXVIFS
) {
967 "%s: Attempting to configure more than MAXVIFS=%d on pim enabled interface %s",
968 __PRETTY_FUNCTION__
, MAXVIFS
, ifp
->name
);
972 if (ifp
->ifindex
== PIM_OIF_PIM_REGISTER_VIF
)
973 flags
= VIFF_REGISTER
;
974 #ifdef VIFF_USE_IFINDEX
976 flags
= VIFF_USE_IFINDEX
;
979 if (pim_mroute_add_vif(ifp
, ifaddr
, flags
)) {
980 /* pim_mroute_add_vif reported error */
984 pim_ifp
->pim
->iface_vif_index
[pim_ifp
->mroute_vif_index
] = 1;
986 /* if the device qualifies as pim_vxlan iif/oif update vxlan entries */
987 pim_vxlan_add_vif(ifp
);
992 int pim_if_del_vif(struct interface
*ifp
)
994 struct pim_interface
*pim_ifp
= ifp
->info
;
996 if (pim_ifp
->mroute_vif_index
< 1) {
997 zlog_warn("%s: vif_index=%d < 1 on interface %s ifindex=%d",
998 __PRETTY_FUNCTION__
, pim_ifp
->mroute_vif_index
,
999 ifp
->name
, ifp
->ifindex
);
1003 /* if the device was a pim_vxlan iif/oif update vxlan mroute entries */
1004 pim_vxlan_del_vif(ifp
);
1006 pim_mroute_del_vif(ifp
);
1011 pim_ifp
->pim
->iface_vif_index
[pim_ifp
->mroute_vif_index
] = 0;
1013 pim_ifp
->mroute_vif_index
= -1;
1019 struct interface
*pim_if_find_by_vif_index(struct pim_instance
*pim
,
1020 ifindex_t vif_index
)
1022 struct interface
*ifp
;
1024 FOR_ALL_INTERFACES (pim
->vrf
, ifp
) {
1026 struct pim_interface
*pim_ifp
;
1027 pim_ifp
= ifp
->info
;
1029 if (vif_index
== pim_ifp
->mroute_vif_index
)
1038 pim_if_add_vif() uses ifindex as vif_index
1040 int pim_if_find_vifindex_by_ifindex(struct pim_instance
*pim
, ifindex_t ifindex
)
1042 struct pim_interface
*pim_ifp
;
1043 struct interface
*ifp
;
1045 ifp
= if_lookup_by_index(ifindex
, pim
->vrf_id
);
1046 if (!ifp
|| !ifp
->info
)
1048 pim_ifp
= ifp
->info
;
1050 return pim_ifp
->mroute_vif_index
;
1053 int pim_if_lan_delay_enabled(struct interface
*ifp
)
1055 struct pim_interface
*pim_ifp
;
1057 pim_ifp
= ifp
->info
;
1059 zassert(pim_ifp
->pim_number_of_nonlandelay_neighbors
>= 0);
1061 return pim_ifp
->pim_number_of_nonlandelay_neighbors
== 0;
1064 uint16_t pim_if_effective_propagation_delay_msec(struct interface
*ifp
)
1066 if (pim_if_lan_delay_enabled(ifp
)) {
1067 struct pim_interface
*pim_ifp
;
1068 pim_ifp
= ifp
->info
;
1069 return pim_ifp
->pim_neighbors_highest_propagation_delay_msec
;
1071 return PIM_DEFAULT_PROPAGATION_DELAY_MSEC
;
1075 uint16_t pim_if_effective_override_interval_msec(struct interface
*ifp
)
1077 if (pim_if_lan_delay_enabled(ifp
)) {
1078 struct pim_interface
*pim_ifp
;
1079 pim_ifp
= ifp
->info
;
1080 return pim_ifp
->pim_neighbors_highest_override_interval_msec
;
1082 return PIM_DEFAULT_OVERRIDE_INTERVAL_MSEC
;
1086 int pim_if_t_override_msec(struct interface
*ifp
)
1088 int effective_override_interval_msec
;
1089 int t_override_msec
;
1091 effective_override_interval_msec
=
1092 pim_if_effective_override_interval_msec(ifp
);
1094 t_override_msec
= random() % (effective_override_interval_msec
+ 1);
1096 return t_override_msec
;
1099 uint16_t pim_if_jp_override_interval_msec(struct interface
*ifp
)
1101 return pim_if_effective_propagation_delay_msec(ifp
)
1102 + pim_if_effective_override_interval_msec(ifp
);
1106 RFC 4601: 4.1.6. State Summarization Macros
1108 The function NBR( I, A ) uses information gathered through PIM Hello
1109 messages to map the IP address A of a directly connected PIM
1110 neighbor router on interface I to the primary IP address of the same
1111 router (Section 4.3.4). The primary IP address of a neighbor is the
1112 address that it uses as the source of its PIM Hello messages.
1114 struct pim_neighbor
*pim_if_find_neighbor(struct interface
*ifp
,
1115 struct in_addr addr
)
1117 struct listnode
*neighnode
;
1118 struct pim_neighbor
*neigh
;
1119 struct pim_interface
*pim_ifp
;
1124 pim_ifp
= ifp
->info
;
1126 zlog_warn("%s: multicast not enabled on interface %s",
1127 __PRETTY_FUNCTION__
, ifp
->name
);
1133 p
.prefixlen
= IPV4_MAX_PREFIXLEN
;
1135 for (ALL_LIST_ELEMENTS_RO(pim_ifp
->pim_neighbor_list
, neighnode
,
1138 /* primary address ? */
1139 if (neigh
->source_addr
.s_addr
== addr
.s_addr
)
1142 /* secondary address ? */
1143 if (pim_neighbor_find_secondary(neigh
, &p
))
1147 if (PIM_DEBUG_PIM_TRACE
) {
1148 char addr_str
[INET_ADDRSTRLEN
];
1149 pim_inet4_dump("<addr?>", addr
, addr_str
, sizeof(addr_str
));
1151 "%s: neighbor not found for address %s on interface %s",
1152 __PRETTY_FUNCTION__
, addr_str
, ifp
->name
);
1158 long pim_if_t_suppressed_msec(struct interface
*ifp
)
1160 struct pim_interface
*pim_ifp
;
1161 long t_suppressed_msec
;
1162 uint32_t ramount
= 0;
1164 pim_ifp
= ifp
->info
;
1167 /* join suppression disabled ? */
1168 if (PIM_IF_TEST_PIM_CAN_DISABLE_JOIN_SUPRESSION(pim_ifp
->options
))
1171 /* t_suppressed = t_periodic * rand(1.1, 1.4) */
1172 ramount
= 1100 + (random() % (1400 - 1100 + 1));
1173 t_suppressed_msec
= router
->t_periodic
* ramount
;
1175 return t_suppressed_msec
;
1178 static void igmp_join_free(struct igmp_join
*ij
)
1180 XFREE(MTYPE_PIM_IGMP_JOIN
, ij
);
1183 static struct igmp_join
*igmp_join_find(struct list
*join_list
,
1184 struct in_addr group_addr
,
1185 struct in_addr source_addr
)
1187 struct listnode
*node
;
1188 struct igmp_join
*ij
;
1192 for (ALL_LIST_ELEMENTS_RO(join_list
, node
, ij
)) {
1193 if ((group_addr
.s_addr
== ij
->group_addr
.s_addr
)
1194 && (source_addr
.s_addr
== ij
->source_addr
.s_addr
))
1201 static int igmp_join_sock(const char *ifname
, ifindex_t ifindex
,
1202 struct in_addr group_addr
, struct in_addr source_addr
)
1206 join_fd
= pim_socket_raw(IPPROTO_IGMP
);
1211 if (pim_igmp_join_source(join_fd
, ifindex
, group_addr
, source_addr
)) {
1212 char group_str
[INET_ADDRSTRLEN
];
1213 char source_str
[INET_ADDRSTRLEN
];
1214 pim_inet4_dump("<grp?>", group_addr
, group_str
,
1216 pim_inet4_dump("<src?>", source_addr
, source_str
,
1217 sizeof(source_str
));
1219 "%s: setsockopt(fd=%d) failure for IGMP group %s source %s ifindex %d on interface %s: errno=%d: %s",
1220 __PRETTY_FUNCTION__
, join_fd
, group_str
, source_str
,
1221 ifindex
, ifname
, errno
, safe_strerror(errno
));
1230 static struct igmp_join
*igmp_join_new(struct interface
*ifp
,
1231 struct in_addr group_addr
,
1232 struct in_addr source_addr
)
1234 struct pim_interface
*pim_ifp
;
1235 struct igmp_join
*ij
;
1238 pim_ifp
= ifp
->info
;
1241 join_fd
= igmp_join_sock(ifp
->name
, ifp
->ifindex
, group_addr
,
1244 char group_str
[INET_ADDRSTRLEN
];
1245 char source_str
[INET_ADDRSTRLEN
];
1247 pim_inet4_dump("<grp?>", group_addr
, group_str
,
1249 pim_inet4_dump("<src?>", source_addr
, source_str
,
1250 sizeof(source_str
));
1252 "%s: igmp_join_sock() failure for IGMP group %s source %s on interface %s",
1253 __PRETTY_FUNCTION__
, group_str
, source_str
, ifp
->name
);
1257 ij
= XCALLOC(MTYPE_PIM_IGMP_JOIN
, sizeof(*ij
));
1259 ij
->sock_fd
= join_fd
;
1260 ij
->group_addr
= group_addr
;
1261 ij
->source_addr
= source_addr
;
1262 ij
->sock_creation
= pim_time_monotonic_sec();
1264 listnode_add(pim_ifp
->igmp_join_list
, ij
);
1269 ferr_r
pim_if_igmp_join_add(struct interface
*ifp
, struct in_addr group_addr
,
1270 struct in_addr source_addr
)
1272 struct pim_interface
*pim_ifp
;
1273 struct igmp_join
*ij
;
1275 pim_ifp
= ifp
->info
;
1277 return ferr_cfg_invalid("multicast not enabled on interface %s",
1281 if (!pim_ifp
->igmp_join_list
) {
1282 pim_ifp
->igmp_join_list
= list_new();
1283 pim_ifp
->igmp_join_list
->del
= (void (*)(void *))igmp_join_free
;
1286 ij
= igmp_join_find(pim_ifp
->igmp_join_list
, group_addr
, source_addr
);
1288 /* This interface has already been configured to join this IGMP group
1294 ij
= igmp_join_new(ifp
, group_addr
, source_addr
);
1296 return ferr_cfg_invalid(
1297 "Failure to create new join data structure, see log file for more information");
1300 if (PIM_DEBUG_IGMP_EVENTS
) {
1301 char group_str
[INET_ADDRSTRLEN
];
1302 char source_str
[INET_ADDRSTRLEN
];
1303 pim_inet4_dump("<grp?>", group_addr
, group_str
,
1305 pim_inet4_dump("<src?>", source_addr
, source_str
,
1306 sizeof(source_str
));
1308 "%s: issued static igmp join for channel (S,G)=(%s,%s) on interface %s",
1309 __PRETTY_FUNCTION__
, source_str
, group_str
, ifp
->name
);
1316 int pim_if_igmp_join_del(struct interface
*ifp
, struct in_addr group_addr
,
1317 struct in_addr source_addr
)
1319 struct pim_interface
*pim_ifp
;
1320 struct igmp_join
*ij
;
1322 pim_ifp
= ifp
->info
;
1324 zlog_warn("%s: multicast not enabled on interface %s",
1325 __PRETTY_FUNCTION__
, ifp
->name
);
1329 if (!pim_ifp
->igmp_join_list
) {
1330 zlog_warn("%s: no IGMP join on interface %s",
1331 __PRETTY_FUNCTION__
, ifp
->name
);
1335 ij
= igmp_join_find(pim_ifp
->igmp_join_list
, group_addr
, source_addr
);
1337 char group_str
[INET_ADDRSTRLEN
];
1338 char source_str
[INET_ADDRSTRLEN
];
1339 pim_inet4_dump("<grp?>", group_addr
, group_str
,
1341 pim_inet4_dump("<src?>", source_addr
, source_str
,
1342 sizeof(source_str
));
1344 "%s: could not find IGMP group %s source %s on interface %s",
1345 __PRETTY_FUNCTION__
, group_str
, source_str
, ifp
->name
);
1349 if (close(ij
->sock_fd
)) {
1350 char group_str
[INET_ADDRSTRLEN
];
1351 char source_str
[INET_ADDRSTRLEN
];
1352 pim_inet4_dump("<grp?>", group_addr
, group_str
,
1354 pim_inet4_dump("<src?>", source_addr
, source_str
,
1355 sizeof(source_str
));
1357 "%s: failure closing sock_fd=%d for IGMP group %s source %s on interface %s: errno=%d: %s",
1358 __PRETTY_FUNCTION__
, ij
->sock_fd
, group_str
, source_str
,
1359 ifp
->name
, errno
, safe_strerror(errno
));
1362 listnode_delete(pim_ifp
->igmp_join_list
, ij
);
1364 if (listcount(pim_ifp
->igmp_join_list
) < 1) {
1365 list_delete(&pim_ifp
->igmp_join_list
);
1366 pim_ifp
->igmp_join_list
= 0;
1372 static void pim_if_igmp_join_del_all(struct interface
*ifp
)
1374 struct pim_interface
*pim_ifp
;
1375 struct listnode
*node
;
1376 struct listnode
*nextnode
;
1377 struct igmp_join
*ij
;
1379 pim_ifp
= ifp
->info
;
1381 zlog_warn("%s: multicast not enabled on interface %s",
1382 __PRETTY_FUNCTION__
, ifp
->name
);
1386 if (!pim_ifp
->igmp_join_list
)
1389 for (ALL_LIST_ELEMENTS(pim_ifp
->igmp_join_list
, node
, nextnode
, ij
))
1390 pim_if_igmp_join_del(ifp
, ij
->group_addr
, ij
->source_addr
);
1396 Transitions from "I am Assert Loser" State
1398 Current Winner's GenID Changes or NLT Expires
1400 The Neighbor Liveness Timer associated with the current winner
1401 expires or we receive a Hello message from the current winner
1402 reporting a different GenID from the one it previously reported.
1403 This indicates that the current winner's interface or router has
1404 gone down (and may have come back up), and so we must assume it no
1405 longer knows it was the winner.
1407 void pim_if_assert_on_neighbor_down(struct interface
*ifp
,
1408 struct in_addr neigh_addr
)
1410 struct pim_interface
*pim_ifp
;
1411 struct pim_ifchannel
*ch
;
1413 pim_ifp
= ifp
->info
;
1416 RB_FOREACH (ch
, pim_ifchannel_rb
, &pim_ifp
->ifchannel_rb
) {
1417 /* Is (S,G,I) assert loser ? */
1418 if (ch
->ifassert_state
!= PIM_IFASSERT_I_AM_LOSER
)
1420 /* Dead neighbor was winner ? */
1421 if (ch
->ifassert_winner
.s_addr
!= neigh_addr
.s_addr
)
1424 assert_action_a5(ch
);
1428 void pim_if_update_join_desired(struct pim_interface
*pim_ifp
)
1430 struct pim_ifchannel
*ch
;
1432 /* clear off flag from interface's upstreams */
1433 RB_FOREACH (ch
, pim_ifchannel_rb
, &pim_ifp
->ifchannel_rb
) {
1434 PIM_UPSTREAM_FLAG_UNSET_DR_JOIN_DESIRED_UPDATED(
1435 ch
->upstream
->flags
);
1438 /* scan per-interface (S,G,I) state on this I interface */
1439 RB_FOREACH (ch
, pim_ifchannel_rb
, &pim_ifp
->ifchannel_rb
) {
1440 struct pim_upstream
*up
= ch
->upstream
;
1442 if (PIM_UPSTREAM_FLAG_TEST_DR_JOIN_DESIRED_UPDATED(up
->flags
))
1445 /* update join_desired for the global (S,G) state */
1446 pim_upstream_update_join_desired(pim_ifp
->pim
, up
);
1447 PIM_UPSTREAM_FLAG_SET_DR_JOIN_DESIRED_UPDATED(up
->flags
);
1451 void pim_if_update_assert_tracking_desired(struct interface
*ifp
)
1453 struct pim_interface
*pim_ifp
;
1454 struct pim_ifchannel
*ch
;
1456 pim_ifp
= ifp
->info
;
1460 RB_FOREACH (ch
, pim_ifchannel_rb
, &pim_ifp
->ifchannel_rb
) {
1461 pim_ifchannel_update_assert_tracking_desired(ch
);
1466 * PIM wants to have an interface pointer for everything it does.
1467 * The pimreg is a special interface that we have that is not
1468 * quite an inteface but a VIF is created for it.
1470 void pim_if_create_pimreg(struct pim_instance
*pim
)
1472 char pimreg_name
[INTERFACE_NAMSIZ
];
1474 if (!pim
->regiface
) {
1475 if (pim
->vrf_id
== VRF_DEFAULT
)
1476 strlcpy(pimreg_name
, "pimreg", sizeof(pimreg_name
));
1478 snprintf(pimreg_name
, sizeof(pimreg_name
), "pimreg%u",
1479 pim
->vrf
->data
.l
.table_id
);
1481 pim
->regiface
= if_create(pimreg_name
, pim
->vrf_id
);
1482 pim
->regiface
->ifindex
= PIM_OIF_PIM_REGISTER_VIF
;
1484 pim_if_new(pim
->regiface
, false, false, true,
1485 false /*vxlan_term*/);
1489 int pim_if_connected_to_source(struct interface
*ifp
, struct in_addr src
)
1491 struct listnode
*cnode
;
1492 struct connected
*c
;
1500 p
.prefixlen
= IPV4_MAX_BITLEN
;
1502 for (ALL_LIST_ELEMENTS_RO(ifp
->connected
, cnode
, c
)) {
1503 if ((c
->address
->family
== AF_INET
)
1504 && prefix_match(CONNECTED_PREFIX(c
), &p
)) {
1512 bool pim_if_is_vrf_device(struct interface
*ifp
)
1520 int pim_if_ifchannel_count(struct pim_interface
*pim_ifp
)
1522 struct pim_ifchannel
*ch
;
1525 RB_FOREACH (ch
, pim_ifchannel_rb
, &pim_ifp
->ifchannel_rb
) {