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"
50 static void pim_if_igmp_join_del_all(struct interface
*ifp
);
51 static int igmp_join_sock(const char *ifname
, ifindex_t ifindex
,
52 struct in_addr group_addr
,
53 struct in_addr source_addr
);
55 void pim_if_init(struct pim_instance
*pim
)
59 for (i
= 0; i
< MAXVIFS
; i
++)
60 pim
->iface_vif_index
[i
] = 0;
63 void pim_if_terminate(struct pim_instance
*pim
)
65 // Nothing to do at this moment
69 static void *if_list_clean(struct pim_interface
*pim_ifp
)
71 struct pim_ifchannel
*ch
;
73 if (pim_ifp
->igmp_join_list
)
74 list_delete_and_null(&pim_ifp
->igmp_join_list
);
76 if (pim_ifp
->igmp_socket_list
)
77 list_delete_and_null(&pim_ifp
->igmp_socket_list
);
79 if (pim_ifp
->pim_neighbor_list
)
80 list_delete_and_null(&pim_ifp
->pim_neighbor_list
);
82 if (pim_ifp
->upstream_switch_list
)
83 list_delete_and_null(&pim_ifp
->upstream_switch_list
);
85 if (pim_ifp
->sec_addr_list
)
86 list_delete_and_null(&pim_ifp
->sec_addr_list
);
88 while (!RB_EMPTY(pim_ifchannel_rb
, &pim_ifp
->ifchannel_rb
)) {
89 ch
= RB_ROOT(pim_ifchannel_rb
, &pim_ifp
->ifchannel_rb
);
91 pim_ifchannel_delete(ch
);
94 XFREE(MTYPE_PIM_INTERFACE
, pim_ifp
);
99 static void pim_sec_addr_free(struct pim_secondary_addr
*sec_addr
)
101 XFREE(MTYPE_PIM_SEC_ADDR
, sec_addr
);
104 static int pim_sec_addr_comp(const void *p1
, const void *p2
)
106 const struct pim_secondary_addr
*sec1
= p1
;
107 const struct pim_secondary_addr
*sec2
= p2
;
109 if (sec1
->addr
.family
== AF_INET
&& sec2
->addr
.family
== AF_INET6
)
112 if (sec1
->addr
.family
== AF_INET6
&& sec2
->addr
.family
== AF_INET
)
115 if (sec1
->addr
.family
== AF_INET
) {
116 if (ntohl(sec1
->addr
.u
.prefix4
.s_addr
)
117 < ntohl(sec2
->addr
.u
.prefix4
.s_addr
))
120 if (ntohl(sec1
->addr
.u
.prefix4
.s_addr
)
121 > ntohl(sec2
->addr
.u
.prefix4
.s_addr
))
124 return memcmp(&sec1
->addr
.u
.prefix6
, &sec2
->addr
.u
.prefix6
,
125 sizeof(struct in6_addr
));
131 struct pim_interface
*pim_if_new(struct interface
*ifp
, int igmp
, int pim
)
133 struct pim_interface
*pim_ifp
;
138 pim_ifp
= XCALLOC(MTYPE_PIM_INTERFACE
, sizeof(*pim_ifp
));
140 zlog_err("PIM XCALLOC(%zu) failure", sizeof(*pim_ifp
));
144 pim_ifp
->options
= 0;
145 pim_ifp
->pim
= pim_get_pim_instance(ifp
->vrf_id
);
146 pim_ifp
->mroute_vif_index
= -1;
148 pim_ifp
->igmp_version
= IGMP_DEFAULT_VERSION
;
149 pim_ifp
->igmp_default_robustness_variable
=
150 IGMP_DEFAULT_ROBUSTNESS_VARIABLE
;
151 pim_ifp
->igmp_default_query_interval
= IGMP_GENERAL_QUERY_INTERVAL
;
152 pim_ifp
->igmp_query_max_response_time_dsec
=
153 IGMP_QUERY_MAX_RESPONSE_TIME_DSEC
;
154 pim_ifp
->igmp_specific_query_max_response_time_dsec
=
155 IGMP_SPECIFIC_QUERY_MAX_RESPONSE_TIME_DSEC
;
158 RFC 3376: 8.3. Query Response Interval
159 The number of seconds represented by the [Query Response Interval]
160 must be less than the [Query Interval].
162 zassert(pim_ifp
->igmp_query_max_response_time_dsec
163 < pim_ifp
->igmp_default_query_interval
);
166 PIM_IF_DO_PIM(pim_ifp
->options
);
168 PIM_IF_DO_IGMP(pim_ifp
->options
);
170 PIM_IF_DO_IGMP_LISTEN_ALLROUTERS(pim_ifp
->options
);
172 pim_ifp
->igmp_join_list
= NULL
;
173 pim_ifp
->igmp_socket_list
= NULL
;
174 pim_ifp
->pim_neighbor_list
= NULL
;
175 pim_ifp
->upstream_switch_list
= NULL
;
176 pim_ifp
->pim_generation_id
= 0;
178 /* list of struct igmp_sock */
179 pim_ifp
->igmp_socket_list
= list_new();
180 if (!pim_ifp
->igmp_socket_list
) {
181 zlog_err("%s: failure: igmp_socket_list=list_new()",
182 __PRETTY_FUNCTION__
);
183 return if_list_clean(pim_ifp
);
185 pim_ifp
->igmp_socket_list
->del
= (void (*)(void *))igmp_sock_free
;
187 /* list of struct pim_neighbor */
188 pim_ifp
->pim_neighbor_list
= list_new();
189 if (!pim_ifp
->pim_neighbor_list
) {
190 zlog_err("%s: failure: pim_neighbor_list=list_new()",
191 __PRETTY_FUNCTION__
);
192 return if_list_clean(pim_ifp
);
194 pim_ifp
->pim_neighbor_list
->del
= (void (*)(void *))pim_neighbor_free
;
196 pim_ifp
->upstream_switch_list
= list_new();
197 if (!pim_ifp
->upstream_switch_list
) {
198 zlog_err("%s: failure: upstream_switch_list=list_new()",
199 __PRETTY_FUNCTION__
);
200 return if_list_clean(pim_ifp
);
202 pim_ifp
->upstream_switch_list
->del
=
203 (void (*)(void *))pim_jp_agg_group_list_free
;
204 pim_ifp
->upstream_switch_list
->cmp
= pim_jp_agg_group_list_cmp
;
206 pim_ifp
->sec_addr_list
= list_new();
207 if (!pim_ifp
->sec_addr_list
) {
208 zlog_err("%s: failure: secondary addresslist",
209 __PRETTY_FUNCTION__
);
210 return if_list_clean(pim_ifp
);
212 pim_ifp
->sec_addr_list
->del
= (void (*)(void *))pim_sec_addr_free
;
213 pim_ifp
->sec_addr_list
->cmp
=
214 (int (*)(void *, void *))pim_sec_addr_comp
;
216 RB_INIT(pim_ifchannel_rb
, &pim_ifp
->ifchannel_rb
);
227 void pim_if_delete(struct interface
*ifp
)
229 struct pim_interface
*pim_ifp
;
230 struct pim_ifchannel
*ch
;
236 if (pim_ifp
->igmp_join_list
) {
237 pim_if_igmp_join_del_all(ifp
);
240 pim_ifchannel_delete_all(ifp
);
241 igmp_sock_delete_all(ifp
);
243 pim_neighbor_delete_all(ifp
, "Interface removed from configuration");
247 list_delete_and_null(&pim_ifp
->igmp_socket_list
);
248 list_delete_and_null(&pim_ifp
->pim_neighbor_list
);
249 list_delete_and_null(&pim_ifp
->upstream_switch_list
);
250 list_delete_and_null(&pim_ifp
->sec_addr_list
);
252 if (pim_ifp
->boundary_oil_plist
)
253 XFREE(MTYPE_PIM_INTERFACE
, pim_ifp
->boundary_oil_plist
);
255 while (!RB_EMPTY(pim_ifchannel_rb
, &pim_ifp
->ifchannel_rb
)) {
256 ch
= RB_ROOT(pim_ifchannel_rb
, &pim_ifp
->ifchannel_rb
);
258 pim_ifchannel_delete(ch
);
261 XFREE(MTYPE_PIM_INTERFACE
, pim_ifp
);
266 void pim_if_update_could_assert(struct interface
*ifp
)
268 struct pim_interface
*pim_ifp
;
269 struct pim_ifchannel
*ch
;
274 RB_FOREACH (ch
, pim_ifchannel_rb
, &pim_ifp
->ifchannel_rb
) {
275 pim_ifchannel_update_could_assert(ch
);
279 static void pim_if_update_my_assert_metric(struct interface
*ifp
)
281 struct pim_interface
*pim_ifp
;
282 struct pim_ifchannel
*ch
;
287 RB_FOREACH (ch
, pim_ifchannel_rb
, &pim_ifp
->ifchannel_rb
) {
288 pim_ifchannel_update_my_assert_metric(ch
);
292 static void pim_addr_change(struct interface
*ifp
)
294 struct pim_interface
*pim_ifp
;
299 pim_if_dr_election(ifp
); /* router's own DR Priority (addr) changes --
301 pim_if_update_join_desired(pim_ifp
); /* depends on DR */
302 pim_if_update_could_assert(ifp
); /* depends on DR */
303 pim_if_update_my_assert_metric(ifp
); /* depends on could_assert */
304 pim_if_update_assert_tracking_desired(
305 ifp
); /* depends on DR, join_desired */
308 RFC 4601: 4.3.1. Sending Hello Messages
310 1) Before an interface goes down or changes primary IP address, a
311 Hello message with a zero HoldTime should be sent immediately
312 (with the old IP address if the IP address changed).
313 -- FIXME See CAVEAT C13
315 2) After an interface has changed its IP address, it MUST send a
316 Hello message with its new IP address.
319 3) If an interface changes one of its secondary IP addresses, a
320 Hello message with an updated Address_List option and a non-zero
321 HoldTime should be sent immediately.
322 -- FIXME See TODO T31
324 pim_ifp
->pim_ifstat_hello_sent
= 0; /* reset hello counter */
325 if (pim_ifp
->pim_sock_fd
< 0)
327 pim_hello_restart_now(ifp
); /* send hello and restart timer */
330 static int detect_primary_address_change(struct interface
*ifp
,
331 int force_prim_as_any
,
334 struct pim_interface
*pim_ifp
= ifp
->info
;
335 struct in_addr new_prim_addr
;
338 if (force_prim_as_any
)
339 new_prim_addr
.s_addr
= INADDR_ANY
;
341 new_prim_addr
= pim_find_primary_addr(ifp
);
343 changed
= new_prim_addr
.s_addr
!= pim_ifp
->primary_address
.s_addr
;
345 if (PIM_DEBUG_ZEBRA
) {
346 char new_prim_str
[INET_ADDRSTRLEN
];
347 char old_prim_str
[INET_ADDRSTRLEN
];
348 pim_inet4_dump("<new?>", new_prim_addr
, new_prim_str
,
349 sizeof(new_prim_str
));
350 pim_inet4_dump("<old?>", pim_ifp
->primary_address
, old_prim_str
,
351 sizeof(old_prim_str
));
352 zlog_debug("%s: old=%s new=%s on interface %s: %s",
353 __PRETTY_FUNCTION__
, old_prim_str
, new_prim_str
,
354 ifp
->name
, changed
? "changed" : "unchanged");
358 pim_ifp
->primary_address
= new_prim_addr
;
364 static struct pim_secondary_addr
*
365 pim_sec_addr_find(struct pim_interface
*pim_ifp
, struct prefix
*addr
)
367 struct pim_secondary_addr
*sec_addr
;
368 struct listnode
*node
;
370 for (ALL_LIST_ELEMENTS_RO(pim_ifp
->sec_addr_list
, node
, sec_addr
)) {
371 if (prefix_cmp(&sec_addr
->addr
, addr
)) {
379 static void pim_sec_addr_del(struct pim_interface
*pim_ifp
,
380 struct pim_secondary_addr
*sec_addr
)
382 listnode_delete(pim_ifp
->sec_addr_list
, sec_addr
);
383 pim_sec_addr_free(sec_addr
);
386 static int pim_sec_addr_add(struct pim_interface
*pim_ifp
, struct prefix
*addr
)
389 struct pim_secondary_addr
*sec_addr
;
391 sec_addr
= pim_sec_addr_find(pim_ifp
, addr
);
393 sec_addr
->flags
&= ~PIM_SEC_ADDRF_STALE
;
397 sec_addr
= XCALLOC(MTYPE_PIM_SEC_ADDR
, sizeof(*sec_addr
));
402 sec_addr
->addr
= *addr
;
403 listnode_add_sort(pim_ifp
->sec_addr_list
, sec_addr
);
408 static int pim_sec_addr_del_all(struct pim_interface
*pim_ifp
)
412 if (!list_isempty(pim_ifp
->sec_addr_list
)) {
414 /* remove all nodes and free up the list itself */
415 list_delete_all_node(pim_ifp
->sec_addr_list
);
421 static int pim_sec_addr_update(struct interface
*ifp
)
423 struct pim_interface
*pim_ifp
= ifp
->info
;
424 struct connected
*ifc
;
425 struct listnode
*node
;
426 struct listnode
*nextnode
;
427 struct pim_secondary_addr
*sec_addr
;
430 for (ALL_LIST_ELEMENTS_RO(pim_ifp
->sec_addr_list
, node
, sec_addr
)) {
431 sec_addr
->flags
|= PIM_SEC_ADDRF_STALE
;
434 for (ALL_LIST_ELEMENTS_RO(ifp
->connected
, node
, ifc
)) {
435 struct prefix
*p
= ifc
->address
;
437 if (PIM_INADDR_IS_ANY(p
->u
.prefix4
)) {
441 if (pim_ifp
->primary_address
.s_addr
== p
->u
.prefix4
.s_addr
) {
442 /* don't add the primary address into the secondary
447 if (pim_sec_addr_add(pim_ifp
, p
)) {
452 /* Drop stale entries */
453 for (ALL_LIST_ELEMENTS(pim_ifp
->sec_addr_list
, node
, nextnode
,
455 if (sec_addr
->flags
& PIM_SEC_ADDRF_STALE
) {
456 pim_sec_addr_del(pim_ifp
, sec_addr
);
464 static int detect_secondary_address_change(struct interface
*ifp
,
465 int force_prim_as_any
,
468 struct pim_interface
*pim_ifp
= ifp
->info
;
471 if (force_prim_as_any
) {
472 /* if primary address is being forced to zero just flush the
473 * secondary address list */
474 changed
= pim_sec_addr_del_all(pim_ifp
);
476 /* re-evaluate the secondary address list */
477 changed
= pim_sec_addr_update(ifp
);
483 static void detect_address_change(struct interface
*ifp
, int force_prim_as_any
,
487 struct pim_interface
*pim_ifp
;
493 if (detect_primary_address_change(ifp
, force_prim_as_any
, caller
)) {
497 if (detect_secondary_address_change(ifp
, force_prim_as_any
, caller
)) {
503 if (!PIM_IF_TEST_PIM(pim_ifp
->options
)) {
507 pim_addr_change(ifp
);
510 /* XXX: if we have unnumbered interfaces we need to run detect address
511 * address change on all of them when the lo address changes */
514 int pim_update_source_set(struct interface
*ifp
, struct in_addr source
)
516 struct pim_interface
*pim_ifp
= ifp
->info
;
519 return PIM_IFACE_NOT_FOUND
;
522 if (pim_ifp
->update_source
.s_addr
== source
.s_addr
) {
523 return PIM_UPDATE_SOURCE_DUP
;
526 pim_ifp
->update_source
= source
;
527 detect_address_change(ifp
, 0 /* force_prim_as_any */,
528 __PRETTY_FUNCTION__
);
533 void pim_if_addr_add(struct connected
*ifc
)
535 struct pim_interface
*pim_ifp
;
536 struct interface
*ifp
;
537 struct in_addr ifaddr
;
547 if (!if_is_operative(ifp
))
550 if (PIM_DEBUG_ZEBRA
) {
552 prefix2str(ifc
->address
, buf
, BUFSIZ
);
553 zlog_debug("%s: %s ifindex=%d connected IP address %s %s",
554 __PRETTY_FUNCTION__
, ifp
->name
, ifp
->ifindex
, buf
,
555 CHECK_FLAG(ifc
->flags
, ZEBRA_IFA_SECONDARY
)
560 ifaddr
= ifc
->address
->u
.prefix4
;
562 detect_address_change(ifp
, 0, __PRETTY_FUNCTION__
);
564 // if (ifc->address->family != AF_INET)
567 if (PIM_IF_TEST_IGMP(pim_ifp
->options
)) {
568 struct igmp_sock
*igmp
;
570 /* lookup IGMP socket */
571 igmp
= pim_igmp_sock_lookup_ifaddr(pim_ifp
->igmp_socket_list
,
574 /* if addr new, add IGMP socket */
575 if (ifc
->address
->family
== AF_INET
)
576 pim_igmp_sock_add(pim_ifp
->igmp_socket_list
,
580 /* Replay Static IGMP groups */
581 if (pim_ifp
->igmp_join_list
) {
582 struct listnode
*node
;
583 struct listnode
*nextnode
;
584 struct igmp_join
*ij
;
587 for (ALL_LIST_ELEMENTS(pim_ifp
->igmp_join_list
, node
,
589 /* Close socket and reopen with Source and Group
592 join_fd
= igmp_join_sock(
593 ifp
->name
, ifp
->ifindex
, ij
->group_addr
,
596 char group_str
[INET_ADDRSTRLEN
];
597 char source_str
[INET_ADDRSTRLEN
];
598 pim_inet4_dump("<grp?>", ij
->group_addr
,
602 "<src?>", ij
->source_addr
,
603 source_str
, sizeof(source_str
));
605 "%s: igmp_join_sock() failure for IGMP group %s source %s on interface %s",
606 __PRETTY_FUNCTION__
, group_str
,
607 source_str
, ifp
->name
);
610 ij
->sock_fd
= join_fd
;
615 if (PIM_IF_TEST_PIM(pim_ifp
->options
)) {
617 if (PIM_INADDR_ISNOT_ANY(pim_ifp
->primary_address
)) {
619 /* Interface has a valid socket ? */
620 if (pim_ifp
->pim_sock_fd
< 0) {
621 if (pim_sock_add(ifp
)) {
623 "Failure creating PIM socket for interface %s",
627 struct pim_nexthop_cache
*pnc
= NULL
;
629 struct zclient
*zclient
= NULL
;
631 zclient
= pim_zebra_zclient_get();
632 /* RP config might come prior to (local RP's interface)
634 In this case, pnc would not have pim enabled
636 Once Interface is UP and pim info is available,
638 with RNH address to receive update and add the
639 interface as nexthop. */
640 memset(&rpf
, 0, sizeof(struct pim_rpf
));
641 rpf
.rpf_addr
.family
= AF_INET
;
642 rpf
.rpf_addr
.prefixlen
= IPV4_MAX_BITLEN
;
643 rpf
.rpf_addr
.u
.prefix4
= ifc
->address
->u
.prefix4
;
644 pnc
= pim_nexthop_cache_find(pim_ifp
->pim
, &rpf
);
646 pim_sendmsg_zebra_rnh(pim_ifp
->pim
, zclient
,
648 ZEBRA_NEXTHOP_REGISTER
);
653 PIM or IGMP is enabled on interface, and there is at least one
654 address assigned, then try to create a vif_index.
656 if (pim_ifp
->mroute_vif_index
< 0) {
659 pim_ifchannel_scan_forward_start(ifp
);
662 static void pim_if_addr_del_igmp(struct connected
*ifc
)
664 struct pim_interface
*pim_ifp
= ifc
->ifp
->info
;
665 struct igmp_sock
*igmp
;
666 struct in_addr ifaddr
;
668 if (ifc
->address
->family
!= AF_INET
) {
669 /* non-IPv4 address */
674 /* IGMP not enabled on interface */
678 ifaddr
= ifc
->address
->u
.prefix4
;
680 /* lookup IGMP socket */
681 igmp
= pim_igmp_sock_lookup_ifaddr(pim_ifp
->igmp_socket_list
, ifaddr
);
683 /* if addr found, del IGMP socket */
684 igmp_sock_delete(igmp
);
688 static void pim_if_addr_del_pim(struct connected
*ifc
)
690 struct pim_interface
*pim_ifp
= ifc
->ifp
->info
;
692 if (ifc
->address
->family
!= AF_INET
) {
693 /* non-IPv4 address */
698 /* PIM not enabled on interface */
702 if (PIM_INADDR_ISNOT_ANY(pim_ifp
->primary_address
)) {
703 /* Interface keeps a valid primary address */
707 if (pim_ifp
->pim_sock_fd
< 0) {
708 /* Interface does not hold a valid socket any longer */
713 pim_sock_delete() closes the socket, stops read and timer threads,
714 and kills all neighbors.
716 pim_sock_delete(ifc
->ifp
,
717 "last address has been removed from interface");
720 void pim_if_addr_del(struct connected
*ifc
, int force_prim_as_any
)
722 struct interface
*ifp
;
728 if (PIM_DEBUG_ZEBRA
) {
730 prefix2str(ifc
->address
, buf
, BUFSIZ
);
731 zlog_debug("%s: %s ifindex=%d disconnected IP address %s %s",
732 __PRETTY_FUNCTION__
, ifp
->name
, ifp
->ifindex
, buf
,
733 CHECK_FLAG(ifc
->flags
, ZEBRA_IFA_SECONDARY
)
738 detect_address_change(ifp
, force_prim_as_any
, __PRETTY_FUNCTION__
);
740 pim_if_addr_del_igmp(ifc
);
741 pim_if_addr_del_pim(ifc
);
744 void pim_if_addr_add_all(struct interface
*ifp
)
746 struct connected
*ifc
;
747 struct listnode
*node
;
748 struct listnode
*nextnode
;
751 struct pim_interface
*pim_ifp
= ifp
->info
;
754 /* PIM/IGMP enabled ? */
758 for (ALL_LIST_ELEMENTS(ifp
->connected
, node
, nextnode
, ifc
)) {
759 struct prefix
*p
= ifc
->address
;
761 if (p
->family
!= AF_INET
)
765 pim_if_addr_add(ifc
);
768 if (!v4_addrs
&& v6_addrs
&& !if_is_loopback(ifp
)) {
769 if (PIM_IF_TEST_PIM(pim_ifp
->options
)) {
771 /* Interface has a valid primary address ? */
772 if (PIM_INADDR_ISNOT_ANY(pim_ifp
->primary_address
)) {
774 /* Interface has a valid socket ? */
775 if (pim_ifp
->pim_sock_fd
< 0) {
776 if (pim_sock_add(ifp
)) {
778 "Failure creating PIM socket for interface %s",
786 * PIM or IGMP is enabled on interface, and there is at least one
787 * address assigned, then try to create a vif_index.
789 if (pim_ifp
->mroute_vif_index
< 0) {
792 pim_ifchannel_scan_forward_start(ifp
);
794 pim_rp_setup(pim_ifp
->pim
);
795 pim_rp_check_on_if_add(pim_ifp
);
798 void pim_if_addr_del_all(struct interface
*ifp
)
800 struct connected
*ifc
;
801 struct listnode
*node
;
802 struct listnode
*nextnode
;
803 struct vrf
*vrf
= vrf_lookup_by_id(ifp
->vrf_id
);
804 struct pim_instance
*pim
;
810 /* PIM/IGMP enabled ? */
814 for (ALL_LIST_ELEMENTS(ifp
->connected
, node
, nextnode
, ifc
)) {
815 struct prefix
*p
= ifc
->address
;
817 if (p
->family
!= AF_INET
)
820 pim_if_addr_del(ifc
, 1 /* force_prim_as_any=true */);
824 pim_i_am_rp_re_evaluate(pim
);
827 void pim_if_addr_del_all_igmp(struct interface
*ifp
)
829 struct connected
*ifc
;
830 struct listnode
*node
;
831 struct listnode
*nextnode
;
833 /* PIM/IGMP enabled ? */
837 for (ALL_LIST_ELEMENTS(ifp
->connected
, node
, nextnode
, ifc
)) {
838 struct prefix
*p
= ifc
->address
;
840 if (p
->family
!= AF_INET
)
843 pim_if_addr_del_igmp(ifc
);
847 void pim_if_addr_del_all_pim(struct interface
*ifp
)
849 struct connected
*ifc
;
850 struct listnode
*node
;
851 struct listnode
*nextnode
;
853 /* PIM/IGMP enabled ? */
857 for (ALL_LIST_ELEMENTS(ifp
->connected
, node
, nextnode
, ifc
)) {
858 struct prefix
*p
= ifc
->address
;
860 if (p
->family
!= AF_INET
)
863 pim_if_addr_del_pim(ifc
);
867 struct in_addr
pim_find_primary_addr(struct interface
*ifp
)
869 struct connected
*ifc
;
870 struct listnode
*node
;
871 struct in_addr addr
= {0};
874 struct pim_interface
*pim_ifp
= ifp
->info
;
875 struct vrf
*vrf
= vrf_lookup_by_id(ifp
->vrf_id
);
880 if (pim_ifp
&& PIM_INADDR_ISNOT_ANY(pim_ifp
->update_source
)) {
881 return pim_ifp
->update_source
;
884 for (ALL_LIST_ELEMENTS_RO(ifp
->connected
, node
, ifc
)) {
885 struct prefix
*p
= ifc
->address
;
887 if (p
->family
!= AF_INET
) {
892 if (PIM_INADDR_IS_ANY(p
->u
.prefix4
)) {
894 "%s: null IPv4 address connected to interface %s",
895 __PRETTY_FUNCTION__
, ifp
->name
);
901 if (CHECK_FLAG(ifc
->flags
, ZEBRA_IFA_SECONDARY
))
908 * If we have no v4_addrs and v6 is configured
909 * We probably are using unnumbered
910 * So let's grab the loopbacks v4 address
911 * and use that as the primary address
913 if (!v4_addrs
&& v6_addrs
&& !if_is_loopback(ifp
)) {
914 struct interface
*lo_ifp
;
915 // DBS - Come back and check here
916 if (ifp
->vrf_id
== VRF_DEFAULT
)
917 lo_ifp
= if_lookup_by_name("lo", vrf
->vrf_id
);
919 lo_ifp
= if_lookup_by_name(vrf
->name
, vrf
->vrf_id
);
922 return pim_find_primary_addr(lo_ifp
);
925 addr
.s_addr
= PIM_NET_INADDR_ANY
;
930 static int pim_iface_next_vif_index(struct interface
*ifp
)
932 struct pim_interface
*pim_ifp
= ifp
->info
;
933 struct pim_instance
*pim
= pim_ifp
->pim
;
937 * The pimreg vif is always going to be in index 0
940 if (ifp
->ifindex
== PIM_OIF_PIM_REGISTER_VIF
)
943 for (i
= 1; i
< MAXVIFS
; i
++) {
944 if (pim
->iface_vif_index
[i
] == 0)
951 pim_if_add_vif() uses ifindex as vif_index
953 see also pim_if_find_vifindex_by_ifindex()
955 int pim_if_add_vif(struct interface
*ifp
)
957 struct pim_interface
*pim_ifp
= ifp
->info
;
958 struct in_addr ifaddr
;
959 unsigned char flags
= 0;
963 if (pim_ifp
->mroute_vif_index
> 0) {
964 zlog_warn("%s: vif_index=%d > 0 on interface %s ifindex=%d",
965 __PRETTY_FUNCTION__
, pim_ifp
->mroute_vif_index
,
966 ifp
->name
, ifp
->ifindex
);
970 if (ifp
->ifindex
< 0) {
971 zlog_warn("%s: ifindex=%d < 1 on interface %s",
972 __PRETTY_FUNCTION__
, ifp
->ifindex
, ifp
->name
);
976 ifaddr
= pim_ifp
->primary_address
;
977 if (ifp
->ifindex
!= PIM_OIF_PIM_REGISTER_VIF
978 && PIM_INADDR_IS_ANY(ifaddr
)) {
980 "%s: could not get address for interface %s ifindex=%d",
981 __PRETTY_FUNCTION__
, ifp
->name
, ifp
->ifindex
);
985 pim_ifp
->mroute_vif_index
= pim_iface_next_vif_index(ifp
);
987 if (pim_ifp
->mroute_vif_index
>= MAXVIFS
) {
989 "%s: Attempting to configure more than MAXVIFS=%d on pim enabled interface %s",
990 __PRETTY_FUNCTION__
, MAXVIFS
, ifp
->name
);
994 if (ifp
->ifindex
== PIM_OIF_PIM_REGISTER_VIF
)
995 flags
= VIFF_REGISTER
;
996 #ifdef VIFF_USE_IFINDEX
998 flags
= VIFF_USE_IFINDEX
;
1001 if (pim_mroute_add_vif(ifp
, ifaddr
, flags
)) {
1002 /* pim_mroute_add_vif reported error */
1006 pim_ifp
->pim
->iface_vif_index
[pim_ifp
->mroute_vif_index
] = 1;
1010 int pim_if_del_vif(struct interface
*ifp
)
1012 struct pim_interface
*pim_ifp
= ifp
->info
;
1014 if (pim_ifp
->mroute_vif_index
< 1) {
1015 zlog_warn("%s: vif_index=%d < 1 on interface %s ifindex=%d",
1016 __PRETTY_FUNCTION__
, pim_ifp
->mroute_vif_index
,
1017 ifp
->name
, ifp
->ifindex
);
1021 pim_mroute_del_vif(ifp
);
1026 pim_ifp
->pim
->iface_vif_index
[pim_ifp
->mroute_vif_index
] = 0;
1028 pim_ifp
->mroute_vif_index
= -1;
1034 struct interface
*pim_if_find_by_vif_index(struct pim_instance
*pim
,
1035 ifindex_t vif_index
)
1037 struct interface
*ifp
;
1039 FOR_ALL_INTERFACES (pim
->vrf
, ifp
) {
1041 struct pim_interface
*pim_ifp
;
1042 pim_ifp
= ifp
->info
;
1044 if (vif_index
== pim_ifp
->mroute_vif_index
)
1053 pim_if_add_vif() uses ifindex as vif_index
1055 int pim_if_find_vifindex_by_ifindex(struct pim_instance
*pim
, ifindex_t ifindex
)
1057 struct pim_interface
*pim_ifp
;
1058 struct interface
*ifp
;
1060 ifp
= if_lookup_by_index(ifindex
, pim
->vrf_id
);
1061 if (!ifp
|| !ifp
->info
)
1063 pim_ifp
= ifp
->info
;
1065 return pim_ifp
->mroute_vif_index
;
1068 int pim_if_lan_delay_enabled(struct interface
*ifp
)
1070 struct pim_interface
*pim_ifp
;
1072 pim_ifp
= ifp
->info
;
1074 zassert(pim_ifp
->pim_number_of_nonlandelay_neighbors
>= 0);
1076 return pim_ifp
->pim_number_of_nonlandelay_neighbors
== 0;
1079 uint16_t pim_if_effective_propagation_delay_msec(struct interface
*ifp
)
1081 if (pim_if_lan_delay_enabled(ifp
)) {
1082 struct pim_interface
*pim_ifp
;
1083 pim_ifp
= ifp
->info
;
1084 return pim_ifp
->pim_neighbors_highest_propagation_delay_msec
;
1086 return PIM_DEFAULT_PROPAGATION_DELAY_MSEC
;
1090 uint16_t pim_if_effective_override_interval_msec(struct interface
*ifp
)
1092 if (pim_if_lan_delay_enabled(ifp
)) {
1093 struct pim_interface
*pim_ifp
;
1094 pim_ifp
= ifp
->info
;
1095 return pim_ifp
->pim_neighbors_highest_override_interval_msec
;
1097 return PIM_DEFAULT_OVERRIDE_INTERVAL_MSEC
;
1101 int pim_if_t_override_msec(struct interface
*ifp
)
1103 int effective_override_interval_msec
;
1104 int t_override_msec
;
1106 effective_override_interval_msec
=
1107 pim_if_effective_override_interval_msec(ifp
);
1109 t_override_msec
= random() % (effective_override_interval_msec
+ 1);
1111 return t_override_msec
;
1114 uint16_t pim_if_jp_override_interval_msec(struct interface
*ifp
)
1116 return pim_if_effective_propagation_delay_msec(ifp
)
1117 + pim_if_effective_override_interval_msec(ifp
);
1121 RFC 4601: 4.1.6. State Summarization Macros
1123 The function NBR( I, A ) uses information gathered through PIM Hello
1124 messages to map the IP address A of a directly connected PIM
1125 neighbor router on interface I to the primary IP address of the same
1126 router (Section 4.3.4). The primary IP address of a neighbor is the
1127 address that it uses as the source of its PIM Hello messages.
1129 struct pim_neighbor
*pim_if_find_neighbor(struct interface
*ifp
,
1130 struct in_addr addr
)
1132 struct listnode
*neighnode
;
1133 struct pim_neighbor
*neigh
;
1134 struct pim_interface
*pim_ifp
;
1139 pim_ifp
= ifp
->info
;
1141 zlog_warn("%s: multicast not enabled on interface %s",
1142 __PRETTY_FUNCTION__
, ifp
->name
);
1148 p
.prefixlen
= IPV4_MAX_PREFIXLEN
;
1150 for (ALL_LIST_ELEMENTS_RO(pim_ifp
->pim_neighbor_list
, neighnode
,
1153 /* primary address ? */
1154 if (neigh
->source_addr
.s_addr
== addr
.s_addr
)
1157 /* secondary address ? */
1158 if (pim_neighbor_find_secondary(neigh
, &p
))
1162 if (PIM_DEBUG_PIM_TRACE
) {
1163 char addr_str
[INET_ADDRSTRLEN
];
1164 pim_inet4_dump("<addr?>", addr
, addr_str
, sizeof(addr_str
));
1166 "%s: neighbor not found for address %s on interface %s",
1167 __PRETTY_FUNCTION__
, addr_str
, ifp
->name
);
1173 long pim_if_t_suppressed_msec(struct interface
*ifp
)
1175 struct pim_interface
*pim_ifp
;
1176 long t_suppressed_msec
;
1177 uint32_t ramount
= 0;
1179 pim_ifp
= ifp
->info
;
1182 /* join suppression disabled ? */
1183 if (PIM_IF_TEST_PIM_CAN_DISABLE_JOIN_SUPRESSION(pim_ifp
->options
))
1186 /* t_suppressed = t_periodic * rand(1.1, 1.4) */
1187 ramount
= 1100 + (random() % (1400 - 1100 + 1));
1188 t_suppressed_msec
= qpim_t_periodic
* ramount
;
1190 return t_suppressed_msec
;
1193 static void igmp_join_free(struct igmp_join
*ij
)
1195 XFREE(MTYPE_PIM_IGMP_JOIN
, ij
);
1198 static struct igmp_join
*igmp_join_find(struct list
*join_list
,
1199 struct in_addr group_addr
,
1200 struct in_addr source_addr
)
1202 struct listnode
*node
;
1203 struct igmp_join
*ij
;
1207 for (ALL_LIST_ELEMENTS_RO(join_list
, node
, ij
)) {
1208 if ((group_addr
.s_addr
== ij
->group_addr
.s_addr
)
1209 && (source_addr
.s_addr
== ij
->source_addr
.s_addr
))
1216 static int igmp_join_sock(const char *ifname
, ifindex_t ifindex
,
1217 struct in_addr group_addr
, struct in_addr source_addr
)
1221 join_fd
= pim_socket_raw(IPPROTO_IGMP
);
1226 if (pim_socket_join_source(join_fd
, ifindex
, group_addr
, source_addr
,
1235 static struct igmp_join
*igmp_join_new(struct interface
*ifp
,
1236 struct in_addr group_addr
,
1237 struct in_addr source_addr
)
1239 struct pim_interface
*pim_ifp
;
1240 struct igmp_join
*ij
;
1243 pim_ifp
= ifp
->info
;
1246 join_fd
= igmp_join_sock(ifp
->name
, ifp
->ifindex
, group_addr
,
1249 char group_str
[INET_ADDRSTRLEN
];
1250 char source_str
[INET_ADDRSTRLEN
];
1251 pim_inet4_dump("<grp?>", group_addr
, group_str
,
1253 pim_inet4_dump("<src?>", source_addr
, source_str
,
1254 sizeof(source_str
));
1256 "%s: igmp_join_sock() failure for IGMP group %s source %s on interface %s",
1257 __PRETTY_FUNCTION__
, group_str
, source_str
, ifp
->name
);
1261 ij
= XCALLOC(MTYPE_PIM_IGMP_JOIN
, sizeof(*ij
));
1263 char group_str
[INET_ADDRSTRLEN
];
1264 char source_str
[INET_ADDRSTRLEN
];
1265 pim_inet4_dump("<grp?>", group_addr
, group_str
,
1267 pim_inet4_dump("<src?>", source_addr
, source_str
,
1268 sizeof(source_str
));
1270 "%s: XCALLOC(%zu) failure for IGMP group %s source %s on interface %s",
1271 __PRETTY_FUNCTION__
, sizeof(*ij
), group_str
, source_str
,
1277 ij
->sock_fd
= join_fd
;
1278 ij
->group_addr
= group_addr
;
1279 ij
->source_addr
= source_addr
;
1280 ij
->sock_creation
= pim_time_monotonic_sec();
1282 listnode_add(pim_ifp
->igmp_join_list
, ij
);
1287 ferr_r
pim_if_igmp_join_add(struct interface
*ifp
, struct in_addr group_addr
,
1288 struct in_addr source_addr
)
1290 struct pim_interface
*pim_ifp
;
1291 struct igmp_join
*ij
;
1293 pim_ifp
= ifp
->info
;
1295 return ferr_cfg_invalid("multicast not enabled on interface %s",
1299 if (!pim_ifp
->igmp_join_list
) {
1300 pim_ifp
->igmp_join_list
= list_new();
1301 if (!pim_ifp
->igmp_join_list
) {
1302 return ferr_cfg_invalid("Insufficient memory");
1304 pim_ifp
->igmp_join_list
->del
= (void (*)(void *))igmp_join_free
;
1307 ij
= igmp_join_find(pim_ifp
->igmp_join_list
, group_addr
, source_addr
);
1309 /* This interface has already been configured to join this IGMP group
1315 ij
= igmp_join_new(ifp
, group_addr
, source_addr
);
1317 return ferr_cfg_invalid(
1318 "Failure to create new join data structure, see log file for more information");
1321 if (PIM_DEBUG_IGMP_EVENTS
) {
1322 char group_str
[INET_ADDRSTRLEN
];
1323 char source_str
[INET_ADDRSTRLEN
];
1324 pim_inet4_dump("<grp?>", group_addr
, group_str
,
1326 pim_inet4_dump("<src?>", source_addr
, source_str
,
1327 sizeof(source_str
));
1329 "%s: issued static igmp join for channel (S,G)=(%s,%s) on interface %s",
1330 __PRETTY_FUNCTION__
, source_str
, group_str
, ifp
->name
);
1337 int pim_if_igmp_join_del(struct interface
*ifp
, struct in_addr group_addr
,
1338 struct in_addr source_addr
)
1340 struct pim_interface
*pim_ifp
;
1341 struct igmp_join
*ij
;
1343 pim_ifp
= ifp
->info
;
1345 zlog_warn("%s: multicast not enabled on interface %s",
1346 __PRETTY_FUNCTION__
, ifp
->name
);
1350 if (!pim_ifp
->igmp_join_list
) {
1351 zlog_warn("%s: no IGMP join on interface %s",
1352 __PRETTY_FUNCTION__
, ifp
->name
);
1356 ij
= igmp_join_find(pim_ifp
->igmp_join_list
, group_addr
, source_addr
);
1358 char group_str
[INET_ADDRSTRLEN
];
1359 char source_str
[INET_ADDRSTRLEN
];
1360 pim_inet4_dump("<grp?>", group_addr
, group_str
,
1362 pim_inet4_dump("<src?>", source_addr
, source_str
,
1363 sizeof(source_str
));
1365 "%s: could not find IGMP group %s source %s on interface %s",
1366 __PRETTY_FUNCTION__
, group_str
, source_str
, ifp
->name
);
1370 if (close(ij
->sock_fd
)) {
1371 char group_str
[INET_ADDRSTRLEN
];
1372 char source_str
[INET_ADDRSTRLEN
];
1373 pim_inet4_dump("<grp?>", group_addr
, group_str
,
1375 pim_inet4_dump("<src?>", source_addr
, source_str
,
1376 sizeof(source_str
));
1378 "%s: failure closing sock_fd=%d for IGMP group %s source %s on interface %s: errno=%d: %s",
1379 __PRETTY_FUNCTION__
, ij
->sock_fd
, group_str
, source_str
,
1380 ifp
->name
, errno
, safe_strerror(errno
));
1383 listnode_delete(pim_ifp
->igmp_join_list
, ij
);
1385 if (listcount(pim_ifp
->igmp_join_list
) < 1) {
1386 list_delete_and_null(&pim_ifp
->igmp_join_list
);
1387 pim_ifp
->igmp_join_list
= 0;
1393 static void pim_if_igmp_join_del_all(struct interface
*ifp
)
1395 struct pim_interface
*pim_ifp
;
1396 struct listnode
*node
;
1397 struct listnode
*nextnode
;
1398 struct igmp_join
*ij
;
1400 pim_ifp
= ifp
->info
;
1402 zlog_warn("%s: multicast not enabled on interface %s",
1403 __PRETTY_FUNCTION__
, ifp
->name
);
1407 if (!pim_ifp
->igmp_join_list
)
1410 for (ALL_LIST_ELEMENTS(pim_ifp
->igmp_join_list
, node
, nextnode
, ij
))
1411 pim_if_igmp_join_del(ifp
, ij
->group_addr
, ij
->source_addr
);
1417 Transitions from "I am Assert Loser" State
1419 Current Winner's GenID Changes or NLT Expires
1421 The Neighbor Liveness Timer associated with the current winner
1422 expires or we receive a Hello message from the current winner
1423 reporting a different GenID from the one it previously reported.
1424 This indicates that the current winner's interface or router has
1425 gone down (and may have come back up), and so we must assume it no
1426 longer knows it was the winner.
1428 void pim_if_assert_on_neighbor_down(struct interface
*ifp
,
1429 struct in_addr neigh_addr
)
1431 struct pim_interface
*pim_ifp
;
1432 struct pim_ifchannel
*ch
;
1434 pim_ifp
= ifp
->info
;
1437 RB_FOREACH (ch
, pim_ifchannel_rb
, &pim_ifp
->ifchannel_rb
) {
1438 /* Is (S,G,I) assert loser ? */
1439 if (ch
->ifassert_state
!= PIM_IFASSERT_I_AM_LOSER
)
1441 /* Dead neighbor was winner ? */
1442 if (ch
->ifassert_winner
.s_addr
!= neigh_addr
.s_addr
)
1445 assert_action_a5(ch
);
1449 void pim_if_update_join_desired(struct pim_interface
*pim_ifp
)
1451 struct pim_ifchannel
*ch
;
1453 /* clear off flag from interface's upstreams */
1454 RB_FOREACH (ch
, pim_ifchannel_rb
, &pim_ifp
->ifchannel_rb
) {
1455 PIM_UPSTREAM_FLAG_UNSET_DR_JOIN_DESIRED_UPDATED(
1456 ch
->upstream
->flags
);
1459 /* scan per-interface (S,G,I) state on this I interface */
1460 RB_FOREACH (ch
, pim_ifchannel_rb
, &pim_ifp
->ifchannel_rb
) {
1461 struct pim_upstream
*up
= ch
->upstream
;
1463 if (PIM_UPSTREAM_FLAG_TEST_DR_JOIN_DESIRED_UPDATED(up
->flags
))
1466 /* update join_desired for the global (S,G) state */
1467 pim_upstream_update_join_desired(pim_ifp
->pim
, up
);
1468 PIM_UPSTREAM_FLAG_SET_DR_JOIN_DESIRED_UPDATED(up
->flags
);
1472 void pim_if_update_assert_tracking_desired(struct interface
*ifp
)
1474 struct pim_interface
*pim_ifp
;
1475 struct pim_ifchannel
*ch
;
1477 pim_ifp
= ifp
->info
;
1481 RB_FOREACH (ch
, pim_ifchannel_rb
, &pim_ifp
->ifchannel_rb
) {
1482 pim_ifchannel_update_assert_tracking_desired(ch
);
1487 * PIM wants to have an interface pointer for everything it does.
1488 * The pimreg is a special interface that we have that is not
1489 * quite an inteface but a VIF is created for it.
1491 void pim_if_create_pimreg(struct pim_instance
*pim
)
1493 char pimreg_name
[INTERFACE_NAMSIZ
];
1495 if (!pim
->regiface
) {
1496 if (pim
->vrf_id
== VRF_DEFAULT
)
1497 strlcpy(pimreg_name
, "pimreg", sizeof(pimreg_name
));
1499 snprintf(pimreg_name
, sizeof(pimreg_name
), "pimreg%u",
1500 pim
->vrf
->data
.l
.table_id
);
1502 pim
->regiface
= if_create(pimreg_name
, pim
->vrf_id
);
1503 pim
->regiface
->ifindex
= PIM_OIF_PIM_REGISTER_VIF
;
1505 pim_if_new(pim
->regiface
, 0, 0);
1509 int pim_if_connected_to_source(struct interface
*ifp
, struct in_addr src
)
1511 struct listnode
*cnode
;
1512 struct connected
*c
;
1520 p
.prefixlen
= IPV4_MAX_BITLEN
;
1522 for (ALL_LIST_ELEMENTS_RO(ifp
->connected
, cnode
, c
)) {
1523 if ((c
->address
->family
== AF_INET
)
1524 && prefix_match(CONNECTED_PREFIX(c
), &p
)) {
1532 int pim_if_is_loopback(struct pim_instance
*pim
, struct interface
*ifp
)
1534 if (if_is_loopback(ifp
))
1537 if (strcmp(ifp
->name
, pim
->vrf
->name
) == 0)
1543 int pim_if_is_vrf_device(struct interface
*ifp
)
1547 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
1548 if (strncmp(ifp
->name
, vrf
->name
, strlen(ifp
->name
)) == 0)
1555 int pim_if_ifchannel_count(struct pim_interface
*pim_ifp
)
1557 struct pim_ifchannel
*ch
;
1560 RB_FOREACH (ch
, pim_ifchannel_rb
, &pim_ifp
->ifchannel_rb
) {