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
22 #include "zebra/rib.h"
36 #include "pim_zebra.h"
37 #include "pim_iface.h"
43 #include "pim_zlookup.h"
44 #include "pim_ifchannel.h"
46 #include "pim_igmpv3.h"
47 #include "pim_jp_agg.h"
51 #undef PIM_DEBUG_IFADDR_DUMP
52 #define PIM_DEBUG_IFADDR_DUMP
54 static struct zclient
*zclient
= NULL
;
57 /* Router-id update message from zebra. */
58 static int pim_router_id_update_zebra(int command
, struct zclient
*zclient
,
59 zebra_size_t length
, vrf_id_t vrf_id
)
61 struct prefix router_id
;
63 zebra_router_id_update_read(zclient
->ibuf
, &router_id
);
68 static int pim_zebra_if_add(int command
, struct zclient
*zclient
,
69 zebra_size_t length
, vrf_id_t vrf_id
)
71 struct interface
*ifp
;
74 zebra api adds/dels interfaces using the same call
75 interface_add_read below, see comments in lib/zclient.c
77 ifp
= zebra_interface_add_read(zclient
->ibuf
, vrf_id
);
81 if (PIM_DEBUG_ZEBRA
) {
83 "%s: %s index %d(%d) flags %ld metric %d mtu %d operative %d",
84 __PRETTY_FUNCTION__
, ifp
->name
, ifp
->ifindex
, vrf_id
,
85 (long)ifp
->flags
, ifp
->metric
, ifp
->mtu
,
86 if_is_operative(ifp
));
89 if (if_is_operative(ifp
))
90 pim_if_addr_add_all(ifp
);
93 * If we are a vrf device that is up, open up the pim_socket for
95 * to incoming pim messages irrelevant if the user has configured us
98 if (pim_if_is_vrf_device(ifp
)) {
99 struct pim_interface
*pim_ifp
;
102 pim_ifp
= pim_if_new(ifp
, 0, 0);
112 static int pim_zebra_if_del(int command
, struct zclient
*zclient
,
113 zebra_size_t length
, vrf_id_t vrf_id
)
115 struct interface
*ifp
;
118 zebra api adds/dels interfaces using the same call
119 interface_add_read below, see comments in lib/zclient.c
121 comments in lib/zclient.c seem to indicate that calling
122 zebra_interface_add_read is the correct call, but that
123 results in an attemted out of bounds read which causes
124 pimd to assert. Other clients use zebra_interface_state_read
125 and it appears to work just fine.
127 ifp
= zebra_interface_state_read(zclient
->ibuf
, vrf_id
);
131 if (PIM_DEBUG_ZEBRA
) {
133 "%s: %s index %d(%d) flags %ld metric %d mtu %d operative %d",
134 __PRETTY_FUNCTION__
, ifp
->name
, ifp
->ifindex
, vrf_id
,
135 (long)ifp
->flags
, ifp
->metric
, ifp
->mtu
,
136 if_is_operative(ifp
));
139 if (!if_is_operative(ifp
))
140 pim_if_addr_del_all(ifp
);
145 static int pim_zebra_if_state_up(int command
, struct zclient
*zclient
,
146 zebra_size_t length
, vrf_id_t vrf_id
)
148 struct interface
*ifp
;
152 zebra api notifies interface up/down events by using the same call
153 zebra_interface_state_read below, see comments in lib/zclient.c
155 ifp
= zebra_interface_state_read(zclient
->ibuf
, vrf_id
);
159 if (PIM_DEBUG_ZEBRA
) {
161 "%s: %s index %d(%d) flags %ld metric %d mtu %d operative %d",
162 __PRETTY_FUNCTION__
, ifp
->name
, ifp
->ifindex
, vrf_id
,
163 (long)ifp
->flags
, ifp
->metric
, ifp
->mtu
,
164 if_is_operative(ifp
));
167 if (if_is_operative(ifp
)) {
169 pim_if_addr_add_all() suffices for bringing up both IGMP and
172 pim_if_addr_add_all(ifp
);
176 * If we have a pimreg device callback and it's for a specific
177 * table set the master appropriately
179 if (sscanf(ifp
->name
, "pimreg%d", &table_id
) == 1) {
181 RB_FOREACH(vrf
, vrf_name_head
, &vrfs_by_name
)
183 if ((table_id
== vrf
->data
.l
.table_id
)
184 && (ifp
->vrf_id
!= vrf
->vrf_id
)) {
185 struct interface
*master
= if_lookup_by_name(
186 vrf
->name
, vrf
->vrf_id
);
187 zclient_interface_set_master(zclient
, master
,
195 static int pim_zebra_if_state_down(int command
, struct zclient
*zclient
,
196 zebra_size_t length
, vrf_id_t vrf_id
)
198 struct interface
*ifp
;
201 zebra api notifies interface up/down events by using the same call
202 zebra_interface_state_read below, see comments in lib/zclient.c
204 ifp
= zebra_interface_state_read(zclient
->ibuf
, vrf_id
);
208 if (PIM_DEBUG_ZEBRA
) {
210 "%s: %s index %d(%d) flags %ld metric %d mtu %d operative %d",
211 __PRETTY_FUNCTION__
, ifp
->name
, ifp
->ifindex
, vrf_id
,
212 (long)ifp
->flags
, ifp
->metric
, ifp
->mtu
,
213 if_is_operative(ifp
));
216 if (!if_is_operative(ifp
)) {
217 pim_ifchannel_delete_all(ifp
);
219 pim_if_addr_del_all() suffices for shutting down IGMP,
220 but not for shutting down PIM
222 pim_if_addr_del_all(ifp
);
225 pim_sock_delete() closes the socket, stops read and timer
227 and kills all neighbors.
230 pim_sock_delete(ifp
, "link down");
240 #ifdef PIM_DEBUG_IFADDR_DUMP
241 static void dump_if_address(struct interface
*ifp
)
243 struct connected
*ifc
;
244 struct listnode
*node
;
246 zlog_debug("%s %s: interface %s addresses:", __FILE__
,
247 __PRETTY_FUNCTION__
, ifp
->name
);
249 for (ALL_LIST_ELEMENTS_RO(ifp
->connected
, node
, ifc
)) {
250 struct prefix
*p
= ifc
->address
;
252 if (p
->family
!= AF_INET
)
255 zlog_debug("%s %s: interface %s address %s %s", __FILE__
,
256 __PRETTY_FUNCTION__
, ifp
->name
,
257 inet_ntoa(p
->u
.prefix4
),
258 CHECK_FLAG(ifc
->flags
, ZEBRA_IFA_SECONDARY
)
265 static int pim_zebra_if_address_add(int command
, struct zclient
*zclient
,
266 zebra_size_t length
, vrf_id_t vrf_id
)
270 struct pim_interface
*pim_ifp
;
273 zebra api notifies address adds/dels events by using the same call
274 interface_add_read below, see comments in lib/zclient.c
276 zebra_interface_address_read(ZEBRA_INTERFACE_ADDRESS_ADD, ...)
277 will add address to interface list by calling
278 connected_add_by_prefix()
280 c
= zebra_interface_address_read(command
, zclient
->ibuf
, vrf_id
);
284 pim_ifp
= c
->ifp
->info
;
287 if (PIM_DEBUG_ZEBRA
) {
289 prefix2str(p
, buf
, BUFSIZ
);
290 zlog_debug("%s: %s(%d) connected IP address %s flags %u %s",
291 __PRETTY_FUNCTION__
, c
->ifp
->name
, vrf_id
, buf
,
292 c
->flags
, CHECK_FLAG(c
->flags
, ZEBRA_IFA_SECONDARY
)
296 #ifdef PIM_DEBUG_IFADDR_DUMP
297 dump_if_address(c
->ifp
);
301 if (!CHECK_FLAG(c
->flags
, ZEBRA_IFA_SECONDARY
)) {
302 /* trying to add primary address */
304 struct in_addr primary_addr
= pim_find_primary_addr(c
->ifp
);
305 if (p
->family
!= AF_INET
306 || primary_addr
.s_addr
!= p
->u
.prefix4
.s_addr
) {
307 if (PIM_DEBUG_ZEBRA
) {
308 /* but we had a primary address already */
312 prefix2str(p
, buf
, BUFSIZ
);
315 "%s: %s : forcing secondary flag on %s",
316 __PRETTY_FUNCTION__
, c
->ifp
->name
, buf
);
318 SET_FLAG(c
->flags
, ZEBRA_IFA_SECONDARY
);
324 pim_rp_check_on_if_add(pim_ifp
);
326 if (if_is_loopback(c
->ifp
)) {
327 struct listnode
*ifnode
;
328 struct interface
*ifp
;
330 for (ALL_LIST_ELEMENTS_RO(vrf_iflist(vrf_id
), ifnode
, ifp
)) {
331 if (!if_is_loopback(ifp
) && if_is_operative(ifp
))
332 pim_if_addr_add_all(ifp
);
339 static int pim_zebra_if_address_del(int command
, struct zclient
*client
,
340 zebra_size_t length
, vrf_id_t vrf_id
)
344 struct vrf
*vrf
= vrf_lookup_by_id(vrf_id
);
345 struct pim_instance
*pim
= vrf
->info
;
348 zebra api notifies address adds/dels events by using the same call
349 interface_add_read below, see comments in lib/zclient.c
351 zebra_interface_address_read(ZEBRA_INTERFACE_ADDRESS_DELETE, ...)
352 will remove address from interface list by calling
353 connected_delete_by_prefix()
355 c
= zebra_interface_address_read(command
, client
->ibuf
, vrf_id
);
360 if (p
->family
== AF_INET
) {
361 if (PIM_DEBUG_ZEBRA
) {
363 prefix2str(p
, buf
, BUFSIZ
);
365 "%s: %s(%d) disconnected IP address %s flags %u %s",
366 __PRETTY_FUNCTION__
, c
->ifp
->name
, vrf_id
, buf
,
368 CHECK_FLAG(c
->flags
, ZEBRA_IFA_SECONDARY
)
372 #ifdef PIM_DEBUG_IFADDR_DUMP
373 dump_if_address(c
->ifp
);
377 pim_if_addr_del(c
, 0);
379 pim_i_am_rp_re_evaluate(pim
);
386 static void scan_upstream_rpf_cache()
388 struct listnode
*up_node
;
389 struct listnode
*ifnode
;
390 struct listnode
*up_nextnode
;
391 struct listnode
*node
;
392 struct pim_upstream
*up
;
393 struct interface
*ifp
;
395 struct pim_instance
*pim
;
397 RB_FOREACH(vrf
, vrf_name_head
, &vrfs_by_name
)
403 for (ALL_LIST_ELEMENTS(pim
->upstream_list
, up_node
, up_nextnode
,
405 enum pim_rpf_result rpf_result
;
409 nht_p
.family
= AF_INET
;
410 nht_p
.prefixlen
= IPV4_MAX_BITLEN
;
411 nht_p
.u
.prefix4
.s_addr
= up
->upstream_addr
.s_addr
;
412 pim_resolve_upstream_nh(pim
, &nht_p
);
414 old
.source_nexthop
.interface
=
415 up
->rpf
.source_nexthop
.interface
;
416 old
.source_nexthop
.nbr
= up
->rpf
.source_nexthop
.nbr
;
417 rpf_result
= pim_rpf_update(pim
, up
, &old
, 0);
419 if (rpf_result
== PIM_RPF_FAILURE
)
422 if (rpf_result
== PIM_RPF_CHANGED
) {
423 struct pim_neighbor
*nbr
;
425 nbr
= pim_neighbor_find(
426 old
.source_nexthop
.interface
,
427 old
.rpf_addr
.u
.prefix4
);
429 pim_jp_agg_remove_group(
430 nbr
->upstream_jp_agg
, up
);
433 * We have detected a case where we might need
435 * the inherited o_list so do it.
437 if (up
->channel_oil
->oil_inherited_rescan
) {
438 pim_upstream_inherited_olist_decide(pim
,
440 up
->channel_oil
->oil_inherited_rescan
=
444 if (up
->join_state
== PIM_UPSTREAM_JOINED
) {
446 * If we come up real fast we can be
448 * where the mroute has not been
452 if (!up
->channel_oil
->installed
)
455 __PRETTY_FUNCTION__
);
458 * RFC 4601: 4.5.7. Sending (S,G)
459 * Join/Prune Messages
461 * Transitions from Joined State
463 * RPF'(S,G) changes not due to an
466 * The upstream (S,G) state machine
468 * state. Send Join(S,G) to the new
469 * upstream neighbor, which is
470 * the new value of RPF'(S,G). Send
471 * Prune(S,G) to the old
472 * upstream neighbor, which is the old
473 * value of RPF'(S,G). Set
474 * the Join Timer (JT) to expire after
475 * t_periodic seconds.
477 pim_jp_agg_switch_interface(
480 pim_upstream_join_timer_restart(up
,
482 } /* up->join_state == PIM_UPSTREAM_JOINED */
484 /* FIXME can join_desired actually be changed by
486 returning PIM_RPF_CHANGED ? */
487 pim_upstream_update_join_desired(pim
, up
);
489 } /* PIM_RPF_CHANGED */
491 } /* for (qpim_upstream_list) */
494 RB_FOREACH(vrf
, vrf_name_head
, &vrfs_by_name
)
500 for (ALL_LIST_ELEMENTS_RO(vrf_iflist(pim
->vrf_id
), ifnode
, ifp
))
502 struct pim_interface
*pim_ifp
= ifp
->info
;
503 struct pim_iface_upstream_switch
*us
;
505 for (ALL_LIST_ELEMENTS_RO(
506 pim_ifp
->upstream_switch_list
,
509 rpf
.source_nexthop
.interface
= ifp
;
510 rpf
.rpf_addr
.u
.prefix4
= us
->address
;
511 pim_joinprune_send(&rpf
, us
->us
);
512 pim_jp_agg_clear_group(us
->us
);
518 void pim_scan_individual_oil(struct channel_oil
*c_oil
, int in_vif_index
)
520 struct in_addr vif_source
;
521 int input_iface_vif_index
;
524 if (!pim_rp_set_upstream_addr(c_oil
->pim
, &vif_source
,
525 c_oil
->oil
.mfcc_origin
,
526 c_oil
->oil
.mfcc_mcastgrp
))
530 input_iface_vif_index
= in_vif_index
;
532 struct prefix src
, grp
;
534 src
.family
= AF_INET
;
535 src
.prefixlen
= IPV4_MAX_BITLEN
;
536 src
.u
.prefix4
= vif_source
;
537 grp
.family
= AF_INET
;
538 grp
.prefixlen
= IPV4_MAX_BITLEN
;
539 grp
.u
.prefix4
= c_oil
->oil
.mfcc_mcastgrp
;
541 if (PIM_DEBUG_ZEBRA
) {
542 char source_str
[INET_ADDRSTRLEN
];
543 char group_str
[INET_ADDRSTRLEN
];
544 pim_inet4_dump("<source?>", c_oil
->oil
.mfcc_origin
,
545 source_str
, sizeof(source_str
));
546 pim_inet4_dump("<group?>", c_oil
->oil
.mfcc_mcastgrp
,
547 group_str
, sizeof(group_str
));
549 "%s: channel_oil (%s, %s) upstream info is not present.",
550 __PRETTY_FUNCTION__
, source_str
, group_str
);
552 input_iface_vif_index
= pim_ecmp_fib_lookup_if_vif_index(
553 c_oil
->pim
, vif_source
, &src
, &grp
);
556 if (input_iface_vif_index
< 1) {
557 if (PIM_DEBUG_ZEBRA
) {
558 char source_str
[INET_ADDRSTRLEN
];
559 char group_str
[INET_ADDRSTRLEN
];
560 pim_inet4_dump("<source?>", c_oil
->oil
.mfcc_origin
,
561 source_str
, sizeof(source_str
));
562 pim_inet4_dump("<group?>", c_oil
->oil
.mfcc_mcastgrp
,
563 group_str
, sizeof(group_str
));
565 "%s %s: could not find input interface(%d) for (S,G)=(%s,%s)",
566 __FILE__
, __PRETTY_FUNCTION__
,
567 c_oil
->oil
.mfcc_parent
, source_str
, group_str
);
569 pim_mroute_del(c_oil
, __PRETTY_FUNCTION__
);
573 if (input_iface_vif_index
== c_oil
->oil
.mfcc_parent
) {
574 if (!c_oil
->installed
)
575 pim_mroute_add(c_oil
, __PRETTY_FUNCTION__
);
581 if (PIM_DEBUG_ZEBRA
) {
582 struct interface
*old_iif
= pim_if_find_by_vif_index(
583 c_oil
->pim
, c_oil
->oil
.mfcc_parent
);
584 struct interface
*new_iif
= pim_if_find_by_vif_index(
585 c_oil
->pim
, input_iface_vif_index
);
586 char source_str
[INET_ADDRSTRLEN
];
587 char group_str
[INET_ADDRSTRLEN
];
588 pim_inet4_dump("<source?>", c_oil
->oil
.mfcc_origin
, source_str
,
590 pim_inet4_dump("<group?>", c_oil
->oil
.mfcc_mcastgrp
, group_str
,
593 "%s %s: (S,G)=(%s,%s) input interface changed from %s vif_index=%d to %s vif_index=%d",
594 __FILE__
, __PRETTY_FUNCTION__
, source_str
, group_str
,
595 old_iif
->name
, c_oil
->oil
.mfcc_parent
, new_iif
->name
,
596 input_iface_vif_index
);
599 /* new iif loops to existing oif ? */
600 if (c_oil
->oil
.mfcc_ttls
[input_iface_vif_index
]) {
601 struct interface
*new_iif
= pim_if_find_by_vif_index(
602 c_oil
->pim
, input_iface_vif_index
);
604 if (PIM_DEBUG_ZEBRA
) {
605 char source_str
[INET_ADDRSTRLEN
];
606 char group_str
[INET_ADDRSTRLEN
];
607 pim_inet4_dump("<source?>", c_oil
->oil
.mfcc_origin
,
608 source_str
, sizeof(source_str
));
609 pim_inet4_dump("<group?>", c_oil
->oil
.mfcc_mcastgrp
,
610 group_str
, sizeof(group_str
));
612 "%s %s: (S,G)=(%s,%s) new iif loops to existing oif: %s vif_index=%d",
613 __FILE__
, __PRETTY_FUNCTION__
, source_str
,
614 group_str
, new_iif
->name
,
615 input_iface_vif_index
);
619 /* update iif vif_index */
620 old_vif_index
= c_oil
->oil
.mfcc_parent
;
621 c_oil
->oil
.mfcc_parent
= input_iface_vif_index
;
623 /* update kernel multicast forwarding cache (MFC) */
624 if (pim_mroute_add(c_oil
, __PRETTY_FUNCTION__
)) {
625 if (PIM_DEBUG_MROUTE
) {
626 /* just log warning */
627 struct interface
*old_iif
= pim_if_find_by_vif_index(
628 c_oil
->pim
, old_vif_index
);
629 struct interface
*new_iif
= pim_if_find_by_vif_index(
630 c_oil
->pim
, input_iface_vif_index
);
631 char source_str
[INET_ADDRSTRLEN
];
632 char group_str
[INET_ADDRSTRLEN
];
633 pim_inet4_dump("<source?>", c_oil
->oil
.mfcc_origin
,
634 source_str
, sizeof(source_str
));
635 pim_inet4_dump("<group?>", c_oil
->oil
.mfcc_mcastgrp
,
636 group_str
, sizeof(group_str
));
638 "%s %s: (S,G)=(%s,%s) failure updating input interface from %s vif_index=%d to %s vif_index=%d",
639 __FILE__
, __PRETTY_FUNCTION__
, source_str
,
641 old_iif
? old_iif
->name
: "<old_iif?>",
642 c_oil
->oil
.mfcc_parent
,
643 new_iif
? new_iif
->name
: "<new_iif?>",
644 input_iface_vif_index
);
649 void pim_scan_oil(struct pim_instance
*pim_matcher
)
651 struct listnode
*node
;
652 struct listnode
*nextnode
;
653 struct channel_oil
*c_oil
;
657 struct pim_instance
*pim
;
659 qpim_scan_oil_last
= pim_time_monotonic_sec();
660 ++qpim_scan_oil_events
;
662 RB_FOREACH(vrf
, vrf_name_head
, &vrfs_by_name
)
668 if (pim_matcher
&& pim
!= pim_matcher
)
671 for (ALL_LIST_ELEMENTS(pim
->channel_oil_list
, node
, nextnode
,
674 && c_oil
->up
->rpf
.source_nexthop
.interface
) {
675 ifindex
= c_oil
->up
->rpf
.source_nexthop
677 vif_index
= pim_if_find_vifindex_by_ifindex(
679 /* Pass Current selected NH vif index to mroute
682 pim_scan_individual_oil(c_oil
,
685 pim_scan_individual_oil(c_oil
, 0);
690 static int on_rpf_cache_refresh(struct thread
*t
)
692 /* update PIM protocol state */
693 scan_upstream_rpf_cache();
695 /* update kernel multicast forwarding cache (MFC) */
698 qpim_rpf_cache_refresh_last
= pim_time_monotonic_sec();
699 ++qpim_rpf_cache_refresh_events
;
701 // It is called as part of pim_neighbor_add
706 void sched_rpf_cache_refresh(void)
708 ++qpim_rpf_cache_refresh_requests
;
710 pim_rpf_set_refresh_time();
712 if (qpim_rpf_cache_refresher
) {
713 /* Refresh timer is already running */
717 /* Start refresh timer */
719 if (PIM_DEBUG_ZEBRA
) {
720 zlog_debug("%s: triggering %ld msec timer", __PRETTY_FUNCTION__
,
721 qpim_rpf_cache_refresh_delay_msec
);
724 thread_add_timer_msec(master
, on_rpf_cache_refresh
, 0,
725 qpim_rpf_cache_refresh_delay_msec
,
726 &qpim_rpf_cache_refresher
);
729 static void pim_zebra_connected(struct zclient
*zclient
)
731 /* Send the client registration */
732 bfd_client_sendmsg(zclient
, ZEBRA_BFD_CLIENT_REGISTER
);
734 zclient_send_reg_requests(zclient
, pimg
->vrf_id
);
737 void pim_zebra_init(void)
741 /* Socket for receiving updates from Zebra daemon */
742 zclient
= zclient_new(master
);
744 zclient
->zebra_connected
= pim_zebra_connected
;
745 zclient
->router_id_update
= pim_router_id_update_zebra
;
746 zclient
->interface_add
= pim_zebra_if_add
;
747 zclient
->interface_delete
= pim_zebra_if_del
;
748 zclient
->interface_up
= pim_zebra_if_state_up
;
749 zclient
->interface_down
= pim_zebra_if_state_down
;
750 zclient
->interface_address_add
= pim_zebra_if_address_add
;
751 zclient
->interface_address_delete
= pim_zebra_if_address_del
;
752 zclient
->nexthop_update
= pim_parse_nexthop_update
;
754 zclient_init(zclient
, ZEBRA_ROUTE_PIM
, 0);
755 if (PIM_DEBUG_PIM_TRACE
) {
756 zlog_info("zclient_init cleared redistribution request");
759 zassert(zclient
->redist_default
== ZEBRA_ROUTE_PIM
);
761 /* Request all redistribution */
762 for (i
= 0; i
< ZEBRA_ROUTE_MAX
; i
++) {
763 if (i
== zclient
->redist_default
)
765 vrf_bitmap_set(zclient
->redist
[AFI_IP
][i
], pimg
->vrf_id
);
767 if (PIM_DEBUG_PIM_TRACE
) {
768 zlog_debug("%s: requesting redistribution for %s (%i)",
769 __PRETTY_FUNCTION__
, zebra_route_string(i
),
774 /* Request default information */
775 zclient_redistribute_default(ZEBRA_REDISTRIBUTE_DEFAULT_ADD
, zclient
,
778 if (PIM_DEBUG_PIM_TRACE
) {
779 zlog_info("%s: requesting default information redistribution",
780 __PRETTY_FUNCTION__
);
782 zlog_notice("%s: zclient update socket initialized",
783 __PRETTY_FUNCTION__
);
786 zclient_lookup_new();
789 void igmp_anysource_forward_start(struct pim_instance
*pim
,
790 struct igmp_group
*group
)
792 struct igmp_source
*source
;
793 struct in_addr src_addr
= {.s_addr
= 0};
794 /* Any source (*,G) is forwarded only if mode is EXCLUDE {empty} */
795 zassert(group
->group_filtermode_isexcl
);
796 zassert(listcount(group
->group_source_list
) < 1);
798 source
= source_new(group
, src_addr
);
800 zlog_warn("%s: Failure to create * source",
801 __PRETTY_FUNCTION__
);
805 igmp_source_forward_start(pim
, source
);
808 void igmp_anysource_forward_stop(struct igmp_group
*group
)
810 struct igmp_source
*source
;
811 struct in_addr star
= {.s_addr
= 0};
813 source
= igmp_find_source_by_addr(group
, star
);
815 igmp_source_forward_stop(source
);
818 static void igmp_source_forward_reevaluate_one(struct pim_instance
*pim
,
819 struct igmp_source
*source
)
822 struct igmp_group
*group
= source
->source_group
;
823 struct pim_ifchannel
*ch
;
825 if ((source
->source_addr
.s_addr
!= INADDR_ANY
)
826 || !IGMP_SOURCE_TEST_FORWARDING(source
->source_flags
))
829 memset(&sg
, 0, sizeof(struct prefix_sg
));
830 sg
.src
= source
->source_addr
;
831 sg
.grp
= group
->group_addr
;
833 ch
= pim_ifchannel_find(group
->group_igmp_sock
->interface
, &sg
);
834 if (pim_is_grp_ssm(pim
, group
->group_addr
)) {
835 /* If SSM group withdraw local membership */
837 && (ch
->local_ifmembership
== PIM_IFMEMBERSHIP_INCLUDE
)) {
838 if (PIM_DEBUG_PIM_EVENTS
)
840 "local membership del for %s as G is now SSM",
841 pim_str_sg_dump(&sg
));
842 pim_ifchannel_local_membership_del(
843 group
->group_igmp_sock
->interface
, &sg
);
846 /* If ASM group add local membership */
848 || (ch
->local_ifmembership
== PIM_IFMEMBERSHIP_NOINFO
)) {
849 if (PIM_DEBUG_PIM_EVENTS
)
851 "local membership add for %s as G is now ASM",
852 pim_str_sg_dump(&sg
));
853 pim_ifchannel_local_membership_add(
854 group
->group_igmp_sock
->interface
, &sg
);
859 void igmp_source_forward_reevaluate_all(void)
861 struct listnode
*ifnode
;
862 struct interface
*ifp
;
864 struct pim_instance
*pim
;
866 RB_FOREACH(vrf
, vrf_name_head
, &vrfs_by_name
)
872 for (ALL_LIST_ELEMENTS_RO(vrf_iflist(pim
->vrf_id
), ifnode
,
874 struct pim_interface
*pim_ifp
= ifp
->info
;
875 struct listnode
*sock_node
;
876 struct igmp_sock
*igmp
;
881 /* scan igmp sockets */
882 for (ALL_LIST_ELEMENTS_RO(pim_ifp
->igmp_socket_list
,
884 struct listnode
*grpnode
;
885 struct igmp_group
*grp
;
887 /* scan igmp groups */
888 for (ALL_LIST_ELEMENTS_RO(igmp
->igmp_group_list
,
890 struct listnode
*srcnode
;
891 struct igmp_source
*src
;
893 /* scan group sources */
894 for (ALL_LIST_ELEMENTS_RO(
895 grp
->group_source_list
,
897 igmp_source_forward_reevaluate_one(
899 } /* scan group sources */
900 } /* scan igmp groups */
901 } /* scan igmp sockets */
902 } /* scan interfaces */
906 void igmp_source_forward_start(struct pim_instance
*pim
,
907 struct igmp_source
*source
)
909 struct igmp_group
*group
;
912 int input_iface_vif_index
= 0;
914 memset(&sg
, 0, sizeof(struct prefix_sg
));
915 sg
.src
= source
->source_addr
;
916 sg
.grp
= source
->source_group
->group_addr
;
918 if (PIM_DEBUG_IGMP_TRACE
) {
920 "%s: (S,G)=%s igmp_sock=%d oif=%s fwd=%d",
921 __PRETTY_FUNCTION__
, pim_str_sg_dump(&sg
),
922 source
->source_group
->group_igmp_sock
->fd
,
923 source
->source_group
->group_igmp_sock
->interface
->name
,
924 IGMP_SOURCE_TEST_FORWARDING(source
->source_flags
));
927 /* Prevent IGMP interface from installing multicast route multiple
929 if (IGMP_SOURCE_TEST_FORWARDING(source
->source_flags
)) {
933 group
= source
->source_group
;
935 if (!source
->source_channel_oil
) {
936 struct in_addr vif_source
;
937 struct pim_interface
*pim_oif
;
938 struct prefix nht_p
, src
, grp
;
939 struct pim_nexthop_cache out_pnc
;
940 struct pim_nexthop nexthop
;
941 struct pim_upstream
*up
= NULL
;
943 if (!pim_rp_set_upstream_addr(pim
, &vif_source
,
944 source
->source_addr
, sg
.grp
))
947 /* Register addr with Zebra NHT */
948 nht_p
.family
= AF_INET
;
949 nht_p
.prefixlen
= IPV4_MAX_BITLEN
;
950 nht_p
.u
.prefix4
= vif_source
;
951 memset(&out_pnc
, 0, sizeof(struct pim_nexthop_cache
));
953 src
.family
= AF_INET
;
954 src
.prefixlen
= IPV4_MAX_BITLEN
;
955 src
.u
.prefix4
= vif_source
; // RP or Src address
956 grp
.family
= AF_INET
;
957 grp
.prefixlen
= IPV4_MAX_BITLEN
;
958 grp
.u
.prefix4
= sg
.grp
;
960 if (pim_find_or_track_nexthop(pim
, &nht_p
, NULL
, NULL
,
962 if (out_pnc
.nexthop_num
) {
963 up
= pim_upstream_find(pim
, &sg
);
964 memset(&nexthop
, 0, sizeof(nexthop
));
967 &up
->rpf
.source_nexthop
,
968 sizeof(struct pim_nexthop
));
969 pim_ecmp_nexthop_search(pim
, &out_pnc
, &nexthop
,
971 if (nexthop
.interface
)
972 input_iface_vif_index
=
973 pim_if_find_vifindex_by_ifindex(
975 nexthop
.interface
->ifindex
);
977 if (PIM_DEBUG_ZEBRA
) {
978 char buf1
[INET_ADDRSTRLEN
];
979 char buf2
[INET_ADDRSTRLEN
];
980 pim_inet4_dump("<source?>",
981 nht_p
.u
.prefix4
, buf1
,
983 pim_inet4_dump("<source?>",
987 "%s: NHT Nexthop not found for addr %s grp %s",
988 __PRETTY_FUNCTION__
, buf1
,
993 input_iface_vif_index
=
994 pim_ecmp_fib_lookup_if_vif_index(
995 pim
, vif_source
, &src
, &grp
);
997 if (PIM_DEBUG_ZEBRA
) {
998 char buf2
[INET_ADDRSTRLEN
];
999 pim_inet4_dump("<source?>", vif_source
, buf2
,
1001 zlog_debug("%s: NHT %s vif_source %s vif_index:%d ",
1002 __PRETTY_FUNCTION__
, pim_str_sg_dump(&sg
),
1003 buf2
, input_iface_vif_index
);
1006 if (input_iface_vif_index
< 1) {
1007 if (PIM_DEBUG_IGMP_TRACE
) {
1008 char source_str
[INET_ADDRSTRLEN
];
1009 pim_inet4_dump("<source?>", source
->source_addr
,
1010 source_str
, sizeof(source_str
));
1012 "%s %s: could not find input interface for source %s",
1013 __FILE__
, __PRETTY_FUNCTION__
,
1020 Protect IGMP against adding looped MFC entries created by both
1021 source and receiver attached to the same interface. See TODO
1025 source
->source_group
->group_igmp_sock
->interface
->info
;
1027 if (PIM_DEBUG_IGMP_TRACE
) {
1029 "%s: multicast not enabled on oif=%s ?",
1030 __PRETTY_FUNCTION__
,
1031 source
->source_group
->group_igmp_sock
1037 if (input_iface_vif_index
== pim_oif
->mroute_vif_index
) {
1038 /* ignore request for looped MFC entry */
1039 if (PIM_DEBUG_IGMP_TRACE
) {
1041 "%s: ignoring request for looped MFC entry (S,G)=%s: igmp_sock=%d oif=%s vif_index=%d",
1042 __PRETTY_FUNCTION__
,
1043 pim_str_sg_dump(&sg
),
1044 source
->source_group
->group_igmp_sock
1046 source
->source_group
->group_igmp_sock
1048 input_iface_vif_index
);
1053 source
->source_channel_oil
=
1054 pim_channel_oil_add(pim
, &sg
, input_iface_vif_index
);
1055 if (!source
->source_channel_oil
) {
1056 if (PIM_DEBUG_IGMP_TRACE
) {
1058 "%s %s: could not create OIL for channel (S,G)=%s",
1059 __FILE__
, __PRETTY_FUNCTION__
,
1060 pim_str_sg_dump(&sg
));
1066 result
= pim_channel_add_oif(source
->source_channel_oil
,
1067 group
->group_igmp_sock
->interface
,
1068 PIM_OIF_FLAG_PROTO_IGMP
);
1070 if (PIM_DEBUG_MROUTE
) {
1071 zlog_warn("%s: add_oif() failed with return=%d",
1078 Feed IGMPv3-gathered local membership information into PIM
1079 per-interface (S,G) state.
1081 if (!pim_ifchannel_local_membership_add(
1082 group
->group_igmp_sock
->interface
, &sg
)) {
1083 if (PIM_DEBUG_MROUTE
)
1084 zlog_warn("%s: Failure to add local membership for %s",
1085 __PRETTY_FUNCTION__
, pim_str_sg_dump(&sg
));
1089 IGMP_SOURCE_DO_FORWARDING(source
->source_flags
);
1093 igmp_source_forward_stop: stop fowarding, but keep the source
1094 igmp_source_delete: stop fowarding, and delete the source
1096 void igmp_source_forward_stop(struct igmp_source
*source
)
1098 struct igmp_group
*group
;
1099 struct prefix_sg sg
;
1102 memset(&sg
, 0, sizeof(struct prefix_sg
));
1103 sg
.src
= source
->source_addr
;
1104 sg
.grp
= source
->source_group
->group_addr
;
1106 if (PIM_DEBUG_IGMP_TRACE
) {
1108 "%s: (S,G)=%s igmp_sock=%d oif=%s fwd=%d",
1109 __PRETTY_FUNCTION__
, pim_str_sg_dump(&sg
),
1110 source
->source_group
->group_igmp_sock
->fd
,
1111 source
->source_group
->group_igmp_sock
->interface
->name
,
1112 IGMP_SOURCE_TEST_FORWARDING(source
->source_flags
));
1115 /* Prevent IGMP interface from removing multicast route multiple
1117 if (!IGMP_SOURCE_TEST_FORWARDING(source
->source_flags
)) {
1121 group
= source
->source_group
;
1124 It appears that in certain circumstances that
1125 igmp_source_forward_stop is called when IGMP forwarding
1126 was not enabled in oif_flags for this outgoing interface.
1127 Possibly because of multiple calls. When that happens, we
1128 enter the below if statement and this function returns early
1129 which in turn triggers the calling function to assert.
1130 Making the call to pim_channel_del_oif and ignoring the return code
1131 fixes the issue without ill effect, similar to
1132 pim_forward_stop below.
1134 result
= pim_channel_del_oif(source
->source_channel_oil
,
1135 group
->group_igmp_sock
->interface
,
1136 PIM_OIF_FLAG_PROTO_IGMP
);
1138 if (PIM_DEBUG_IGMP_TRACE
)
1140 "%s: pim_channel_del_oif() failed with return=%d",
1146 Feed IGMPv3-gathered local membership information into PIM
1147 per-interface (S,G) state.
1149 pim_ifchannel_local_membership_del(group
->group_igmp_sock
->interface
,
1152 IGMP_SOURCE_DONT_FORWARDING(source
->source_flags
);
1155 void pim_forward_start(struct pim_ifchannel
*ch
)
1157 struct pim_upstream
*up
= ch
->upstream
;
1158 uint32_t mask
= PIM_OIF_FLAG_PROTO_PIM
;
1159 int input_iface_vif_index
= 0;
1160 struct pim_instance
*pim
;
1161 struct pim_interface
*pim_ifp
;
1163 pim_ifp
= ch
->interface
->info
;
1166 if (PIM_DEBUG_PIM_TRACE
) {
1167 char source_str
[INET_ADDRSTRLEN
];
1168 char group_str
[INET_ADDRSTRLEN
];
1169 char upstream_str
[INET_ADDRSTRLEN
];
1171 pim_inet4_dump("<source?>", ch
->sg
.src
, source_str
,
1172 sizeof(source_str
));
1173 pim_inet4_dump("<group?>", ch
->sg
.grp
, group_str
,
1175 pim_inet4_dump("<upstream?>", up
->upstream_addr
, upstream_str
,
1176 sizeof(upstream_str
));
1177 zlog_debug("%s: (S,G)=(%s,%s) oif=%s (%s)", __PRETTY_FUNCTION__
,
1178 source_str
, group_str
, ch
->interface
->name
,
1182 /* Resolve IIF for upstream as mroute_del sets mfcc_parent to MAXVIFS,
1183 as part of mroute_del called by pim_forward_stop.
1185 if (!up
->channel_oil
1187 && up
->channel_oil
->oil
.mfcc_parent
>= MAXVIFS
)) {
1188 struct prefix nht_p
, src
, grp
;
1189 struct pim_nexthop_cache out_pnc
;
1191 /* Register addr with Zebra NHT */
1192 nht_p
.family
= AF_INET
;
1193 nht_p
.prefixlen
= IPV4_MAX_BITLEN
;
1194 nht_p
.u
.prefix4
.s_addr
= up
->upstream_addr
.s_addr
;
1195 grp
.family
= AF_INET
;
1196 grp
.prefixlen
= IPV4_MAX_BITLEN
;
1197 grp
.u
.prefix4
= up
->sg
.grp
;
1198 memset(&out_pnc
, 0, sizeof(struct pim_nexthop_cache
));
1200 if (pim_find_or_track_nexthop(pim
, &nht_p
, NULL
, NULL
,
1202 if (out_pnc
.nexthop_num
) {
1203 src
.family
= AF_INET
;
1204 src
.prefixlen
= IPV4_MAX_BITLEN
;
1206 up
->upstream_addr
; // RP or Src address
1207 grp
.family
= AF_INET
;
1208 grp
.prefixlen
= IPV4_MAX_BITLEN
;
1209 grp
.u
.prefix4
= up
->sg
.grp
;
1210 // Compute PIM RPF using Cached nexthop
1211 if (pim_ecmp_nexthop_search(
1213 &up
->rpf
.source_nexthop
, &src
, &grp
,
1215 input_iface_vif_index
=
1216 pim_if_find_vifindex_by_ifindex(
1218 up
->rpf
.source_nexthop
1219 .interface
->ifindex
);
1221 if (PIM_DEBUG_TRACE
)
1223 "%s: Nexthop selection failed for %s ",
1224 __PRETTY_FUNCTION__
,
1228 if (PIM_DEBUG_ZEBRA
) {
1229 char buf1
[INET_ADDRSTRLEN
];
1230 char buf2
[INET_ADDRSTRLEN
];
1231 pim_inet4_dump("<source?>",
1232 nht_p
.u
.prefix4
, buf1
,
1234 pim_inet4_dump("<source?>",
1235 grp
.u
.prefix4
, buf2
,
1238 "%s: NHT pnc is NULL for addr %s grp %s",
1239 __PRETTY_FUNCTION__
, buf1
,
1244 input_iface_vif_index
=
1245 pim_ecmp_fib_lookup_if_vif_index(
1246 pim
, up
->upstream_addr
, &src
, &grp
);
1248 if (input_iface_vif_index
< 1) {
1249 if (PIM_DEBUG_PIM_TRACE
) {
1250 char source_str
[INET_ADDRSTRLEN
];
1251 pim_inet4_dump("<source?>", up
->sg
.src
,
1252 source_str
, sizeof(source_str
));
1254 "%s %s: could not find input interface for source %s",
1255 __FILE__
, __PRETTY_FUNCTION__
,
1260 if (PIM_DEBUG_TRACE
) {
1261 struct interface
*in_intf
= pim_if_find_by_vif_index(
1262 pim
, input_iface_vif_index
);
1264 "%s: Update channel_oil IIF %s VIFI %d entry %s ",
1265 __PRETTY_FUNCTION__
,
1266 in_intf
? in_intf
->name
: "NIL",
1267 input_iface_vif_index
, up
->sg_str
);
1269 up
->channel_oil
= pim_channel_oil_add(pim
, &up
->sg
,
1270 input_iface_vif_index
);
1271 if (!up
->channel_oil
) {
1272 if (PIM_DEBUG_PIM_TRACE
)
1274 "%s %s: could not create OIL for channel (S,G)=%s",
1275 __FILE__
, __PRETTY_FUNCTION__
,
1281 if (up
->flags
& PIM_UPSTREAM_FLAG_MASK_SRC_IGMP
)
1282 mask
= PIM_OIF_FLAG_PROTO_IGMP
;
1284 pim_channel_add_oif(up
->channel_oil
, ch
->interface
, mask
);
1287 void pim_forward_stop(struct pim_ifchannel
*ch
)
1289 struct pim_upstream
*up
= ch
->upstream
;
1291 if (PIM_DEBUG_PIM_TRACE
) {
1292 zlog_debug("%s: (S,G)=%s oif=%s", __PRETTY_FUNCTION__
,
1293 ch
->sg_str
, ch
->interface
->name
);
1296 pim_channel_del_oif(up
->channel_oil
, ch
->interface
,
1297 PIM_OIF_FLAG_PROTO_PIM
);
1300 void pim_zebra_zclient_update(struct vty
*vty
)
1302 vty_out(vty
, "Zclient update socket: ");
1305 vty_out(vty
, "%d failures=%d\n", zclient
->sock
, zclient
->fail
);
1307 vty_out(vty
, "<null zclient>\n");
1311 struct zclient
*pim_zebra_zclient_get(void)