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"
51 #undef PIM_DEBUG_IFADDR_DUMP
52 #define PIM_DEBUG_IFADDR_DUMP
54 struct zclient
*zclient
;
57 /* Router-id update message from zebra. */
58 static int pim_router_id_update_zebra(ZAPI_CALLBACK_ARGS
)
60 struct prefix router_id
;
62 zebra_router_id_update_read(zclient
->ibuf
, &router_id
);
67 static int pim_zebra_interface_vrf_update(ZAPI_CALLBACK_ARGS
)
69 struct interface
*ifp
;
72 ifp
= zebra_interface_vrf_update_read(zclient
->ibuf
, vrf_id
,
78 zlog_debug("%s: %s updating from %u to %u", __func__
, ifp
->name
,
81 if_update_to_new_vrf(ifp
, new_vrf_id
);
86 #ifdef PIM_DEBUG_IFADDR_DUMP
87 static void dump_if_address(struct interface
*ifp
)
89 struct connected
*ifc
;
90 struct listnode
*node
;
92 zlog_debug("%s %s: interface %s addresses:", __FILE__
,
93 __PRETTY_FUNCTION__
, ifp
->name
);
95 for (ALL_LIST_ELEMENTS_RO(ifp
->connected
, node
, ifc
)) {
96 struct prefix
*p
= ifc
->address
;
98 if (p
->family
!= AF_INET
)
101 zlog_debug("%s %s: interface %s address %s %s", __FILE__
,
102 __PRETTY_FUNCTION__
, ifp
->name
,
103 inet_ntoa(p
->u
.prefix4
),
104 CHECK_FLAG(ifc
->flags
, ZEBRA_IFA_SECONDARY
)
111 static int pim_zebra_if_address_add(ZAPI_CALLBACK_ARGS
)
115 struct pim_interface
*pim_ifp
;
116 struct pim_instance
*pim
;
119 zebra api notifies address adds/dels events by using the same call
120 interface_add_read below, see comments in lib/zclient.c
122 zebra_interface_address_read(ZEBRA_INTERFACE_ADDRESS_ADD, ...)
123 will add address to interface list by calling
124 connected_add_by_prefix()
126 c
= zebra_interface_address_read(cmd
, zclient
->ibuf
, vrf_id
);
130 pim_ifp
= c
->ifp
->info
;
133 if (PIM_DEBUG_ZEBRA
) {
135 prefix2str(p
, buf
, BUFSIZ
);
136 zlog_debug("%s: %s(%u) connected IP address %s flags %u %s",
137 __func__
, c
->ifp
->name
, vrf_id
, buf
, c
->flags
,
138 CHECK_FLAG(c
->flags
, ZEBRA_IFA_SECONDARY
)
142 #ifdef PIM_DEBUG_IFADDR_DUMP
143 dump_if_address(c
->ifp
);
147 if (!CHECK_FLAG(c
->flags
, ZEBRA_IFA_SECONDARY
)) {
148 /* trying to add primary address */
150 struct in_addr primary_addr
= pim_find_primary_addr(c
->ifp
);
151 if (p
->family
!= AF_INET
152 || primary_addr
.s_addr
!= p
->u
.prefix4
.s_addr
) {
153 if (PIM_DEBUG_ZEBRA
) {
154 /* but we had a primary address already */
158 prefix2str(p
, buf
, BUFSIZ
);
161 "%s: %s : forcing secondary flag on %s",
162 __func__
, c
->ifp
->name
, buf
);
164 SET_FLAG(c
->flags
, ZEBRA_IFA_SECONDARY
);
170 pim
= pim_get_pim_instance(vrf_id
);
173 pim_rp_check_on_if_add(pim_ifp
);
176 if (if_is_loopback(c
->ifp
)) {
177 struct vrf
*vrf
= vrf_lookup_by_id(VRF_DEFAULT
);
178 struct interface
*ifp
;
180 FOR_ALL_INTERFACES (vrf
, ifp
) {
181 if (!if_is_loopback(ifp
) && if_is_operative(ifp
))
182 pim_if_addr_add_all(ifp
);
189 static int pim_zebra_if_address_del(ZAPI_CALLBACK_ARGS
)
193 struct vrf
*vrf
= vrf_lookup_by_id(vrf_id
);
194 struct pim_instance
*pim
;
201 zebra api notifies address adds/dels events by using the same call
202 interface_add_read below, see comments in lib/zclient.c
204 zebra_interface_address_read(ZEBRA_INTERFACE_ADDRESS_DELETE, ...)
205 will remove address from interface list by calling
206 connected_delete_by_prefix()
208 c
= zebra_interface_address_read(cmd
, zclient
->ibuf
, vrf_id
);
213 if (p
->family
== AF_INET
) {
214 if (PIM_DEBUG_ZEBRA
) {
216 prefix2str(p
, buf
, BUFSIZ
);
218 "%s: %s(%u) disconnected IP address %s flags %u %s",
219 __func__
, c
->ifp
->name
, vrf_id
, buf
, c
->flags
,
220 CHECK_FLAG(c
->flags
, ZEBRA_IFA_SECONDARY
)
224 #ifdef PIM_DEBUG_IFADDR_DUMP
225 dump_if_address(c
->ifp
);
229 pim_if_addr_del(c
, 0);
231 pim_i_am_rp_re_evaluate(pim
);
238 void pim_zebra_update_all_interfaces(struct pim_instance
*pim
)
240 struct interface
*ifp
;
242 FOR_ALL_INTERFACES (pim
->vrf
, ifp
) {
243 struct pim_interface
*pim_ifp
= ifp
->info
;
244 struct pim_iface_upstream_switch
*us
;
245 struct listnode
*node
;
250 for (ALL_LIST_ELEMENTS_RO(pim_ifp
->upstream_switch_list
, node
,
254 rpf
.source_nexthop
.interface
= ifp
;
255 rpf
.rpf_addr
.u
.prefix4
= us
->address
;
256 pim_joinprune_send(&rpf
, us
->us
);
257 pim_jp_agg_clear_group(us
->us
);
262 void pim_zebra_upstream_rpf_changed(struct pim_instance
*pim
,
263 struct pim_upstream
*up
,
266 if (old
->source_nexthop
.interface
) {
267 struct pim_neighbor
*nbr
;
269 nbr
= pim_neighbor_find(old
->source_nexthop
.interface
,
270 old
->rpf_addr
.u
.prefix4
);
272 pim_jp_agg_remove_group(nbr
->upstream_jp_agg
, up
, nbr
);
275 * We have detected a case where we might need
276 * to rescan the inherited o_list so do it.
278 if (up
->channel_oil
->oil_inherited_rescan
) {
279 pim_upstream_inherited_olist_decide(pim
, up
);
280 up
->channel_oil
->oil_inherited_rescan
= 0;
283 if (up
->join_state
== PIM_UPSTREAM_JOINED
) {
285 * If we come up real fast we can be here
286 * where the mroute has not been installed
289 if (!up
->channel_oil
->installed
)
290 pim_upstream_mroute_add(up
->channel_oil
,
294 * RFC 4601: 4.5.7. Sending (S,G)
295 * Join/Prune Messages
297 * Transitions from Joined State
299 * RPF'(S,G) changes not due to an Assert
301 * The upstream (S,G) state machine remains
302 * in Joined state. Send Join(S,G) to the new
303 * upstream neighbor, which is the new value
304 * of RPF'(S,G). Send Prune(S,G) to the old
305 * upstream neighbor, which is the old value
306 * of RPF'(S,G). Set the Join Timer (JT) to
307 * expire after t_periodic seconds.
309 pim_jp_agg_switch_interface(old
, &up
->rpf
, up
);
311 pim_upstream_join_timer_restart(up
, old
);
312 } /* up->join_state == PIM_UPSTREAM_JOINED */
317 * We have detected a case where we might need
318 * to rescan the inherited o_list so do it.
320 if (up
->channel_oil
->oil_inherited_rescan
) {
321 pim_upstream_inherited_olist_decide(pim
, up
);
322 up
->channel_oil
->oil_inherited_rescan
= 0;
325 if (up
->join_state
== PIM_UPSTREAM_JOINED
)
326 pim_jp_agg_switch_interface(old
, &up
->rpf
, up
);
328 if (!up
->channel_oil
->installed
)
329 pim_upstream_mroute_add(up
->channel_oil
, __func__
);
332 /* FIXME can join_desired actually be changed by pim_rpf_update()
333 * returning PIM_RPF_CHANGED ?
335 pim_upstream_update_join_desired(pim
, up
);
338 static int pim_zebra_vxlan_sg_proc(ZAPI_CALLBACK_ARGS
)
341 struct pim_instance
*pim
;
344 pim
= pim_get_pim_instance(vrf_id
);
351 sg
.prefixlen
= stream_getl(s
);
352 stream_get(&sg
.src
.s_addr
, s
, sg
.prefixlen
);
353 stream_get(&sg
.grp
.s_addr
, s
, sg
.prefixlen
);
355 if (PIM_DEBUG_ZEBRA
) {
356 char sg_str
[PIM_SG_LEN
];
358 pim_str_sg_set(&sg
, sg_str
);
359 zlog_debug("%u:recv SG %s %s", vrf_id
,
360 (cmd
== ZEBRA_VXLAN_SG_ADD
)?"add":"del",
364 if (cmd
== ZEBRA_VXLAN_SG_ADD
)
365 pim_vxlan_sg_add(pim
, &sg
);
367 pim_vxlan_sg_del(pim
, &sg
);
372 static void pim_zebra_vxlan_replay(void)
374 struct stream
*s
= NULL
;
377 if (!zclient
|| zclient
->sock
< 0)
383 zclient_create_header(s
, ZEBRA_VXLAN_SG_REPLAY
, VRF_DEFAULT
);
384 stream_putw_at(s
, 0, stream_get_endp(s
));
386 zclient_send_message(zclient
);
389 void pim_scan_oil(struct pim_instance
*pim
)
391 struct channel_oil
*c_oil
;
393 pim
->scan_oil_last
= pim_time_monotonic_sec();
394 ++pim
->scan_oil_events
;
396 frr_each (rb_pim_oil
, &pim
->channel_oil_head
, c_oil
)
397 pim_upstream_mroute_iif_update(c_oil
, __func__
);
400 static int on_rpf_cache_refresh(struct thread
*t
)
402 struct pim_instance
*pim
= THREAD_ARG(t
);
404 /* update kernel multicast forwarding cache (MFC) */
407 pim
->rpf_cache_refresh_last
= pim_time_monotonic_sec();
408 ++pim
->rpf_cache_refresh_events
;
410 // It is called as part of pim_neighbor_add
415 void sched_rpf_cache_refresh(struct pim_instance
*pim
)
417 ++pim
->rpf_cache_refresh_requests
;
419 pim_rpf_set_refresh_time(pim
);
421 if (pim
->rpf_cache_refresher
) {
422 /* Refresh timer is already running */
426 /* Start refresh timer */
428 if (PIM_DEBUG_ZEBRA
) {
429 zlog_debug("%s: triggering %ld msec timer", __func__
,
430 router
->rpf_cache_refresh_delay_msec
);
433 thread_add_timer_msec(router
->master
, on_rpf_cache_refresh
, pim
,
434 router
->rpf_cache_refresh_delay_msec
,
435 &pim
->rpf_cache_refresher
);
438 static void pim_zebra_connected(struct zclient
*zclient
)
440 /* Send the client registration */
441 bfd_client_sendmsg(zclient
, ZEBRA_BFD_CLIENT_REGISTER
, router
->vrf_id
);
443 zclient_send_reg_requests(zclient
, router
->vrf_id
);
445 /* request for VxLAN BUM group addresses */
446 pim_zebra_vxlan_replay();
449 static void pim_zebra_capabilities(struct zclient_capabilities
*cap
)
451 router
->mlag_role
= cap
->role
;
454 void pim_zebra_init(void)
456 /* Socket for receiving updates from Zebra daemon */
457 zclient
= zclient_new(router
->master
, &zclient_options_default
);
459 zclient
->zebra_capabilities
= pim_zebra_capabilities
;
460 zclient
->zebra_connected
= pim_zebra_connected
;
461 zclient
->router_id_update
= pim_router_id_update_zebra
;
462 zclient
->interface_address_add
= pim_zebra_if_address_add
;
463 zclient
->interface_address_delete
= pim_zebra_if_address_del
;
464 zclient
->interface_vrf_update
= pim_zebra_interface_vrf_update
;
465 zclient
->nexthop_update
= pim_parse_nexthop_update
;
466 zclient
->vxlan_sg_add
= pim_zebra_vxlan_sg_proc
;
467 zclient
->vxlan_sg_del
= pim_zebra_vxlan_sg_proc
;
468 zclient
->mlag_process_up
= pim_zebra_mlag_process_up
;
469 zclient
->mlag_process_down
= pim_zebra_mlag_process_down
;
470 zclient
->mlag_handle_msg
= pim_zebra_mlag_handle_msg
;
472 zclient_init(zclient
, ZEBRA_ROUTE_PIM
, 0, &pimd_privs
);
473 if (PIM_DEBUG_PIM_TRACE
) {
474 zlog_notice("%s: zclient socket initialized", __func__
);
477 zclient_lookup_new();
480 void igmp_anysource_forward_start(struct pim_instance
*pim
,
481 struct igmp_group
*group
)
483 struct igmp_source
*source
;
484 struct in_addr src_addr
= {.s_addr
= 0};
485 /* Any source (*,G) is forwarded only if mode is EXCLUDE {empty} */
486 zassert(group
->group_filtermode_isexcl
);
487 zassert(listcount(group
->group_source_list
) < 1);
489 source
= source_new(group
, src_addr
);
491 zlog_warn("%s: Failure to create * source", __func__
);
495 igmp_source_forward_start(pim
, source
);
498 void igmp_anysource_forward_stop(struct igmp_group
*group
)
500 struct igmp_source
*source
;
501 struct in_addr star
= {.s_addr
= 0};
503 source
= igmp_find_source_by_addr(group
, star
);
505 igmp_source_forward_stop(source
);
508 static void igmp_source_forward_reevaluate_one(struct pim_instance
*pim
,
509 struct igmp_source
*source
)
512 struct igmp_group
*group
= source
->source_group
;
513 struct pim_ifchannel
*ch
;
515 if ((source
->source_addr
.s_addr
!= INADDR_ANY
)
516 || !IGMP_SOURCE_TEST_FORWARDING(source
->source_flags
))
519 memset(&sg
, 0, sizeof(struct prefix_sg
));
520 sg
.src
= source
->source_addr
;
521 sg
.grp
= group
->group_addr
;
523 ch
= pim_ifchannel_find(group
->group_igmp_sock
->interface
, &sg
);
524 if (pim_is_grp_ssm(pim
, group
->group_addr
)) {
525 /* If SSM group withdraw local membership */
527 && (ch
->local_ifmembership
== PIM_IFMEMBERSHIP_INCLUDE
)) {
528 if (PIM_DEBUG_PIM_EVENTS
)
530 "local membership del for %s as G is now SSM",
531 pim_str_sg_dump(&sg
));
532 pim_ifchannel_local_membership_del(
533 group
->group_igmp_sock
->interface
, &sg
);
536 /* If ASM group add local membership */
538 || (ch
->local_ifmembership
== PIM_IFMEMBERSHIP_NOINFO
)) {
539 if (PIM_DEBUG_PIM_EVENTS
)
541 "local membership add for %s as G is now ASM",
542 pim_str_sg_dump(&sg
));
543 pim_ifchannel_local_membership_add(
544 group
->group_igmp_sock
->interface
, &sg
,
550 void igmp_source_forward_reevaluate_all(struct pim_instance
*pim
)
552 struct interface
*ifp
;
554 FOR_ALL_INTERFACES (pim
->vrf
, ifp
) {
555 struct pim_interface
*pim_ifp
= ifp
->info
;
556 struct listnode
*sock_node
;
557 struct igmp_sock
*igmp
;
562 /* scan igmp sockets */
563 for (ALL_LIST_ELEMENTS_RO(pim_ifp
->igmp_socket_list
, sock_node
,
565 struct listnode
*grpnode
;
566 struct igmp_group
*grp
;
568 /* scan igmp groups */
569 for (ALL_LIST_ELEMENTS_RO(igmp
->igmp_group_list
,
571 struct listnode
*srcnode
;
572 struct igmp_source
*src
;
574 /* scan group sources */
575 for (ALL_LIST_ELEMENTS_RO(
576 grp
->group_source_list
, srcnode
,
578 igmp_source_forward_reevaluate_one(pim
,
580 } /* scan group sources */
581 } /* scan igmp groups */
582 } /* scan igmp sockets */
583 } /* scan interfaces */
586 void igmp_source_forward_start(struct pim_instance
*pim
,
587 struct igmp_source
*source
)
589 struct pim_interface
*pim_oif
;
590 struct igmp_group
*group
;
593 int input_iface_vif_index
= 0;
595 memset(&sg
, 0, sizeof(struct prefix_sg
));
596 sg
.src
= source
->source_addr
;
597 sg
.grp
= source
->source_group
->group_addr
;
599 if (PIM_DEBUG_IGMP_TRACE
) {
601 "%s: (S,G)=%s igmp_sock=%d oif=%s fwd=%d", __func__
,
602 pim_str_sg_dump(&sg
),
603 source
->source_group
->group_igmp_sock
->fd
,
604 source
->source_group
->group_igmp_sock
->interface
->name
,
605 IGMP_SOURCE_TEST_FORWARDING(source
->source_flags
));
608 /* Prevent IGMP interface from installing multicast route multiple
610 if (IGMP_SOURCE_TEST_FORWARDING(source
->source_flags
)) {
614 group
= source
->source_group
;
615 pim_oif
= group
->group_igmp_sock
->interface
->info
;
617 if (PIM_DEBUG_IGMP_TRACE
) {
618 zlog_debug("%s: multicast not enabled on oif=%s ?",
620 source
->source_group
->group_igmp_sock
626 if (!source
->source_channel_oil
) {
627 struct in_addr vif_source
;
628 struct prefix src
, grp
;
629 struct pim_nexthop nexthop
;
630 struct pim_upstream
*up
= NULL
;
632 if (!pim_rp_set_upstream_addr(pim
, &vif_source
,
633 source
->source_addr
, sg
.grp
)) {
634 /*Create a dummy channel oil */
635 source
->source_channel_oil
=
636 pim_channel_oil_add(pim
, &sg
, __func__
);
640 src
.family
= AF_INET
;
641 src
.prefixlen
= IPV4_MAX_BITLEN
;
642 src
.u
.prefix4
= vif_source
; // RP or Src address
643 grp
.family
= AF_INET
;
644 grp
.prefixlen
= IPV4_MAX_BITLEN
;
645 grp
.u
.prefix4
= sg
.grp
;
647 up
= pim_upstream_find(pim
, &sg
);
649 memcpy(&nexthop
, &up
->rpf
.source_nexthop
,
650 sizeof(struct pim_nexthop
));
651 pim_ecmp_nexthop_lookup(pim
, &nexthop
, &src
,
653 if (nexthop
.interface
)
654 input_iface_vif_index
=
655 pim_if_find_vifindex_by_ifindex(
657 nexthop
.interface
->ifindex
);
659 input_iface_vif_index
=
660 pim_ecmp_fib_lookup_if_vif_index(
663 if (PIM_DEBUG_ZEBRA
) {
664 char buf2
[INET_ADDRSTRLEN
];
666 pim_inet4_dump("<source?>", vif_source
, buf2
,
669 "%s: NHT %s vif_source %s vif_index:%d ",
670 __func__
, pim_str_sg_dump(&sg
), buf2
,
671 input_iface_vif_index
);
674 if (input_iface_vif_index
< 1) {
675 if (PIM_DEBUG_IGMP_TRACE
) {
676 char source_str
[INET_ADDRSTRLEN
];
677 pim_inet4_dump("<source?>",
679 source_str
, sizeof(source_str
));
681 "%s %s: could not find input interface for source %s",
682 __FILE__
, __func__
, source_str
);
684 source
->source_channel_oil
=
685 pim_channel_oil_add(pim
, &sg
, __func__
);
690 * Protect IGMP against adding looped MFC
691 * entries created by both source and receiver
692 * attached to the same interface. See TODO
693 * T22. Block only when the intf is non DR
694 * DR must create upstream.
696 if ((input_iface_vif_index
==
697 pim_oif
->mroute_vif_index
) &&
698 !(PIM_I_am_DR(pim_oif
))) {
699 /* ignore request for looped MFC entry
701 if (PIM_DEBUG_IGMP_TRACE
) {
703 "%s: ignoring request for looped MFC entry (S,G)=%s: igmp_sock=%d oif=%s vif_index=%d",
705 pim_str_sg_dump(&sg
),
712 input_iface_vif_index
);
717 source
->source_channel_oil
=
718 pim_channel_oil_add(pim
, &sg
, __func__
);
719 if (!source
->source_channel_oil
) {
720 if (PIM_DEBUG_IGMP_TRACE
) {
722 "%s %s: could not create OIL for channel (S,G)=%s",
724 pim_str_sg_dump(&sg
));
732 if (PIM_I_am_DR(pim_oif
)) {
733 result
= pim_channel_add_oif(source
->source_channel_oil
,
734 group
->group_igmp_sock
->interface
,
735 PIM_OIF_FLAG_PROTO_IGMP
, __func__
);
737 if (PIM_DEBUG_MROUTE
) {
738 zlog_warn("%s: add_oif() failed with return=%d",
744 if (PIM_DEBUG_IGMP_TRACE
)
746 "%s: %s was received on %s interface but we are not DR for that interface",
747 __func__
, pim_str_sg_dump(&sg
),
748 group
->group_igmp_sock
->interface
->name
);
753 Feed IGMPv3-gathered local membership information into PIM
754 per-interface (S,G) state.
756 if (!pim_ifchannel_local_membership_add(
757 group
->group_igmp_sock
->interface
, &sg
,
758 false /*is_vxlan*/)) {
759 if (PIM_DEBUG_MROUTE
)
760 zlog_warn("%s: Failure to add local membership for %s",
761 __func__
, pim_str_sg_dump(&sg
));
763 pim_channel_del_oif(source
->source_channel_oil
,
764 group
->group_igmp_sock
->interface
,
765 PIM_OIF_FLAG_PROTO_IGMP
, __func__
);
769 IGMP_SOURCE_DO_FORWARDING(source
->source_flags
);
773 igmp_source_forward_stop: stop fowarding, but keep the source
774 igmp_source_delete: stop fowarding, and delete the source
776 void igmp_source_forward_stop(struct igmp_source
*source
)
778 struct igmp_group
*group
;
782 memset(&sg
, 0, sizeof(struct prefix_sg
));
783 sg
.src
= source
->source_addr
;
784 sg
.grp
= source
->source_group
->group_addr
;
786 if (PIM_DEBUG_IGMP_TRACE
) {
788 "%s: (S,G)=%s igmp_sock=%d oif=%s fwd=%d", __func__
,
789 pim_str_sg_dump(&sg
),
790 source
->source_group
->group_igmp_sock
->fd
,
791 source
->source_group
->group_igmp_sock
->interface
->name
,
792 IGMP_SOURCE_TEST_FORWARDING(source
->source_flags
));
795 /* Prevent IGMP interface from removing multicast route multiple
797 if (!IGMP_SOURCE_TEST_FORWARDING(source
->source_flags
)) {
801 group
= source
->source_group
;
804 It appears that in certain circumstances that
805 igmp_source_forward_stop is called when IGMP forwarding
806 was not enabled in oif_flags for this outgoing interface.
807 Possibly because of multiple calls. When that happens, we
808 enter the below if statement and this function returns early
809 which in turn triggers the calling function to assert.
810 Making the call to pim_channel_del_oif and ignoring the return code
811 fixes the issue without ill effect, similar to
812 pim_forward_stop below.
814 result
= pim_channel_del_oif(source
->source_channel_oil
,
815 group
->group_igmp_sock
->interface
,
816 PIM_OIF_FLAG_PROTO_IGMP
,
819 if (PIM_DEBUG_IGMP_TRACE
)
821 "%s: pim_channel_del_oif() failed with return=%d",
827 Feed IGMPv3-gathered local membership information into PIM
828 per-interface (S,G) state.
830 pim_ifchannel_local_membership_del(group
->group_igmp_sock
->interface
,
833 IGMP_SOURCE_DONT_FORWARDING(source
->source_flags
);
836 void pim_forward_start(struct pim_ifchannel
*ch
)
838 struct pim_upstream
*up
= ch
->upstream
;
839 uint32_t mask
= PIM_OIF_FLAG_PROTO_PIM
;
841 if (PIM_DEBUG_PIM_TRACE
) {
842 char source_str
[INET_ADDRSTRLEN
];
843 char group_str
[INET_ADDRSTRLEN
];
844 char upstream_str
[INET_ADDRSTRLEN
];
846 pim_inet4_dump("<source?>", ch
->sg
.src
, source_str
,
848 pim_inet4_dump("<group?>", ch
->sg
.grp
, group_str
,
850 pim_inet4_dump("<upstream?>", up
->upstream_addr
, upstream_str
,
851 sizeof(upstream_str
));
852 zlog_debug("%s: (S,G)=(%s,%s) oif=%s (%s)", __func__
,
853 source_str
, group_str
, ch
->interface
->name
,
854 inet_ntoa(up
->upstream_addr
));
857 if (up
->flags
& PIM_UPSTREAM_FLAG_MASK_SRC_IGMP
)
858 mask
= PIM_OIF_FLAG_PROTO_IGMP
;
860 pim_channel_add_oif(up
->channel_oil
, ch
->interface
,
864 void pim_forward_stop(struct pim_ifchannel
*ch
, bool install_it
)
866 struct pim_upstream
*up
= ch
->upstream
;
868 if (PIM_DEBUG_PIM_TRACE
) {
869 zlog_debug("%s: (S,G)=%s oif=%s install_it: %d installed: %d",
870 __func__
, ch
->sg_str
, ch
->interface
->name
,
871 install_it
, up
->channel_oil
->installed
);
875 * If a channel is being removed, check to see if we still need
876 * to inherit the interface. If so make sure it is added in
878 if (pim_upstream_evaluate_join_desired_interface(up
, ch
, ch
->parent
))
879 pim_channel_add_oif(up
->channel_oil
, ch
->interface
,
880 PIM_OIF_FLAG_PROTO_PIM
, __func__
);
882 pim_channel_del_oif(up
->channel_oil
, ch
->interface
,
883 PIM_OIF_FLAG_PROTO_PIM
, __func__
);
885 if (install_it
&& !up
->channel_oil
->installed
)
886 pim_upstream_mroute_add(up
->channel_oil
, __func__
);
889 void pim_zebra_zclient_update(struct vty
*vty
)
891 vty_out(vty
, "Zclient update socket: ");
894 vty_out(vty
, "%d failures=%d\n", zclient
->sock
, zclient
->fail
);
896 vty_out(vty
, "<null zclient>\n");
900 struct zclient
*pim_zebra_zclient_get(void)
908 void pim_zebra_interface_set_master(struct interface
*vrf
,
909 struct interface
*ifp
)
911 zclient_interface_set_master(zclient
, vrf
, ifp
);