3 * Copyright (C) 2008 Everton da Silva Marques
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
15 * You should have received a copy of the GNU General Public License along
16 * with this program; see the file COPYING; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
34 #include "pim_zebra.h"
35 #include "pim_iface.h"
41 #include "pim_zlookup.h"
42 #include "pim_ifchannel.h"
44 #include "pim_igmpv3.h"
45 #include "pim_jp_agg.h"
48 #include "pim_vxlan.h"
50 #undef PIM_DEBUG_IFADDR_DUMP
51 #define PIM_DEBUG_IFADDR_DUMP
53 static struct zclient
*zclient
= NULL
;
56 /* Router-id update message from zebra. */
57 static int pim_router_id_update_zebra(ZAPI_CALLBACK_ARGS
)
59 struct prefix router_id
;
61 zebra_router_id_update_read(zclient
->ibuf
, &router_id
);
66 static int pim_zebra_if_del(ZAPI_CALLBACK_ARGS
)
68 struct interface
*ifp
;
69 struct pim_instance
*pim
;
71 ifp
= zebra_interface_state_read(zclient
->ibuf
, vrf_id
);
75 if (PIM_DEBUG_ZEBRA
) {
77 "%s: %s index %d(%u) flags %ld metric %d mtu %d operative %d",
78 __PRETTY_FUNCTION__
, ifp
->name
, ifp
->ifindex
, vrf_id
,
79 (long)ifp
->flags
, ifp
->metric
, ifp
->mtu
,
80 if_is_operative(ifp
));
83 if (!if_is_operative(ifp
))
84 pim_if_addr_del_all(ifp
);
86 if_set_index(ifp
, IFINDEX_INTERNAL
);
88 pim
= pim_get_pim_instance(vrf_id
);
89 if (pim
&& pim
->vxlan
.term_if
== ifp
)
90 pim_vxlan_del_term_dev(pim
);
95 static int pim_zebra_if_state_up(ZAPI_CALLBACK_ARGS
)
97 struct pim_instance
*pim
;
98 struct interface
*ifp
;
102 zebra api notifies interface up/down events by using the same call
103 zebra_interface_state_read below, see comments in lib/zclient.c
105 ifp
= zebra_interface_state_read(zclient
->ibuf
, vrf_id
);
109 if (PIM_DEBUG_ZEBRA
) {
111 "%s: %s index %d(%u) flags %ld metric %d mtu %d operative %d",
112 __PRETTY_FUNCTION__
, ifp
->name
, ifp
->ifindex
, vrf_id
,
113 (long)ifp
->flags
, ifp
->metric
, ifp
->mtu
,
114 if_is_operative(ifp
));
117 pim
= pim_get_pim_instance(vrf_id
);
118 if (if_is_operative(ifp
)) {
119 struct pim_interface
*pim_ifp
;
123 * If we have a pim_ifp already and this is an if_add
124 * that means that we probably have a vrf move event
125 * If that is the case, set the proper vrfness.
131 pim_if_addr_add_all() suffices for bringing up both IGMP and
134 pim_if_addr_add_all(ifp
);
138 * If we have a pimreg device callback and it's for a specific
139 * table set the master appropriately
141 if (sscanf(ifp
->name
, "pimreg%" SCNu32
, &table_id
) == 1) {
143 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
144 if ((table_id
== vrf
->data
.l
.table_id
)
145 && (ifp
->vrf_id
!= vrf
->vrf_id
)) {
146 struct interface
*master
= if_lookup_by_name(
147 vrf
->name
, vrf
->vrf_id
);
151 "%s: Unable to find Master interface for %s",
152 __PRETTY_FUNCTION__
, vrf
->name
);
155 zclient_interface_set_master(zclient
, master
,
163 static int pim_zebra_if_state_down(ZAPI_CALLBACK_ARGS
)
165 struct interface
*ifp
;
168 zebra api notifies interface up/down events by using the same call
169 zebra_interface_state_read below, see comments in lib/zclient.c
171 ifp
= zebra_interface_state_read(zclient
->ibuf
, vrf_id
);
175 if (PIM_DEBUG_ZEBRA
) {
177 "%s: %s index %d(%u) flags %ld metric %d mtu %d operative %d",
178 __PRETTY_FUNCTION__
, ifp
->name
, ifp
->ifindex
, vrf_id
,
179 (long)ifp
->flags
, ifp
->metric
, ifp
->mtu
,
180 if_is_operative(ifp
));
183 if (!if_is_operative(ifp
)) {
184 pim_ifchannel_delete_all(ifp
);
186 pim_if_addr_del_all() suffices for shutting down IGMP,
187 but not for shutting down PIM
189 pim_if_addr_del_all(ifp
);
192 pim_sock_delete() closes the socket, stops read and timer
194 and kills all neighbors.
197 pim_sock_delete(ifp
, "link down");
207 static int pim_zebra_interface_vrf_update(ZAPI_CALLBACK_ARGS
)
209 struct interface
*ifp
;
212 ifp
= zebra_interface_vrf_update_read(zclient
->ibuf
, vrf_id
,
218 zlog_debug("%s: %s updating from %u to %u",
220 ifp
->name
, vrf_id
, new_vrf_id
);
222 if_update_to_new_vrf(ifp
, new_vrf_id
);
227 #ifdef PIM_DEBUG_IFADDR_DUMP
228 static void dump_if_address(struct interface
*ifp
)
230 struct connected
*ifc
;
231 struct listnode
*node
;
233 zlog_debug("%s %s: interface %s addresses:", __FILE__
,
234 __PRETTY_FUNCTION__
, ifp
->name
);
236 for (ALL_LIST_ELEMENTS_RO(ifp
->connected
, node
, ifc
)) {
237 struct prefix
*p
= ifc
->address
;
239 if (p
->family
!= AF_INET
)
242 zlog_debug("%s %s: interface %s address %s %s", __FILE__
,
243 __PRETTY_FUNCTION__
, ifp
->name
,
244 inet_ntoa(p
->u
.prefix4
),
245 CHECK_FLAG(ifc
->flags
, ZEBRA_IFA_SECONDARY
)
252 static int pim_zebra_if_address_add(ZAPI_CALLBACK_ARGS
)
256 struct pim_interface
*pim_ifp
;
257 struct pim_instance
*pim
;
260 zebra api notifies address adds/dels events by using the same call
261 interface_add_read below, see comments in lib/zclient.c
263 zebra_interface_address_read(ZEBRA_INTERFACE_ADDRESS_ADD, ...)
264 will add address to interface list by calling
265 connected_add_by_prefix()
267 c
= zebra_interface_address_read(cmd
, zclient
->ibuf
, vrf_id
);
271 pim_ifp
= c
->ifp
->info
;
274 if (PIM_DEBUG_ZEBRA
) {
276 prefix2str(p
, buf
, BUFSIZ
);
277 zlog_debug("%s: %s(%u) connected IP address %s flags %u %s",
278 __PRETTY_FUNCTION__
, c
->ifp
->name
, vrf_id
, buf
,
280 CHECK_FLAG(c
->flags
, ZEBRA_IFA_SECONDARY
)
284 #ifdef PIM_DEBUG_IFADDR_DUMP
285 dump_if_address(c
->ifp
);
289 if (!CHECK_FLAG(c
->flags
, ZEBRA_IFA_SECONDARY
)) {
290 /* trying to add primary address */
292 struct in_addr primary_addr
= pim_find_primary_addr(c
->ifp
);
293 if (p
->family
!= AF_INET
294 || primary_addr
.s_addr
!= p
->u
.prefix4
.s_addr
) {
295 if (PIM_DEBUG_ZEBRA
) {
296 /* but we had a primary address already */
300 prefix2str(p
, buf
, BUFSIZ
);
303 "%s: %s : forcing secondary flag on %s",
304 __PRETTY_FUNCTION__
, c
->ifp
->name
, buf
);
306 SET_FLAG(c
->flags
, ZEBRA_IFA_SECONDARY
);
312 pim
= pim_get_pim_instance(vrf_id
);
315 pim_rp_check_on_if_add(pim_ifp
);
318 if (if_is_loopback(c
->ifp
)) {
319 struct vrf
*vrf
= vrf_lookup_by_id(VRF_DEFAULT
);
320 struct interface
*ifp
;
322 FOR_ALL_INTERFACES (vrf
, ifp
) {
323 if (!if_is_loopback(ifp
) && if_is_operative(ifp
))
324 pim_if_addr_add_all(ifp
);
331 static int pim_zebra_if_address_del(ZAPI_CALLBACK_ARGS
)
335 struct vrf
*vrf
= vrf_lookup_by_id(vrf_id
);
336 struct pim_instance
*pim
;
343 zebra api notifies address adds/dels events by using the same call
344 interface_add_read below, see comments in lib/zclient.c
346 zebra_interface_address_read(ZEBRA_INTERFACE_ADDRESS_DELETE, ...)
347 will remove address from interface list by calling
348 connected_delete_by_prefix()
350 c
= zebra_interface_address_read(cmd
, zclient
->ibuf
, vrf_id
);
355 if (p
->family
== AF_INET
) {
356 if (PIM_DEBUG_ZEBRA
) {
358 prefix2str(p
, buf
, BUFSIZ
);
360 "%s: %s(%u) disconnected IP address %s flags %u %s",
361 __PRETTY_FUNCTION__
, c
->ifp
->name
, vrf_id
, buf
,
363 CHECK_FLAG(c
->flags
, ZEBRA_IFA_SECONDARY
)
367 #ifdef PIM_DEBUG_IFADDR_DUMP
368 dump_if_address(c
->ifp
);
372 pim_if_addr_del(c
, 0);
374 pim_i_am_rp_re_evaluate(pim
);
381 void pim_zebra_update_all_interfaces(struct pim_instance
*pim
)
383 struct interface
*ifp
;
385 FOR_ALL_INTERFACES (pim
->vrf
, ifp
) {
386 struct pim_interface
*pim_ifp
= ifp
->info
;
387 struct pim_iface_upstream_switch
*us
;
388 struct listnode
*node
;
393 for (ALL_LIST_ELEMENTS_RO(pim_ifp
->upstream_switch_list
, node
,
397 rpf
.source_nexthop
.interface
= ifp
;
398 rpf
.rpf_addr
.u
.prefix4
= us
->address
;
399 pim_joinprune_send(&rpf
, us
->us
);
400 pim_jp_agg_clear_group(us
->us
);
405 void pim_zebra_upstream_rpf_changed(struct pim_instance
*pim
,
406 struct pim_upstream
*up
,
409 if (old
->source_nexthop
.interface
) {
410 struct pim_neighbor
*nbr
;
412 nbr
= pim_neighbor_find(old
->source_nexthop
.interface
,
413 old
->rpf_addr
.u
.prefix4
);
415 pim_jp_agg_remove_group(nbr
->upstream_jp_agg
, up
);
418 * We have detected a case where we might need
419 * to rescan the inherited o_list so do it.
421 if (up
->channel_oil
->oil_inherited_rescan
) {
422 pim_upstream_inherited_olist_decide(pim
, up
);
423 up
->channel_oil
->oil_inherited_rescan
= 0;
426 if (up
->join_state
== PIM_UPSTREAM_JOINED
) {
428 * If we come up real fast we can be here
429 * where the mroute has not been installed
432 if (!up
->channel_oil
->installed
)
433 pim_mroute_add(up
->channel_oil
,
434 __PRETTY_FUNCTION__
);
437 * RFC 4601: 4.5.7. Sending (S,G)
438 * Join/Prune Messages
440 * Transitions from Joined State
442 * RPF'(S,G) changes not due to an Assert
444 * The upstream (S,G) state machine remains
445 * in Joined state. Send Join(S,G) to the new
446 * upstream neighbor, which is the new value
447 * of RPF'(S,G). Send Prune(S,G) to the old
448 * upstream neighbor, which is the old value
449 * of RPF'(S,G). Set the Join Timer (JT) to
450 * expire after t_periodic seconds.
452 pim_jp_agg_switch_interface(old
, &up
->rpf
, up
);
454 pim_upstream_join_timer_restart(up
, old
);
455 } /* up->join_state == PIM_UPSTREAM_JOINED */
460 * We have detected a case where we might need
461 * to rescan the inherited o_list so do it.
463 if (up
->channel_oil
->oil_inherited_rescan
) {
464 pim_upstream_inherited_olist_decide(pim
, up
);
465 up
->channel_oil
->oil_inherited_rescan
= 0;
468 if (!up
->channel_oil
->installed
)
469 pim_mroute_add(up
->channel_oil
, __PRETTY_FUNCTION__
);
472 /* FIXME can join_desired actually be changed by pim_rpf_update()
473 * returning PIM_RPF_CHANGED ?
475 pim_upstream_update_join_desired(pim
, up
);
478 static int pim_zebra_vxlan_sg_proc(ZAPI_CALLBACK_ARGS
)
481 struct pim_instance
*pim
;
484 pim
= pim_get_pim_instance(vrf_id
);
491 sg
.prefixlen
= stream_getl(s
);
492 stream_get(&sg
.src
.s_addr
, s
, sg
.prefixlen
);
493 stream_get(&sg
.grp
.s_addr
, s
, sg
.prefixlen
);
495 if (PIM_DEBUG_ZEBRA
) {
496 char sg_str
[PIM_SG_LEN
];
498 pim_str_sg_set(&sg
, sg_str
);
499 zlog_debug("%u:recv SG %s %s", vrf_id
,
500 (cmd
== ZEBRA_VXLAN_SG_ADD
)?"add":"del",
504 if (cmd
== ZEBRA_VXLAN_SG_ADD
)
505 pim_vxlan_sg_add(pim
, &sg
);
507 pim_vxlan_sg_del(pim
, &sg
);
512 static void pim_zebra_vxlan_replay(void)
514 struct stream
*s
= NULL
;
517 if (!zclient
|| zclient
->sock
< 0)
523 zclient_create_header(s
, ZEBRA_VXLAN_SG_REPLAY
, VRF_DEFAULT
);
524 stream_putw_at(s
, 0, stream_get_endp(s
));
526 zclient_send_message(zclient
);
529 void pim_scan_individual_oil(struct channel_oil
*c_oil
, int in_vif_index
)
531 struct in_addr vif_source
;
532 int input_iface_vif_index
;
534 pim_rp_set_upstream_addr(c_oil
->pim
, &vif_source
,
535 c_oil
->oil
.mfcc_origin
,
536 c_oil
->oil
.mfcc_mcastgrp
);
539 input_iface_vif_index
= in_vif_index
;
541 struct prefix src
, grp
;
543 src
.family
= AF_INET
;
544 src
.prefixlen
= IPV4_MAX_BITLEN
;
545 src
.u
.prefix4
= vif_source
;
546 grp
.family
= AF_INET
;
547 grp
.prefixlen
= IPV4_MAX_BITLEN
;
548 grp
.u
.prefix4
= c_oil
->oil
.mfcc_mcastgrp
;
550 if (PIM_DEBUG_ZEBRA
) {
551 char source_str
[INET_ADDRSTRLEN
];
552 char group_str
[INET_ADDRSTRLEN
];
553 pim_inet4_dump("<source?>", c_oil
->oil
.mfcc_origin
,
554 source_str
, sizeof(source_str
));
555 pim_inet4_dump("<group?>", c_oil
->oil
.mfcc_mcastgrp
,
556 group_str
, sizeof(group_str
));
558 "%s: channel_oil (%s,%s) upstream info is not present.",
559 __PRETTY_FUNCTION__
, source_str
, group_str
);
561 input_iface_vif_index
= pim_ecmp_fib_lookup_if_vif_index(
562 c_oil
->pim
, &src
, &grp
);
565 if (input_iface_vif_index
< 1) {
566 if (PIM_DEBUG_ZEBRA
) {
567 char source_str
[INET_ADDRSTRLEN
];
568 char group_str
[INET_ADDRSTRLEN
];
569 pim_inet4_dump("<source?>", c_oil
->oil
.mfcc_origin
,
570 source_str
, sizeof(source_str
));
571 pim_inet4_dump("<group?>", c_oil
->oil
.mfcc_mcastgrp
,
572 group_str
, sizeof(group_str
));
574 "%s %s: could not find input interface(%d) for (S,G)=(%s,%s)",
575 __FILE__
, __PRETTY_FUNCTION__
,
576 c_oil
->oil
.mfcc_parent
, source_str
, group_str
);
578 pim_mroute_del(c_oil
, __PRETTY_FUNCTION__
);
582 if (input_iface_vif_index
== c_oil
->oil
.mfcc_parent
) {
583 if (!c_oil
->installed
)
584 pim_mroute_add(c_oil
, __PRETTY_FUNCTION__
);
590 if (PIM_DEBUG_ZEBRA
) {
591 struct interface
*old_iif
= pim_if_find_by_vif_index(
592 c_oil
->pim
, c_oil
->oil
.mfcc_parent
);
593 struct interface
*new_iif
= pim_if_find_by_vif_index(
594 c_oil
->pim
, input_iface_vif_index
);
595 char source_str
[INET_ADDRSTRLEN
];
596 char group_str
[INET_ADDRSTRLEN
];
597 pim_inet4_dump("<source?>", c_oil
->oil
.mfcc_origin
, source_str
,
599 pim_inet4_dump("<group?>", c_oil
->oil
.mfcc_mcastgrp
, group_str
,
602 "%s %s: (S,G)=(%s,%s) input interface changed from %s vif_index=%d to %s vif_index=%d",
603 __FILE__
, __PRETTY_FUNCTION__
, source_str
, group_str
,
604 (old_iif
) ? old_iif
->name
: "<old_iif?>",
605 c_oil
->oil
.mfcc_parent
,
606 (new_iif
) ? new_iif
->name
: "<new_iif?>",
607 input_iface_vif_index
);
610 /* new iif loops to existing oif ? */
611 if (c_oil
->oil
.mfcc_ttls
[input_iface_vif_index
]) {
612 struct interface
*new_iif
= pim_if_find_by_vif_index(
613 c_oil
->pim
, input_iface_vif_index
);
615 if (PIM_DEBUG_ZEBRA
) {
616 char source_str
[INET_ADDRSTRLEN
];
617 char group_str
[INET_ADDRSTRLEN
];
618 pim_inet4_dump("<source?>", c_oil
->oil
.mfcc_origin
,
619 source_str
, sizeof(source_str
));
620 pim_inet4_dump("<group?>", c_oil
->oil
.mfcc_mcastgrp
,
621 group_str
, sizeof(group_str
));
623 "%s %s: (S,G)=(%s,%s) new iif loops to existing oif: %s vif_index=%d",
624 __FILE__
, __PRETTY_FUNCTION__
, source_str
,
626 (new_iif
) ? new_iif
->name
: "<new_iif?>",
627 input_iface_vif_index
);
631 /* update iif vif_index */
632 pim_channel_oil_change_iif(c_oil
->pim
, c_oil
, input_iface_vif_index
,
633 __PRETTY_FUNCTION__
);
634 pim_mroute_add(c_oil
, __PRETTY_FUNCTION__
);
637 void pim_scan_oil(struct pim_instance
*pim
)
639 struct listnode
*node
;
640 struct listnode
*nextnode
;
641 struct channel_oil
*c_oil
;
645 pim
->scan_oil_last
= pim_time_monotonic_sec();
646 ++pim
->scan_oil_events
;
648 for (ALL_LIST_ELEMENTS(pim
->channel_oil_list
, node
, nextnode
, c_oil
)) {
649 if (c_oil
->up
&& c_oil
->up
->rpf
.source_nexthop
.interface
) {
650 ifindex
= c_oil
->up
->rpf
.source_nexthop
653 pim_if_find_vifindex_by_ifindex(pim
, ifindex
);
654 /* Pass Current selected NH vif index to mroute
657 pim_scan_individual_oil(c_oil
, vif_index
);
659 pim_scan_individual_oil(c_oil
, 0);
663 static int on_rpf_cache_refresh(struct thread
*t
)
665 struct pim_instance
*pim
= THREAD_ARG(t
);
667 /* update kernel multicast forwarding cache (MFC) */
670 pim
->rpf_cache_refresh_last
= pim_time_monotonic_sec();
671 ++pim
->rpf_cache_refresh_events
;
673 // It is called as part of pim_neighbor_add
678 void sched_rpf_cache_refresh(struct pim_instance
*pim
)
680 ++pim
->rpf_cache_refresh_requests
;
682 pim_rpf_set_refresh_time(pim
);
684 if (pim
->rpf_cache_refresher
) {
685 /* Refresh timer is already running */
689 /* Start refresh timer */
691 if (PIM_DEBUG_ZEBRA
) {
692 zlog_debug("%s: triggering %ld msec timer", __PRETTY_FUNCTION__
,
693 router
->rpf_cache_refresh_delay_msec
);
696 thread_add_timer_msec(router
->master
, on_rpf_cache_refresh
, pim
,
697 router
->rpf_cache_refresh_delay_msec
,
698 &pim
->rpf_cache_refresher
);
701 static void pim_zebra_connected(struct zclient
*zclient
)
703 /* Send the client registration */
704 bfd_client_sendmsg(zclient
, ZEBRA_BFD_CLIENT_REGISTER
, router
->vrf_id
);
706 zclient_send_reg_requests(zclient
, router
->vrf_id
);
708 /* request for VxLAN BUM group addresses */
709 pim_zebra_vxlan_replay();
712 static void pim_zebra_capabilities(struct zclient_capabilities
*cap
)
714 router
->role
= cap
->role
;
717 void pim_zebra_init(void)
719 /* Socket for receiving updates from Zebra daemon */
720 zclient
= zclient_new(router
->master
, &zclient_options_default
);
722 zclient
->zebra_capabilities
= pim_zebra_capabilities
;
723 zclient
->zebra_connected
= pim_zebra_connected
;
724 zclient
->router_id_update
= pim_router_id_update_zebra
;
725 zclient
->interface_delete
= pim_zebra_if_del
;
726 zclient
->interface_up
= pim_zebra_if_state_up
;
727 zclient
->interface_down
= pim_zebra_if_state_down
;
728 zclient
->interface_address_add
= pim_zebra_if_address_add
;
729 zclient
->interface_address_delete
= pim_zebra_if_address_del
;
730 zclient
->interface_vrf_update
= pim_zebra_interface_vrf_update
;
731 zclient
->nexthop_update
= pim_parse_nexthop_update
;
732 zclient
->vxlan_sg_add
= pim_zebra_vxlan_sg_proc
;
733 zclient
->vxlan_sg_del
= pim_zebra_vxlan_sg_proc
;
735 zclient_init(zclient
, ZEBRA_ROUTE_PIM
, 0, &pimd_privs
);
736 if (PIM_DEBUG_PIM_TRACE
) {
737 zlog_notice("%s: zclient socket initialized",
738 __PRETTY_FUNCTION__
);
741 zclient_lookup_new();
744 void igmp_anysource_forward_start(struct pim_instance
*pim
,
745 struct igmp_group
*group
)
747 struct igmp_source
*source
;
748 struct in_addr src_addr
= {.s_addr
= 0};
749 /* Any source (*,G) is forwarded only if mode is EXCLUDE {empty} */
750 zassert(group
->group_filtermode_isexcl
);
751 zassert(listcount(group
->group_source_list
) < 1);
753 source
= source_new(group
, src_addr
);
755 zlog_warn("%s: Failure to create * source",
756 __PRETTY_FUNCTION__
);
760 igmp_source_forward_start(pim
, source
);
763 void igmp_anysource_forward_stop(struct igmp_group
*group
)
765 struct igmp_source
*source
;
766 struct in_addr star
= {.s_addr
= 0};
768 source
= igmp_find_source_by_addr(group
, star
);
770 igmp_source_forward_stop(source
);
773 static void igmp_source_forward_reevaluate_one(struct pim_instance
*pim
,
774 struct igmp_source
*source
)
777 struct igmp_group
*group
= source
->source_group
;
778 struct pim_ifchannel
*ch
;
780 if ((source
->source_addr
.s_addr
!= INADDR_ANY
)
781 || !IGMP_SOURCE_TEST_FORWARDING(source
->source_flags
))
784 memset(&sg
, 0, sizeof(struct prefix_sg
));
785 sg
.src
= source
->source_addr
;
786 sg
.grp
= group
->group_addr
;
788 ch
= pim_ifchannel_find(group
->group_igmp_sock
->interface
, &sg
);
789 if (pim_is_grp_ssm(pim
, group
->group_addr
)) {
790 /* If SSM group withdraw local membership */
792 && (ch
->local_ifmembership
== PIM_IFMEMBERSHIP_INCLUDE
)) {
793 if (PIM_DEBUG_PIM_EVENTS
)
795 "local membership del for %s as G is now SSM",
796 pim_str_sg_dump(&sg
));
797 pim_ifchannel_local_membership_del(
798 group
->group_igmp_sock
->interface
, &sg
);
801 /* If ASM group add local membership */
803 || (ch
->local_ifmembership
== PIM_IFMEMBERSHIP_NOINFO
)) {
804 if (PIM_DEBUG_PIM_EVENTS
)
806 "local membership add for %s as G is now ASM",
807 pim_str_sg_dump(&sg
));
808 pim_ifchannel_local_membership_add(
809 group
->group_igmp_sock
->interface
, &sg
);
814 void igmp_source_forward_reevaluate_all(struct pim_instance
*pim
)
816 struct interface
*ifp
;
818 FOR_ALL_INTERFACES (pim
->vrf
, ifp
) {
819 struct pim_interface
*pim_ifp
= ifp
->info
;
820 struct listnode
*sock_node
;
821 struct igmp_sock
*igmp
;
826 /* scan igmp sockets */
827 for (ALL_LIST_ELEMENTS_RO(pim_ifp
->igmp_socket_list
, sock_node
,
829 struct listnode
*grpnode
;
830 struct igmp_group
*grp
;
832 /* scan igmp groups */
833 for (ALL_LIST_ELEMENTS_RO(igmp
->igmp_group_list
,
835 struct listnode
*srcnode
;
836 struct igmp_source
*src
;
838 /* scan group sources */
839 for (ALL_LIST_ELEMENTS_RO(
840 grp
->group_source_list
, srcnode
,
842 igmp_source_forward_reevaluate_one(pim
,
844 } /* scan group sources */
845 } /* scan igmp groups */
846 } /* scan igmp sockets */
847 } /* scan interfaces */
850 void igmp_source_forward_start(struct pim_instance
*pim
,
851 struct igmp_source
*source
)
853 struct pim_interface
*pim_oif
;
854 struct igmp_group
*group
;
857 int input_iface_vif_index
= 0;
859 memset(&sg
, 0, sizeof(struct prefix_sg
));
860 sg
.src
= source
->source_addr
;
861 sg
.grp
= source
->source_group
->group_addr
;
863 if (PIM_DEBUG_IGMP_TRACE
) {
865 "%s: (S,G)=%s igmp_sock=%d oif=%s fwd=%d",
866 __PRETTY_FUNCTION__
, pim_str_sg_dump(&sg
),
867 source
->source_group
->group_igmp_sock
->fd
,
868 source
->source_group
->group_igmp_sock
->interface
->name
,
869 IGMP_SOURCE_TEST_FORWARDING(source
->source_flags
));
872 /* Prevent IGMP interface from installing multicast route multiple
874 if (IGMP_SOURCE_TEST_FORWARDING(source
->source_flags
)) {
878 group
= source
->source_group
;
879 pim_oif
= group
->group_igmp_sock
->interface
->info
;
881 if (PIM_DEBUG_IGMP_TRACE
) {
883 "%s: multicast not enabled on oif=%s ?",
885 source
->source_group
->group_igmp_sock
891 if (!source
->source_channel_oil
) {
892 struct in_addr vif_source
;
893 struct prefix src
, grp
;
894 struct pim_nexthop nexthop
;
895 struct pim_upstream
*up
= NULL
;
897 if (!pim_rp_set_upstream_addr(pim
, &vif_source
,
898 source
->source_addr
, sg
.grp
)) {
899 /*Create a dummy channel oil */
900 source
->source_channel_oil
= pim_channel_oil_add(
901 pim
, &sg
, MAXVIFS
, __PRETTY_FUNCTION__
);
905 src
.family
= AF_INET
;
906 src
.prefixlen
= IPV4_MAX_BITLEN
;
907 src
.u
.prefix4
= vif_source
; // RP or Src address
908 grp
.family
= AF_INET
;
909 grp
.prefixlen
= IPV4_MAX_BITLEN
;
910 grp
.u
.prefix4
= sg
.grp
;
912 up
= pim_upstream_find(pim
, &sg
);
914 memcpy(&nexthop
, &up
->rpf
.source_nexthop
,
915 sizeof(struct pim_nexthop
));
916 pim_ecmp_nexthop_lookup(pim
, &nexthop
, &src
,
918 if (nexthop
.interface
)
919 input_iface_vif_index
=
920 pim_if_find_vifindex_by_ifindex(
922 nexthop
.interface
->ifindex
);
924 input_iface_vif_index
=
925 pim_ecmp_fib_lookup_if_vif_index(
928 if (PIM_DEBUG_ZEBRA
) {
929 char buf2
[INET_ADDRSTRLEN
];
931 pim_inet4_dump("<source?>", vif_source
, buf2
,
933 zlog_debug("%s: NHT %s vif_source %s vif_index:%d ",
935 pim_str_sg_dump(&sg
),
936 buf2
, input_iface_vif_index
);
939 if (input_iface_vif_index
< 1) {
940 if (PIM_DEBUG_IGMP_TRACE
) {
941 char source_str
[INET_ADDRSTRLEN
];
942 pim_inet4_dump("<source?>",
944 source_str
, sizeof(source_str
));
946 "%s %s: could not find input interface for source %s",
947 __FILE__
, __PRETTY_FUNCTION__
,
950 source
->source_channel_oil
=
953 __PRETTY_FUNCTION__
);
958 * Protect IGMP against adding looped MFC
959 * entries created by both source and receiver
960 * attached to the same interface. See TODO
961 * T22. Block only when the intf is non DR
962 * DR must create upstream.
964 if ((input_iface_vif_index
==
965 pim_oif
->mroute_vif_index
) &&
966 !(PIM_I_am_DR(pim_oif
))) {
967 /* ignore request for looped MFC entry
969 if (PIM_DEBUG_IGMP_TRACE
) {
971 "%s: ignoring request for looped MFC entry (S,G)=%s: igmp_sock=%d oif=%s vif_index=%d",
973 pim_str_sg_dump(&sg
),
975 ->group_igmp_sock
->fd
,
979 input_iface_vif_index
);
984 source
->source_channel_oil
=
986 pim
, &sg
, input_iface_vif_index
,
987 __PRETTY_FUNCTION__
);
988 if (!source
->source_channel_oil
) {
989 if (PIM_DEBUG_IGMP_TRACE
) {
991 "%s %s: could not create OIL for channel (S,G)=%s",
994 pim_str_sg_dump(&sg
));
1002 result
= pim_channel_add_oif(source
->source_channel_oil
,
1003 group
->group_igmp_sock
->interface
,
1004 PIM_OIF_FLAG_PROTO_IGMP
);
1006 if (PIM_DEBUG_MROUTE
) {
1007 zlog_warn("%s: add_oif() failed with return=%d",
1013 if (!(PIM_I_am_DR(pim_oif
))) {
1014 if (PIM_DEBUG_IGMP_TRACE
)
1015 zlog_debug("%s: %s was received on %s interface but we are not DR for that interface",
1016 __PRETTY_FUNCTION__
,
1017 pim_str_sg_dump(&sg
),
1018 group
->group_igmp_sock
->interface
->name
);
1020 pim_channel_del_oif(source
->source_channel_oil
,
1021 group
->group_igmp_sock
->interface
,
1022 PIM_OIF_FLAG_PROTO_IGMP
);
1026 Feed IGMPv3-gathered local membership information into PIM
1027 per-interface (S,G) state.
1029 if (!pim_ifchannel_local_membership_add(
1030 group
->group_igmp_sock
->interface
, &sg
)) {
1031 if (PIM_DEBUG_MROUTE
)
1032 zlog_warn("%s: Failure to add local membership for %s",
1033 __PRETTY_FUNCTION__
, pim_str_sg_dump(&sg
));
1035 pim_channel_del_oif(source
->source_channel_oil
,
1036 group
->group_igmp_sock
->interface
,
1037 PIM_OIF_FLAG_PROTO_IGMP
);
1041 IGMP_SOURCE_DO_FORWARDING(source
->source_flags
);
1045 igmp_source_forward_stop: stop fowarding, but keep the source
1046 igmp_source_delete: stop fowarding, and delete the source
1048 void igmp_source_forward_stop(struct igmp_source
*source
)
1050 struct igmp_group
*group
;
1051 struct prefix_sg sg
;
1054 memset(&sg
, 0, sizeof(struct prefix_sg
));
1055 sg
.src
= source
->source_addr
;
1056 sg
.grp
= source
->source_group
->group_addr
;
1058 if (PIM_DEBUG_IGMP_TRACE
) {
1060 "%s: (S,G)=%s igmp_sock=%d oif=%s fwd=%d",
1061 __PRETTY_FUNCTION__
, pim_str_sg_dump(&sg
),
1062 source
->source_group
->group_igmp_sock
->fd
,
1063 source
->source_group
->group_igmp_sock
->interface
->name
,
1064 IGMP_SOURCE_TEST_FORWARDING(source
->source_flags
));
1067 /* Prevent IGMP interface from removing multicast route multiple
1069 if (!IGMP_SOURCE_TEST_FORWARDING(source
->source_flags
)) {
1073 group
= source
->source_group
;
1076 It appears that in certain circumstances that
1077 igmp_source_forward_stop is called when IGMP forwarding
1078 was not enabled in oif_flags for this outgoing interface.
1079 Possibly because of multiple calls. When that happens, we
1080 enter the below if statement and this function returns early
1081 which in turn triggers the calling function to assert.
1082 Making the call to pim_channel_del_oif and ignoring the return code
1083 fixes the issue without ill effect, similar to
1084 pim_forward_stop below.
1086 result
= pim_channel_del_oif(source
->source_channel_oil
,
1087 group
->group_igmp_sock
->interface
,
1088 PIM_OIF_FLAG_PROTO_IGMP
);
1090 if (PIM_DEBUG_IGMP_TRACE
)
1092 "%s: pim_channel_del_oif() failed with return=%d",
1098 Feed IGMPv3-gathered local membership information into PIM
1099 per-interface (S,G) state.
1101 pim_ifchannel_local_membership_del(group
->group_igmp_sock
->interface
,
1104 IGMP_SOURCE_DONT_FORWARDING(source
->source_flags
);
1107 void pim_forward_start(struct pim_ifchannel
*ch
)
1109 struct pim_upstream
*up
= ch
->upstream
;
1110 uint32_t mask
= PIM_OIF_FLAG_PROTO_PIM
;
1111 int input_iface_vif_index
= 0;
1112 struct pim_instance
*pim
;
1113 struct pim_interface
*pim_ifp
;
1115 pim_ifp
= ch
->interface
->info
;
1118 if (PIM_DEBUG_PIM_TRACE
) {
1119 char source_str
[INET_ADDRSTRLEN
];
1120 char group_str
[INET_ADDRSTRLEN
];
1121 char upstream_str
[INET_ADDRSTRLEN
];
1123 pim_inet4_dump("<source?>", ch
->sg
.src
, source_str
,
1124 sizeof(source_str
));
1125 pim_inet4_dump("<group?>", ch
->sg
.grp
, group_str
,
1127 pim_inet4_dump("<upstream?>", up
->upstream_addr
, upstream_str
,
1128 sizeof(upstream_str
));
1129 zlog_debug("%s: (S,G)=(%s,%s) oif=%s (%s)", __PRETTY_FUNCTION__
,
1130 source_str
, group_str
, ch
->interface
->name
,
1131 inet_ntoa(up
->upstream_addr
));
1134 /* Resolve IIF for upstream as mroute_del sets mfcc_parent to MAXVIFS,
1135 as part of mroute_del called by pim_forward_stop.
1137 if ((up
->upstream_addr
.s_addr
!= INADDR_ANY
) && (!up
->channel_oil
)) {
1138 struct prefix src
, grp
;
1140 grp
.family
= AF_INET
;
1141 grp
.prefixlen
= IPV4_MAX_BITLEN
;
1142 grp
.u
.prefix4
= up
->sg
.grp
;
1143 src
.family
= AF_INET
;
1144 src
.prefixlen
= IPV4_MAX_BITLEN
;
1145 src
.u
.prefix4
= up
->sg
.src
;
1147 if (pim_ecmp_nexthop_lookup(pim
, &up
->rpf
.source_nexthop
, &src
,
1149 input_iface_vif_index
= pim_if_find_vifindex_by_ifindex(
1150 pim
, up
->rpf
.source_nexthop
.interface
->ifindex
);
1152 if (input_iface_vif_index
< 1) {
1153 if (PIM_DEBUG_PIM_TRACE
) {
1154 char source_str
[INET_ADDRSTRLEN
];
1155 pim_inet4_dump("<source?>", up
->sg
.src
,
1156 source_str
, sizeof(source_str
));
1158 "%s %s: could not find input interface for source %s",
1159 __FILE__
, __PRETTY_FUNCTION__
,
1162 pim_channel_oil_change_iif(pim
, up
->channel_oil
,
1164 __PRETTY_FUNCTION__
);
1168 pim_channel_oil_change_iif(pim
, up
->channel_oil
,
1169 input_iface_vif_index
,
1170 __PRETTY_FUNCTION__
);
1172 if (PIM_DEBUG_TRACE
) {
1173 struct interface
*in_intf
= pim_if_find_by_vif_index(
1174 pim
, input_iface_vif_index
);
1176 "%s: Update channel_oil IIF %s VIFI %d entry %s ",
1177 __PRETTY_FUNCTION__
,
1178 in_intf
? in_intf
->name
: "Unknown",
1179 input_iface_vif_index
, up
->sg_str
);
1183 if (up
->flags
& PIM_UPSTREAM_FLAG_MASK_SRC_IGMP
)
1184 mask
= PIM_OIF_FLAG_PROTO_IGMP
;
1186 pim_channel_add_oif(up
->channel_oil
, ch
->interface
, mask
);
1189 void pim_forward_stop(struct pim_ifchannel
*ch
, bool install_it
)
1191 struct pim_upstream
*up
= ch
->upstream
;
1193 if (PIM_DEBUG_PIM_TRACE
) {
1194 zlog_debug("%s: (S,G)=%s oif=%s install_it: %d installed: %d",
1195 __PRETTY_FUNCTION__
, ch
->sg_str
, ch
->interface
->name
,
1196 install_it
, up
->channel_oil
->installed
);
1200 * If a channel is being removed, check to see if we still need
1201 * to inherit the interface. If so make sure it is added in
1203 if (pim_upstream_evaluate_join_desired_interface(up
, ch
, ch
->parent
))
1204 pim_channel_add_oif(up
->channel_oil
, ch
->interface
,
1205 PIM_OIF_FLAG_PROTO_PIM
);
1207 pim_channel_del_oif(up
->channel_oil
, ch
->interface
,
1208 PIM_OIF_FLAG_PROTO_PIM
);
1210 if (install_it
&& !up
->channel_oil
->installed
)
1211 pim_mroute_add(up
->channel_oil
, __PRETTY_FUNCTION__
);
1214 void pim_zebra_zclient_update(struct vty
*vty
)
1216 vty_out(vty
, "Zclient update socket: ");
1219 vty_out(vty
, "%d failures=%d\n", zclient
->sock
, zclient
->fail
);
1221 vty_out(vty
, "<null zclient>\n");
1225 struct zclient
*pim_zebra_zclient_get(void)