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
;
72 struct pim_instance
*pim
;
75 zebra api adds/dels interfaces using the same call
76 interface_add_read below, see comments in lib/zclient.c
78 ifp
= zebra_interface_add_read(zclient
->ibuf
, vrf_id
);
82 pim
= pim_get_pim_instance(vrf_id
);
83 if (PIM_DEBUG_ZEBRA
) {
85 "%s: %s index %d(%u) flags %ld metric %d mtu %d operative %d",
86 __PRETTY_FUNCTION__
, ifp
->name
, ifp
->ifindex
, vrf_id
,
87 (long)ifp
->flags
, ifp
->metric
, ifp
->mtu
,
88 if_is_operative(ifp
));
91 if (if_is_operative(ifp
)) {
92 struct pim_interface
*pim_ifp
;
96 * If we have a pim_ifp already and this is an if_add
97 * that means that we probably have a vrf move event
98 * If that is the case, set the proper vrfness.
102 pim_if_addr_add_all(ifp
);
106 * If we are a vrf device that is up, open up the pim_socket for
108 * to incoming pim messages irrelevant if the user has configured us
111 if (pim_if_is_vrf_device(ifp
)) {
112 struct pim_interface
*pim_ifp
;
115 pim_ifp
= pim_if_new(ifp
, 0, 0);
125 static int pim_zebra_if_del(int command
, struct zclient
*zclient
,
126 zebra_size_t length
, vrf_id_t vrf_id
)
128 struct interface
*ifp
;
131 zebra api adds/dels interfaces using the same call
132 interface_add_read below, see comments in lib/zclient.c
134 comments in lib/zclient.c seem to indicate that calling
135 zebra_interface_add_read is the correct call, but that
136 results in an attemted out of bounds read which causes
137 pimd to assert. Other clients use zebra_interface_state_read
138 and it appears to work just fine.
140 ifp
= zebra_interface_state_read(zclient
->ibuf
, vrf_id
);
144 if (PIM_DEBUG_ZEBRA
) {
146 "%s: %s index %d(%u) flags %ld metric %d mtu %d operative %d",
147 __PRETTY_FUNCTION__
, ifp
->name
, ifp
->ifindex
, vrf_id
,
148 (long)ifp
->flags
, ifp
->metric
, ifp
->mtu
,
149 if_is_operative(ifp
));
152 if (!if_is_operative(ifp
))
153 pim_if_addr_del_all(ifp
);
158 static int pim_zebra_if_state_up(int command
, struct zclient
*zclient
,
159 zebra_size_t length
, vrf_id_t vrf_id
)
161 struct pim_instance
*pim
;
162 struct interface
*ifp
;
166 zebra api notifies interface up/down events by using the same call
167 zebra_interface_state_read below, see comments in lib/zclient.c
169 ifp
= zebra_interface_state_read(zclient
->ibuf
, vrf_id
);
173 if (PIM_DEBUG_ZEBRA
) {
175 "%s: %s index %d(%u) flags %ld metric %d mtu %d operative %d",
176 __PRETTY_FUNCTION__
, ifp
->name
, ifp
->ifindex
, vrf_id
,
177 (long)ifp
->flags
, ifp
->metric
, ifp
->mtu
,
178 if_is_operative(ifp
));
181 pim
= pim_get_pim_instance(vrf_id
);
182 if (if_is_operative(ifp
)) {
183 struct pim_interface
*pim_ifp
;
187 * If we have a pim_ifp already and this is an if_add
188 * that means that we probably have a vrf move event
189 * If that is the case, set the proper vrfness.
195 pim_if_addr_add_all() suffices for bringing up both IGMP and
198 pim_if_addr_add_all(ifp
);
202 * If we have a pimreg device callback and it's for a specific
203 * table set the master appropriately
205 if (sscanf(ifp
->name
, "pimreg%" SCNu32
, &table_id
) == 1) {
207 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
208 if ((table_id
== vrf
->data
.l
.table_id
)
209 && (ifp
->vrf_id
!= vrf
->vrf_id
)) {
210 struct interface
*master
= if_lookup_by_name(
211 vrf
->name
, vrf
->vrf_id
);
215 "%s: Unable to find Master interface for %s",
216 __PRETTY_FUNCTION__
, vrf
->name
);
219 zclient_interface_set_master(zclient
, master
,
227 static int pim_zebra_if_state_down(int command
, struct zclient
*zclient
,
228 zebra_size_t length
, vrf_id_t vrf_id
)
230 struct interface
*ifp
;
233 zebra api notifies interface up/down events by using the same call
234 zebra_interface_state_read below, see comments in lib/zclient.c
236 ifp
= zebra_interface_state_read(zclient
->ibuf
, vrf_id
);
240 if (PIM_DEBUG_ZEBRA
) {
242 "%s: %s index %d(%u) flags %ld metric %d mtu %d operative %d",
243 __PRETTY_FUNCTION__
, ifp
->name
, ifp
->ifindex
, vrf_id
,
244 (long)ifp
->flags
, ifp
->metric
, ifp
->mtu
,
245 if_is_operative(ifp
));
248 if (!if_is_operative(ifp
)) {
249 pim_ifchannel_delete_all(ifp
);
251 pim_if_addr_del_all() suffices for shutting down IGMP,
252 but not for shutting down PIM
254 pim_if_addr_del_all(ifp
);
257 pim_sock_delete() closes the socket, stops read and timer
259 and kills all neighbors.
262 pim_sock_delete(ifp
, "link down");
272 #ifdef PIM_DEBUG_IFADDR_DUMP
273 static void dump_if_address(struct interface
*ifp
)
275 struct connected
*ifc
;
276 struct listnode
*node
;
278 zlog_debug("%s %s: interface %s addresses:", __FILE__
,
279 __PRETTY_FUNCTION__
, ifp
->name
);
281 for (ALL_LIST_ELEMENTS_RO(ifp
->connected
, node
, ifc
)) {
282 struct prefix
*p
= ifc
->address
;
284 if (p
->family
!= AF_INET
)
287 zlog_debug("%s %s: interface %s address %s %s", __FILE__
,
288 __PRETTY_FUNCTION__
, ifp
->name
,
289 inet_ntoa(p
->u
.prefix4
),
290 CHECK_FLAG(ifc
->flags
, ZEBRA_IFA_SECONDARY
)
297 static int pim_zebra_if_address_add(int command
, struct zclient
*zclient
,
298 zebra_size_t length
, vrf_id_t vrf_id
)
302 struct pim_interface
*pim_ifp
;
303 struct pim_instance
*pim
;
306 zebra api notifies address adds/dels events by using the same call
307 interface_add_read below, see comments in lib/zclient.c
309 zebra_interface_address_read(ZEBRA_INTERFACE_ADDRESS_ADD, ...)
310 will add address to interface list by calling
311 connected_add_by_prefix()
313 c
= zebra_interface_address_read(command
, zclient
->ibuf
, vrf_id
);
317 pim_ifp
= c
->ifp
->info
;
320 if (PIM_DEBUG_ZEBRA
) {
322 prefix2str(p
, buf
, BUFSIZ
);
323 zlog_debug("%s: %s(%u) connected IP address %s flags %u %s",
324 __PRETTY_FUNCTION__
, c
->ifp
->name
, vrf_id
, buf
,
326 CHECK_FLAG(c
->flags
, ZEBRA_IFA_SECONDARY
)
330 #ifdef PIM_DEBUG_IFADDR_DUMP
331 dump_if_address(c
->ifp
);
335 if (!CHECK_FLAG(c
->flags
, ZEBRA_IFA_SECONDARY
)) {
336 /* trying to add primary address */
338 struct in_addr primary_addr
= pim_find_primary_addr(c
->ifp
);
339 if (p
->family
!= AF_INET
340 || primary_addr
.s_addr
!= p
->u
.prefix4
.s_addr
) {
341 if (PIM_DEBUG_ZEBRA
) {
342 /* but we had a primary address already */
346 prefix2str(p
, buf
, BUFSIZ
);
349 "%s: %s : forcing secondary flag on %s",
350 __PRETTY_FUNCTION__
, c
->ifp
->name
, buf
);
352 SET_FLAG(c
->flags
, ZEBRA_IFA_SECONDARY
);
358 pim
= pim_get_pim_instance(vrf_id
);
361 pim_rp_check_on_if_add(pim_ifp
);
364 if (if_is_loopback(c
->ifp
)) {
365 struct vrf
*vrf
= vrf_lookup_by_id(VRF_DEFAULT
);
366 struct interface
*ifp
;
368 FOR_ALL_INTERFACES (vrf
, ifp
) {
369 if (!if_is_loopback(ifp
) && if_is_operative(ifp
))
370 pim_if_addr_add_all(ifp
);
377 static int pim_zebra_if_address_del(int command
, struct zclient
*client
,
378 zebra_size_t length
, vrf_id_t vrf_id
)
382 struct vrf
*vrf
= vrf_lookup_by_id(vrf_id
);
383 struct pim_instance
*pim
;
390 zebra api notifies address adds/dels events by using the same call
391 interface_add_read below, see comments in lib/zclient.c
393 zebra_interface_address_read(ZEBRA_INTERFACE_ADDRESS_DELETE, ...)
394 will remove address from interface list by calling
395 connected_delete_by_prefix()
397 c
= zebra_interface_address_read(command
, client
->ibuf
, vrf_id
);
402 if (p
->family
== AF_INET
) {
403 if (PIM_DEBUG_ZEBRA
) {
405 prefix2str(p
, buf
, BUFSIZ
);
407 "%s: %s(%u) disconnected IP address %s flags %u %s",
408 __PRETTY_FUNCTION__
, c
->ifp
->name
, vrf_id
, buf
,
410 CHECK_FLAG(c
->flags
, ZEBRA_IFA_SECONDARY
)
414 #ifdef PIM_DEBUG_IFADDR_DUMP
415 dump_if_address(c
->ifp
);
419 pim_if_addr_del(c
, 0);
421 pim_i_am_rp_re_evaluate(pim
);
428 static void scan_upstream_rpf_cache(struct pim_instance
*pim
)
430 struct listnode
*up_node
;
431 struct listnode
*up_nextnode
;
432 struct listnode
*node
;
433 struct pim_upstream
*up
;
434 struct interface
*ifp
;
436 for (ALL_LIST_ELEMENTS(pim
->upstream_list
, up_node
, up_nextnode
, up
)) {
437 enum pim_rpf_result rpf_result
;
441 nht_p
.family
= AF_INET
;
442 nht_p
.prefixlen
= IPV4_MAX_BITLEN
;
443 nht_p
.u
.prefix4
.s_addr
= up
->upstream_addr
.s_addr
;
444 pim_resolve_upstream_nh(pim
, &nht_p
);
446 old
.source_nexthop
.interface
= up
->rpf
.source_nexthop
.interface
;
447 old
.source_nexthop
.nbr
= up
->rpf
.source_nexthop
.nbr
;
448 rpf_result
= pim_rpf_update(pim
, up
, &old
, 0);
450 if (rpf_result
== PIM_RPF_FAILURE
)
453 if (rpf_result
== PIM_RPF_CHANGED
) {
454 struct pim_neighbor
*nbr
;
456 nbr
= pim_neighbor_find(old
.source_nexthop
.interface
,
457 old
.rpf_addr
.u
.prefix4
);
459 pim_jp_agg_remove_group(nbr
->upstream_jp_agg
,
463 * We have detected a case where we might need
465 * the inherited o_list so do it.
467 if (up
->channel_oil
->oil_inherited_rescan
) {
468 pim_upstream_inherited_olist_decide(pim
, up
);
469 up
->channel_oil
->oil_inherited_rescan
= 0;
472 if (up
->join_state
== PIM_UPSTREAM_JOINED
) {
474 * If we come up real fast we can be here
475 * where the mroute has not been installed
478 if (!up
->channel_oil
->installed
)
479 pim_mroute_add(up
->channel_oil
,
480 __PRETTY_FUNCTION__
);
483 * RFC 4601: 4.5.7. Sending (S,G)
484 * Join/Prune Messages
486 * Transitions from Joined State
488 * RPF'(S,G) changes not due to an Assert
490 * The upstream (S,G) state machine remains
491 * in Joined state. Send Join(S,G) to the new
492 * upstream neighbor, which is the new value
493 * of RPF'(S,G). Send Prune(S,G) to the old
494 * upstream neighbor, which is the old value
495 * of RPF'(S,G). Set the Join Timer (JT) to
496 * expire after t_periodic seconds.
498 pim_jp_agg_switch_interface(&old
, &up
->rpf
, up
);
500 pim_upstream_join_timer_restart(up
, &old
);
501 } /* up->join_state == PIM_UPSTREAM_JOINED */
503 /* FIXME can join_desired actually be changed by
505 returning PIM_RPF_CHANGED ? */
506 pim_upstream_update_join_desired(pim
, up
);
508 } /* PIM_RPF_CHANGED */
510 } /* for (qpim_upstream_list) */
512 FOR_ALL_INTERFACES (pim
->vrf
, ifp
)
514 struct pim_interface
*pim_ifp
= ifp
->info
;
515 struct pim_iface_upstream_switch
*us
;
517 for (ALL_LIST_ELEMENTS_RO(pim_ifp
->upstream_switch_list
,
521 rpf
.source_nexthop
.interface
= ifp
;
522 rpf
.rpf_addr
.u
.prefix4
= us
->address
;
523 pim_joinprune_send(&rpf
, us
->us
);
524 pim_jp_agg_clear_group(us
->us
);
529 void pim_scan_individual_oil(struct channel_oil
*c_oil
, int in_vif_index
)
531 struct in_addr vif_source
;
532 int input_iface_vif_index
;
535 if (!pim_rp_set_upstream_addr(c_oil
->pim
, &vif_source
,
536 c_oil
->oil
.mfcc_origin
,
537 c_oil
->oil
.mfcc_mcastgrp
))
541 input_iface_vif_index
= in_vif_index
;
543 struct prefix src
, grp
;
545 src
.family
= AF_INET
;
546 src
.prefixlen
= IPV4_MAX_BITLEN
;
547 src
.u
.prefix4
= vif_source
;
548 grp
.family
= AF_INET
;
549 grp
.prefixlen
= IPV4_MAX_BITLEN
;
550 grp
.u
.prefix4
= c_oil
->oil
.mfcc_mcastgrp
;
552 if (PIM_DEBUG_ZEBRA
) {
553 char source_str
[INET_ADDRSTRLEN
];
554 char group_str
[INET_ADDRSTRLEN
];
555 pim_inet4_dump("<source?>", c_oil
->oil
.mfcc_origin
,
556 source_str
, sizeof(source_str
));
557 pim_inet4_dump("<group?>", c_oil
->oil
.mfcc_mcastgrp
,
558 group_str
, sizeof(group_str
));
560 "%s: channel_oil (%s,%s) upstream info is not present.",
561 __PRETTY_FUNCTION__
, source_str
, group_str
);
563 input_iface_vif_index
= pim_ecmp_fib_lookup_if_vif_index(
564 c_oil
->pim
, vif_source
, &src
, &grp
);
567 if (input_iface_vif_index
< 1) {
568 if (PIM_DEBUG_ZEBRA
) {
569 char source_str
[INET_ADDRSTRLEN
];
570 char group_str
[INET_ADDRSTRLEN
];
571 pim_inet4_dump("<source?>", c_oil
->oil
.mfcc_origin
,
572 source_str
, sizeof(source_str
));
573 pim_inet4_dump("<group?>", c_oil
->oil
.mfcc_mcastgrp
,
574 group_str
, sizeof(group_str
));
576 "%s %s: could not find input interface(%d) for (S,G)=(%s,%s)",
577 __FILE__
, __PRETTY_FUNCTION__
,
578 c_oil
->oil
.mfcc_parent
, source_str
, group_str
);
580 pim_mroute_del(c_oil
, __PRETTY_FUNCTION__
);
584 if (input_iface_vif_index
== c_oil
->oil
.mfcc_parent
) {
585 if (!c_oil
->installed
)
586 pim_mroute_add(c_oil
, __PRETTY_FUNCTION__
);
592 if (PIM_DEBUG_ZEBRA
) {
593 struct interface
*old_iif
= pim_if_find_by_vif_index(
594 c_oil
->pim
, c_oil
->oil
.mfcc_parent
);
595 struct interface
*new_iif
= pim_if_find_by_vif_index(
596 c_oil
->pim
, input_iface_vif_index
);
597 char source_str
[INET_ADDRSTRLEN
];
598 char group_str
[INET_ADDRSTRLEN
];
599 pim_inet4_dump("<source?>", c_oil
->oil
.mfcc_origin
, source_str
,
601 pim_inet4_dump("<group?>", c_oil
->oil
.mfcc_mcastgrp
, group_str
,
604 "%s %s: (S,G)=(%s,%s) input interface changed from %s vif_index=%d to %s vif_index=%d",
605 __FILE__
, __PRETTY_FUNCTION__
, source_str
, group_str
,
606 (old_iif
) ? old_iif
->name
: "<old_iif?>",
607 c_oil
->oil
.mfcc_parent
,
608 (new_iif
) ? new_iif
->name
: "<new_iif?>",
609 input_iface_vif_index
);
612 /* new iif loops to existing oif ? */
613 if (c_oil
->oil
.mfcc_ttls
[input_iface_vif_index
]) {
614 struct interface
*new_iif
= pim_if_find_by_vif_index(
615 c_oil
->pim
, input_iface_vif_index
);
617 if (PIM_DEBUG_ZEBRA
) {
618 char source_str
[INET_ADDRSTRLEN
];
619 char group_str
[INET_ADDRSTRLEN
];
620 pim_inet4_dump("<source?>", c_oil
->oil
.mfcc_origin
,
621 source_str
, sizeof(source_str
));
622 pim_inet4_dump("<group?>", c_oil
->oil
.mfcc_mcastgrp
,
623 group_str
, sizeof(group_str
));
625 "%s %s: (S,G)=(%s,%s) new iif loops to existing oif: %s vif_index=%d",
626 __FILE__
, __PRETTY_FUNCTION__
, source_str
,
628 (new_iif
) ? new_iif
->name
: "<new_iif?>",
629 input_iface_vif_index
);
633 /* update iif vif_index */
634 old_vif_index
= c_oil
->oil
.mfcc_parent
;
635 c_oil
->oil
.mfcc_parent
= input_iface_vif_index
;
637 /* update kernel multicast forwarding cache (MFC) */
638 if (pim_mroute_add(c_oil
, __PRETTY_FUNCTION__
)) {
639 if (PIM_DEBUG_MROUTE
) {
640 /* just log warning */
641 struct interface
*old_iif
= pim_if_find_by_vif_index(
642 c_oil
->pim
, old_vif_index
);
643 struct interface
*new_iif
= pim_if_find_by_vif_index(
644 c_oil
->pim
, input_iface_vif_index
);
645 char source_str
[INET_ADDRSTRLEN
];
646 char group_str
[INET_ADDRSTRLEN
];
647 pim_inet4_dump("<source?>", c_oil
->oil
.mfcc_origin
,
648 source_str
, sizeof(source_str
));
649 pim_inet4_dump("<group?>", c_oil
->oil
.mfcc_mcastgrp
,
650 group_str
, sizeof(group_str
));
652 "%s %s: (S,G)=(%s,%s) failure updating input interface from %s vif_index=%d to %s vif_index=%d",
653 __FILE__
, __PRETTY_FUNCTION__
, source_str
,
655 old_iif
? old_iif
->name
: "<old_iif?>",
656 c_oil
->oil
.mfcc_parent
,
657 new_iif
? new_iif
->name
: "<new_iif?>",
658 input_iface_vif_index
);
663 void pim_scan_oil(struct pim_instance
*pim
)
665 struct listnode
*node
;
666 struct listnode
*nextnode
;
667 struct channel_oil
*c_oil
;
671 pim
->scan_oil_last
= pim_time_monotonic_sec();
672 ++pim
->scan_oil_events
;
674 for (ALL_LIST_ELEMENTS(pim
->channel_oil_list
, node
, nextnode
, c_oil
)) {
675 if (c_oil
->up
&& c_oil
->up
->rpf
.source_nexthop
.interface
) {
676 ifindex
= c_oil
->up
->rpf
.source_nexthop
679 pim_if_find_vifindex_by_ifindex(pim
, ifindex
);
680 /* Pass Current selected NH vif index to mroute
683 pim_scan_individual_oil(c_oil
, vif_index
);
685 pim_scan_individual_oil(c_oil
, 0);
689 static int on_rpf_cache_refresh(struct thread
*t
)
691 struct pim_instance
*pim
= THREAD_ARG(t
);
693 /* update PIM protocol state */
694 scan_upstream_rpf_cache(pim
);
696 /* update kernel multicast forwarding cache (MFC) */
699 pim
->rpf_cache_refresh_last
= pim_time_monotonic_sec();
700 ++pim
->rpf_cache_refresh_events
;
702 // It is called as part of pim_neighbor_add
707 void sched_rpf_cache_refresh(struct pim_instance
*pim
)
709 ++pim
->rpf_cache_refresh_requests
;
711 pim_rpf_set_refresh_time(pim
);
713 if (pim
->rpf_cache_refresher
) {
714 /* Refresh timer is already running */
718 /* Start refresh timer */
720 if (PIM_DEBUG_ZEBRA
) {
721 zlog_debug("%s: triggering %ld msec timer", __PRETTY_FUNCTION__
,
722 qpim_rpf_cache_refresh_delay_msec
);
725 thread_add_timer_msec(master
, on_rpf_cache_refresh
, pim
,
726 qpim_rpf_cache_refresh_delay_msec
,
727 &pim
->rpf_cache_refresher
);
730 static void pim_zebra_connected(struct zclient
*zclient
)
732 /* Send the client registration */
733 bfd_client_sendmsg(zclient
, ZEBRA_BFD_CLIENT_REGISTER
);
735 zclient_send_reg_requests(zclient
, pimg
->vrf_id
);
738 void pim_zebra_init(void)
740 /* Socket for receiving updates from Zebra daemon */
741 zclient
= zclient_new_notify(master
, &zclient_options_default
);
743 zclient
->zebra_connected
= pim_zebra_connected
;
744 zclient
->router_id_update
= pim_router_id_update_zebra
;
745 zclient
->interface_add
= pim_zebra_if_add
;
746 zclient
->interface_delete
= pim_zebra_if_del
;
747 zclient
->interface_up
= pim_zebra_if_state_up
;
748 zclient
->interface_down
= pim_zebra_if_state_down
;
749 zclient
->interface_address_add
= pim_zebra_if_address_add
;
750 zclient
->interface_address_delete
= pim_zebra_if_address_del
;
751 zclient
->nexthop_update
= pim_parse_nexthop_update
;
753 zclient_init(zclient
, ZEBRA_ROUTE_PIM
, 0, &pimd_privs
);
754 if (PIM_DEBUG_PIM_TRACE
) {
755 zlog_notice("%s: zclient socket initialized",
756 __PRETTY_FUNCTION__
);
759 zclient_lookup_new();
762 void igmp_anysource_forward_start(struct pim_instance
*pim
,
763 struct igmp_group
*group
)
765 struct igmp_source
*source
;
766 struct in_addr src_addr
= {.s_addr
= 0};
767 /* Any source (*,G) is forwarded only if mode is EXCLUDE {empty} */
768 zassert(group
->group_filtermode_isexcl
);
769 zassert(listcount(group
->group_source_list
) < 1);
771 source
= source_new(group
, src_addr
);
773 zlog_warn("%s: Failure to create * source",
774 __PRETTY_FUNCTION__
);
778 igmp_source_forward_start(pim
, source
);
781 void igmp_anysource_forward_stop(struct igmp_group
*group
)
783 struct igmp_source
*source
;
784 struct in_addr star
= {.s_addr
= 0};
786 source
= igmp_find_source_by_addr(group
, star
);
788 igmp_source_forward_stop(source
);
791 static void igmp_source_forward_reevaluate_one(struct pim_instance
*pim
,
792 struct igmp_source
*source
)
795 struct igmp_group
*group
= source
->source_group
;
796 struct pim_ifchannel
*ch
;
798 if ((source
->source_addr
.s_addr
!= INADDR_ANY
)
799 || !IGMP_SOURCE_TEST_FORWARDING(source
->source_flags
))
802 memset(&sg
, 0, sizeof(struct prefix_sg
));
803 sg
.src
= source
->source_addr
;
804 sg
.grp
= group
->group_addr
;
806 ch
= pim_ifchannel_find(group
->group_igmp_sock
->interface
, &sg
);
807 if (pim_is_grp_ssm(pim
, group
->group_addr
)) {
808 /* If SSM group withdraw local membership */
810 && (ch
->local_ifmembership
== PIM_IFMEMBERSHIP_INCLUDE
)) {
811 if (PIM_DEBUG_PIM_EVENTS
)
813 "local membership del for %s as G is now SSM",
814 pim_str_sg_dump(&sg
));
815 pim_ifchannel_local_membership_del(
816 group
->group_igmp_sock
->interface
, &sg
);
819 /* If ASM group add local membership */
821 || (ch
->local_ifmembership
== PIM_IFMEMBERSHIP_NOINFO
)) {
822 if (PIM_DEBUG_PIM_EVENTS
)
824 "local membership add for %s as G is now ASM",
825 pim_str_sg_dump(&sg
));
826 pim_ifchannel_local_membership_add(
827 group
->group_igmp_sock
->interface
, &sg
);
832 void igmp_source_forward_reevaluate_all(struct pim_instance
*pim
)
834 struct interface
*ifp
;
836 FOR_ALL_INTERFACES (pim
->vrf
, ifp
) {
837 struct pim_interface
*pim_ifp
= ifp
->info
;
838 struct listnode
*sock_node
;
839 struct igmp_sock
*igmp
;
844 /* scan igmp sockets */
845 for (ALL_LIST_ELEMENTS_RO(pim_ifp
->igmp_socket_list
, sock_node
,
847 struct listnode
*grpnode
;
848 struct igmp_group
*grp
;
850 /* scan igmp groups */
851 for (ALL_LIST_ELEMENTS_RO(igmp
->igmp_group_list
,
853 struct listnode
*srcnode
;
854 struct igmp_source
*src
;
856 /* scan group sources */
857 for (ALL_LIST_ELEMENTS_RO(
858 grp
->group_source_list
, srcnode
,
860 igmp_source_forward_reevaluate_one(pim
,
862 } /* scan group sources */
863 } /* scan igmp groups */
864 } /* scan igmp sockets */
865 } /* scan interfaces */
868 void igmp_source_forward_start(struct pim_instance
*pim
,
869 struct igmp_source
*source
)
871 struct igmp_group
*group
;
874 int input_iface_vif_index
= 0;
876 memset(&sg
, 0, sizeof(struct prefix_sg
));
877 sg
.src
= source
->source_addr
;
878 sg
.grp
= source
->source_group
->group_addr
;
880 if (PIM_DEBUG_IGMP_TRACE
) {
882 "%s: (S,G)=%s igmp_sock=%d oif=%s fwd=%d",
883 __PRETTY_FUNCTION__
, pim_str_sg_dump(&sg
),
884 source
->source_group
->group_igmp_sock
->fd
,
885 source
->source_group
->group_igmp_sock
->interface
->name
,
886 IGMP_SOURCE_TEST_FORWARDING(source
->source_flags
));
889 /* Prevent IGMP interface from installing multicast route multiple
891 if (IGMP_SOURCE_TEST_FORWARDING(source
->source_flags
)) {
895 group
= source
->source_group
;
897 if (!source
->source_channel_oil
) {
898 struct in_addr vif_source
;
899 struct pim_interface
*pim_oif
;
900 struct prefix nht_p
, src
, grp
;
901 struct pim_nexthop_cache out_pnc
;
902 struct pim_nexthop nexthop
;
903 struct pim_upstream
*up
= NULL
;
905 if (!pim_rp_set_upstream_addr(pim
, &vif_source
,
906 source
->source_addr
, sg
.grp
))
909 /* Register addr with Zebra NHT */
910 nht_p
.family
= AF_INET
;
911 nht_p
.prefixlen
= IPV4_MAX_BITLEN
;
912 nht_p
.u
.prefix4
= vif_source
;
913 memset(&out_pnc
, 0, sizeof(struct pim_nexthop_cache
));
915 src
.family
= AF_INET
;
916 src
.prefixlen
= IPV4_MAX_BITLEN
;
917 src
.u
.prefix4
= vif_source
; // RP or Src address
918 grp
.family
= AF_INET
;
919 grp
.prefixlen
= IPV4_MAX_BITLEN
;
920 grp
.u
.prefix4
= sg
.grp
;
922 if (pim_find_or_track_nexthop(pim
, &nht_p
, NULL
, NULL
,
924 if (out_pnc
.nexthop_num
) {
925 up
= pim_upstream_find(pim
, &sg
);
926 memset(&nexthop
, 0, sizeof(nexthop
));
929 &up
->rpf
.source_nexthop
,
930 sizeof(struct pim_nexthop
));
931 pim_ecmp_nexthop_search(pim
, &out_pnc
, &nexthop
,
933 if (nexthop
.interface
)
934 input_iface_vif_index
=
935 pim_if_find_vifindex_by_ifindex(
937 nexthop
.interface
->ifindex
);
939 if (PIM_DEBUG_ZEBRA
) {
940 char buf1
[INET_ADDRSTRLEN
];
941 char buf2
[INET_ADDRSTRLEN
];
942 pim_inet4_dump("<source?>",
943 nht_p
.u
.prefix4
, buf1
,
945 pim_inet4_dump("<source?>",
949 "%s: NHT Nexthop not found for addr %s grp %s",
950 __PRETTY_FUNCTION__
, buf1
,
955 input_iface_vif_index
=
956 pim_ecmp_fib_lookup_if_vif_index(
957 pim
, vif_source
, &src
, &grp
);
959 if (PIM_DEBUG_ZEBRA
) {
960 char buf2
[INET_ADDRSTRLEN
];
961 pim_inet4_dump("<source?>", vif_source
, buf2
,
963 zlog_debug("%s: NHT %s vif_source %s vif_index:%d ",
964 __PRETTY_FUNCTION__
, pim_str_sg_dump(&sg
),
965 buf2
, input_iface_vif_index
);
968 if (input_iface_vif_index
< 1) {
969 if (PIM_DEBUG_IGMP_TRACE
) {
970 char source_str
[INET_ADDRSTRLEN
];
971 pim_inet4_dump("<source?>", source
->source_addr
,
972 source_str
, sizeof(source_str
));
974 "%s %s: could not find input interface for source %s",
975 __FILE__
, __PRETTY_FUNCTION__
,
982 Protect IGMP against adding looped MFC entries created by both
983 source and receiver attached to the same interface. See TODO
987 source
->source_group
->group_igmp_sock
->interface
->info
;
989 if (PIM_DEBUG_IGMP_TRACE
) {
991 "%s: multicast not enabled on oif=%s ?",
993 source
->source_group
->group_igmp_sock
999 if (input_iface_vif_index
== pim_oif
->mroute_vif_index
) {
1000 /* ignore request for looped MFC entry */
1001 if (PIM_DEBUG_IGMP_TRACE
) {
1003 "%s: ignoring request for looped MFC entry (S,G)=%s: igmp_sock=%d oif=%s vif_index=%d",
1004 __PRETTY_FUNCTION__
,
1005 pim_str_sg_dump(&sg
),
1006 source
->source_group
->group_igmp_sock
1008 source
->source_group
->group_igmp_sock
1010 input_iface_vif_index
);
1015 source
->source_channel_oil
=
1016 pim_channel_oil_add(pim
, &sg
, input_iface_vif_index
);
1017 if (!source
->source_channel_oil
) {
1018 if (PIM_DEBUG_IGMP_TRACE
) {
1020 "%s %s: could not create OIL for channel (S,G)=%s",
1021 __FILE__
, __PRETTY_FUNCTION__
,
1022 pim_str_sg_dump(&sg
));
1028 result
= pim_channel_add_oif(source
->source_channel_oil
,
1029 group
->group_igmp_sock
->interface
,
1030 PIM_OIF_FLAG_PROTO_IGMP
);
1032 if (PIM_DEBUG_MROUTE
) {
1033 zlog_warn("%s: add_oif() failed with return=%d",
1040 Feed IGMPv3-gathered local membership information into PIM
1041 per-interface (S,G) state.
1043 if (!pim_ifchannel_local_membership_add(
1044 group
->group_igmp_sock
->interface
, &sg
)) {
1045 if (PIM_DEBUG_MROUTE
)
1046 zlog_warn("%s: Failure to add local membership for %s",
1047 __PRETTY_FUNCTION__
, pim_str_sg_dump(&sg
));
1051 IGMP_SOURCE_DO_FORWARDING(source
->source_flags
);
1055 igmp_source_forward_stop: stop fowarding, but keep the source
1056 igmp_source_delete: stop fowarding, and delete the source
1058 void igmp_source_forward_stop(struct igmp_source
*source
)
1060 struct igmp_group
*group
;
1061 struct prefix_sg sg
;
1064 memset(&sg
, 0, sizeof(struct prefix_sg
));
1065 sg
.src
= source
->source_addr
;
1066 sg
.grp
= source
->source_group
->group_addr
;
1068 if (PIM_DEBUG_IGMP_TRACE
) {
1070 "%s: (S,G)=%s igmp_sock=%d oif=%s fwd=%d",
1071 __PRETTY_FUNCTION__
, pim_str_sg_dump(&sg
),
1072 source
->source_group
->group_igmp_sock
->fd
,
1073 source
->source_group
->group_igmp_sock
->interface
->name
,
1074 IGMP_SOURCE_TEST_FORWARDING(source
->source_flags
));
1077 /* Prevent IGMP interface from removing multicast route multiple
1079 if (!IGMP_SOURCE_TEST_FORWARDING(source
->source_flags
)) {
1083 group
= source
->source_group
;
1086 It appears that in certain circumstances that
1087 igmp_source_forward_stop is called when IGMP forwarding
1088 was not enabled in oif_flags for this outgoing interface.
1089 Possibly because of multiple calls. When that happens, we
1090 enter the below if statement and this function returns early
1091 which in turn triggers the calling function to assert.
1092 Making the call to pim_channel_del_oif and ignoring the return code
1093 fixes the issue without ill effect, similar to
1094 pim_forward_stop below.
1096 result
= pim_channel_del_oif(source
->source_channel_oil
,
1097 group
->group_igmp_sock
->interface
,
1098 PIM_OIF_FLAG_PROTO_IGMP
);
1100 if (PIM_DEBUG_IGMP_TRACE
)
1102 "%s: pim_channel_del_oif() failed with return=%d",
1108 Feed IGMPv3-gathered local membership information into PIM
1109 per-interface (S,G) state.
1111 pim_ifchannel_local_membership_del(group
->group_igmp_sock
->interface
,
1114 IGMP_SOURCE_DONT_FORWARDING(source
->source_flags
);
1117 void pim_forward_start(struct pim_ifchannel
*ch
)
1119 struct pim_upstream
*up
= ch
->upstream
;
1120 uint32_t mask
= PIM_OIF_FLAG_PROTO_PIM
;
1121 int input_iface_vif_index
= 0;
1122 struct pim_instance
*pim
;
1123 struct pim_interface
*pim_ifp
;
1125 pim_ifp
= ch
->interface
->info
;
1128 if (PIM_DEBUG_PIM_TRACE
) {
1129 char source_str
[INET_ADDRSTRLEN
];
1130 char group_str
[INET_ADDRSTRLEN
];
1131 char upstream_str
[INET_ADDRSTRLEN
];
1133 pim_inet4_dump("<source?>", ch
->sg
.src
, source_str
,
1134 sizeof(source_str
));
1135 pim_inet4_dump("<group?>", ch
->sg
.grp
, group_str
,
1137 pim_inet4_dump("<upstream?>", up
->upstream_addr
, upstream_str
,
1138 sizeof(upstream_str
));
1139 zlog_debug("%s: (S,G)=(%s,%s) oif=%s (%s)", __PRETTY_FUNCTION__
,
1140 source_str
, group_str
, ch
->interface
->name
,
1144 /* Resolve IIF for upstream as mroute_del sets mfcc_parent to MAXVIFS,
1145 as part of mroute_del called by pim_forward_stop.
1147 if (!up
->channel_oil
1149 && up
->channel_oil
->oil
.mfcc_parent
>= MAXVIFS
)) {
1150 struct prefix nht_p
, src
, grp
;
1151 struct pim_nexthop_cache out_pnc
;
1153 /* Register addr with Zebra NHT */
1154 nht_p
.family
= AF_INET
;
1155 nht_p
.prefixlen
= IPV4_MAX_BITLEN
;
1156 nht_p
.u
.prefix4
.s_addr
= up
->upstream_addr
.s_addr
;
1157 grp
.family
= AF_INET
;
1158 grp
.prefixlen
= IPV4_MAX_BITLEN
;
1159 grp
.u
.prefix4
= up
->sg
.grp
;
1160 memset(&out_pnc
, 0, sizeof(struct pim_nexthop_cache
));
1162 if (pim_find_or_track_nexthop(pim
, &nht_p
, NULL
, NULL
,
1164 if (out_pnc
.nexthop_num
) {
1165 src
.family
= AF_INET
;
1166 src
.prefixlen
= IPV4_MAX_BITLEN
;
1168 up
->upstream_addr
; // RP or Src address
1169 grp
.family
= AF_INET
;
1170 grp
.prefixlen
= IPV4_MAX_BITLEN
;
1171 grp
.u
.prefix4
= up
->sg
.grp
;
1172 // Compute PIM RPF using Cached nexthop
1173 if (pim_ecmp_nexthop_search(
1175 &up
->rpf
.source_nexthop
, &src
, &grp
,
1177 input_iface_vif_index
=
1178 pim_if_find_vifindex_by_ifindex(
1180 up
->rpf
.source_nexthop
1181 .interface
->ifindex
);
1183 if (PIM_DEBUG_TRACE
)
1185 "%s: Nexthop selection failed for %s ",
1186 __PRETTY_FUNCTION__
,
1190 if (PIM_DEBUG_ZEBRA
) {
1191 char buf1
[INET_ADDRSTRLEN
];
1192 char buf2
[INET_ADDRSTRLEN
];
1193 pim_inet4_dump("<source?>",
1194 nht_p
.u
.prefix4
, buf1
,
1196 pim_inet4_dump("<source?>",
1197 grp
.u
.prefix4
, buf2
,
1200 "%s: NHT pnc is NULL for addr %s grp %s",
1201 __PRETTY_FUNCTION__
, buf1
,
1206 input_iface_vif_index
=
1207 pim_ecmp_fib_lookup_if_vif_index(
1208 pim
, up
->upstream_addr
, &src
, &grp
);
1210 if (input_iface_vif_index
< 1) {
1211 if (PIM_DEBUG_PIM_TRACE
) {
1212 char source_str
[INET_ADDRSTRLEN
];
1213 pim_inet4_dump("<source?>", up
->sg
.src
,
1214 source_str
, sizeof(source_str
));
1216 "%s %s: could not find input interface for source %s",
1217 __FILE__
, __PRETTY_FUNCTION__
,
1222 if (PIM_DEBUG_TRACE
) {
1223 struct interface
*in_intf
= pim_if_find_by_vif_index(
1224 pim
, input_iface_vif_index
);
1226 "%s: Update channel_oil IIF %s VIFI %d entry %s ",
1227 __PRETTY_FUNCTION__
,
1228 in_intf
? in_intf
->name
: "NIL",
1229 input_iface_vif_index
, up
->sg_str
);
1231 up
->channel_oil
= pim_channel_oil_add(pim
, &up
->sg
,
1232 input_iface_vif_index
);
1233 if (!up
->channel_oil
) {
1234 if (PIM_DEBUG_PIM_TRACE
)
1236 "%s %s: could not create OIL for channel (S,G)=%s",
1237 __FILE__
, __PRETTY_FUNCTION__
,
1243 if (up
->flags
& PIM_UPSTREAM_FLAG_MASK_SRC_IGMP
)
1244 mask
= PIM_OIF_FLAG_PROTO_IGMP
;
1246 pim_channel_add_oif(up
->channel_oil
, ch
->interface
, mask
);
1249 void pim_forward_stop(struct pim_ifchannel
*ch
, bool install_it
)
1251 struct pim_upstream
*up
= ch
->upstream
;
1253 if (PIM_DEBUG_PIM_TRACE
) {
1254 zlog_debug("%s: (S,G)=%s oif=%s install_it: %d installed: %d",
1255 __PRETTY_FUNCTION__
, ch
->sg_str
, ch
->interface
->name
,
1256 install_it
, up
->channel_oil
->installed
);
1259 pim_channel_del_oif(up
->channel_oil
, ch
->interface
,
1260 PIM_OIF_FLAG_PROTO_PIM
);
1262 if (install_it
&& !up
->channel_oil
->installed
)
1263 pim_mroute_add(up
->channel_oil
, __PRETTY_FUNCTION__
);
1266 void pim_zebra_zclient_update(struct vty
*vty
)
1268 vty_out(vty
, "Zclient update socket: ");
1271 vty_out(vty
, "%d failures=%d\n", zclient
->sock
, zclient
->fail
);
1273 vty_out(vty
, "<null zclient>\n");
1277 struct zclient
*pim_zebra_zclient_get(void)