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
, false, false, false);
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 void pim_zebra_update_all_interfaces(struct pim_instance
*pim
)
430 struct interface
*ifp
;
432 FOR_ALL_INTERFACES (pim
->vrf
, ifp
) {
433 struct pim_interface
*pim_ifp
= ifp
->info
;
434 struct pim_iface_upstream_switch
*us
;
435 struct listnode
*node
;
440 for (ALL_LIST_ELEMENTS_RO(pim_ifp
->upstream_switch_list
, node
,
444 rpf
.source_nexthop
.interface
= ifp
;
445 rpf
.rpf_addr
.u
.prefix4
= us
->address
;
446 pim_joinprune_send(&rpf
, us
->us
);
447 pim_jp_agg_clear_group(us
->us
);
452 void pim_zebra_upstream_rpf_changed(struct pim_instance
*pim
,
453 struct pim_upstream
*up
,
456 struct pim_neighbor
*nbr
;
458 nbr
= pim_neighbor_find(old
->source_nexthop
.interface
,
459 old
->rpf_addr
.u
.prefix4
);
461 pim_jp_agg_remove_group(nbr
->upstream_jp_agg
, up
);
464 * We have detected a case where we might need
465 * to rescan 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
, __PRETTY_FUNCTION__
);
482 * RFC 4601: 4.5.7. Sending (S,G)
483 * Join/Prune Messages
485 * Transitions from Joined State
487 * RPF'(S,G) changes not due to an Assert
489 * The upstream (S,G) state machine remains
490 * in Joined state. Send Join(S,G) to the new
491 * upstream neighbor, which is the new value
492 * of RPF'(S,G). Send Prune(S,G) to the old
493 * upstream neighbor, which is the old value
494 * of RPF'(S,G). Set the Join Timer (JT) to
495 * expire after t_periodic seconds.
497 pim_jp_agg_switch_interface(old
, &up
->rpf
, up
);
499 pim_upstream_join_timer_restart(up
, old
);
500 } /* up->join_state == PIM_UPSTREAM_JOINED */
502 /* FIXME can join_desired actually be changed by
504 returning PIM_RPF_CHANGED ? */
505 pim_upstream_update_join_desired(pim
, up
);
508 static void scan_upstream_rpf_cache(struct pim_instance
*pim
)
510 struct listnode
*up_node
;
511 struct listnode
*up_nextnode
;
512 struct pim_upstream
*up
;
514 for (ALL_LIST_ELEMENTS(pim
->upstream_list
, up_node
, up_nextnode
, up
)) {
515 enum pim_rpf_result rpf_result
;
519 nht_p
.family
= AF_INET
;
520 nht_p
.prefixlen
= IPV4_MAX_BITLEN
;
521 nht_p
.u
.prefix4
.s_addr
= up
->upstream_addr
.s_addr
;
522 pim_resolve_upstream_nh(pim
, &nht_p
);
524 old
.source_nexthop
.interface
= up
->rpf
.source_nexthop
.interface
;
525 old
.source_nexthop
.nbr
= up
->rpf
.source_nexthop
.nbr
;
526 rpf_result
= pim_rpf_update(pim
, up
, &old
, 0);
528 if (rpf_result
== PIM_RPF_FAILURE
)
531 if (rpf_result
== PIM_RPF_CHANGED
)
532 pim_zebra_upstream_rpf_changed(pim
, up
, &old
);
534 } /* for (qpim_upstream_list) */
536 pim_zebra_update_all_interfaces(pim
);
539 void pim_scan_individual_oil(struct channel_oil
*c_oil
, int in_vif_index
)
541 struct in_addr vif_source
;
542 int input_iface_vif_index
;
545 if (!pim_rp_set_upstream_addr(c_oil
->pim
, &vif_source
,
546 c_oil
->oil
.mfcc_origin
,
547 c_oil
->oil
.mfcc_mcastgrp
))
551 input_iface_vif_index
= in_vif_index
;
553 struct prefix src
, grp
;
555 src
.family
= AF_INET
;
556 src
.prefixlen
= IPV4_MAX_BITLEN
;
557 src
.u
.prefix4
= vif_source
;
558 grp
.family
= AF_INET
;
559 grp
.prefixlen
= IPV4_MAX_BITLEN
;
560 grp
.u
.prefix4
= c_oil
->oil
.mfcc_mcastgrp
;
562 if (PIM_DEBUG_ZEBRA
) {
563 char source_str
[INET_ADDRSTRLEN
];
564 char group_str
[INET_ADDRSTRLEN
];
565 pim_inet4_dump("<source?>", c_oil
->oil
.mfcc_origin
,
566 source_str
, sizeof(source_str
));
567 pim_inet4_dump("<group?>", c_oil
->oil
.mfcc_mcastgrp
,
568 group_str
, sizeof(group_str
));
570 "%s: channel_oil (%s,%s) upstream info is not present.",
571 __PRETTY_FUNCTION__
, source_str
, group_str
);
573 input_iface_vif_index
= pim_ecmp_fib_lookup_if_vif_index(
574 c_oil
->pim
, &src
, &grp
);
577 if (input_iface_vif_index
< 1) {
578 if (PIM_DEBUG_ZEBRA
) {
579 char source_str
[INET_ADDRSTRLEN
];
580 char group_str
[INET_ADDRSTRLEN
];
581 pim_inet4_dump("<source?>", c_oil
->oil
.mfcc_origin
,
582 source_str
, sizeof(source_str
));
583 pim_inet4_dump("<group?>", c_oil
->oil
.mfcc_mcastgrp
,
584 group_str
, sizeof(group_str
));
586 "%s %s: could not find input interface(%d) for (S,G)=(%s,%s)",
587 __FILE__
, __PRETTY_FUNCTION__
,
588 c_oil
->oil
.mfcc_parent
, source_str
, group_str
);
590 pim_mroute_del(c_oil
, __PRETTY_FUNCTION__
);
594 if (input_iface_vif_index
== c_oil
->oil
.mfcc_parent
) {
595 if (!c_oil
->installed
)
596 pim_mroute_add(c_oil
, __PRETTY_FUNCTION__
);
602 if (PIM_DEBUG_ZEBRA
) {
603 struct interface
*old_iif
= pim_if_find_by_vif_index(
604 c_oil
->pim
, c_oil
->oil
.mfcc_parent
);
605 struct interface
*new_iif
= pim_if_find_by_vif_index(
606 c_oil
->pim
, input_iface_vif_index
);
607 char source_str
[INET_ADDRSTRLEN
];
608 char group_str
[INET_ADDRSTRLEN
];
609 pim_inet4_dump("<source?>", c_oil
->oil
.mfcc_origin
, source_str
,
611 pim_inet4_dump("<group?>", c_oil
->oil
.mfcc_mcastgrp
, group_str
,
614 "%s %s: (S,G)=(%s,%s) input interface changed from %s vif_index=%d to %s vif_index=%d",
615 __FILE__
, __PRETTY_FUNCTION__
, source_str
, group_str
,
616 (old_iif
) ? old_iif
->name
: "<old_iif?>",
617 c_oil
->oil
.mfcc_parent
,
618 (new_iif
) ? new_iif
->name
: "<new_iif?>",
619 input_iface_vif_index
);
622 /* new iif loops to existing oif ? */
623 if (c_oil
->oil
.mfcc_ttls
[input_iface_vif_index
]) {
624 struct interface
*new_iif
= pim_if_find_by_vif_index(
625 c_oil
->pim
, input_iface_vif_index
);
627 if (PIM_DEBUG_ZEBRA
) {
628 char source_str
[INET_ADDRSTRLEN
];
629 char group_str
[INET_ADDRSTRLEN
];
630 pim_inet4_dump("<source?>", c_oil
->oil
.mfcc_origin
,
631 source_str
, sizeof(source_str
));
632 pim_inet4_dump("<group?>", c_oil
->oil
.mfcc_mcastgrp
,
633 group_str
, sizeof(group_str
));
635 "%s %s: (S,G)=(%s,%s) new iif loops to existing oif: %s vif_index=%d",
636 __FILE__
, __PRETTY_FUNCTION__
, source_str
,
638 (new_iif
) ? new_iif
->name
: "<new_iif?>",
639 input_iface_vif_index
);
643 /* update iif vif_index */
644 old_vif_index
= c_oil
->oil
.mfcc_parent
;
645 c_oil
->oil
.mfcc_parent
= input_iface_vif_index
;
647 /* update kernel multicast forwarding cache (MFC) */
648 if (pim_mroute_add(c_oil
, __PRETTY_FUNCTION__
)) {
649 if (PIM_DEBUG_MROUTE
) {
650 /* just log warning */
651 struct interface
*old_iif
= pim_if_find_by_vif_index(
652 c_oil
->pim
, old_vif_index
);
653 struct interface
*new_iif
= pim_if_find_by_vif_index(
654 c_oil
->pim
, input_iface_vif_index
);
655 char source_str
[INET_ADDRSTRLEN
];
656 char group_str
[INET_ADDRSTRLEN
];
657 pim_inet4_dump("<source?>", c_oil
->oil
.mfcc_origin
,
658 source_str
, sizeof(source_str
));
659 pim_inet4_dump("<group?>", c_oil
->oil
.mfcc_mcastgrp
,
660 group_str
, sizeof(group_str
));
662 "%s %s: (S,G)=(%s,%s) failure updating input interface from %s vif_index=%d to %s vif_index=%d",
663 __FILE__
, __PRETTY_FUNCTION__
, source_str
,
665 old_iif
? old_iif
->name
: "<old_iif?>",
666 c_oil
->oil
.mfcc_parent
,
667 new_iif
? new_iif
->name
: "<new_iif?>",
668 input_iface_vif_index
);
673 void pim_scan_oil(struct pim_instance
*pim
)
675 struct listnode
*node
;
676 struct listnode
*nextnode
;
677 struct channel_oil
*c_oil
;
681 pim
->scan_oil_last
= pim_time_monotonic_sec();
682 ++pim
->scan_oil_events
;
684 for (ALL_LIST_ELEMENTS(pim
->channel_oil_list
, node
, nextnode
, c_oil
)) {
685 if (c_oil
->up
&& c_oil
->up
->rpf
.source_nexthop
.interface
) {
686 ifindex
= c_oil
->up
->rpf
.source_nexthop
689 pim_if_find_vifindex_by_ifindex(pim
, ifindex
);
690 /* Pass Current selected NH vif index to mroute
693 pim_scan_individual_oil(c_oil
, vif_index
);
695 pim_scan_individual_oil(c_oil
, 0);
699 static int on_rpf_cache_refresh(struct thread
*t
)
701 struct pim_instance
*pim
= THREAD_ARG(t
);
703 /* update PIM protocol state */
704 scan_upstream_rpf_cache(pim
);
706 /* update kernel multicast forwarding cache (MFC) */
709 pim
->rpf_cache_refresh_last
= pim_time_monotonic_sec();
710 ++pim
->rpf_cache_refresh_events
;
712 // It is called as part of pim_neighbor_add
717 void sched_rpf_cache_refresh(struct pim_instance
*pim
)
719 ++pim
->rpf_cache_refresh_requests
;
721 pim_rpf_set_refresh_time(pim
);
723 if (pim
->rpf_cache_refresher
) {
724 /* Refresh timer is already running */
728 /* Start refresh timer */
730 if (PIM_DEBUG_ZEBRA
) {
731 zlog_debug("%s: triggering %ld msec timer", __PRETTY_FUNCTION__
,
732 qpim_rpf_cache_refresh_delay_msec
);
735 thread_add_timer_msec(master
, on_rpf_cache_refresh
, pim
,
736 qpim_rpf_cache_refresh_delay_msec
,
737 &pim
->rpf_cache_refresher
);
740 static void pim_zebra_connected(struct zclient
*zclient
)
742 /* Send the client registration */
743 bfd_client_sendmsg(zclient
, ZEBRA_BFD_CLIENT_REGISTER
);
745 zclient_send_reg_requests(zclient
, pimg
->vrf_id
);
748 void pim_zebra_init(void)
750 /* Socket for receiving updates from Zebra daemon */
751 zclient
= zclient_new_notify(master
, &zclient_options_default
);
753 zclient
->zebra_connected
= pim_zebra_connected
;
754 zclient
->router_id_update
= pim_router_id_update_zebra
;
755 zclient
->interface_add
= pim_zebra_if_add
;
756 zclient
->interface_delete
= pim_zebra_if_del
;
757 zclient
->interface_up
= pim_zebra_if_state_up
;
758 zclient
->interface_down
= pim_zebra_if_state_down
;
759 zclient
->interface_address_add
= pim_zebra_if_address_add
;
760 zclient
->interface_address_delete
= pim_zebra_if_address_del
;
761 zclient
->nexthop_update
= pim_parse_nexthop_update
;
763 zclient_init(zclient
, ZEBRA_ROUTE_PIM
, 0, &pimd_privs
);
764 if (PIM_DEBUG_PIM_TRACE
) {
765 zlog_notice("%s: zclient socket initialized",
766 __PRETTY_FUNCTION__
);
769 zclient_lookup_new();
772 void igmp_anysource_forward_start(struct pim_instance
*pim
,
773 struct igmp_group
*group
)
775 struct igmp_source
*source
;
776 struct in_addr src_addr
= {.s_addr
= 0};
777 /* Any source (*,G) is forwarded only if mode is EXCLUDE {empty} */
778 zassert(group
->group_filtermode_isexcl
);
779 zassert(listcount(group
->group_source_list
) < 1);
781 source
= source_new(group
, src_addr
);
783 zlog_warn("%s: Failure to create * source",
784 __PRETTY_FUNCTION__
);
788 igmp_source_forward_start(pim
, source
);
791 void igmp_anysource_forward_stop(struct igmp_group
*group
)
793 struct igmp_source
*source
;
794 struct in_addr star
= {.s_addr
= 0};
796 source
= igmp_find_source_by_addr(group
, star
);
798 igmp_source_forward_stop(source
);
801 static void igmp_source_forward_reevaluate_one(struct pim_instance
*pim
,
802 struct igmp_source
*source
)
805 struct igmp_group
*group
= source
->source_group
;
806 struct pim_ifchannel
*ch
;
808 if ((source
->source_addr
.s_addr
!= INADDR_ANY
)
809 || !IGMP_SOURCE_TEST_FORWARDING(source
->source_flags
))
812 memset(&sg
, 0, sizeof(struct prefix_sg
));
813 sg
.src
= source
->source_addr
;
814 sg
.grp
= group
->group_addr
;
816 ch
= pim_ifchannel_find(group
->group_igmp_sock
->interface
, &sg
);
817 if (pim_is_grp_ssm(pim
, group
->group_addr
)) {
818 /* If SSM group withdraw local membership */
820 && (ch
->local_ifmembership
== PIM_IFMEMBERSHIP_INCLUDE
)) {
821 if (PIM_DEBUG_PIM_EVENTS
)
823 "local membership del for %s as G is now SSM",
824 pim_str_sg_dump(&sg
));
825 pim_ifchannel_local_membership_del(
826 group
->group_igmp_sock
->interface
, &sg
);
829 /* If ASM group add local membership */
831 || (ch
->local_ifmembership
== PIM_IFMEMBERSHIP_NOINFO
)) {
832 if (PIM_DEBUG_PIM_EVENTS
)
834 "local membership add for %s as G is now ASM",
835 pim_str_sg_dump(&sg
));
836 pim_ifchannel_local_membership_add(
837 group
->group_igmp_sock
->interface
, &sg
);
842 void igmp_source_forward_reevaluate_all(struct pim_instance
*pim
)
844 struct interface
*ifp
;
846 FOR_ALL_INTERFACES (pim
->vrf
, ifp
) {
847 struct pim_interface
*pim_ifp
= ifp
->info
;
848 struct listnode
*sock_node
;
849 struct igmp_sock
*igmp
;
854 /* scan igmp sockets */
855 for (ALL_LIST_ELEMENTS_RO(pim_ifp
->igmp_socket_list
, sock_node
,
857 struct listnode
*grpnode
;
858 struct igmp_group
*grp
;
860 /* scan igmp groups */
861 for (ALL_LIST_ELEMENTS_RO(igmp
->igmp_group_list
,
863 struct listnode
*srcnode
;
864 struct igmp_source
*src
;
866 /* scan group sources */
867 for (ALL_LIST_ELEMENTS_RO(
868 grp
->group_source_list
, srcnode
,
870 igmp_source_forward_reevaluate_one(pim
,
872 } /* scan group sources */
873 } /* scan igmp groups */
874 } /* scan igmp sockets */
875 } /* scan interfaces */
878 void igmp_source_forward_start(struct pim_instance
*pim
,
879 struct igmp_source
*source
)
881 struct pim_interface
*pim_oif
;
882 struct igmp_group
*group
;
885 int input_iface_vif_index
= 0;
887 memset(&sg
, 0, sizeof(struct prefix_sg
));
888 sg
.src
= source
->source_addr
;
889 sg
.grp
= source
->source_group
->group_addr
;
891 if (PIM_DEBUG_IGMP_TRACE
) {
893 "%s: (S,G)=%s igmp_sock=%d oif=%s fwd=%d",
894 __PRETTY_FUNCTION__
, pim_str_sg_dump(&sg
),
895 source
->source_group
->group_igmp_sock
->fd
,
896 source
->source_group
->group_igmp_sock
->interface
->name
,
897 IGMP_SOURCE_TEST_FORWARDING(source
->source_flags
));
900 /* Prevent IGMP interface from installing multicast route multiple
902 if (IGMP_SOURCE_TEST_FORWARDING(source
->source_flags
)) {
906 group
= source
->source_group
;
907 pim_oif
= group
->group_igmp_sock
->interface
->info
;
909 if (PIM_DEBUG_IGMP_TRACE
) {
911 "%s: multicast not enabled on oif=%s ?",
913 source
->source_group
->group_igmp_sock
919 if (!source
->source_channel_oil
) {
920 struct in_addr vif_source
;
921 struct prefix nht_p
, src
, grp
;
922 struct pim_nexthop_cache out_pnc
;
923 struct pim_nexthop nexthop
;
924 struct pim_upstream
*up
= NULL
;
926 if (!pim_rp_set_upstream_addr(pim
, &vif_source
,
927 source
->source_addr
, sg
.grp
))
930 /* Register addr with Zebra NHT */
931 nht_p
.family
= AF_INET
;
932 nht_p
.prefixlen
= IPV4_MAX_BITLEN
;
933 nht_p
.u
.prefix4
= vif_source
;
934 memset(&out_pnc
, 0, sizeof(struct pim_nexthop_cache
));
936 src
.family
= AF_INET
;
937 src
.prefixlen
= IPV4_MAX_BITLEN
;
938 src
.u
.prefix4
= vif_source
; // RP or Src address
939 grp
.family
= AF_INET
;
940 grp
.prefixlen
= IPV4_MAX_BITLEN
;
941 grp
.u
.prefix4
= sg
.grp
;
943 if (pim_find_or_track_nexthop(pim
, &nht_p
, NULL
, NULL
,
945 if (out_pnc
.nexthop_num
) {
946 up
= pim_upstream_find(pim
, &sg
);
947 memset(&nexthop
, 0, sizeof(nexthop
));
950 &up
->rpf
.source_nexthop
,
951 sizeof(struct pim_nexthop
));
952 pim_ecmp_nexthop_search(pim
, &out_pnc
, &nexthop
,
954 if (nexthop
.interface
)
955 input_iface_vif_index
=
956 pim_if_find_vifindex_by_ifindex(
958 nexthop
.interface
->ifindex
);
960 if (PIM_DEBUG_ZEBRA
) {
961 char buf1
[INET_ADDRSTRLEN
];
962 char buf2
[INET_ADDRSTRLEN
];
963 pim_inet4_dump("<source?>",
964 nht_p
.u
.prefix4
, buf1
,
966 pim_inet4_dump("<source?>",
970 "%s: NHT Nexthop not found for addr %s grp %s",
971 __PRETTY_FUNCTION__
, buf1
,
976 input_iface_vif_index
=
977 pim_ecmp_fib_lookup_if_vif_index(pim
, &src
,
980 if (PIM_DEBUG_ZEBRA
) {
981 char buf2
[INET_ADDRSTRLEN
];
982 pim_inet4_dump("<source?>", vif_source
, buf2
,
984 zlog_debug("%s: NHT %s vif_source %s vif_index:%d ",
985 __PRETTY_FUNCTION__
, pim_str_sg_dump(&sg
),
986 buf2
, input_iface_vif_index
);
989 if (input_iface_vif_index
< 1) {
990 if (PIM_DEBUG_IGMP_TRACE
) {
991 char source_str
[INET_ADDRSTRLEN
];
992 pim_inet4_dump("<source?>", source
->source_addr
,
993 source_str
, sizeof(source_str
));
995 "%s %s: could not find input interface for source %s",
996 __FILE__
, __PRETTY_FUNCTION__
,
1003 Protect IGMP against adding looped MFC entries created by both
1004 source and receiver attached to the same interface. See TODO
1007 if (input_iface_vif_index
== pim_oif
->mroute_vif_index
) {
1008 /* ignore request for looped MFC entry */
1009 if (PIM_DEBUG_IGMP_TRACE
) {
1011 "%s: ignoring request for looped MFC entry (S,G)=%s: igmp_sock=%d oif=%s vif_index=%d",
1012 __PRETTY_FUNCTION__
,
1013 pim_str_sg_dump(&sg
),
1014 source
->source_group
->group_igmp_sock
1016 source
->source_group
->group_igmp_sock
1018 input_iface_vif_index
);
1023 source
->source_channel_oil
=
1024 pim_channel_oil_add(pim
, &sg
, input_iface_vif_index
);
1025 if (!source
->source_channel_oil
) {
1026 if (PIM_DEBUG_IGMP_TRACE
) {
1028 "%s %s: could not create OIL for channel (S,G)=%s",
1029 __FILE__
, __PRETTY_FUNCTION__
,
1030 pim_str_sg_dump(&sg
));
1036 result
= pim_channel_add_oif(source
->source_channel_oil
,
1037 group
->group_igmp_sock
->interface
,
1038 PIM_OIF_FLAG_PROTO_IGMP
);
1040 if (PIM_DEBUG_MROUTE
) {
1041 zlog_warn("%s: add_oif() failed with return=%d",
1047 if (!(PIM_I_am_DR(pim_oif
))) {
1048 if (PIM_DEBUG_IGMP_TRACE
)
1049 zlog_debug("%s: %s was received on %s interface but we are not DR for that interface",
1050 __PRETTY_FUNCTION__
,
1051 pim_str_sg_dump(&sg
),
1052 group
->group_igmp_sock
->interface
->name
);
1056 Feed IGMPv3-gathered local membership information into PIM
1057 per-interface (S,G) state.
1059 if (!pim_ifchannel_local_membership_add(
1060 group
->group_igmp_sock
->interface
, &sg
)) {
1061 if (PIM_DEBUG_MROUTE
)
1062 zlog_warn("%s: Failure to add local membership for %s",
1063 __PRETTY_FUNCTION__
, pim_str_sg_dump(&sg
));
1067 IGMP_SOURCE_DO_FORWARDING(source
->source_flags
);
1071 igmp_source_forward_stop: stop fowarding, but keep the source
1072 igmp_source_delete: stop fowarding, and delete the source
1074 void igmp_source_forward_stop(struct igmp_source
*source
)
1076 struct igmp_group
*group
;
1077 struct prefix_sg sg
;
1080 memset(&sg
, 0, sizeof(struct prefix_sg
));
1081 sg
.src
= source
->source_addr
;
1082 sg
.grp
= source
->source_group
->group_addr
;
1084 if (PIM_DEBUG_IGMP_TRACE
) {
1086 "%s: (S,G)=%s igmp_sock=%d oif=%s fwd=%d",
1087 __PRETTY_FUNCTION__
, pim_str_sg_dump(&sg
),
1088 source
->source_group
->group_igmp_sock
->fd
,
1089 source
->source_group
->group_igmp_sock
->interface
->name
,
1090 IGMP_SOURCE_TEST_FORWARDING(source
->source_flags
));
1093 /* Prevent IGMP interface from removing multicast route multiple
1095 if (!IGMP_SOURCE_TEST_FORWARDING(source
->source_flags
)) {
1099 group
= source
->source_group
;
1102 It appears that in certain circumstances that
1103 igmp_source_forward_stop is called when IGMP forwarding
1104 was not enabled in oif_flags for this outgoing interface.
1105 Possibly because of multiple calls. When that happens, we
1106 enter the below if statement and this function returns early
1107 which in turn triggers the calling function to assert.
1108 Making the call to pim_channel_del_oif and ignoring the return code
1109 fixes the issue without ill effect, similar to
1110 pim_forward_stop below.
1112 result
= pim_channel_del_oif(source
->source_channel_oil
,
1113 group
->group_igmp_sock
->interface
,
1114 PIM_OIF_FLAG_PROTO_IGMP
);
1116 if (PIM_DEBUG_IGMP_TRACE
)
1118 "%s: pim_channel_del_oif() failed with return=%d",
1124 Feed IGMPv3-gathered local membership information into PIM
1125 per-interface (S,G) state.
1127 pim_ifchannel_local_membership_del(group
->group_igmp_sock
->interface
,
1130 IGMP_SOURCE_DONT_FORWARDING(source
->source_flags
);
1133 void pim_forward_start(struct pim_ifchannel
*ch
)
1135 struct pim_upstream
*up
= ch
->upstream
;
1136 uint32_t mask
= PIM_OIF_FLAG_PROTO_PIM
;
1137 int input_iface_vif_index
= 0;
1138 struct pim_instance
*pim
;
1139 struct pim_interface
*pim_ifp
;
1141 pim_ifp
= ch
->interface
->info
;
1144 if (PIM_DEBUG_PIM_TRACE
) {
1145 char source_str
[INET_ADDRSTRLEN
];
1146 char group_str
[INET_ADDRSTRLEN
];
1147 char upstream_str
[INET_ADDRSTRLEN
];
1149 pim_inet4_dump("<source?>", ch
->sg
.src
, source_str
,
1150 sizeof(source_str
));
1151 pim_inet4_dump("<group?>", ch
->sg
.grp
, group_str
,
1153 pim_inet4_dump("<upstream?>", up
->upstream_addr
, upstream_str
,
1154 sizeof(upstream_str
));
1155 zlog_debug("%s: (S,G)=(%s,%s) oif=%s (%s)", __PRETTY_FUNCTION__
,
1156 source_str
, group_str
, ch
->interface
->name
,
1160 /* Resolve IIF for upstream as mroute_del sets mfcc_parent to MAXVIFS,
1161 as part of mroute_del called by pim_forward_stop.
1163 if (!up
->channel_oil
1165 && up
->channel_oil
->oil
.mfcc_parent
>= MAXVIFS
)) {
1166 struct prefix nht_p
, src
, grp
;
1167 struct pim_nexthop_cache out_pnc
;
1169 /* Register addr with Zebra NHT */
1170 nht_p
.family
= AF_INET
;
1171 nht_p
.prefixlen
= IPV4_MAX_BITLEN
;
1172 nht_p
.u
.prefix4
= up
->upstream_addr
;
1173 grp
.family
= AF_INET
;
1174 grp
.prefixlen
= IPV4_MAX_BITLEN
;
1175 grp
.u
.prefix4
= up
->sg
.grp
;
1176 memset(&out_pnc
, 0, sizeof(struct pim_nexthop_cache
));
1178 if (pim_find_or_track_nexthop(pim
, &nht_p
, NULL
, NULL
,
1180 if (out_pnc
.nexthop_num
) {
1181 src
.family
= AF_INET
;
1182 src
.prefixlen
= IPV4_MAX_BITLEN
;
1184 up
->upstream_addr
; // RP or Src address
1185 grp
.family
= AF_INET
;
1186 grp
.prefixlen
= IPV4_MAX_BITLEN
;
1187 grp
.u
.prefix4
= up
->sg
.grp
;
1188 // Compute PIM RPF using Cached nexthop
1189 if (pim_ecmp_nexthop_search(
1191 &up
->rpf
.source_nexthop
, &src
, &grp
,
1193 input_iface_vif_index
=
1194 pim_if_find_vifindex_by_ifindex(
1196 up
->rpf
.source_nexthop
1197 .interface
->ifindex
);
1199 if (PIM_DEBUG_TRACE
)
1201 "%s: Nexthop selection failed for %s ",
1202 __PRETTY_FUNCTION__
,
1206 if (PIM_DEBUG_ZEBRA
) {
1207 char buf1
[INET_ADDRSTRLEN
];
1208 char buf2
[INET_ADDRSTRLEN
];
1209 pim_inet4_dump("<source?>",
1210 nht_p
.u
.prefix4
, buf1
,
1212 pim_inet4_dump("<source?>",
1213 grp
.u
.prefix4
, buf2
,
1216 "%s: NHT pnc is NULL for addr %s grp %s",
1217 __PRETTY_FUNCTION__
, buf1
,
1222 input_iface_vif_index
=
1223 pim_ecmp_fib_lookup_if_vif_index(pim
, &src
,
1226 if (input_iface_vif_index
< 1) {
1227 if (PIM_DEBUG_PIM_TRACE
) {
1228 char source_str
[INET_ADDRSTRLEN
];
1229 pim_inet4_dump("<source?>", up
->sg
.src
,
1230 source_str
, sizeof(source_str
));
1232 "%s %s: could not find input interface for source %s",
1233 __FILE__
, __PRETTY_FUNCTION__
,
1238 if (PIM_DEBUG_TRACE
) {
1239 struct interface
*in_intf
= pim_if_find_by_vif_index(
1240 pim
, input_iface_vif_index
);
1242 "%s: Update channel_oil IIF %s VIFI %d entry %s ",
1243 __PRETTY_FUNCTION__
,
1244 in_intf
? in_intf
->name
: "NIL",
1245 input_iface_vif_index
, up
->sg_str
);
1247 up
->channel_oil
= pim_channel_oil_add(pim
, &up
->sg
,
1248 input_iface_vif_index
);
1249 if (!up
->channel_oil
) {
1250 if (PIM_DEBUG_PIM_TRACE
)
1252 "%s %s: could not create OIL for channel (S,G)=%s",
1253 __FILE__
, __PRETTY_FUNCTION__
,
1259 if (up
->flags
& PIM_UPSTREAM_FLAG_MASK_SRC_IGMP
)
1260 mask
= PIM_OIF_FLAG_PROTO_IGMP
;
1262 pim_channel_add_oif(up
->channel_oil
, ch
->interface
, mask
);
1265 void pim_forward_stop(struct pim_ifchannel
*ch
, bool install_it
)
1267 struct pim_upstream
*up
= ch
->upstream
;
1269 if (PIM_DEBUG_PIM_TRACE
) {
1270 zlog_debug("%s: (S,G)=%s oif=%s install_it: %d installed: %d",
1271 __PRETTY_FUNCTION__
, ch
->sg_str
, ch
->interface
->name
,
1272 install_it
, up
->channel_oil
->installed
);
1275 pim_channel_del_oif(up
->channel_oil
, ch
->interface
,
1276 PIM_OIF_FLAG_PROTO_PIM
);
1278 if (install_it
&& !up
->channel_oil
->installed
)
1279 pim_mroute_add(up
->channel_oil
, __PRETTY_FUNCTION__
);
1282 void pim_zebra_zclient_update(struct vty
*vty
)
1284 vty_out(vty
, "Zclient update socket: ");
1287 vty_out(vty
, "%d failures=%d\n", zclient
->sock
, zclient
->fail
);
1289 vty_out(vty
, "<null zclient>\n");
1293 struct zclient
*pim_zebra_zclient_get(void)