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 struct zclient
*zclient
;
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_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_mroute_add(up
->channel_oil
, __PRETTY_FUNCTION__
);
331 /* FIXME can join_desired actually be changed by pim_rpf_update()
332 * returning PIM_RPF_CHANGED ?
334 pim_upstream_update_join_desired(pim
, up
);
337 static int pim_zebra_vxlan_sg_proc(ZAPI_CALLBACK_ARGS
)
340 struct pim_instance
*pim
;
343 pim
= pim_get_pim_instance(vrf_id
);
350 sg
.prefixlen
= stream_getl(s
);
351 stream_get(&sg
.src
.s_addr
, s
, sg
.prefixlen
);
352 stream_get(&sg
.grp
.s_addr
, s
, sg
.prefixlen
);
354 if (PIM_DEBUG_ZEBRA
) {
355 char sg_str
[PIM_SG_LEN
];
357 pim_str_sg_set(&sg
, sg_str
);
358 zlog_debug("%u:recv SG %s %s", vrf_id
,
359 (cmd
== ZEBRA_VXLAN_SG_ADD
)?"add":"del",
363 if (cmd
== ZEBRA_VXLAN_SG_ADD
)
364 pim_vxlan_sg_add(pim
, &sg
);
366 pim_vxlan_sg_del(pim
, &sg
);
371 static void pim_zebra_vxlan_replay(void)
373 struct stream
*s
= NULL
;
376 if (!zclient
|| zclient
->sock
< 0)
382 zclient_create_header(s
, ZEBRA_VXLAN_SG_REPLAY
, VRF_DEFAULT
);
383 stream_putw_at(s
, 0, stream_get_endp(s
));
385 zclient_send_message(zclient
);
388 void pim_scan_individual_oil(struct channel_oil
*c_oil
, int in_vif_index
)
390 struct in_addr vif_source
;
391 int input_iface_vif_index
;
393 pim_rp_set_upstream_addr(c_oil
->pim
, &vif_source
,
394 c_oil
->oil
.mfcc_origin
,
395 c_oil
->oil
.mfcc_mcastgrp
);
398 input_iface_vif_index
= in_vif_index
;
400 struct prefix src
, grp
;
402 src
.family
= AF_INET
;
403 src
.prefixlen
= IPV4_MAX_BITLEN
;
404 src
.u
.prefix4
= vif_source
;
405 grp
.family
= AF_INET
;
406 grp
.prefixlen
= IPV4_MAX_BITLEN
;
407 grp
.u
.prefix4
= c_oil
->oil
.mfcc_mcastgrp
;
409 if (PIM_DEBUG_ZEBRA
) {
410 char source_str
[INET_ADDRSTRLEN
];
411 char group_str
[INET_ADDRSTRLEN
];
412 pim_inet4_dump("<source?>", c_oil
->oil
.mfcc_origin
,
413 source_str
, sizeof(source_str
));
414 pim_inet4_dump("<group?>", c_oil
->oil
.mfcc_mcastgrp
,
415 group_str
, sizeof(group_str
));
417 "%s: channel_oil (%s,%s) upstream info is not present.",
418 __PRETTY_FUNCTION__
, source_str
, group_str
);
420 input_iface_vif_index
= pim_ecmp_fib_lookup_if_vif_index(
421 c_oil
->pim
, &src
, &grp
);
424 if (input_iface_vif_index
< 1) {
425 if (PIM_DEBUG_ZEBRA
) {
426 char source_str
[INET_ADDRSTRLEN
];
427 char group_str
[INET_ADDRSTRLEN
];
428 pim_inet4_dump("<source?>", c_oil
->oil
.mfcc_origin
,
429 source_str
, sizeof(source_str
));
430 pim_inet4_dump("<group?>", c_oil
->oil
.mfcc_mcastgrp
,
431 group_str
, sizeof(group_str
));
433 "%s %s: could not find input interface(%d) for (S,G)=(%s,%s)",
434 __FILE__
, __PRETTY_FUNCTION__
,
435 c_oil
->oil
.mfcc_parent
, source_str
, group_str
);
437 pim_mroute_del(c_oil
, __PRETTY_FUNCTION__
);
441 if (input_iface_vif_index
== c_oil
->oil
.mfcc_parent
) {
442 if (!c_oil
->installed
)
443 pim_mroute_add(c_oil
, __PRETTY_FUNCTION__
);
449 if (PIM_DEBUG_ZEBRA
) {
450 struct interface
*old_iif
= pim_if_find_by_vif_index(
451 c_oil
->pim
, c_oil
->oil
.mfcc_parent
);
452 struct interface
*new_iif
= pim_if_find_by_vif_index(
453 c_oil
->pim
, input_iface_vif_index
);
454 char source_str
[INET_ADDRSTRLEN
];
455 char group_str
[INET_ADDRSTRLEN
];
456 pim_inet4_dump("<source?>", c_oil
->oil
.mfcc_origin
, source_str
,
458 pim_inet4_dump("<group?>", c_oil
->oil
.mfcc_mcastgrp
, group_str
,
461 "%s %s: (S,G)=(%s,%s) input interface changed from %s vif_index=%d to %s vif_index=%d",
462 __FILE__
, __PRETTY_FUNCTION__
, source_str
, group_str
,
463 (old_iif
) ? old_iif
->name
: "<old_iif?>",
464 c_oil
->oil
.mfcc_parent
,
465 (new_iif
) ? new_iif
->name
: "<new_iif?>",
466 input_iface_vif_index
);
469 /* new iif loops to existing oif ? */
470 if (c_oil
->oil
.mfcc_ttls
[input_iface_vif_index
]) {
471 struct interface
*new_iif
= pim_if_find_by_vif_index(
472 c_oil
->pim
, input_iface_vif_index
);
474 if (PIM_DEBUG_ZEBRA
) {
475 char source_str
[INET_ADDRSTRLEN
];
476 char group_str
[INET_ADDRSTRLEN
];
477 pim_inet4_dump("<source?>", c_oil
->oil
.mfcc_origin
,
478 source_str
, sizeof(source_str
));
479 pim_inet4_dump("<group?>", c_oil
->oil
.mfcc_mcastgrp
,
480 group_str
, sizeof(group_str
));
482 "%s %s: (S,G)=(%s,%s) new iif loops to existing oif: %s vif_index=%d",
483 __FILE__
, __PRETTY_FUNCTION__
, source_str
,
485 (new_iif
) ? new_iif
->name
: "<new_iif?>",
486 input_iface_vif_index
);
490 /* update iif vif_index */
491 pim_channel_oil_change_iif(c_oil
->pim
, c_oil
, input_iface_vif_index
,
492 __PRETTY_FUNCTION__
);
493 pim_mroute_add(c_oil
, __PRETTY_FUNCTION__
);
496 void pim_scan_oil(struct pim_instance
*pim
)
498 struct listnode
*node
;
499 struct listnode
*nextnode
;
500 struct channel_oil
*c_oil
;
504 pim
->scan_oil_last
= pim_time_monotonic_sec();
505 ++pim
->scan_oil_events
;
507 for (ALL_LIST_ELEMENTS(pim
->channel_oil_list
, node
, nextnode
, c_oil
)) {
508 if (c_oil
->up
&& c_oil
->up
->rpf
.source_nexthop
.interface
) {
509 ifindex
= c_oil
->up
->rpf
.source_nexthop
512 pim_if_find_vifindex_by_ifindex(pim
, ifindex
);
513 /* Pass Current selected NH vif index to mroute
516 pim_scan_individual_oil(c_oil
, vif_index
);
518 pim_scan_individual_oil(c_oil
, 0);
522 static int on_rpf_cache_refresh(struct thread
*t
)
524 struct pim_instance
*pim
= THREAD_ARG(t
);
526 /* update kernel multicast forwarding cache (MFC) */
529 pim
->rpf_cache_refresh_last
= pim_time_monotonic_sec();
530 ++pim
->rpf_cache_refresh_events
;
532 // It is called as part of pim_neighbor_add
537 void sched_rpf_cache_refresh(struct pim_instance
*pim
)
539 ++pim
->rpf_cache_refresh_requests
;
541 pim_rpf_set_refresh_time(pim
);
543 if (pim
->rpf_cache_refresher
) {
544 /* Refresh timer is already running */
548 /* Start refresh timer */
550 if (PIM_DEBUG_ZEBRA
) {
551 zlog_debug("%s: triggering %ld msec timer", __PRETTY_FUNCTION__
,
552 router
->rpf_cache_refresh_delay_msec
);
555 thread_add_timer_msec(router
->master
, on_rpf_cache_refresh
, pim
,
556 router
->rpf_cache_refresh_delay_msec
,
557 &pim
->rpf_cache_refresher
);
560 static void pim_zebra_connected(struct zclient
*zclient
)
562 /* Send the client registration */
563 bfd_client_sendmsg(zclient
, ZEBRA_BFD_CLIENT_REGISTER
, router
->vrf_id
);
565 zclient_send_reg_requests(zclient
, router
->vrf_id
);
567 /* request for VxLAN BUM group addresses */
568 pim_zebra_vxlan_replay();
571 static void pim_zebra_capabilities(struct zclient_capabilities
*cap
)
573 router
->role
= cap
->role
;
576 void pim_zebra_init(void)
578 /* Socket for receiving updates from Zebra daemon */
579 zclient
= zclient_new(router
->master
, &zclient_options_default
);
581 zclient
->zebra_capabilities
= pim_zebra_capabilities
;
582 zclient
->zebra_connected
= pim_zebra_connected
;
583 zclient
->router_id_update
= pim_router_id_update_zebra
;
584 zclient
->interface_address_add
= pim_zebra_if_address_add
;
585 zclient
->interface_address_delete
= pim_zebra_if_address_del
;
586 zclient
->interface_vrf_update
= pim_zebra_interface_vrf_update
;
587 zclient
->nexthop_update
= pim_parse_nexthop_update
;
588 zclient
->vxlan_sg_add
= pim_zebra_vxlan_sg_proc
;
589 zclient
->vxlan_sg_del
= pim_zebra_vxlan_sg_proc
;
591 zclient_init(zclient
, ZEBRA_ROUTE_PIM
, 0, &pimd_privs
);
592 if (PIM_DEBUG_PIM_TRACE
) {
593 zlog_notice("%s: zclient socket initialized",
594 __PRETTY_FUNCTION__
);
597 zclient_lookup_new();
600 void igmp_anysource_forward_start(struct pim_instance
*pim
,
601 struct igmp_group
*group
)
603 struct igmp_source
*source
;
604 struct in_addr src_addr
= {.s_addr
= 0};
605 /* Any source (*,G) is forwarded only if mode is EXCLUDE {empty} */
606 zassert(group
->group_filtermode_isexcl
);
607 zassert(listcount(group
->group_source_list
) < 1);
609 source
= source_new(group
, src_addr
);
611 zlog_warn("%s: Failure to create * source",
612 __PRETTY_FUNCTION__
);
616 igmp_source_forward_start(pim
, source
);
619 void igmp_anysource_forward_stop(struct igmp_group
*group
)
621 struct igmp_source
*source
;
622 struct in_addr star
= {.s_addr
= 0};
624 source
= igmp_find_source_by_addr(group
, star
);
626 igmp_source_forward_stop(source
);
629 static void igmp_source_forward_reevaluate_one(struct pim_instance
*pim
,
630 struct igmp_source
*source
)
633 struct igmp_group
*group
= source
->source_group
;
634 struct pim_ifchannel
*ch
;
636 if ((source
->source_addr
.s_addr
!= INADDR_ANY
)
637 || !IGMP_SOURCE_TEST_FORWARDING(source
->source_flags
))
640 memset(&sg
, 0, sizeof(struct prefix_sg
));
641 sg
.src
= source
->source_addr
;
642 sg
.grp
= group
->group_addr
;
644 ch
= pim_ifchannel_find(group
->group_igmp_sock
->interface
, &sg
);
645 if (pim_is_grp_ssm(pim
, group
->group_addr
)) {
646 /* If SSM group withdraw local membership */
648 && (ch
->local_ifmembership
== PIM_IFMEMBERSHIP_INCLUDE
)) {
649 if (PIM_DEBUG_PIM_EVENTS
)
651 "local membership del for %s as G is now SSM",
652 pim_str_sg_dump(&sg
));
653 pim_ifchannel_local_membership_del(
654 group
->group_igmp_sock
->interface
, &sg
);
657 /* If ASM group add local membership */
659 || (ch
->local_ifmembership
== PIM_IFMEMBERSHIP_NOINFO
)) {
660 if (PIM_DEBUG_PIM_EVENTS
)
662 "local membership add for %s as G is now ASM",
663 pim_str_sg_dump(&sg
));
664 pim_ifchannel_local_membership_add(
665 group
->group_igmp_sock
->interface
, &sg
);
670 void igmp_source_forward_reevaluate_all(struct pim_instance
*pim
)
672 struct interface
*ifp
;
674 FOR_ALL_INTERFACES (pim
->vrf
, ifp
) {
675 struct pim_interface
*pim_ifp
= ifp
->info
;
676 struct listnode
*sock_node
;
677 struct igmp_sock
*igmp
;
682 /* scan igmp sockets */
683 for (ALL_LIST_ELEMENTS_RO(pim_ifp
->igmp_socket_list
, sock_node
,
685 struct listnode
*grpnode
;
686 struct igmp_group
*grp
;
688 /* scan igmp groups */
689 for (ALL_LIST_ELEMENTS_RO(igmp
->igmp_group_list
,
691 struct listnode
*srcnode
;
692 struct igmp_source
*src
;
694 /* scan group sources */
695 for (ALL_LIST_ELEMENTS_RO(
696 grp
->group_source_list
, srcnode
,
698 igmp_source_forward_reevaluate_one(pim
,
700 } /* scan group sources */
701 } /* scan igmp groups */
702 } /* scan igmp sockets */
703 } /* scan interfaces */
706 void igmp_source_forward_start(struct pim_instance
*pim
,
707 struct igmp_source
*source
)
709 struct pim_interface
*pim_oif
;
710 struct igmp_group
*group
;
713 int input_iface_vif_index
= 0;
715 memset(&sg
, 0, sizeof(struct prefix_sg
));
716 sg
.src
= source
->source_addr
;
717 sg
.grp
= source
->source_group
->group_addr
;
719 if (PIM_DEBUG_IGMP_TRACE
) {
721 "%s: (S,G)=%s igmp_sock=%d oif=%s fwd=%d",
722 __PRETTY_FUNCTION__
, pim_str_sg_dump(&sg
),
723 source
->source_group
->group_igmp_sock
->fd
,
724 source
->source_group
->group_igmp_sock
->interface
->name
,
725 IGMP_SOURCE_TEST_FORWARDING(source
->source_flags
));
728 /* Prevent IGMP interface from installing multicast route multiple
730 if (IGMP_SOURCE_TEST_FORWARDING(source
->source_flags
)) {
734 group
= source
->source_group
;
735 pim_oif
= group
->group_igmp_sock
->interface
->info
;
737 if (PIM_DEBUG_IGMP_TRACE
) {
739 "%s: multicast not enabled on oif=%s ?",
741 source
->source_group
->group_igmp_sock
747 if (!source
->source_channel_oil
) {
748 struct in_addr vif_source
;
749 struct prefix src
, grp
;
750 struct pim_nexthop nexthop
;
751 struct pim_upstream
*up
= NULL
;
753 if (!pim_rp_set_upstream_addr(pim
, &vif_source
,
754 source
->source_addr
, sg
.grp
)) {
755 /*Create a dummy channel oil */
756 source
->source_channel_oil
= pim_channel_oil_add(
757 pim
, &sg
, MAXVIFS
, __PRETTY_FUNCTION__
);
761 src
.family
= AF_INET
;
762 src
.prefixlen
= IPV4_MAX_BITLEN
;
763 src
.u
.prefix4
= vif_source
; // RP or Src address
764 grp
.family
= AF_INET
;
765 grp
.prefixlen
= IPV4_MAX_BITLEN
;
766 grp
.u
.prefix4
= sg
.grp
;
768 up
= pim_upstream_find(pim
, &sg
);
770 memcpy(&nexthop
, &up
->rpf
.source_nexthop
,
771 sizeof(struct pim_nexthop
));
772 pim_ecmp_nexthop_lookup(pim
, &nexthop
, &src
,
774 if (nexthop
.interface
)
775 input_iface_vif_index
=
776 pim_if_find_vifindex_by_ifindex(
778 nexthop
.interface
->ifindex
);
780 input_iface_vif_index
=
781 pim_ecmp_fib_lookup_if_vif_index(
784 if (PIM_DEBUG_ZEBRA
) {
785 char buf2
[INET_ADDRSTRLEN
];
787 pim_inet4_dump("<source?>", vif_source
, buf2
,
789 zlog_debug("%s: NHT %s vif_source %s vif_index:%d ",
791 pim_str_sg_dump(&sg
),
792 buf2
, input_iface_vif_index
);
795 if (input_iface_vif_index
< 1) {
796 if (PIM_DEBUG_IGMP_TRACE
) {
797 char source_str
[INET_ADDRSTRLEN
];
798 pim_inet4_dump("<source?>",
800 source_str
, sizeof(source_str
));
802 "%s %s: could not find input interface for source %s",
803 __FILE__
, __PRETTY_FUNCTION__
,
806 source
->source_channel_oil
=
809 __PRETTY_FUNCTION__
);
814 * Protect IGMP against adding looped MFC
815 * entries created by both source and receiver
816 * attached to the same interface. See TODO
817 * T22. Block only when the intf is non DR
818 * DR must create upstream.
820 if ((input_iface_vif_index
==
821 pim_oif
->mroute_vif_index
) &&
822 !(PIM_I_am_DR(pim_oif
))) {
823 /* ignore request for looped MFC entry
825 if (PIM_DEBUG_IGMP_TRACE
) {
827 "%s: ignoring request for looped MFC entry (S,G)=%s: igmp_sock=%d oif=%s vif_index=%d",
829 pim_str_sg_dump(&sg
),
831 ->group_igmp_sock
->fd
,
835 input_iface_vif_index
);
840 source
->source_channel_oil
=
842 pim
, &sg
, input_iface_vif_index
,
843 __PRETTY_FUNCTION__
);
844 if (!source
->source_channel_oil
) {
845 if (PIM_DEBUG_IGMP_TRACE
) {
847 "%s %s: could not create OIL for channel (S,G)=%s",
850 pim_str_sg_dump(&sg
));
858 result
= pim_channel_add_oif(source
->source_channel_oil
,
859 group
->group_igmp_sock
->interface
,
860 PIM_OIF_FLAG_PROTO_IGMP
);
862 if (PIM_DEBUG_MROUTE
) {
863 zlog_warn("%s: add_oif() failed with return=%d",
869 if (!(PIM_I_am_DR(pim_oif
))) {
870 if (PIM_DEBUG_IGMP_TRACE
)
871 zlog_debug("%s: %s was received on %s interface but we are not DR for that interface",
873 pim_str_sg_dump(&sg
),
874 group
->group_igmp_sock
->interface
->name
);
876 pim_channel_del_oif(source
->source_channel_oil
,
877 group
->group_igmp_sock
->interface
,
878 PIM_OIF_FLAG_PROTO_IGMP
);
882 Feed IGMPv3-gathered local membership information into PIM
883 per-interface (S,G) state.
885 if (!pim_ifchannel_local_membership_add(
886 group
->group_igmp_sock
->interface
, &sg
)) {
887 if (PIM_DEBUG_MROUTE
)
888 zlog_warn("%s: Failure to add local membership for %s",
889 __PRETTY_FUNCTION__
, pim_str_sg_dump(&sg
));
891 pim_channel_del_oif(source
->source_channel_oil
,
892 group
->group_igmp_sock
->interface
,
893 PIM_OIF_FLAG_PROTO_IGMP
);
897 IGMP_SOURCE_DO_FORWARDING(source
->source_flags
);
901 igmp_source_forward_stop: stop fowarding, but keep the source
902 igmp_source_delete: stop fowarding, and delete the source
904 void igmp_source_forward_stop(struct igmp_source
*source
)
906 struct igmp_group
*group
;
910 memset(&sg
, 0, sizeof(struct prefix_sg
));
911 sg
.src
= source
->source_addr
;
912 sg
.grp
= source
->source_group
->group_addr
;
914 if (PIM_DEBUG_IGMP_TRACE
) {
916 "%s: (S,G)=%s igmp_sock=%d oif=%s fwd=%d",
917 __PRETTY_FUNCTION__
, pim_str_sg_dump(&sg
),
918 source
->source_group
->group_igmp_sock
->fd
,
919 source
->source_group
->group_igmp_sock
->interface
->name
,
920 IGMP_SOURCE_TEST_FORWARDING(source
->source_flags
));
923 /* Prevent IGMP interface from removing multicast route multiple
925 if (!IGMP_SOURCE_TEST_FORWARDING(source
->source_flags
)) {
929 group
= source
->source_group
;
932 It appears that in certain circumstances that
933 igmp_source_forward_stop is called when IGMP forwarding
934 was not enabled in oif_flags for this outgoing interface.
935 Possibly because of multiple calls. When that happens, we
936 enter the below if statement and this function returns early
937 which in turn triggers the calling function to assert.
938 Making the call to pim_channel_del_oif and ignoring the return code
939 fixes the issue without ill effect, similar to
940 pim_forward_stop below.
942 result
= pim_channel_del_oif(source
->source_channel_oil
,
943 group
->group_igmp_sock
->interface
,
944 PIM_OIF_FLAG_PROTO_IGMP
);
946 if (PIM_DEBUG_IGMP_TRACE
)
948 "%s: pim_channel_del_oif() failed with return=%d",
954 Feed IGMPv3-gathered local membership information into PIM
955 per-interface (S,G) state.
957 pim_ifchannel_local_membership_del(group
->group_igmp_sock
->interface
,
960 IGMP_SOURCE_DONT_FORWARDING(source
->source_flags
);
963 void pim_forward_start(struct pim_ifchannel
*ch
)
965 struct pim_upstream
*up
= ch
->upstream
;
966 uint32_t mask
= PIM_OIF_FLAG_PROTO_PIM
;
968 if (PIM_DEBUG_PIM_TRACE
) {
969 char source_str
[INET_ADDRSTRLEN
];
970 char group_str
[INET_ADDRSTRLEN
];
971 char upstream_str
[INET_ADDRSTRLEN
];
973 pim_inet4_dump("<source?>", ch
->sg
.src
, source_str
,
975 pim_inet4_dump("<group?>", ch
->sg
.grp
, group_str
,
977 pim_inet4_dump("<upstream?>", up
->upstream_addr
, upstream_str
,
978 sizeof(upstream_str
));
979 zlog_debug("%s: (S,G)=(%s,%s) oif=%s (%s)", __PRETTY_FUNCTION__
,
980 source_str
, group_str
, ch
->interface
->name
,
981 inet_ntoa(up
->upstream_addr
));
984 if (up
->flags
& PIM_UPSTREAM_FLAG_MASK_SRC_IGMP
)
985 mask
= PIM_OIF_FLAG_PROTO_IGMP
;
987 pim_channel_add_oif(up
->channel_oil
, ch
->interface
, mask
);
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
);
1008 pim_channel_del_oif(up
->channel_oil
, ch
->interface
,
1009 PIM_OIF_FLAG_PROTO_PIM
);
1011 if (install_it
&& !up
->channel_oil
->installed
)
1012 pim_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
);