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",
80 ifp
->name
, vrf_id
, new_vrf_id
);
82 if_update_to_new_vrf(ifp
, new_vrf_id
);
87 #ifdef PIM_DEBUG_IFADDR_DUMP
88 static void dump_if_address(struct interface
*ifp
)
90 struct connected
*ifc
;
91 struct listnode
*node
;
93 zlog_debug("%s %s: interface %s addresses:", __FILE__
,
94 __PRETTY_FUNCTION__
, ifp
->name
);
96 for (ALL_LIST_ELEMENTS_RO(ifp
->connected
, node
, ifc
)) {
97 struct prefix
*p
= ifc
->address
;
99 if (p
->family
!= AF_INET
)
102 zlog_debug("%s %s: interface %s address %s %s", __FILE__
,
103 __PRETTY_FUNCTION__
, ifp
->name
,
104 inet_ntoa(p
->u
.prefix4
),
105 CHECK_FLAG(ifc
->flags
, ZEBRA_IFA_SECONDARY
)
112 static int pim_zebra_if_address_add(ZAPI_CALLBACK_ARGS
)
116 struct pim_interface
*pim_ifp
;
117 struct pim_instance
*pim
;
120 zebra api notifies address adds/dels events by using the same call
121 interface_add_read below, see comments in lib/zclient.c
123 zebra_interface_address_read(ZEBRA_INTERFACE_ADDRESS_ADD, ...)
124 will add address to interface list by calling
125 connected_add_by_prefix()
127 c
= zebra_interface_address_read(cmd
, zclient
->ibuf
, vrf_id
);
131 pim_ifp
= c
->ifp
->info
;
134 if (PIM_DEBUG_ZEBRA
) {
136 prefix2str(p
, buf
, BUFSIZ
);
137 zlog_debug("%s: %s(%u) connected IP address %s flags %u %s",
138 __PRETTY_FUNCTION__
, c
->ifp
->name
, vrf_id
, buf
,
140 CHECK_FLAG(c
->flags
, ZEBRA_IFA_SECONDARY
)
144 #ifdef PIM_DEBUG_IFADDR_DUMP
145 dump_if_address(c
->ifp
);
149 if (!CHECK_FLAG(c
->flags
, ZEBRA_IFA_SECONDARY
)) {
150 /* trying to add primary address */
152 struct in_addr primary_addr
= pim_find_primary_addr(c
->ifp
);
153 if (p
->family
!= AF_INET
154 || primary_addr
.s_addr
!= p
->u
.prefix4
.s_addr
) {
155 if (PIM_DEBUG_ZEBRA
) {
156 /* but we had a primary address already */
160 prefix2str(p
, buf
, BUFSIZ
);
163 "%s: %s : forcing secondary flag on %s",
164 __PRETTY_FUNCTION__
, c
->ifp
->name
, buf
);
166 SET_FLAG(c
->flags
, ZEBRA_IFA_SECONDARY
);
172 pim
= pim_get_pim_instance(vrf_id
);
175 pim_rp_check_on_if_add(pim_ifp
);
178 if (if_is_loopback(c
->ifp
)) {
179 struct vrf
*vrf
= vrf_lookup_by_id(VRF_DEFAULT
);
180 struct interface
*ifp
;
182 FOR_ALL_INTERFACES (vrf
, ifp
) {
183 if (!if_is_loopback(ifp
) && if_is_operative(ifp
))
184 pim_if_addr_add_all(ifp
);
191 static int pim_zebra_if_address_del(ZAPI_CALLBACK_ARGS
)
195 struct vrf
*vrf
= vrf_lookup_by_id(vrf_id
);
196 struct pim_instance
*pim
;
203 zebra api notifies address adds/dels events by using the same call
204 interface_add_read below, see comments in lib/zclient.c
206 zebra_interface_address_read(ZEBRA_INTERFACE_ADDRESS_DELETE, ...)
207 will remove address from interface list by calling
208 connected_delete_by_prefix()
210 c
= zebra_interface_address_read(cmd
, zclient
->ibuf
, vrf_id
);
215 if (p
->family
== AF_INET
) {
216 if (PIM_DEBUG_ZEBRA
) {
218 prefix2str(p
, buf
, BUFSIZ
);
220 "%s: %s(%u) disconnected IP address %s flags %u %s",
221 __PRETTY_FUNCTION__
, c
->ifp
->name
, vrf_id
, buf
,
223 CHECK_FLAG(c
->flags
, ZEBRA_IFA_SECONDARY
)
227 #ifdef PIM_DEBUG_IFADDR_DUMP
228 dump_if_address(c
->ifp
);
232 pim_if_addr_del(c
, 0);
234 pim_i_am_rp_re_evaluate(pim
);
241 void pim_zebra_update_all_interfaces(struct pim_instance
*pim
)
243 struct interface
*ifp
;
245 FOR_ALL_INTERFACES (pim
->vrf
, ifp
) {
246 struct pim_interface
*pim_ifp
= ifp
->info
;
247 struct pim_iface_upstream_switch
*us
;
248 struct listnode
*node
;
253 for (ALL_LIST_ELEMENTS_RO(pim_ifp
->upstream_switch_list
, node
,
257 rpf
.source_nexthop
.interface
= ifp
;
258 rpf
.rpf_addr
.u
.prefix4
= us
->address
;
259 pim_joinprune_send(&rpf
, us
->us
);
260 pim_jp_agg_clear_group(us
->us
);
265 void pim_zebra_upstream_rpf_changed(struct pim_instance
*pim
,
266 struct pim_upstream
*up
,
269 if (old
->source_nexthop
.interface
) {
270 struct pim_neighbor
*nbr
;
272 nbr
= pim_neighbor_find(old
->source_nexthop
.interface
,
273 old
->rpf_addr
.u
.prefix4
);
275 pim_jp_agg_remove_group(nbr
->upstream_jp_agg
, up
);
278 * We have detected a case where we might need
279 * to rescan the inherited o_list so do it.
281 if (up
->channel_oil
->oil_inherited_rescan
) {
282 pim_upstream_inherited_olist_decide(pim
, up
);
283 up
->channel_oil
->oil_inherited_rescan
= 0;
286 if (up
->join_state
== PIM_UPSTREAM_JOINED
) {
288 * If we come up real fast we can be here
289 * where the mroute has not been installed
292 if (!up
->channel_oil
->installed
)
293 pim_mroute_add(up
->channel_oil
,
294 __PRETTY_FUNCTION__
);
297 * RFC 4601: 4.5.7. Sending (S,G)
298 * Join/Prune Messages
300 * Transitions from Joined State
302 * RPF'(S,G) changes not due to an Assert
304 * The upstream (S,G) state machine remains
305 * in Joined state. Send Join(S,G) to the new
306 * upstream neighbor, which is the new value
307 * of RPF'(S,G). Send Prune(S,G) to the old
308 * upstream neighbor, which is the old value
309 * of RPF'(S,G). Set the Join Timer (JT) to
310 * expire after t_periodic seconds.
312 pim_jp_agg_switch_interface(old
, &up
->rpf
, up
);
314 pim_upstream_join_timer_restart(up
, old
);
315 } /* up->join_state == PIM_UPSTREAM_JOINED */
320 * We have detected a case where we might need
321 * to rescan the inherited o_list so do it.
323 if (up
->channel_oil
->oil_inherited_rescan
) {
324 pim_upstream_inherited_olist_decide(pim
, up
);
325 up
->channel_oil
->oil_inherited_rescan
= 0;
328 if (!up
->channel_oil
->installed
)
329 pim_mroute_add(up
->channel_oil
, __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_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_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
;
591 zclient
->mlag_process_up
= pim_zebra_mlag_process_up
;
592 zclient
->mlag_process_down
= pim_zebra_mlag_process_down
;
593 zclient
->mlag_handle_msg
= pim_zebra_mlag_handle_msg
;
595 zclient_init(zclient
, ZEBRA_ROUTE_PIM
, 0, &pimd_privs
);
596 if (PIM_DEBUG_PIM_TRACE
) {
597 zlog_notice("%s: zclient socket initialized",
598 __PRETTY_FUNCTION__
);
601 zclient_lookup_new();
604 void igmp_anysource_forward_start(struct pim_instance
*pim
,
605 struct igmp_group
*group
)
607 struct igmp_source
*source
;
608 struct in_addr src_addr
= {.s_addr
= 0};
609 /* Any source (*,G) is forwarded only if mode is EXCLUDE {empty} */
610 zassert(group
->group_filtermode_isexcl
);
611 zassert(listcount(group
->group_source_list
) < 1);
613 source
= source_new(group
, src_addr
);
615 zlog_warn("%s: Failure to create * source",
616 __PRETTY_FUNCTION__
);
620 igmp_source_forward_start(pim
, source
);
623 void igmp_anysource_forward_stop(struct igmp_group
*group
)
625 struct igmp_source
*source
;
626 struct in_addr star
= {.s_addr
= 0};
628 source
= igmp_find_source_by_addr(group
, star
);
630 igmp_source_forward_stop(source
);
633 static void igmp_source_forward_reevaluate_one(struct pim_instance
*pim
,
634 struct igmp_source
*source
)
637 struct igmp_group
*group
= source
->source_group
;
638 struct pim_ifchannel
*ch
;
640 if ((source
->source_addr
.s_addr
!= INADDR_ANY
)
641 || !IGMP_SOURCE_TEST_FORWARDING(source
->source_flags
))
644 memset(&sg
, 0, sizeof(struct prefix_sg
));
645 sg
.src
= source
->source_addr
;
646 sg
.grp
= group
->group_addr
;
648 ch
= pim_ifchannel_find(group
->group_igmp_sock
->interface
, &sg
);
649 if (pim_is_grp_ssm(pim
, group
->group_addr
)) {
650 /* If SSM group withdraw local membership */
652 && (ch
->local_ifmembership
== PIM_IFMEMBERSHIP_INCLUDE
)) {
653 if (PIM_DEBUG_PIM_EVENTS
)
655 "local membership del for %s as G is now SSM",
656 pim_str_sg_dump(&sg
));
657 pim_ifchannel_local_membership_del(
658 group
->group_igmp_sock
->interface
, &sg
);
661 /* If ASM group add local membership */
663 || (ch
->local_ifmembership
== PIM_IFMEMBERSHIP_NOINFO
)) {
664 if (PIM_DEBUG_PIM_EVENTS
)
666 "local membership add for %s as G is now ASM",
667 pim_str_sg_dump(&sg
));
668 pim_ifchannel_local_membership_add(
669 group
->group_igmp_sock
->interface
, &sg
);
674 void igmp_source_forward_reevaluate_all(struct pim_instance
*pim
)
676 struct interface
*ifp
;
678 FOR_ALL_INTERFACES (pim
->vrf
, ifp
) {
679 struct pim_interface
*pim_ifp
= ifp
->info
;
680 struct listnode
*sock_node
;
681 struct igmp_sock
*igmp
;
686 /* scan igmp sockets */
687 for (ALL_LIST_ELEMENTS_RO(pim_ifp
->igmp_socket_list
, sock_node
,
689 struct listnode
*grpnode
;
690 struct igmp_group
*grp
;
692 /* scan igmp groups */
693 for (ALL_LIST_ELEMENTS_RO(igmp
->igmp_group_list
,
695 struct listnode
*srcnode
;
696 struct igmp_source
*src
;
698 /* scan group sources */
699 for (ALL_LIST_ELEMENTS_RO(
700 grp
->group_source_list
, srcnode
,
702 igmp_source_forward_reevaluate_one(pim
,
704 } /* scan group sources */
705 } /* scan igmp groups */
706 } /* scan igmp sockets */
707 } /* scan interfaces */
710 void igmp_source_forward_start(struct pim_instance
*pim
,
711 struct igmp_source
*source
)
713 struct pim_interface
*pim_oif
;
714 struct igmp_group
*group
;
717 int input_iface_vif_index
= 0;
719 memset(&sg
, 0, sizeof(struct prefix_sg
));
720 sg
.src
= source
->source_addr
;
721 sg
.grp
= source
->source_group
->group_addr
;
723 if (PIM_DEBUG_IGMP_TRACE
) {
725 "%s: (S,G)=%s igmp_sock=%d oif=%s fwd=%d",
726 __PRETTY_FUNCTION__
, pim_str_sg_dump(&sg
),
727 source
->source_group
->group_igmp_sock
->fd
,
728 source
->source_group
->group_igmp_sock
->interface
->name
,
729 IGMP_SOURCE_TEST_FORWARDING(source
->source_flags
));
732 /* Prevent IGMP interface from installing multicast route multiple
734 if (IGMP_SOURCE_TEST_FORWARDING(source
->source_flags
)) {
738 group
= source
->source_group
;
739 pim_oif
= group
->group_igmp_sock
->interface
->info
;
741 if (PIM_DEBUG_IGMP_TRACE
) {
743 "%s: multicast not enabled on oif=%s ?",
745 source
->source_group
->group_igmp_sock
751 if (!source
->source_channel_oil
) {
752 struct in_addr vif_source
;
753 struct prefix src
, grp
;
754 struct pim_nexthop nexthop
;
755 struct pim_upstream
*up
= NULL
;
757 if (!pim_rp_set_upstream_addr(pim
, &vif_source
,
758 source
->source_addr
, sg
.grp
)) {
759 /*Create a dummy channel oil */
760 source
->source_channel_oil
= pim_channel_oil_add(
761 pim
, &sg
, MAXVIFS
, __PRETTY_FUNCTION__
);
765 src
.family
= AF_INET
;
766 src
.prefixlen
= IPV4_MAX_BITLEN
;
767 src
.u
.prefix4
= vif_source
; // RP or Src address
768 grp
.family
= AF_INET
;
769 grp
.prefixlen
= IPV4_MAX_BITLEN
;
770 grp
.u
.prefix4
= sg
.grp
;
772 up
= pim_upstream_find(pim
, &sg
);
774 memcpy(&nexthop
, &up
->rpf
.source_nexthop
,
775 sizeof(struct pim_nexthop
));
776 pim_ecmp_nexthop_lookup(pim
, &nexthop
, &src
,
778 if (nexthop
.interface
)
779 input_iface_vif_index
=
780 pim_if_find_vifindex_by_ifindex(
782 nexthop
.interface
->ifindex
);
784 input_iface_vif_index
=
785 pim_ecmp_fib_lookup_if_vif_index(
788 if (PIM_DEBUG_ZEBRA
) {
789 char buf2
[INET_ADDRSTRLEN
];
791 pim_inet4_dump("<source?>", vif_source
, buf2
,
793 zlog_debug("%s: NHT %s vif_source %s vif_index:%d ",
795 pim_str_sg_dump(&sg
),
796 buf2
, input_iface_vif_index
);
799 if (input_iface_vif_index
< 1) {
800 if (PIM_DEBUG_IGMP_TRACE
) {
801 char source_str
[INET_ADDRSTRLEN
];
802 pim_inet4_dump("<source?>",
804 source_str
, sizeof(source_str
));
806 "%s %s: could not find input interface for source %s",
807 __FILE__
, __PRETTY_FUNCTION__
,
810 source
->source_channel_oil
=
813 __PRETTY_FUNCTION__
);
818 * Protect IGMP against adding looped MFC
819 * entries created by both source and receiver
820 * attached to the same interface. See TODO
821 * T22. Block only when the intf is non DR
822 * DR must create upstream.
824 if ((input_iface_vif_index
==
825 pim_oif
->mroute_vif_index
) &&
826 !(PIM_I_am_DR(pim_oif
))) {
827 /* ignore request for looped MFC entry
829 if (PIM_DEBUG_IGMP_TRACE
) {
831 "%s: ignoring request for looped MFC entry (S,G)=%s: igmp_sock=%d oif=%s vif_index=%d",
833 pim_str_sg_dump(&sg
),
835 ->group_igmp_sock
->fd
,
839 input_iface_vif_index
);
844 source
->source_channel_oil
=
846 pim
, &sg
, input_iface_vif_index
,
847 __PRETTY_FUNCTION__
);
848 if (!source
->source_channel_oil
) {
849 if (PIM_DEBUG_IGMP_TRACE
) {
851 "%s %s: could not create OIL for channel (S,G)=%s",
854 pim_str_sg_dump(&sg
));
862 if (PIM_I_am_DR(pim_oif
)) {
863 result
= pim_channel_add_oif(source
->source_channel_oil
,
864 group
->group_igmp_sock
->interface
,
865 PIM_OIF_FLAG_PROTO_IGMP
);
867 if (PIM_DEBUG_MROUTE
) {
868 zlog_warn("%s: add_oif() failed with return=%d",
874 if (PIM_DEBUG_IGMP_TRACE
)
875 zlog_debug("%s: %s was received on %s interface but we are not DR for that interface",
877 pim_str_sg_dump(&sg
),
878 group
->group_igmp_sock
->interface
->name
);
883 Feed IGMPv3-gathered local membership information into PIM
884 per-interface (S,G) state.
886 if (!pim_ifchannel_local_membership_add(
887 group
->group_igmp_sock
->interface
, &sg
)) {
888 if (PIM_DEBUG_MROUTE
)
889 zlog_warn("%s: Failure to add local membership for %s",
890 __PRETTY_FUNCTION__
, pim_str_sg_dump(&sg
));
892 pim_channel_del_oif(source
->source_channel_oil
,
893 group
->group_igmp_sock
->interface
,
894 PIM_OIF_FLAG_PROTO_IGMP
);
898 IGMP_SOURCE_DO_FORWARDING(source
->source_flags
);
902 igmp_source_forward_stop: stop fowarding, but keep the source
903 igmp_source_delete: stop fowarding, and delete the source
905 void igmp_source_forward_stop(struct igmp_source
*source
)
907 struct igmp_group
*group
;
911 memset(&sg
, 0, sizeof(struct prefix_sg
));
912 sg
.src
= source
->source_addr
;
913 sg
.grp
= source
->source_group
->group_addr
;
915 if (PIM_DEBUG_IGMP_TRACE
) {
917 "%s: (S,G)=%s igmp_sock=%d oif=%s fwd=%d",
918 __PRETTY_FUNCTION__
, pim_str_sg_dump(&sg
),
919 source
->source_group
->group_igmp_sock
->fd
,
920 source
->source_group
->group_igmp_sock
->interface
->name
,
921 IGMP_SOURCE_TEST_FORWARDING(source
->source_flags
));
924 /* Prevent IGMP interface from removing multicast route multiple
926 if (!IGMP_SOURCE_TEST_FORWARDING(source
->source_flags
)) {
930 group
= source
->source_group
;
933 It appears that in certain circumstances that
934 igmp_source_forward_stop is called when IGMP forwarding
935 was not enabled in oif_flags for this outgoing interface.
936 Possibly because of multiple calls. When that happens, we
937 enter the below if statement and this function returns early
938 which in turn triggers the calling function to assert.
939 Making the call to pim_channel_del_oif and ignoring the return code
940 fixes the issue without ill effect, similar to
941 pim_forward_stop below.
943 result
= pim_channel_del_oif(source
->source_channel_oil
,
944 group
->group_igmp_sock
->interface
,
945 PIM_OIF_FLAG_PROTO_IGMP
);
947 if (PIM_DEBUG_IGMP_TRACE
)
949 "%s: pim_channel_del_oif() failed with return=%d",
955 Feed IGMPv3-gathered local membership information into PIM
956 per-interface (S,G) state.
958 pim_ifchannel_local_membership_del(group
->group_igmp_sock
->interface
,
961 IGMP_SOURCE_DONT_FORWARDING(source
->source_flags
);
964 void pim_forward_start(struct pim_ifchannel
*ch
)
966 struct pim_upstream
*up
= ch
->upstream
;
967 uint32_t mask
= PIM_OIF_FLAG_PROTO_PIM
;
969 if (PIM_DEBUG_PIM_TRACE
) {
970 char source_str
[INET_ADDRSTRLEN
];
971 char group_str
[INET_ADDRSTRLEN
];
972 char upstream_str
[INET_ADDRSTRLEN
];
974 pim_inet4_dump("<source?>", ch
->sg
.src
, source_str
,
976 pim_inet4_dump("<group?>", ch
->sg
.grp
, group_str
,
978 pim_inet4_dump("<upstream?>", up
->upstream_addr
, upstream_str
,
979 sizeof(upstream_str
));
980 zlog_debug("%s: (S,G)=(%s,%s) oif=%s (%s)", __PRETTY_FUNCTION__
,
981 source_str
, group_str
, ch
->interface
->name
,
982 inet_ntoa(up
->upstream_addr
));
985 if (up
->flags
& PIM_UPSTREAM_FLAG_MASK_SRC_IGMP
)
986 mask
= PIM_OIF_FLAG_PROTO_IGMP
;
988 pim_channel_add_oif(up
->channel_oil
, ch
->interface
, mask
);
991 void pim_forward_stop(struct pim_ifchannel
*ch
, bool install_it
)
993 struct pim_upstream
*up
= ch
->upstream
;
995 if (PIM_DEBUG_PIM_TRACE
) {
996 zlog_debug("%s: (S,G)=%s oif=%s install_it: %d installed: %d",
997 __PRETTY_FUNCTION__
, ch
->sg_str
, ch
->interface
->name
,
998 install_it
, up
->channel_oil
->installed
);
1002 * If a channel is being removed, check to see if we still need
1003 * to inherit the interface. If so make sure it is added in
1005 if (pim_upstream_evaluate_join_desired_interface(up
, ch
, ch
->parent
))
1006 pim_channel_add_oif(up
->channel_oil
, ch
->interface
,
1007 PIM_OIF_FLAG_PROTO_PIM
);
1009 pim_channel_del_oif(up
->channel_oil
, ch
->interface
,
1010 PIM_OIF_FLAG_PROTO_PIM
);
1012 if (install_it
&& !up
->channel_oil
->installed
)
1013 pim_mroute_add(up
->channel_oil
, __PRETTY_FUNCTION__
);
1016 void pim_zebra_zclient_update(struct vty
*vty
)
1018 vty_out(vty
, "Zclient update socket: ");
1021 vty_out(vty
, "%d failures=%d\n", zclient
->sock
, zclient
->fail
);
1023 vty_out(vty
, "<null zclient>\n");
1027 struct zclient
*pim_zebra_zclient_get(void)
1035 void pim_zebra_interface_set_master(struct interface
*vrf
,
1036 struct interface
*ifp
)
1038 zclient_interface_set_master(zclient
, vrf
, ifp
);