3 * Copyright (C) 2008 Everton da Silva Marques
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
15 * You should have received a copy of the GNU General Public License along
16 * with this program; see the file COPYING; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
34 #include "pim_zebra.h"
35 #include "pim_iface.h"
41 #include "pim_zlookup.h"
42 #include "pim_ifchannel.h"
44 #include "pim_igmpv3.h"
45 #include "pim_jp_agg.h"
48 #include "pim_vxlan.h"
50 #undef PIM_DEBUG_IFADDR_DUMP
51 #define PIM_DEBUG_IFADDR_DUMP
53 static struct zclient
*zclient
= NULL
;
56 /* Router-id update message from zebra. */
57 static int pim_router_id_update_zebra(ZAPI_CALLBACK_ARGS
)
59 struct prefix router_id
;
61 zebra_router_id_update_read(zclient
->ibuf
, &router_id
);
66 static int pim_zebra_if_del(ZAPI_CALLBACK_ARGS
)
68 struct interface
*ifp
;
69 struct pim_instance
*pim
;
71 ifp
= zebra_interface_state_read(zclient
->ibuf
, vrf_id
);
75 if (PIM_DEBUG_ZEBRA
) {
77 "%s: %s index %d(%u) flags %ld metric %d mtu %d operative %d",
78 __PRETTY_FUNCTION__
, ifp
->name
, ifp
->ifindex
, vrf_id
,
79 (long)ifp
->flags
, ifp
->metric
, ifp
->mtu
,
80 if_is_operative(ifp
));
83 if (!if_is_operative(ifp
))
84 pim_if_addr_del_all(ifp
);
86 if_set_index(ifp
, IFINDEX_INTERNAL
);
88 pim
= pim_get_pim_instance(vrf_id
);
89 if (pim
&& pim
->vxlan
.term_if
== ifp
)
90 pim_vxlan_del_term_dev(pim
);
95 static int pim_zebra_if_state_down(ZAPI_CALLBACK_ARGS
)
97 struct interface
*ifp
;
100 zebra api notifies interface up/down events by using the same call
101 zebra_interface_state_read below, see comments in lib/zclient.c
103 ifp
= zebra_interface_state_read(zclient
->ibuf
, vrf_id
);
107 if (PIM_DEBUG_ZEBRA
) {
109 "%s: %s index %d(%u) flags %ld metric %d mtu %d operative %d",
110 __PRETTY_FUNCTION__
, ifp
->name
, ifp
->ifindex
, vrf_id
,
111 (long)ifp
->flags
, ifp
->metric
, ifp
->mtu
,
112 if_is_operative(ifp
));
115 if (!if_is_operative(ifp
)) {
116 pim_ifchannel_delete_all(ifp
);
118 pim_if_addr_del_all() suffices for shutting down IGMP,
119 but not for shutting down PIM
121 pim_if_addr_del_all(ifp
);
124 pim_sock_delete() closes the socket, stops read and timer
126 and kills all neighbors.
129 pim_sock_delete(ifp
, "link down");
139 static int pim_zebra_interface_vrf_update(ZAPI_CALLBACK_ARGS
)
141 struct interface
*ifp
;
144 ifp
= zebra_interface_vrf_update_read(zclient
->ibuf
, vrf_id
,
150 zlog_debug("%s: %s updating from %u to %u",
152 ifp
->name
, vrf_id
, new_vrf_id
);
154 if_update_to_new_vrf(ifp
, new_vrf_id
);
159 #ifdef PIM_DEBUG_IFADDR_DUMP
160 static void dump_if_address(struct interface
*ifp
)
162 struct connected
*ifc
;
163 struct listnode
*node
;
165 zlog_debug("%s %s: interface %s addresses:", __FILE__
,
166 __PRETTY_FUNCTION__
, ifp
->name
);
168 for (ALL_LIST_ELEMENTS_RO(ifp
->connected
, node
, ifc
)) {
169 struct prefix
*p
= ifc
->address
;
171 if (p
->family
!= AF_INET
)
174 zlog_debug("%s %s: interface %s address %s %s", __FILE__
,
175 __PRETTY_FUNCTION__
, ifp
->name
,
176 inet_ntoa(p
->u
.prefix4
),
177 CHECK_FLAG(ifc
->flags
, ZEBRA_IFA_SECONDARY
)
184 static int pim_zebra_if_address_add(ZAPI_CALLBACK_ARGS
)
188 struct pim_interface
*pim_ifp
;
189 struct pim_instance
*pim
;
192 zebra api notifies address adds/dels events by using the same call
193 interface_add_read below, see comments in lib/zclient.c
195 zebra_interface_address_read(ZEBRA_INTERFACE_ADDRESS_ADD, ...)
196 will add address to interface list by calling
197 connected_add_by_prefix()
199 c
= zebra_interface_address_read(cmd
, zclient
->ibuf
, vrf_id
);
203 pim_ifp
= c
->ifp
->info
;
206 if (PIM_DEBUG_ZEBRA
) {
208 prefix2str(p
, buf
, BUFSIZ
);
209 zlog_debug("%s: %s(%u) connected IP address %s flags %u %s",
210 __PRETTY_FUNCTION__
, c
->ifp
->name
, vrf_id
, buf
,
212 CHECK_FLAG(c
->flags
, ZEBRA_IFA_SECONDARY
)
216 #ifdef PIM_DEBUG_IFADDR_DUMP
217 dump_if_address(c
->ifp
);
221 if (!CHECK_FLAG(c
->flags
, ZEBRA_IFA_SECONDARY
)) {
222 /* trying to add primary address */
224 struct in_addr primary_addr
= pim_find_primary_addr(c
->ifp
);
225 if (p
->family
!= AF_INET
226 || primary_addr
.s_addr
!= p
->u
.prefix4
.s_addr
) {
227 if (PIM_DEBUG_ZEBRA
) {
228 /* but we had a primary address already */
232 prefix2str(p
, buf
, BUFSIZ
);
235 "%s: %s : forcing secondary flag on %s",
236 __PRETTY_FUNCTION__
, c
->ifp
->name
, buf
);
238 SET_FLAG(c
->flags
, ZEBRA_IFA_SECONDARY
);
244 pim
= pim_get_pim_instance(vrf_id
);
247 pim_rp_check_on_if_add(pim_ifp
);
250 if (if_is_loopback(c
->ifp
)) {
251 struct vrf
*vrf
= vrf_lookup_by_id(VRF_DEFAULT
);
252 struct interface
*ifp
;
254 FOR_ALL_INTERFACES (vrf
, ifp
) {
255 if (!if_is_loopback(ifp
) && if_is_operative(ifp
))
256 pim_if_addr_add_all(ifp
);
263 static int pim_zebra_if_address_del(ZAPI_CALLBACK_ARGS
)
267 struct vrf
*vrf
= vrf_lookup_by_id(vrf_id
);
268 struct pim_instance
*pim
;
275 zebra api notifies address adds/dels events by using the same call
276 interface_add_read below, see comments in lib/zclient.c
278 zebra_interface_address_read(ZEBRA_INTERFACE_ADDRESS_DELETE, ...)
279 will remove address from interface list by calling
280 connected_delete_by_prefix()
282 c
= zebra_interface_address_read(cmd
, zclient
->ibuf
, vrf_id
);
287 if (p
->family
== AF_INET
) {
288 if (PIM_DEBUG_ZEBRA
) {
290 prefix2str(p
, buf
, BUFSIZ
);
292 "%s: %s(%u) disconnected IP address %s flags %u %s",
293 __PRETTY_FUNCTION__
, c
->ifp
->name
, vrf_id
, buf
,
295 CHECK_FLAG(c
->flags
, ZEBRA_IFA_SECONDARY
)
299 #ifdef PIM_DEBUG_IFADDR_DUMP
300 dump_if_address(c
->ifp
);
304 pim_if_addr_del(c
, 0);
306 pim_i_am_rp_re_evaluate(pim
);
313 void pim_zebra_update_all_interfaces(struct pim_instance
*pim
)
315 struct interface
*ifp
;
317 FOR_ALL_INTERFACES (pim
->vrf
, ifp
) {
318 struct pim_interface
*pim_ifp
= ifp
->info
;
319 struct pim_iface_upstream_switch
*us
;
320 struct listnode
*node
;
325 for (ALL_LIST_ELEMENTS_RO(pim_ifp
->upstream_switch_list
, node
,
329 rpf
.source_nexthop
.interface
= ifp
;
330 rpf
.rpf_addr
.u
.prefix4
= us
->address
;
331 pim_joinprune_send(&rpf
, us
->us
);
332 pim_jp_agg_clear_group(us
->us
);
337 void pim_zebra_upstream_rpf_changed(struct pim_instance
*pim
,
338 struct pim_upstream
*up
,
341 if (old
->source_nexthop
.interface
) {
342 struct pim_neighbor
*nbr
;
344 nbr
= pim_neighbor_find(old
->source_nexthop
.interface
,
345 old
->rpf_addr
.u
.prefix4
);
347 pim_jp_agg_remove_group(nbr
->upstream_jp_agg
, up
);
350 * We have detected a case where we might need
351 * to rescan the inherited o_list so do it.
353 if (up
->channel_oil
->oil_inherited_rescan
) {
354 pim_upstream_inherited_olist_decide(pim
, up
);
355 up
->channel_oil
->oil_inherited_rescan
= 0;
358 if (up
->join_state
== PIM_UPSTREAM_JOINED
) {
360 * If we come up real fast we can be here
361 * where the mroute has not been installed
364 if (!up
->channel_oil
->installed
)
365 pim_mroute_add(up
->channel_oil
,
366 __PRETTY_FUNCTION__
);
369 * RFC 4601: 4.5.7. Sending (S,G)
370 * Join/Prune Messages
372 * Transitions from Joined State
374 * RPF'(S,G) changes not due to an Assert
376 * The upstream (S,G) state machine remains
377 * in Joined state. Send Join(S,G) to the new
378 * upstream neighbor, which is the new value
379 * of RPF'(S,G). Send Prune(S,G) to the old
380 * upstream neighbor, which is the old value
381 * of RPF'(S,G). Set the Join Timer (JT) to
382 * expire after t_periodic seconds.
384 pim_jp_agg_switch_interface(old
, &up
->rpf
, up
);
386 pim_upstream_join_timer_restart(up
, old
);
387 } /* up->join_state == PIM_UPSTREAM_JOINED */
392 * We have detected a case where we might need
393 * to rescan the inherited o_list so do it.
395 if (up
->channel_oil
->oil_inherited_rescan
) {
396 pim_upstream_inherited_olist_decide(pim
, up
);
397 up
->channel_oil
->oil_inherited_rescan
= 0;
400 if (!up
->channel_oil
->installed
)
401 pim_mroute_add(up
->channel_oil
, __PRETTY_FUNCTION__
);
404 /* FIXME can join_desired actually be changed by pim_rpf_update()
405 * returning PIM_RPF_CHANGED ?
407 pim_upstream_update_join_desired(pim
, up
);
410 static int pim_zebra_vxlan_sg_proc(ZAPI_CALLBACK_ARGS
)
413 struct pim_instance
*pim
;
416 pim
= pim_get_pim_instance(vrf_id
);
423 sg
.prefixlen
= stream_getl(s
);
424 stream_get(&sg
.src
.s_addr
, s
, sg
.prefixlen
);
425 stream_get(&sg
.grp
.s_addr
, s
, sg
.prefixlen
);
427 if (PIM_DEBUG_ZEBRA
) {
428 char sg_str
[PIM_SG_LEN
];
430 pim_str_sg_set(&sg
, sg_str
);
431 zlog_debug("%u:recv SG %s %s", vrf_id
,
432 (cmd
== ZEBRA_VXLAN_SG_ADD
)?"add":"del",
436 if (cmd
== ZEBRA_VXLAN_SG_ADD
)
437 pim_vxlan_sg_add(pim
, &sg
);
439 pim_vxlan_sg_del(pim
, &sg
);
444 static void pim_zebra_vxlan_replay(void)
446 struct stream
*s
= NULL
;
449 if (!zclient
|| zclient
->sock
< 0)
455 zclient_create_header(s
, ZEBRA_VXLAN_SG_REPLAY
, VRF_DEFAULT
);
456 stream_putw_at(s
, 0, stream_get_endp(s
));
458 zclient_send_message(zclient
);
461 void pim_scan_individual_oil(struct channel_oil
*c_oil
, int in_vif_index
)
463 struct in_addr vif_source
;
464 int input_iface_vif_index
;
466 pim_rp_set_upstream_addr(c_oil
->pim
, &vif_source
,
467 c_oil
->oil
.mfcc_origin
,
468 c_oil
->oil
.mfcc_mcastgrp
);
471 input_iface_vif_index
= in_vif_index
;
473 struct prefix src
, grp
;
475 src
.family
= AF_INET
;
476 src
.prefixlen
= IPV4_MAX_BITLEN
;
477 src
.u
.prefix4
= vif_source
;
478 grp
.family
= AF_INET
;
479 grp
.prefixlen
= IPV4_MAX_BITLEN
;
480 grp
.u
.prefix4
= c_oil
->oil
.mfcc_mcastgrp
;
482 if (PIM_DEBUG_ZEBRA
) {
483 char source_str
[INET_ADDRSTRLEN
];
484 char group_str
[INET_ADDRSTRLEN
];
485 pim_inet4_dump("<source?>", c_oil
->oil
.mfcc_origin
,
486 source_str
, sizeof(source_str
));
487 pim_inet4_dump("<group?>", c_oil
->oil
.mfcc_mcastgrp
,
488 group_str
, sizeof(group_str
));
490 "%s: channel_oil (%s,%s) upstream info is not present.",
491 __PRETTY_FUNCTION__
, source_str
, group_str
);
493 input_iface_vif_index
= pim_ecmp_fib_lookup_if_vif_index(
494 c_oil
->pim
, &src
, &grp
);
497 if (input_iface_vif_index
< 1) {
498 if (PIM_DEBUG_ZEBRA
) {
499 char source_str
[INET_ADDRSTRLEN
];
500 char group_str
[INET_ADDRSTRLEN
];
501 pim_inet4_dump("<source?>", c_oil
->oil
.mfcc_origin
,
502 source_str
, sizeof(source_str
));
503 pim_inet4_dump("<group?>", c_oil
->oil
.mfcc_mcastgrp
,
504 group_str
, sizeof(group_str
));
506 "%s %s: could not find input interface(%d) for (S,G)=(%s,%s)",
507 __FILE__
, __PRETTY_FUNCTION__
,
508 c_oil
->oil
.mfcc_parent
, source_str
, group_str
);
510 pim_mroute_del(c_oil
, __PRETTY_FUNCTION__
);
514 if (input_iface_vif_index
== c_oil
->oil
.mfcc_parent
) {
515 if (!c_oil
->installed
)
516 pim_mroute_add(c_oil
, __PRETTY_FUNCTION__
);
522 if (PIM_DEBUG_ZEBRA
) {
523 struct interface
*old_iif
= pim_if_find_by_vif_index(
524 c_oil
->pim
, c_oil
->oil
.mfcc_parent
);
525 struct interface
*new_iif
= pim_if_find_by_vif_index(
526 c_oil
->pim
, input_iface_vif_index
);
527 char source_str
[INET_ADDRSTRLEN
];
528 char group_str
[INET_ADDRSTRLEN
];
529 pim_inet4_dump("<source?>", c_oil
->oil
.mfcc_origin
, source_str
,
531 pim_inet4_dump("<group?>", c_oil
->oil
.mfcc_mcastgrp
, group_str
,
534 "%s %s: (S,G)=(%s,%s) input interface changed from %s vif_index=%d to %s vif_index=%d",
535 __FILE__
, __PRETTY_FUNCTION__
, source_str
, group_str
,
536 (old_iif
) ? old_iif
->name
: "<old_iif?>",
537 c_oil
->oil
.mfcc_parent
,
538 (new_iif
) ? new_iif
->name
: "<new_iif?>",
539 input_iface_vif_index
);
542 /* new iif loops to existing oif ? */
543 if (c_oil
->oil
.mfcc_ttls
[input_iface_vif_index
]) {
544 struct interface
*new_iif
= pim_if_find_by_vif_index(
545 c_oil
->pim
, input_iface_vif_index
);
547 if (PIM_DEBUG_ZEBRA
) {
548 char source_str
[INET_ADDRSTRLEN
];
549 char group_str
[INET_ADDRSTRLEN
];
550 pim_inet4_dump("<source?>", c_oil
->oil
.mfcc_origin
,
551 source_str
, sizeof(source_str
));
552 pim_inet4_dump("<group?>", c_oil
->oil
.mfcc_mcastgrp
,
553 group_str
, sizeof(group_str
));
555 "%s %s: (S,G)=(%s,%s) new iif loops to existing oif: %s vif_index=%d",
556 __FILE__
, __PRETTY_FUNCTION__
, source_str
,
558 (new_iif
) ? new_iif
->name
: "<new_iif?>",
559 input_iface_vif_index
);
563 /* update iif vif_index */
564 pim_channel_oil_change_iif(c_oil
->pim
, c_oil
, input_iface_vif_index
,
565 __PRETTY_FUNCTION__
);
566 pim_mroute_add(c_oil
, __PRETTY_FUNCTION__
);
569 void pim_scan_oil(struct pim_instance
*pim
)
571 struct listnode
*node
;
572 struct listnode
*nextnode
;
573 struct channel_oil
*c_oil
;
577 pim
->scan_oil_last
= pim_time_monotonic_sec();
578 ++pim
->scan_oil_events
;
580 for (ALL_LIST_ELEMENTS(pim
->channel_oil_list
, node
, nextnode
, c_oil
)) {
581 if (c_oil
->up
&& c_oil
->up
->rpf
.source_nexthop
.interface
) {
582 ifindex
= c_oil
->up
->rpf
.source_nexthop
585 pim_if_find_vifindex_by_ifindex(pim
, ifindex
);
586 /* Pass Current selected NH vif index to mroute
589 pim_scan_individual_oil(c_oil
, vif_index
);
591 pim_scan_individual_oil(c_oil
, 0);
595 static int on_rpf_cache_refresh(struct thread
*t
)
597 struct pim_instance
*pim
= THREAD_ARG(t
);
599 /* update kernel multicast forwarding cache (MFC) */
602 pim
->rpf_cache_refresh_last
= pim_time_monotonic_sec();
603 ++pim
->rpf_cache_refresh_events
;
605 // It is called as part of pim_neighbor_add
610 void sched_rpf_cache_refresh(struct pim_instance
*pim
)
612 ++pim
->rpf_cache_refresh_requests
;
614 pim_rpf_set_refresh_time(pim
);
616 if (pim
->rpf_cache_refresher
) {
617 /* Refresh timer is already running */
621 /* Start refresh timer */
623 if (PIM_DEBUG_ZEBRA
) {
624 zlog_debug("%s: triggering %ld msec timer", __PRETTY_FUNCTION__
,
625 router
->rpf_cache_refresh_delay_msec
);
628 thread_add_timer_msec(router
->master
, on_rpf_cache_refresh
, pim
,
629 router
->rpf_cache_refresh_delay_msec
,
630 &pim
->rpf_cache_refresher
);
633 static void pim_zebra_connected(struct zclient
*zclient
)
635 /* Send the client registration */
636 bfd_client_sendmsg(zclient
, ZEBRA_BFD_CLIENT_REGISTER
, router
->vrf_id
);
638 zclient_send_reg_requests(zclient
, router
->vrf_id
);
640 /* request for VxLAN BUM group addresses */
641 pim_zebra_vxlan_replay();
644 static void pim_zebra_capabilities(struct zclient_capabilities
*cap
)
646 router
->role
= cap
->role
;
649 void pim_zebra_init(void)
651 /* Socket for receiving updates from Zebra daemon */
652 zclient
= zclient_new(router
->master
, &zclient_options_default
);
654 zclient
->zebra_capabilities
= pim_zebra_capabilities
;
655 zclient
->zebra_connected
= pim_zebra_connected
;
656 zclient
->router_id_update
= pim_router_id_update_zebra
;
657 zclient
->interface_delete
= pim_zebra_if_del
;
658 zclient
->interface_down
= pim_zebra_if_state_down
;
659 zclient
->interface_address_add
= pim_zebra_if_address_add
;
660 zclient
->interface_address_delete
= pim_zebra_if_address_del
;
661 zclient
->interface_vrf_update
= pim_zebra_interface_vrf_update
;
662 zclient
->nexthop_update
= pim_parse_nexthop_update
;
663 zclient
->vxlan_sg_add
= pim_zebra_vxlan_sg_proc
;
664 zclient
->vxlan_sg_del
= pim_zebra_vxlan_sg_proc
;
666 zclient_init(zclient
, ZEBRA_ROUTE_PIM
, 0, &pimd_privs
);
667 if (PIM_DEBUG_PIM_TRACE
) {
668 zlog_notice("%s: zclient socket initialized",
669 __PRETTY_FUNCTION__
);
672 zclient_lookup_new();
675 void igmp_anysource_forward_start(struct pim_instance
*pim
,
676 struct igmp_group
*group
)
678 struct igmp_source
*source
;
679 struct in_addr src_addr
= {.s_addr
= 0};
680 /* Any source (*,G) is forwarded only if mode is EXCLUDE {empty} */
681 zassert(group
->group_filtermode_isexcl
);
682 zassert(listcount(group
->group_source_list
) < 1);
684 source
= source_new(group
, src_addr
);
686 zlog_warn("%s: Failure to create * source",
687 __PRETTY_FUNCTION__
);
691 igmp_source_forward_start(pim
, source
);
694 void igmp_anysource_forward_stop(struct igmp_group
*group
)
696 struct igmp_source
*source
;
697 struct in_addr star
= {.s_addr
= 0};
699 source
= igmp_find_source_by_addr(group
, star
);
701 igmp_source_forward_stop(source
);
704 static void igmp_source_forward_reevaluate_one(struct pim_instance
*pim
,
705 struct igmp_source
*source
)
708 struct igmp_group
*group
= source
->source_group
;
709 struct pim_ifchannel
*ch
;
711 if ((source
->source_addr
.s_addr
!= INADDR_ANY
)
712 || !IGMP_SOURCE_TEST_FORWARDING(source
->source_flags
))
715 memset(&sg
, 0, sizeof(struct prefix_sg
));
716 sg
.src
= source
->source_addr
;
717 sg
.grp
= group
->group_addr
;
719 ch
= pim_ifchannel_find(group
->group_igmp_sock
->interface
, &sg
);
720 if (pim_is_grp_ssm(pim
, group
->group_addr
)) {
721 /* If SSM group withdraw local membership */
723 && (ch
->local_ifmembership
== PIM_IFMEMBERSHIP_INCLUDE
)) {
724 if (PIM_DEBUG_PIM_EVENTS
)
726 "local membership del for %s as G is now SSM",
727 pim_str_sg_dump(&sg
));
728 pim_ifchannel_local_membership_del(
729 group
->group_igmp_sock
->interface
, &sg
);
732 /* If ASM group add local membership */
734 || (ch
->local_ifmembership
== PIM_IFMEMBERSHIP_NOINFO
)) {
735 if (PIM_DEBUG_PIM_EVENTS
)
737 "local membership add for %s as G is now ASM",
738 pim_str_sg_dump(&sg
));
739 pim_ifchannel_local_membership_add(
740 group
->group_igmp_sock
->interface
, &sg
);
745 void igmp_source_forward_reevaluate_all(struct pim_instance
*pim
)
747 struct interface
*ifp
;
749 FOR_ALL_INTERFACES (pim
->vrf
, ifp
) {
750 struct pim_interface
*pim_ifp
= ifp
->info
;
751 struct listnode
*sock_node
;
752 struct igmp_sock
*igmp
;
757 /* scan igmp sockets */
758 for (ALL_LIST_ELEMENTS_RO(pim_ifp
->igmp_socket_list
, sock_node
,
760 struct listnode
*grpnode
;
761 struct igmp_group
*grp
;
763 /* scan igmp groups */
764 for (ALL_LIST_ELEMENTS_RO(igmp
->igmp_group_list
,
766 struct listnode
*srcnode
;
767 struct igmp_source
*src
;
769 /* scan group sources */
770 for (ALL_LIST_ELEMENTS_RO(
771 grp
->group_source_list
, srcnode
,
773 igmp_source_forward_reevaluate_one(pim
,
775 } /* scan group sources */
776 } /* scan igmp groups */
777 } /* scan igmp sockets */
778 } /* scan interfaces */
781 void igmp_source_forward_start(struct pim_instance
*pim
,
782 struct igmp_source
*source
)
784 struct pim_interface
*pim_oif
;
785 struct igmp_group
*group
;
788 int input_iface_vif_index
= 0;
790 memset(&sg
, 0, sizeof(struct prefix_sg
));
791 sg
.src
= source
->source_addr
;
792 sg
.grp
= source
->source_group
->group_addr
;
794 if (PIM_DEBUG_IGMP_TRACE
) {
796 "%s: (S,G)=%s igmp_sock=%d oif=%s fwd=%d",
797 __PRETTY_FUNCTION__
, pim_str_sg_dump(&sg
),
798 source
->source_group
->group_igmp_sock
->fd
,
799 source
->source_group
->group_igmp_sock
->interface
->name
,
800 IGMP_SOURCE_TEST_FORWARDING(source
->source_flags
));
803 /* Prevent IGMP interface from installing multicast route multiple
805 if (IGMP_SOURCE_TEST_FORWARDING(source
->source_flags
)) {
809 group
= source
->source_group
;
810 pim_oif
= group
->group_igmp_sock
->interface
->info
;
812 if (PIM_DEBUG_IGMP_TRACE
) {
814 "%s: multicast not enabled on oif=%s ?",
816 source
->source_group
->group_igmp_sock
822 if (!source
->source_channel_oil
) {
823 struct in_addr vif_source
;
824 struct prefix src
, grp
;
825 struct pim_nexthop nexthop
;
826 struct pim_upstream
*up
= NULL
;
828 if (!pim_rp_set_upstream_addr(pim
, &vif_source
,
829 source
->source_addr
, sg
.grp
)) {
830 /*Create a dummy channel oil */
831 source
->source_channel_oil
= pim_channel_oil_add(
832 pim
, &sg
, MAXVIFS
, __PRETTY_FUNCTION__
);
836 src
.family
= AF_INET
;
837 src
.prefixlen
= IPV4_MAX_BITLEN
;
838 src
.u
.prefix4
= vif_source
; // RP or Src address
839 grp
.family
= AF_INET
;
840 grp
.prefixlen
= IPV4_MAX_BITLEN
;
841 grp
.u
.prefix4
= sg
.grp
;
843 up
= pim_upstream_find(pim
, &sg
);
845 memcpy(&nexthop
, &up
->rpf
.source_nexthop
,
846 sizeof(struct pim_nexthop
));
847 pim_ecmp_nexthop_lookup(pim
, &nexthop
, &src
,
849 if (nexthop
.interface
)
850 input_iface_vif_index
=
851 pim_if_find_vifindex_by_ifindex(
853 nexthop
.interface
->ifindex
);
855 input_iface_vif_index
=
856 pim_ecmp_fib_lookup_if_vif_index(
859 if (PIM_DEBUG_ZEBRA
) {
860 char buf2
[INET_ADDRSTRLEN
];
862 pim_inet4_dump("<source?>", vif_source
, buf2
,
864 zlog_debug("%s: NHT %s vif_source %s vif_index:%d ",
866 pim_str_sg_dump(&sg
),
867 buf2
, input_iface_vif_index
);
870 if (input_iface_vif_index
< 1) {
871 if (PIM_DEBUG_IGMP_TRACE
) {
872 char source_str
[INET_ADDRSTRLEN
];
873 pim_inet4_dump("<source?>",
875 source_str
, sizeof(source_str
));
877 "%s %s: could not find input interface for source %s",
878 __FILE__
, __PRETTY_FUNCTION__
,
881 source
->source_channel_oil
=
884 __PRETTY_FUNCTION__
);
889 * Protect IGMP against adding looped MFC
890 * entries created by both source and receiver
891 * attached to the same interface. See TODO
892 * T22. Block only when the intf is non DR
893 * DR must create upstream.
895 if ((input_iface_vif_index
==
896 pim_oif
->mroute_vif_index
) &&
897 !(PIM_I_am_DR(pim_oif
))) {
898 /* ignore request for looped MFC entry
900 if (PIM_DEBUG_IGMP_TRACE
) {
902 "%s: ignoring request for looped MFC entry (S,G)=%s: igmp_sock=%d oif=%s vif_index=%d",
904 pim_str_sg_dump(&sg
),
906 ->group_igmp_sock
->fd
,
910 input_iface_vif_index
);
915 source
->source_channel_oil
=
917 pim
, &sg
, input_iface_vif_index
,
918 __PRETTY_FUNCTION__
);
919 if (!source
->source_channel_oil
) {
920 if (PIM_DEBUG_IGMP_TRACE
) {
922 "%s %s: could not create OIL for channel (S,G)=%s",
925 pim_str_sg_dump(&sg
));
933 result
= pim_channel_add_oif(source
->source_channel_oil
,
934 group
->group_igmp_sock
->interface
,
935 PIM_OIF_FLAG_PROTO_IGMP
);
937 if (PIM_DEBUG_MROUTE
) {
938 zlog_warn("%s: add_oif() failed with return=%d",
944 if (!(PIM_I_am_DR(pim_oif
))) {
945 if (PIM_DEBUG_IGMP_TRACE
)
946 zlog_debug("%s: %s was received on %s interface but we are not DR for that interface",
948 pim_str_sg_dump(&sg
),
949 group
->group_igmp_sock
->interface
->name
);
951 pim_channel_del_oif(source
->source_channel_oil
,
952 group
->group_igmp_sock
->interface
,
953 PIM_OIF_FLAG_PROTO_IGMP
);
957 Feed IGMPv3-gathered local membership information into PIM
958 per-interface (S,G) state.
960 if (!pim_ifchannel_local_membership_add(
961 group
->group_igmp_sock
->interface
, &sg
)) {
962 if (PIM_DEBUG_MROUTE
)
963 zlog_warn("%s: Failure to add local membership for %s",
964 __PRETTY_FUNCTION__
, pim_str_sg_dump(&sg
));
966 pim_channel_del_oif(source
->source_channel_oil
,
967 group
->group_igmp_sock
->interface
,
968 PIM_OIF_FLAG_PROTO_IGMP
);
972 IGMP_SOURCE_DO_FORWARDING(source
->source_flags
);
976 igmp_source_forward_stop: stop fowarding, but keep the source
977 igmp_source_delete: stop fowarding, and delete the source
979 void igmp_source_forward_stop(struct igmp_source
*source
)
981 struct igmp_group
*group
;
985 memset(&sg
, 0, sizeof(struct prefix_sg
));
986 sg
.src
= source
->source_addr
;
987 sg
.grp
= source
->source_group
->group_addr
;
989 if (PIM_DEBUG_IGMP_TRACE
) {
991 "%s: (S,G)=%s igmp_sock=%d oif=%s fwd=%d",
992 __PRETTY_FUNCTION__
, pim_str_sg_dump(&sg
),
993 source
->source_group
->group_igmp_sock
->fd
,
994 source
->source_group
->group_igmp_sock
->interface
->name
,
995 IGMP_SOURCE_TEST_FORWARDING(source
->source_flags
));
998 /* Prevent IGMP interface from removing multicast route multiple
1000 if (!IGMP_SOURCE_TEST_FORWARDING(source
->source_flags
)) {
1004 group
= source
->source_group
;
1007 It appears that in certain circumstances that
1008 igmp_source_forward_stop is called when IGMP forwarding
1009 was not enabled in oif_flags for this outgoing interface.
1010 Possibly because of multiple calls. When that happens, we
1011 enter the below if statement and this function returns early
1012 which in turn triggers the calling function to assert.
1013 Making the call to pim_channel_del_oif and ignoring the return code
1014 fixes the issue without ill effect, similar to
1015 pim_forward_stop below.
1017 result
= pim_channel_del_oif(source
->source_channel_oil
,
1018 group
->group_igmp_sock
->interface
,
1019 PIM_OIF_FLAG_PROTO_IGMP
);
1021 if (PIM_DEBUG_IGMP_TRACE
)
1023 "%s: pim_channel_del_oif() failed with return=%d",
1029 Feed IGMPv3-gathered local membership information into PIM
1030 per-interface (S,G) state.
1032 pim_ifchannel_local_membership_del(group
->group_igmp_sock
->interface
,
1035 IGMP_SOURCE_DONT_FORWARDING(source
->source_flags
);
1038 void pim_forward_start(struct pim_ifchannel
*ch
)
1040 struct pim_upstream
*up
= ch
->upstream
;
1041 uint32_t mask
= PIM_OIF_FLAG_PROTO_PIM
;
1042 int input_iface_vif_index
= 0;
1043 struct pim_instance
*pim
;
1044 struct pim_interface
*pim_ifp
;
1046 pim_ifp
= ch
->interface
->info
;
1049 if (PIM_DEBUG_PIM_TRACE
) {
1050 char source_str
[INET_ADDRSTRLEN
];
1051 char group_str
[INET_ADDRSTRLEN
];
1052 char upstream_str
[INET_ADDRSTRLEN
];
1054 pim_inet4_dump("<source?>", ch
->sg
.src
, source_str
,
1055 sizeof(source_str
));
1056 pim_inet4_dump("<group?>", ch
->sg
.grp
, group_str
,
1058 pim_inet4_dump("<upstream?>", up
->upstream_addr
, upstream_str
,
1059 sizeof(upstream_str
));
1060 zlog_debug("%s: (S,G)=(%s,%s) oif=%s (%s)", __PRETTY_FUNCTION__
,
1061 source_str
, group_str
, ch
->interface
->name
,
1062 inet_ntoa(up
->upstream_addr
));
1065 /* Resolve IIF for upstream as mroute_del sets mfcc_parent to MAXVIFS,
1066 as part of mroute_del called by pim_forward_stop.
1068 if ((up
->upstream_addr
.s_addr
!= INADDR_ANY
) && (!up
->channel_oil
)) {
1069 struct prefix src
, grp
;
1071 grp
.family
= AF_INET
;
1072 grp
.prefixlen
= IPV4_MAX_BITLEN
;
1073 grp
.u
.prefix4
= up
->sg
.grp
;
1074 src
.family
= AF_INET
;
1075 src
.prefixlen
= IPV4_MAX_BITLEN
;
1076 src
.u
.prefix4
= up
->sg
.src
;
1078 if (pim_ecmp_nexthop_lookup(pim
, &up
->rpf
.source_nexthop
, &src
,
1080 input_iface_vif_index
= pim_if_find_vifindex_by_ifindex(
1081 pim
, up
->rpf
.source_nexthop
.interface
->ifindex
);
1083 if (input_iface_vif_index
< 1) {
1084 if (PIM_DEBUG_PIM_TRACE
) {
1085 char source_str
[INET_ADDRSTRLEN
];
1086 pim_inet4_dump("<source?>", up
->sg
.src
,
1087 source_str
, sizeof(source_str
));
1089 "%s %s: could not find input interface for source %s",
1090 __FILE__
, __PRETTY_FUNCTION__
,
1093 pim_channel_oil_change_iif(pim
, up
->channel_oil
,
1095 __PRETTY_FUNCTION__
);
1099 pim_channel_oil_change_iif(pim
, up
->channel_oil
,
1100 input_iface_vif_index
,
1101 __PRETTY_FUNCTION__
);
1103 if (PIM_DEBUG_TRACE
) {
1104 struct interface
*in_intf
= pim_if_find_by_vif_index(
1105 pim
, input_iface_vif_index
);
1107 "%s: Update channel_oil IIF %s VIFI %d entry %s ",
1108 __PRETTY_FUNCTION__
,
1109 in_intf
? in_intf
->name
: "Unknown",
1110 input_iface_vif_index
, up
->sg_str
);
1114 if (up
->flags
& PIM_UPSTREAM_FLAG_MASK_SRC_IGMP
)
1115 mask
= PIM_OIF_FLAG_PROTO_IGMP
;
1117 pim_channel_add_oif(up
->channel_oil
, ch
->interface
, mask
);
1120 void pim_forward_stop(struct pim_ifchannel
*ch
, bool install_it
)
1122 struct pim_upstream
*up
= ch
->upstream
;
1124 if (PIM_DEBUG_PIM_TRACE
) {
1125 zlog_debug("%s: (S,G)=%s oif=%s install_it: %d installed: %d",
1126 __PRETTY_FUNCTION__
, ch
->sg_str
, ch
->interface
->name
,
1127 install_it
, up
->channel_oil
->installed
);
1131 * If a channel is being removed, check to see if we still need
1132 * to inherit the interface. If so make sure it is added in
1134 if (pim_upstream_evaluate_join_desired_interface(up
, ch
, ch
->parent
))
1135 pim_channel_add_oif(up
->channel_oil
, ch
->interface
,
1136 PIM_OIF_FLAG_PROTO_PIM
);
1138 pim_channel_del_oif(up
->channel_oil
, ch
->interface
,
1139 PIM_OIF_FLAG_PROTO_PIM
);
1141 if (install_it
&& !up
->channel_oil
->installed
)
1142 pim_mroute_add(up
->channel_oil
, __PRETTY_FUNCTION__
);
1145 void pim_zebra_zclient_update(struct vty
*vty
)
1147 vty_out(vty
, "Zclient update socket: ");
1150 vty_out(vty
, "%d failures=%d\n", zclient
->sock
, zclient
->fail
);
1152 vty_out(vty
, "<null zclient>\n");
1156 struct zclient
*pim_zebra_zclient_get(void)
1164 void pim_zebra_interface_set_master(struct interface
*vrf
,
1165 struct interface
*ifp
)
1167 zclient_interface_set_master(zclient
, vrf
, ifp
);