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_interface_vrf_update(ZAPI_CALLBACK_ARGS
)
68 struct interface
*ifp
;
71 ifp
= zebra_interface_vrf_update_read(zclient
->ibuf
, vrf_id
,
77 zlog_debug("%s: %s updating from %u to %u",
79 ifp
->name
, vrf_id
, new_vrf_id
);
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 __PRETTY_FUNCTION__
, c
->ifp
->name
, vrf_id
, buf
,
139 CHECK_FLAG(c
->flags
, ZEBRA_IFA_SECONDARY
)
143 #ifdef PIM_DEBUG_IFADDR_DUMP
144 dump_if_address(c
->ifp
);
148 if (!CHECK_FLAG(c
->flags
, ZEBRA_IFA_SECONDARY
)) {
149 /* trying to add primary address */
151 struct in_addr primary_addr
= pim_find_primary_addr(c
->ifp
);
152 if (p
->family
!= AF_INET
153 || primary_addr
.s_addr
!= p
->u
.prefix4
.s_addr
) {
154 if (PIM_DEBUG_ZEBRA
) {
155 /* but we had a primary address already */
159 prefix2str(p
, buf
, BUFSIZ
);
162 "%s: %s : forcing secondary flag on %s",
163 __PRETTY_FUNCTION__
, c
->ifp
->name
, buf
);
165 SET_FLAG(c
->flags
, ZEBRA_IFA_SECONDARY
);
171 pim
= pim_get_pim_instance(vrf_id
);
174 pim_rp_check_on_if_add(pim_ifp
);
177 if (if_is_loopback(c
->ifp
)) {
178 struct vrf
*vrf
= vrf_lookup_by_id(VRF_DEFAULT
);
179 struct interface
*ifp
;
181 FOR_ALL_INTERFACES (vrf
, ifp
) {
182 if (!if_is_loopback(ifp
) && if_is_operative(ifp
))
183 pim_if_addr_add_all(ifp
);
190 static int pim_zebra_if_address_del(ZAPI_CALLBACK_ARGS
)
194 struct vrf
*vrf
= vrf_lookup_by_id(vrf_id
);
195 struct pim_instance
*pim
;
202 zebra api notifies address adds/dels events by using the same call
203 interface_add_read below, see comments in lib/zclient.c
205 zebra_interface_address_read(ZEBRA_INTERFACE_ADDRESS_DELETE, ...)
206 will remove address from interface list by calling
207 connected_delete_by_prefix()
209 c
= zebra_interface_address_read(cmd
, zclient
->ibuf
, vrf_id
);
214 if (p
->family
== AF_INET
) {
215 if (PIM_DEBUG_ZEBRA
) {
217 prefix2str(p
, buf
, BUFSIZ
);
219 "%s: %s(%u) disconnected IP address %s flags %u %s",
220 __PRETTY_FUNCTION__
, c
->ifp
->name
, vrf_id
, buf
,
222 CHECK_FLAG(c
->flags
, ZEBRA_IFA_SECONDARY
)
226 #ifdef PIM_DEBUG_IFADDR_DUMP
227 dump_if_address(c
->ifp
);
231 pim_if_addr_del(c
, 0);
233 pim_i_am_rp_re_evaluate(pim
);
240 void pim_zebra_update_all_interfaces(struct pim_instance
*pim
)
242 struct interface
*ifp
;
244 FOR_ALL_INTERFACES (pim
->vrf
, ifp
) {
245 struct pim_interface
*pim_ifp
= ifp
->info
;
246 struct pim_iface_upstream_switch
*us
;
247 struct listnode
*node
;
252 for (ALL_LIST_ELEMENTS_RO(pim_ifp
->upstream_switch_list
, node
,
256 rpf
.source_nexthop
.interface
= ifp
;
257 rpf
.rpf_addr
.u
.prefix4
= us
->address
;
258 pim_joinprune_send(&rpf
, us
->us
);
259 pim_jp_agg_clear_group(us
->us
);
264 void pim_zebra_upstream_rpf_changed(struct pim_instance
*pim
,
265 struct pim_upstream
*up
,
268 if (old
->source_nexthop
.interface
) {
269 struct pim_neighbor
*nbr
;
271 nbr
= pim_neighbor_find(old
->source_nexthop
.interface
,
272 old
->rpf_addr
.u
.prefix4
);
274 pim_jp_agg_remove_group(nbr
->upstream_jp_agg
, up
);
277 * We have detected a case where we might need
278 * to rescan the inherited o_list so do it.
280 if (up
->channel_oil
->oil_inherited_rescan
) {
281 pim_upstream_inherited_olist_decide(pim
, up
);
282 up
->channel_oil
->oil_inherited_rescan
= 0;
285 if (up
->join_state
== PIM_UPSTREAM_JOINED
) {
287 * If we come up real fast we can be here
288 * where the mroute has not been installed
291 if (!up
->channel_oil
->installed
)
292 pim_upstream_mroute_add(up
->channel_oil
,
293 __PRETTY_FUNCTION__
);
296 * RFC 4601: 4.5.7. Sending (S,G)
297 * Join/Prune Messages
299 * Transitions from Joined State
301 * RPF'(S,G) changes not due to an Assert
303 * The upstream (S,G) state machine remains
304 * in Joined state. Send Join(S,G) to the new
305 * upstream neighbor, which is the new value
306 * of RPF'(S,G). Send Prune(S,G) to the old
307 * upstream neighbor, which is the old value
308 * of RPF'(S,G). Set the Join Timer (JT) to
309 * expire after t_periodic seconds.
311 pim_jp_agg_switch_interface(old
, &up
->rpf
, up
);
313 pim_upstream_join_timer_restart(up
, old
);
314 } /* up->join_state == PIM_UPSTREAM_JOINED */
319 * We have detected a case where we might need
320 * to rescan the inherited o_list so do it.
322 if (up
->channel_oil
->oil_inherited_rescan
) {
323 pim_upstream_inherited_olist_decide(pim
, up
);
324 up
->channel_oil
->oil_inherited_rescan
= 0;
327 if (!up
->channel_oil
->installed
)
328 pim_upstream_mroute_add(up
->channel_oil
,
329 __PRETTY_FUNCTION__
);
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_individual_oil(struct channel_oil
*c_oil
, int in_vif_index
)
391 struct in_addr vif_source
;
392 int input_iface_vif_index
;
394 pim_rp_set_upstream_addr(c_oil
->pim
, &vif_source
,
395 c_oil
->oil
.mfcc_origin
,
396 c_oil
->oil
.mfcc_mcastgrp
);
399 input_iface_vif_index
= in_vif_index
;
401 struct prefix src
, grp
;
403 src
.family
= AF_INET
;
404 src
.prefixlen
= IPV4_MAX_BITLEN
;
405 src
.u
.prefix4
= vif_source
;
406 grp
.family
= AF_INET
;
407 grp
.prefixlen
= IPV4_MAX_BITLEN
;
408 grp
.u
.prefix4
= c_oil
->oil
.mfcc_mcastgrp
;
410 if (PIM_DEBUG_ZEBRA
) {
411 char source_str
[INET_ADDRSTRLEN
];
412 char group_str
[INET_ADDRSTRLEN
];
413 pim_inet4_dump("<source?>", c_oil
->oil
.mfcc_origin
,
414 source_str
, sizeof(source_str
));
415 pim_inet4_dump("<group?>", c_oil
->oil
.mfcc_mcastgrp
,
416 group_str
, sizeof(group_str
));
418 "%s: channel_oil (%s,%s) upstream info is not present.",
419 __PRETTY_FUNCTION__
, source_str
, group_str
);
421 input_iface_vif_index
= pim_ecmp_fib_lookup_if_vif_index(
422 c_oil
->pim
, &src
, &grp
);
425 if (input_iface_vif_index
< 1) {
426 if (PIM_DEBUG_ZEBRA
) {
427 char source_str
[INET_ADDRSTRLEN
];
428 char group_str
[INET_ADDRSTRLEN
];
429 pim_inet4_dump("<source?>", c_oil
->oil
.mfcc_origin
,
430 source_str
, sizeof(source_str
));
431 pim_inet4_dump("<group?>", c_oil
->oil
.mfcc_mcastgrp
,
432 group_str
, sizeof(group_str
));
434 "%s %s: could not find input interface(%d) for (S,G)=(%s,%s)",
435 __FILE__
, __PRETTY_FUNCTION__
,
436 c_oil
->oil
.mfcc_parent
, source_str
, group_str
);
438 pim_mroute_del(c_oil
, __PRETTY_FUNCTION__
);
442 if (input_iface_vif_index
== c_oil
->oil
.mfcc_parent
) {
443 if (!c_oil
->installed
)
444 pim_upstream_mroute_add(c_oil
, __PRETTY_FUNCTION__
);
450 if (PIM_DEBUG_ZEBRA
) {
451 struct interface
*old_iif
= pim_if_find_by_vif_index(
452 c_oil
->pim
, c_oil
->oil
.mfcc_parent
);
453 struct interface
*new_iif
= pim_if_find_by_vif_index(
454 c_oil
->pim
, input_iface_vif_index
);
455 char source_str
[INET_ADDRSTRLEN
];
456 char group_str
[INET_ADDRSTRLEN
];
457 pim_inet4_dump("<source?>", c_oil
->oil
.mfcc_origin
, source_str
,
459 pim_inet4_dump("<group?>", c_oil
->oil
.mfcc_mcastgrp
, group_str
,
462 "%s %s: (S,G)=(%s,%s) input interface changed from %s vif_index=%d to %s vif_index=%d",
463 __FILE__
, __PRETTY_FUNCTION__
, source_str
, group_str
,
464 (old_iif
) ? old_iif
->name
: "<old_iif?>",
465 c_oil
->oil
.mfcc_parent
,
466 (new_iif
) ? new_iif
->name
: "<new_iif?>",
467 input_iface_vif_index
);
470 /* new iif loops to existing oif ? */
471 if (c_oil
->oil
.mfcc_ttls
[input_iface_vif_index
]) {
472 struct interface
*new_iif
= pim_if_find_by_vif_index(
473 c_oil
->pim
, input_iface_vif_index
);
475 if (PIM_DEBUG_ZEBRA
) {
476 char source_str
[INET_ADDRSTRLEN
];
477 char group_str
[INET_ADDRSTRLEN
];
478 pim_inet4_dump("<source?>", c_oil
->oil
.mfcc_origin
,
479 source_str
, sizeof(source_str
));
480 pim_inet4_dump("<group?>", c_oil
->oil
.mfcc_mcastgrp
,
481 group_str
, sizeof(group_str
));
483 "%s %s: (S,G)=(%s,%s) new iif loops to existing oif: %s vif_index=%d",
484 __FILE__
, __PRETTY_FUNCTION__
, source_str
,
486 (new_iif
) ? new_iif
->name
: "<new_iif?>",
487 input_iface_vif_index
);
491 /* update iif vif_index */
492 pim_channel_oil_change_iif(c_oil
->pim
, c_oil
, input_iface_vif_index
,
493 __PRETTY_FUNCTION__
);
494 pim_upstream_mroute_add(c_oil
, __PRETTY_FUNCTION__
);
497 void pim_scan_oil(struct pim_instance
*pim
)
499 struct listnode
*node
;
500 struct listnode
*nextnode
;
501 struct channel_oil
*c_oil
;
505 pim
->scan_oil_last
= pim_time_monotonic_sec();
506 ++pim
->scan_oil_events
;
508 for (ALL_LIST_ELEMENTS(pim
->channel_oil_list
, node
, nextnode
, c_oil
)) {
509 if (c_oil
->up
&& c_oil
->up
->rpf
.source_nexthop
.interface
) {
510 ifindex
= c_oil
->up
->rpf
.source_nexthop
513 pim_if_find_vifindex_by_ifindex(pim
, ifindex
);
514 /* Pass Current selected NH vif index to mroute
517 pim_scan_individual_oil(c_oil
, vif_index
);
519 pim_scan_individual_oil(c_oil
, 0);
523 static int on_rpf_cache_refresh(struct thread
*t
)
525 struct pim_instance
*pim
= THREAD_ARG(t
);
527 /* update kernel multicast forwarding cache (MFC) */
530 pim
->rpf_cache_refresh_last
= pim_time_monotonic_sec();
531 ++pim
->rpf_cache_refresh_events
;
533 // It is called as part of pim_neighbor_add
538 void sched_rpf_cache_refresh(struct pim_instance
*pim
)
540 ++pim
->rpf_cache_refresh_requests
;
542 pim_rpf_set_refresh_time(pim
);
544 if (pim
->rpf_cache_refresher
) {
545 /* Refresh timer is already running */
549 /* Start refresh timer */
551 if (PIM_DEBUG_ZEBRA
) {
552 zlog_debug("%s: triggering %ld msec timer", __PRETTY_FUNCTION__
,
553 router
->rpf_cache_refresh_delay_msec
);
556 thread_add_timer_msec(router
->master
, on_rpf_cache_refresh
, pim
,
557 router
->rpf_cache_refresh_delay_msec
,
558 &pim
->rpf_cache_refresher
);
561 static void pim_zebra_connected(struct zclient
*zclient
)
563 /* Send the client registration */
564 bfd_client_sendmsg(zclient
, ZEBRA_BFD_CLIENT_REGISTER
, router
->vrf_id
);
566 zclient_send_reg_requests(zclient
, router
->vrf_id
);
568 /* request for VxLAN BUM group addresses */
569 pim_zebra_vxlan_replay();
572 static void pim_zebra_capabilities(struct zclient_capabilities
*cap
)
574 router
->role
= cap
->role
;
577 void pim_zebra_init(void)
579 /* Socket for receiving updates from Zebra daemon */
580 zclient
= zclient_new(router
->master
, &zclient_options_default
);
582 zclient
->zebra_capabilities
= pim_zebra_capabilities
;
583 zclient
->zebra_connected
= pim_zebra_connected
;
584 zclient
->router_id_update
= pim_router_id_update_zebra
;
585 zclient
->interface_address_add
= pim_zebra_if_address_add
;
586 zclient
->interface_address_delete
= pim_zebra_if_address_del
;
587 zclient
->interface_vrf_update
= pim_zebra_interface_vrf_update
;
588 zclient
->nexthop_update
= pim_parse_nexthop_update
;
589 zclient
->vxlan_sg_add
= pim_zebra_vxlan_sg_proc
;
590 zclient
->vxlan_sg_del
= pim_zebra_vxlan_sg_proc
;
592 zclient_init(zclient
, ZEBRA_ROUTE_PIM
, 0, &pimd_privs
);
593 if (PIM_DEBUG_PIM_TRACE
) {
594 zlog_notice("%s: zclient socket initialized",
595 __PRETTY_FUNCTION__
);
598 zclient_lookup_new();
601 void igmp_anysource_forward_start(struct pim_instance
*pim
,
602 struct igmp_group
*group
)
604 struct igmp_source
*source
;
605 struct in_addr src_addr
= {.s_addr
= 0};
606 /* Any source (*,G) is forwarded only if mode is EXCLUDE {empty} */
607 zassert(group
->group_filtermode_isexcl
);
608 zassert(listcount(group
->group_source_list
) < 1);
610 source
= source_new(group
, src_addr
);
612 zlog_warn("%s: Failure to create * source",
613 __PRETTY_FUNCTION__
);
617 igmp_source_forward_start(pim
, source
);
620 void igmp_anysource_forward_stop(struct igmp_group
*group
)
622 struct igmp_source
*source
;
623 struct in_addr star
= {.s_addr
= 0};
625 source
= igmp_find_source_by_addr(group
, star
);
627 igmp_source_forward_stop(source
);
630 static void igmp_source_forward_reevaluate_one(struct pim_instance
*pim
,
631 struct igmp_source
*source
)
634 struct igmp_group
*group
= source
->source_group
;
635 struct pim_ifchannel
*ch
;
637 if ((source
->source_addr
.s_addr
!= INADDR_ANY
)
638 || !IGMP_SOURCE_TEST_FORWARDING(source
->source_flags
))
641 memset(&sg
, 0, sizeof(struct prefix_sg
));
642 sg
.src
= source
->source_addr
;
643 sg
.grp
= group
->group_addr
;
645 ch
= pim_ifchannel_find(group
->group_igmp_sock
->interface
, &sg
);
646 if (pim_is_grp_ssm(pim
, group
->group_addr
)) {
647 /* If SSM group withdraw local membership */
649 && (ch
->local_ifmembership
== PIM_IFMEMBERSHIP_INCLUDE
)) {
650 if (PIM_DEBUG_PIM_EVENTS
)
652 "local membership del for %s as G is now SSM",
653 pim_str_sg_dump(&sg
));
654 pim_ifchannel_local_membership_del(
655 group
->group_igmp_sock
->interface
, &sg
);
658 /* If ASM group add local membership */
660 || (ch
->local_ifmembership
== PIM_IFMEMBERSHIP_NOINFO
)) {
661 if (PIM_DEBUG_PIM_EVENTS
)
663 "local membership add for %s as G is now ASM",
664 pim_str_sg_dump(&sg
));
665 pim_ifchannel_local_membership_add(
666 group
->group_igmp_sock
->interface
, &sg
);
671 void igmp_source_forward_reevaluate_all(struct pim_instance
*pim
)
673 struct interface
*ifp
;
675 FOR_ALL_INTERFACES (pim
->vrf
, ifp
) {
676 struct pim_interface
*pim_ifp
= ifp
->info
;
677 struct listnode
*sock_node
;
678 struct igmp_sock
*igmp
;
683 /* scan igmp sockets */
684 for (ALL_LIST_ELEMENTS_RO(pim_ifp
->igmp_socket_list
, sock_node
,
686 struct listnode
*grpnode
;
687 struct igmp_group
*grp
;
689 /* scan igmp groups */
690 for (ALL_LIST_ELEMENTS_RO(igmp
->igmp_group_list
,
692 struct listnode
*srcnode
;
693 struct igmp_source
*src
;
695 /* scan group sources */
696 for (ALL_LIST_ELEMENTS_RO(
697 grp
->group_source_list
, srcnode
,
699 igmp_source_forward_reevaluate_one(pim
,
701 } /* scan group sources */
702 } /* scan igmp groups */
703 } /* scan igmp sockets */
704 } /* scan interfaces */
707 void igmp_source_forward_start(struct pim_instance
*pim
,
708 struct igmp_source
*source
)
710 struct pim_interface
*pim_oif
;
711 struct igmp_group
*group
;
714 int input_iface_vif_index
= 0;
716 memset(&sg
, 0, sizeof(struct prefix_sg
));
717 sg
.src
= source
->source_addr
;
718 sg
.grp
= source
->source_group
->group_addr
;
720 if (PIM_DEBUG_IGMP_TRACE
) {
722 "%s: (S,G)=%s igmp_sock=%d oif=%s fwd=%d",
723 __PRETTY_FUNCTION__
, pim_str_sg_dump(&sg
),
724 source
->source_group
->group_igmp_sock
->fd
,
725 source
->source_group
->group_igmp_sock
->interface
->name
,
726 IGMP_SOURCE_TEST_FORWARDING(source
->source_flags
));
729 /* Prevent IGMP interface from installing multicast route multiple
731 if (IGMP_SOURCE_TEST_FORWARDING(source
->source_flags
)) {
735 group
= source
->source_group
;
736 pim_oif
= group
->group_igmp_sock
->interface
->info
;
738 if (PIM_DEBUG_IGMP_TRACE
) {
740 "%s: multicast not enabled on oif=%s ?",
742 source
->source_group
->group_igmp_sock
748 if (!source
->source_channel_oil
) {
749 struct in_addr vif_source
;
750 struct prefix src
, grp
;
751 struct pim_nexthop nexthop
;
752 struct pim_upstream
*up
= NULL
;
754 if (!pim_rp_set_upstream_addr(pim
, &vif_source
,
755 source
->source_addr
, sg
.grp
)) {
756 /*Create a dummy channel oil */
757 source
->source_channel_oil
= pim_channel_oil_add(
758 pim
, &sg
, MAXVIFS
, __PRETTY_FUNCTION__
);
762 src
.family
= AF_INET
;
763 src
.prefixlen
= IPV4_MAX_BITLEN
;
764 src
.u
.prefix4
= vif_source
; // RP or Src address
765 grp
.family
= AF_INET
;
766 grp
.prefixlen
= IPV4_MAX_BITLEN
;
767 grp
.u
.prefix4
= sg
.grp
;
769 up
= pim_upstream_find(pim
, &sg
);
771 memcpy(&nexthop
, &up
->rpf
.source_nexthop
,
772 sizeof(struct pim_nexthop
));
773 pim_ecmp_nexthop_lookup(pim
, &nexthop
, &src
,
775 if (nexthop
.interface
)
776 input_iface_vif_index
=
777 pim_if_find_vifindex_by_ifindex(
779 nexthop
.interface
->ifindex
);
781 input_iface_vif_index
=
782 pim_ecmp_fib_lookup_if_vif_index(
785 if (PIM_DEBUG_ZEBRA
) {
786 char buf2
[INET_ADDRSTRLEN
];
788 pim_inet4_dump("<source?>", vif_source
, buf2
,
790 zlog_debug("%s: NHT %s vif_source %s vif_index:%d ",
792 pim_str_sg_dump(&sg
),
793 buf2
, input_iface_vif_index
);
796 if (input_iface_vif_index
< 1) {
797 if (PIM_DEBUG_IGMP_TRACE
) {
798 char source_str
[INET_ADDRSTRLEN
];
799 pim_inet4_dump("<source?>",
801 source_str
, sizeof(source_str
));
803 "%s %s: could not find input interface for source %s",
804 __FILE__
, __PRETTY_FUNCTION__
,
807 source
->source_channel_oil
=
810 __PRETTY_FUNCTION__
);
815 * Protect IGMP against adding looped MFC
816 * entries created by both source and receiver
817 * attached to the same interface. See TODO
818 * T22. Block only when the intf is non DR
819 * DR must create upstream.
821 if ((input_iface_vif_index
==
822 pim_oif
->mroute_vif_index
) &&
823 !(PIM_I_am_DR(pim_oif
))) {
824 /* ignore request for looped MFC entry
826 if (PIM_DEBUG_IGMP_TRACE
) {
828 "%s: ignoring request for looped MFC entry (S,G)=%s: igmp_sock=%d oif=%s vif_index=%d",
830 pim_str_sg_dump(&sg
),
832 ->group_igmp_sock
->fd
,
836 input_iface_vif_index
);
841 source
->source_channel_oil
=
843 pim
, &sg
, input_iface_vif_index
,
844 __PRETTY_FUNCTION__
);
845 if (!source
->source_channel_oil
) {
846 if (PIM_DEBUG_IGMP_TRACE
) {
848 "%s %s: could not create OIL for channel (S,G)=%s",
851 pim_str_sg_dump(&sg
));
859 if (PIM_I_am_DR(pim_oif
)) {
860 result
= pim_channel_add_oif(source
->source_channel_oil
,
861 group
->group_igmp_sock
->interface
,
862 PIM_OIF_FLAG_PROTO_IGMP
, __func__
);
864 if (PIM_DEBUG_MROUTE
) {
865 zlog_warn("%s: add_oif() failed with return=%d",
871 if (PIM_DEBUG_IGMP_TRACE
)
872 zlog_debug("%s: %s was received on %s interface but we are not DR for that interface",
874 pim_str_sg_dump(&sg
),
875 group
->group_igmp_sock
->interface
->name
);
880 Feed IGMPv3-gathered local membership information into PIM
881 per-interface (S,G) state.
883 if (!pim_ifchannel_local_membership_add(
884 group
->group_igmp_sock
->interface
, &sg
)) {
885 if (PIM_DEBUG_MROUTE
)
886 zlog_warn("%s: Failure to add local membership for %s",
887 __PRETTY_FUNCTION__
, pim_str_sg_dump(&sg
));
889 pim_channel_del_oif(source
->source_channel_oil
,
890 group
->group_igmp_sock
->interface
,
891 PIM_OIF_FLAG_PROTO_IGMP
, __func__
);
895 IGMP_SOURCE_DO_FORWARDING(source
->source_flags
);
899 igmp_source_forward_stop: stop fowarding, but keep the source
900 igmp_source_delete: stop fowarding, and delete the source
902 void igmp_source_forward_stop(struct igmp_source
*source
)
904 struct igmp_group
*group
;
908 memset(&sg
, 0, sizeof(struct prefix_sg
));
909 sg
.src
= source
->source_addr
;
910 sg
.grp
= source
->source_group
->group_addr
;
912 if (PIM_DEBUG_IGMP_TRACE
) {
914 "%s: (S,G)=%s igmp_sock=%d oif=%s fwd=%d",
915 __PRETTY_FUNCTION__
, pim_str_sg_dump(&sg
),
916 source
->source_group
->group_igmp_sock
->fd
,
917 source
->source_group
->group_igmp_sock
->interface
->name
,
918 IGMP_SOURCE_TEST_FORWARDING(source
->source_flags
));
921 /* Prevent IGMP interface from removing multicast route multiple
923 if (!IGMP_SOURCE_TEST_FORWARDING(source
->source_flags
)) {
927 group
= source
->source_group
;
930 It appears that in certain circumstances that
931 igmp_source_forward_stop is called when IGMP forwarding
932 was not enabled in oif_flags for this outgoing interface.
933 Possibly because of multiple calls. When that happens, we
934 enter the below if statement and this function returns early
935 which in turn triggers the calling function to assert.
936 Making the call to pim_channel_del_oif and ignoring the return code
937 fixes the issue without ill effect, similar to
938 pim_forward_stop below.
940 result
= pim_channel_del_oif(source
->source_channel_oil
,
941 group
->group_igmp_sock
->interface
,
942 PIM_OIF_FLAG_PROTO_IGMP
,
945 if (PIM_DEBUG_IGMP_TRACE
)
947 "%s: pim_channel_del_oif() failed with return=%d",
953 Feed IGMPv3-gathered local membership information into PIM
954 per-interface (S,G) state.
956 pim_ifchannel_local_membership_del(group
->group_igmp_sock
->interface
,
959 IGMP_SOURCE_DONT_FORWARDING(source
->source_flags
);
962 void pim_forward_start(struct pim_ifchannel
*ch
)
964 struct pim_upstream
*up
= ch
->upstream
;
965 uint32_t mask
= PIM_OIF_FLAG_PROTO_PIM
;
967 if (PIM_DEBUG_PIM_TRACE
) {
968 char source_str
[INET_ADDRSTRLEN
];
969 char group_str
[INET_ADDRSTRLEN
];
970 char upstream_str
[INET_ADDRSTRLEN
];
972 pim_inet4_dump("<source?>", ch
->sg
.src
, source_str
,
974 pim_inet4_dump("<group?>", ch
->sg
.grp
, group_str
,
976 pim_inet4_dump("<upstream?>", up
->upstream_addr
, upstream_str
,
977 sizeof(upstream_str
));
978 zlog_debug("%s: (S,G)=(%s,%s) oif=%s (%s)", __PRETTY_FUNCTION__
,
979 source_str
, group_str
, ch
->interface
->name
,
980 inet_ntoa(up
->upstream_addr
));
983 if (up
->flags
& PIM_UPSTREAM_FLAG_MASK_SRC_IGMP
)
984 mask
= PIM_OIF_FLAG_PROTO_IGMP
;
986 pim_channel_add_oif(up
->channel_oil
, ch
->interface
,
990 void pim_forward_stop(struct pim_ifchannel
*ch
, bool install_it
)
992 struct pim_upstream
*up
= ch
->upstream
;
994 if (PIM_DEBUG_PIM_TRACE
) {
995 zlog_debug("%s: (S,G)=%s oif=%s install_it: %d installed: %d",
996 __PRETTY_FUNCTION__
, ch
->sg_str
, ch
->interface
->name
,
997 install_it
, up
->channel_oil
->installed
);
1001 * If a channel is being removed, check to see if we still need
1002 * to inherit the interface. If so make sure it is added in
1004 if (pim_upstream_evaluate_join_desired_interface(up
, ch
, ch
->parent
))
1005 pim_channel_add_oif(up
->channel_oil
, ch
->interface
,
1006 PIM_OIF_FLAG_PROTO_PIM
, __func__
);
1008 pim_channel_del_oif(up
->channel_oil
, ch
->interface
,
1009 PIM_OIF_FLAG_PROTO_PIM
, __func__
);
1011 if (install_it
&& !up
->channel_oil
->installed
)
1012 pim_upstream_mroute_add(up
->channel_oil
, __PRETTY_FUNCTION__
);
1015 void pim_zebra_zclient_update(struct vty
*vty
)
1017 vty_out(vty
, "Zclient update socket: ");
1020 vty_out(vty
, "%d failures=%d\n", zclient
->sock
, zclient
->fail
);
1022 vty_out(vty
, "<null zclient>\n");
1026 struct zclient
*pim_zebra_zclient_get(void)
1034 void pim_zebra_interface_set_master(struct interface
*vrf
,
1035 struct interface
*ifp
)
1037 zclient_interface_set_master(zclient
, vrf
, ifp
);