3 * Copyright (C) 2008 Everton da Silva Marques
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
15 * You should have received a copy of the GNU General Public License along
16 * with this program; see the file COPYING; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
34 #include "pim_zebra.h"
35 #include "pim_iface.h"
41 #include "pim_zlookup.h"
42 #include "pim_ifchannel.h"
44 #include "pim_igmpv3.h"
45 #include "pim_jp_agg.h"
49 #undef PIM_DEBUG_IFADDR_DUMP
50 #define PIM_DEBUG_IFADDR_DUMP
52 static struct zclient
*zclient
= NULL
;
55 /* Router-id update message from zebra. */
56 static int pim_router_id_update_zebra(int command
, struct zclient
*zclient
,
57 zebra_size_t length
, vrf_id_t vrf_id
)
59 struct prefix router_id
;
61 zebra_router_id_update_read(zclient
->ibuf
, &router_id
);
66 static int pim_zebra_if_add(int command
, struct zclient
*zclient
,
67 zebra_size_t length
, vrf_id_t vrf_id
)
69 struct interface
*ifp
;
70 struct pim_instance
*pim
;
73 zebra api adds/dels interfaces using the same call
74 interface_add_read below, see comments in lib/zclient.c
76 ifp
= zebra_interface_add_read(zclient
->ibuf
, vrf_id
);
80 pim
= pim_get_pim_instance(vrf_id
);
81 if (PIM_DEBUG_ZEBRA
) {
83 "%s: %s index %d(%u) 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 struct pim_interface
*pim_ifp
;
94 * If we have a pim_ifp already and this is an if_add
95 * that means that we probably have a vrf move event
96 * If that is the case, set the proper vrfness.
100 pim_if_addr_add_all(ifp
);
104 * If we are a vrf device that is up, open up the pim_socket for
106 * to incoming pim messages irrelevant if the user has configured us
109 if (pim_if_is_vrf_device(ifp
)) {
110 struct pim_interface
*pim_ifp
;
113 pim_ifp
= pim_if_new(ifp
, false, false, false);
123 static int pim_zebra_if_del(int command
, struct zclient
*zclient
,
124 zebra_size_t length
, vrf_id_t vrf_id
)
126 struct interface
*ifp
;
129 zebra api adds/dels interfaces using the same call
130 interface_add_read below, see comments in lib/zclient.c
132 comments in lib/zclient.c seem to indicate that calling
133 zebra_interface_add_read is the correct call, but that
134 results in an attemted out of bounds read which causes
135 pimd to assert. Other clients use zebra_interface_state_read
136 and it appears to work just fine.
138 ifp
= zebra_interface_state_read(zclient
->ibuf
, vrf_id
);
142 if (PIM_DEBUG_ZEBRA
) {
144 "%s: %s index %d(%u) flags %ld metric %d mtu %d operative %d",
145 __PRETTY_FUNCTION__
, ifp
->name
, ifp
->ifindex
, vrf_id
,
146 (long)ifp
->flags
, ifp
->metric
, ifp
->mtu
,
147 if_is_operative(ifp
));
150 if (!if_is_operative(ifp
))
151 pim_if_addr_del_all(ifp
);
156 static int pim_zebra_if_state_up(int command
, struct zclient
*zclient
,
157 zebra_size_t length
, vrf_id_t vrf_id
)
159 struct pim_instance
*pim
;
160 struct interface
*ifp
;
164 zebra api notifies interface up/down events by using the same call
165 zebra_interface_state_read below, see comments in lib/zclient.c
167 ifp
= zebra_interface_state_read(zclient
->ibuf
, vrf_id
);
171 if (PIM_DEBUG_ZEBRA
) {
173 "%s: %s index %d(%u) flags %ld metric %d mtu %d operative %d",
174 __PRETTY_FUNCTION__
, ifp
->name
, ifp
->ifindex
, vrf_id
,
175 (long)ifp
->flags
, ifp
->metric
, ifp
->mtu
,
176 if_is_operative(ifp
));
179 pim
= pim_get_pim_instance(vrf_id
);
180 if (if_is_operative(ifp
)) {
181 struct pim_interface
*pim_ifp
;
185 * If we have a pim_ifp already and this is an if_add
186 * that means that we probably have a vrf move event
187 * If that is the case, set the proper vrfness.
193 pim_if_addr_add_all() suffices for bringing up both IGMP and
196 pim_if_addr_add_all(ifp
);
200 * If we have a pimreg device callback and it's for a specific
201 * table set the master appropriately
203 if (sscanf(ifp
->name
, "pimreg%" SCNu32
, &table_id
) == 1) {
205 RB_FOREACH (vrf
, vrf_name_head
, &vrfs_by_name
) {
206 if ((table_id
== vrf
->data
.l
.table_id
)
207 && (ifp
->vrf_id
!= vrf
->vrf_id
)) {
208 struct interface
*master
= if_lookup_by_name(
209 vrf
->name
, vrf
->vrf_id
);
213 "%s: Unable to find Master interface for %s",
214 __PRETTY_FUNCTION__
, vrf
->name
);
217 zclient_interface_set_master(zclient
, master
,
225 static int pim_zebra_if_state_down(int command
, struct zclient
*zclient
,
226 zebra_size_t length
, vrf_id_t vrf_id
)
228 struct interface
*ifp
;
231 zebra api notifies interface up/down events by using the same call
232 zebra_interface_state_read below, see comments in lib/zclient.c
234 ifp
= zebra_interface_state_read(zclient
->ibuf
, vrf_id
);
238 if (PIM_DEBUG_ZEBRA
) {
240 "%s: %s index %d(%u) flags %ld metric %d mtu %d operative %d",
241 __PRETTY_FUNCTION__
, ifp
->name
, ifp
->ifindex
, vrf_id
,
242 (long)ifp
->flags
, ifp
->metric
, ifp
->mtu
,
243 if_is_operative(ifp
));
246 if (!if_is_operative(ifp
)) {
247 pim_ifchannel_delete_all(ifp
);
249 pim_if_addr_del_all() suffices for shutting down IGMP,
250 but not for shutting down PIM
252 pim_if_addr_del_all(ifp
);
255 pim_sock_delete() closes the socket, stops read and timer
257 and kills all neighbors.
260 pim_sock_delete(ifp
, "link down");
270 #ifdef PIM_DEBUG_IFADDR_DUMP
271 static void dump_if_address(struct interface
*ifp
)
273 struct connected
*ifc
;
274 struct listnode
*node
;
276 zlog_debug("%s %s: interface %s addresses:", __FILE__
,
277 __PRETTY_FUNCTION__
, ifp
->name
);
279 for (ALL_LIST_ELEMENTS_RO(ifp
->connected
, node
, ifc
)) {
280 struct prefix
*p
= ifc
->address
;
282 if (p
->family
!= AF_INET
)
285 zlog_debug("%s %s: interface %s address %s %s", __FILE__
,
286 __PRETTY_FUNCTION__
, ifp
->name
,
287 inet_ntoa(p
->u
.prefix4
),
288 CHECK_FLAG(ifc
->flags
, ZEBRA_IFA_SECONDARY
)
295 static int pim_zebra_if_address_add(int command
, struct zclient
*zclient
,
296 zebra_size_t length
, vrf_id_t vrf_id
)
300 struct pim_interface
*pim_ifp
;
301 struct pim_instance
*pim
;
304 zebra api notifies address adds/dels events by using the same call
305 interface_add_read below, see comments in lib/zclient.c
307 zebra_interface_address_read(ZEBRA_INTERFACE_ADDRESS_ADD, ...)
308 will add address to interface list by calling
309 connected_add_by_prefix()
311 c
= zebra_interface_address_read(command
, zclient
->ibuf
, vrf_id
);
315 pim_ifp
= c
->ifp
->info
;
318 if (PIM_DEBUG_ZEBRA
) {
320 prefix2str(p
, buf
, BUFSIZ
);
321 zlog_debug("%s: %s(%u) connected IP address %s flags %u %s",
322 __PRETTY_FUNCTION__
, c
->ifp
->name
, vrf_id
, buf
,
324 CHECK_FLAG(c
->flags
, ZEBRA_IFA_SECONDARY
)
328 #ifdef PIM_DEBUG_IFADDR_DUMP
329 dump_if_address(c
->ifp
);
333 if (!CHECK_FLAG(c
->flags
, ZEBRA_IFA_SECONDARY
)) {
334 /* trying to add primary address */
336 struct in_addr primary_addr
= pim_find_primary_addr(c
->ifp
);
337 if (p
->family
!= AF_INET
338 || primary_addr
.s_addr
!= p
->u
.prefix4
.s_addr
) {
339 if (PIM_DEBUG_ZEBRA
) {
340 /* but we had a primary address already */
344 prefix2str(p
, buf
, BUFSIZ
);
347 "%s: %s : forcing secondary flag on %s",
348 __PRETTY_FUNCTION__
, c
->ifp
->name
, buf
);
350 SET_FLAG(c
->flags
, ZEBRA_IFA_SECONDARY
);
356 pim
= pim_get_pim_instance(vrf_id
);
359 pim_rp_check_on_if_add(pim_ifp
);
362 if (if_is_loopback(c
->ifp
)) {
363 struct vrf
*vrf
= vrf_lookup_by_id(VRF_DEFAULT
);
364 struct interface
*ifp
;
366 FOR_ALL_INTERFACES (vrf
, ifp
) {
367 if (!if_is_loopback(ifp
) && if_is_operative(ifp
))
368 pim_if_addr_add_all(ifp
);
375 static int pim_zebra_if_address_del(int command
, struct zclient
*client
,
376 zebra_size_t length
, vrf_id_t vrf_id
)
380 struct vrf
*vrf
= vrf_lookup_by_id(vrf_id
);
381 struct pim_instance
*pim
;
388 zebra api notifies address adds/dels events by using the same call
389 interface_add_read below, see comments in lib/zclient.c
391 zebra_interface_address_read(ZEBRA_INTERFACE_ADDRESS_DELETE, ...)
392 will remove address from interface list by calling
393 connected_delete_by_prefix()
395 c
= zebra_interface_address_read(command
, client
->ibuf
, vrf_id
);
400 if (p
->family
== AF_INET
) {
401 if (PIM_DEBUG_ZEBRA
) {
403 prefix2str(p
, buf
, BUFSIZ
);
405 "%s: %s(%u) disconnected IP address %s flags %u %s",
406 __PRETTY_FUNCTION__
, c
->ifp
->name
, vrf_id
, buf
,
408 CHECK_FLAG(c
->flags
, ZEBRA_IFA_SECONDARY
)
412 #ifdef PIM_DEBUG_IFADDR_DUMP
413 dump_if_address(c
->ifp
);
417 pim_if_addr_del(c
, 0);
419 pim_i_am_rp_re_evaluate(pim
);
426 void pim_zebra_update_all_interfaces(struct pim_instance
*pim
)
428 struct interface
*ifp
;
430 FOR_ALL_INTERFACES (pim
->vrf
, ifp
) {
431 struct pim_interface
*pim_ifp
= ifp
->info
;
432 struct pim_iface_upstream_switch
*us
;
433 struct listnode
*node
;
438 for (ALL_LIST_ELEMENTS_RO(pim_ifp
->upstream_switch_list
, node
,
442 rpf
.source_nexthop
.interface
= ifp
;
443 rpf
.rpf_addr
.u
.prefix4
= us
->address
;
444 pim_joinprune_send(&rpf
, us
->us
);
445 pim_jp_agg_clear_group(us
->us
);
450 void pim_zebra_upstream_rpf_changed(struct pim_instance
*pim
,
451 struct pim_upstream
*up
,
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
, up
);
462 * We have detected a case where we might need
463 * to rescan the inherited o_list so do it.
465 if (up
->channel_oil
->oil_inherited_rescan
) {
466 pim_upstream_inherited_olist_decide(pim
, up
);
467 up
->channel_oil
->oil_inherited_rescan
= 0;
470 if (up
->join_state
== PIM_UPSTREAM_JOINED
) {
472 * If we come up real fast we can be here
473 * where the mroute has not been installed
476 if (!up
->channel_oil
->installed
)
477 pim_mroute_add(up
->channel_oil
, __PRETTY_FUNCTION__
);
480 * RFC 4601: 4.5.7. Sending (S,G)
481 * Join/Prune Messages
483 * Transitions from Joined State
485 * RPF'(S,G) changes not due to an Assert
487 * The upstream (S,G) state machine remains
488 * in Joined state. Send Join(S,G) to the new
489 * upstream neighbor, which is the new value
490 * of RPF'(S,G). Send Prune(S,G) to the old
491 * upstream neighbor, which is the old value
492 * of RPF'(S,G). Set the Join Timer (JT) to
493 * expire after t_periodic seconds.
495 pim_jp_agg_switch_interface(old
, &up
->rpf
, up
);
497 pim_upstream_join_timer_restart(up
, old
);
498 } /* up->join_state == PIM_UPSTREAM_JOINED */
500 /* FIXME can join_desired actually be changed by
502 returning PIM_RPF_CHANGED ? */
503 pim_upstream_update_join_desired(pim
, up
);
506 static void scan_upstream_rpf_cache(struct pim_instance
*pim
)
508 struct listnode
*up_node
;
509 struct listnode
*up_nextnode
;
510 struct pim_upstream
*up
;
512 for (ALL_LIST_ELEMENTS(pim
->upstream_list
, up_node
, up_nextnode
, up
)) {
513 enum pim_rpf_result rpf_result
;
517 nht_p
.family
= AF_INET
;
518 nht_p
.prefixlen
= IPV4_MAX_BITLEN
;
519 nht_p
.u
.prefix4
.s_addr
= up
->upstream_addr
.s_addr
;
520 pim_resolve_upstream_nh(pim
, &nht_p
);
522 old
.source_nexthop
.interface
= up
->rpf
.source_nexthop
.interface
;
523 old
.source_nexthop
.nbr
= up
->rpf
.source_nexthop
.nbr
;
524 rpf_result
= pim_rpf_update(pim
, up
, &old
, 0);
526 if (rpf_result
== PIM_RPF_FAILURE
)
529 if (rpf_result
== PIM_RPF_CHANGED
)
530 pim_zebra_upstream_rpf_changed(pim
, up
, &old
);
532 } /* for (qpim_upstream_list) */
534 pim_zebra_update_all_interfaces(pim
);
537 void pim_scan_individual_oil(struct channel_oil
*c_oil
, int in_vif_index
)
539 struct in_addr vif_source
;
540 int input_iface_vif_index
;
543 if (!pim_rp_set_upstream_addr(c_oil
->pim
, &vif_source
,
544 c_oil
->oil
.mfcc_origin
,
545 c_oil
->oil
.mfcc_mcastgrp
))
549 input_iface_vif_index
= in_vif_index
;
551 struct prefix src
, grp
;
553 src
.family
= AF_INET
;
554 src
.prefixlen
= IPV4_MAX_BITLEN
;
555 src
.u
.prefix4
= vif_source
;
556 grp
.family
= AF_INET
;
557 grp
.prefixlen
= IPV4_MAX_BITLEN
;
558 grp
.u
.prefix4
= c_oil
->oil
.mfcc_mcastgrp
;
560 if (PIM_DEBUG_ZEBRA
) {
561 char source_str
[INET_ADDRSTRLEN
];
562 char group_str
[INET_ADDRSTRLEN
];
563 pim_inet4_dump("<source?>", c_oil
->oil
.mfcc_origin
,
564 source_str
, sizeof(source_str
));
565 pim_inet4_dump("<group?>", c_oil
->oil
.mfcc_mcastgrp
,
566 group_str
, sizeof(group_str
));
568 "%s: channel_oil (%s,%s) upstream info is not present.",
569 __PRETTY_FUNCTION__
, source_str
, group_str
);
571 input_iface_vif_index
= pim_ecmp_fib_lookup_if_vif_index(
572 c_oil
->pim
, &src
, &grp
);
575 if (input_iface_vif_index
< 1) {
576 if (PIM_DEBUG_ZEBRA
) {
577 char source_str
[INET_ADDRSTRLEN
];
578 char group_str
[INET_ADDRSTRLEN
];
579 pim_inet4_dump("<source?>", c_oil
->oil
.mfcc_origin
,
580 source_str
, sizeof(source_str
));
581 pim_inet4_dump("<group?>", c_oil
->oil
.mfcc_mcastgrp
,
582 group_str
, sizeof(group_str
));
584 "%s %s: could not find input interface(%d) for (S,G)=(%s,%s)",
585 __FILE__
, __PRETTY_FUNCTION__
,
586 c_oil
->oil
.mfcc_parent
, source_str
, group_str
);
588 pim_mroute_del(c_oil
, __PRETTY_FUNCTION__
);
592 if (input_iface_vif_index
== c_oil
->oil
.mfcc_parent
) {
593 if (!c_oil
->installed
)
594 pim_mroute_add(c_oil
, __PRETTY_FUNCTION__
);
600 if (PIM_DEBUG_ZEBRA
) {
601 struct interface
*old_iif
= pim_if_find_by_vif_index(
602 c_oil
->pim
, c_oil
->oil
.mfcc_parent
);
603 struct interface
*new_iif
= pim_if_find_by_vif_index(
604 c_oil
->pim
, input_iface_vif_index
);
605 char source_str
[INET_ADDRSTRLEN
];
606 char group_str
[INET_ADDRSTRLEN
];
607 pim_inet4_dump("<source?>", c_oil
->oil
.mfcc_origin
, source_str
,
609 pim_inet4_dump("<group?>", c_oil
->oil
.mfcc_mcastgrp
, group_str
,
612 "%s %s: (S,G)=(%s,%s) input interface changed from %s vif_index=%d to %s vif_index=%d",
613 __FILE__
, __PRETTY_FUNCTION__
, source_str
, group_str
,
614 (old_iif
) ? old_iif
->name
: "<old_iif?>",
615 c_oil
->oil
.mfcc_parent
,
616 (new_iif
) ? new_iif
->name
: "<new_iif?>",
617 input_iface_vif_index
);
620 /* new iif loops to existing oif ? */
621 if (c_oil
->oil
.mfcc_ttls
[input_iface_vif_index
]) {
622 struct interface
*new_iif
= pim_if_find_by_vif_index(
623 c_oil
->pim
, input_iface_vif_index
);
625 if (PIM_DEBUG_ZEBRA
) {
626 char source_str
[INET_ADDRSTRLEN
];
627 char group_str
[INET_ADDRSTRLEN
];
628 pim_inet4_dump("<source?>", c_oil
->oil
.mfcc_origin
,
629 source_str
, sizeof(source_str
));
630 pim_inet4_dump("<group?>", c_oil
->oil
.mfcc_mcastgrp
,
631 group_str
, sizeof(group_str
));
633 "%s %s: (S,G)=(%s,%s) new iif loops to existing oif: %s vif_index=%d",
634 __FILE__
, __PRETTY_FUNCTION__
, source_str
,
636 (new_iif
) ? new_iif
->name
: "<new_iif?>",
637 input_iface_vif_index
);
641 /* update iif vif_index */
642 old_vif_index
= c_oil
->oil
.mfcc_parent
;
643 c_oil
->oil
.mfcc_parent
= input_iface_vif_index
;
645 /* update kernel multicast forwarding cache (MFC) */
646 if (pim_mroute_add(c_oil
, __PRETTY_FUNCTION__
)) {
647 if (PIM_DEBUG_MROUTE
) {
648 /* just log warning */
649 struct interface
*old_iif
= pim_if_find_by_vif_index(
650 c_oil
->pim
, old_vif_index
);
651 struct interface
*new_iif
= pim_if_find_by_vif_index(
652 c_oil
->pim
, input_iface_vif_index
);
653 char source_str
[INET_ADDRSTRLEN
];
654 char group_str
[INET_ADDRSTRLEN
];
655 pim_inet4_dump("<source?>", c_oil
->oil
.mfcc_origin
,
656 source_str
, sizeof(source_str
));
657 pim_inet4_dump("<group?>", c_oil
->oil
.mfcc_mcastgrp
,
658 group_str
, sizeof(group_str
));
660 "%s %s: (S,G)=(%s,%s) failure updating input interface from %s vif_index=%d to %s vif_index=%d",
661 __FILE__
, __PRETTY_FUNCTION__
, source_str
,
663 old_iif
? old_iif
->name
: "<old_iif?>",
664 c_oil
->oil
.mfcc_parent
,
665 new_iif
? new_iif
->name
: "<new_iif?>",
666 input_iface_vif_index
);
671 void pim_scan_oil(struct pim_instance
*pim
)
673 struct listnode
*node
;
674 struct listnode
*nextnode
;
675 struct channel_oil
*c_oil
;
679 pim
->scan_oil_last
= pim_time_monotonic_sec();
680 ++pim
->scan_oil_events
;
682 for (ALL_LIST_ELEMENTS(pim
->channel_oil_list
, node
, nextnode
, c_oil
)) {
683 if (c_oil
->up
&& c_oil
->up
->rpf
.source_nexthop
.interface
) {
684 ifindex
= c_oil
->up
->rpf
.source_nexthop
687 pim_if_find_vifindex_by_ifindex(pim
, ifindex
);
688 /* Pass Current selected NH vif index to mroute
691 pim_scan_individual_oil(c_oil
, vif_index
);
693 pim_scan_individual_oil(c_oil
, 0);
697 static int on_rpf_cache_refresh(struct thread
*t
)
699 struct pim_instance
*pim
= THREAD_ARG(t
);
701 /* update PIM protocol state */
702 scan_upstream_rpf_cache(pim
);
704 /* update kernel multicast forwarding cache (MFC) */
707 pim
->rpf_cache_refresh_last
= pim_time_monotonic_sec();
708 ++pim
->rpf_cache_refresh_events
;
710 // It is called as part of pim_neighbor_add
715 void sched_rpf_cache_refresh(struct pim_instance
*pim
)
717 ++pim
->rpf_cache_refresh_requests
;
719 pim_rpf_set_refresh_time(pim
);
721 if (pim
->rpf_cache_refresher
) {
722 /* Refresh timer is already running */
726 /* Start refresh timer */
728 if (PIM_DEBUG_ZEBRA
) {
729 zlog_debug("%s: triggering %ld msec timer", __PRETTY_FUNCTION__
,
730 router
->rpf_cache_refresh_delay_msec
);
733 thread_add_timer_msec(router
->master
, on_rpf_cache_refresh
, pim
,
734 router
->rpf_cache_refresh_delay_msec
,
735 &pim
->rpf_cache_refresher
);
738 static void pim_zebra_connected(struct zclient
*zclient
)
740 /* Send the client registration */
741 bfd_client_sendmsg(zclient
, ZEBRA_BFD_CLIENT_REGISTER
);
743 zclient_send_reg_requests(zclient
, router
->vrf_id
);
746 static void pim_zebra_capabilities(struct zclient_capabilities
*cap
)
748 router
->role
= cap
->role
;
751 void pim_zebra_init(void)
753 /* Socket for receiving updates from Zebra daemon */
754 zclient
= zclient_new(router
->master
, &zclient_options_default
);
756 zclient
->zebra_capabilities
= pim_zebra_capabilities
;
757 zclient
->zebra_connected
= pim_zebra_connected
;
758 zclient
->router_id_update
= pim_router_id_update_zebra
;
759 zclient
->interface_add
= pim_zebra_if_add
;
760 zclient
->interface_delete
= pim_zebra_if_del
;
761 zclient
->interface_up
= pim_zebra_if_state_up
;
762 zclient
->interface_down
= pim_zebra_if_state_down
;
763 zclient
->interface_address_add
= pim_zebra_if_address_add
;
764 zclient
->interface_address_delete
= pim_zebra_if_address_del
;
765 zclient
->nexthop_update
= pim_parse_nexthop_update
;
767 zclient_init(zclient
, ZEBRA_ROUTE_PIM
, 0, &pimd_privs
);
768 if (PIM_DEBUG_PIM_TRACE
) {
769 zlog_notice("%s: zclient socket initialized",
770 __PRETTY_FUNCTION__
);
773 zclient_lookup_new();
776 void igmp_anysource_forward_start(struct pim_instance
*pim
,
777 struct igmp_group
*group
)
779 struct igmp_source
*source
;
780 struct in_addr src_addr
= {.s_addr
= 0};
781 /* Any source (*,G) is forwarded only if mode is EXCLUDE {empty} */
782 zassert(group
->group_filtermode_isexcl
);
783 zassert(listcount(group
->group_source_list
) < 1);
785 source
= source_new(group
, src_addr
);
787 zlog_warn("%s: Failure to create * source",
788 __PRETTY_FUNCTION__
);
792 igmp_source_forward_start(pim
, source
);
795 void igmp_anysource_forward_stop(struct igmp_group
*group
)
797 struct igmp_source
*source
;
798 struct in_addr star
= {.s_addr
= 0};
800 source
= igmp_find_source_by_addr(group
, star
);
802 igmp_source_forward_stop(source
);
805 static void igmp_source_forward_reevaluate_one(struct pim_instance
*pim
,
806 struct igmp_source
*source
)
809 struct igmp_group
*group
= source
->source_group
;
810 struct pim_ifchannel
*ch
;
812 if ((source
->source_addr
.s_addr
!= INADDR_ANY
)
813 || !IGMP_SOURCE_TEST_FORWARDING(source
->source_flags
))
816 memset(&sg
, 0, sizeof(struct prefix_sg
));
817 sg
.src
= source
->source_addr
;
818 sg
.grp
= group
->group_addr
;
820 ch
= pim_ifchannel_find(group
->group_igmp_sock
->interface
, &sg
);
821 if (pim_is_grp_ssm(pim
, group
->group_addr
)) {
822 /* If SSM group withdraw local membership */
824 && (ch
->local_ifmembership
== PIM_IFMEMBERSHIP_INCLUDE
)) {
825 if (PIM_DEBUG_PIM_EVENTS
)
827 "local membership del for %s as G is now SSM",
828 pim_str_sg_dump(&sg
));
829 pim_ifchannel_local_membership_del(
830 group
->group_igmp_sock
->interface
, &sg
);
833 /* If ASM group add local membership */
835 || (ch
->local_ifmembership
== PIM_IFMEMBERSHIP_NOINFO
)) {
836 if (PIM_DEBUG_PIM_EVENTS
)
838 "local membership add for %s as G is now ASM",
839 pim_str_sg_dump(&sg
));
840 pim_ifchannel_local_membership_add(
841 group
->group_igmp_sock
->interface
, &sg
);
846 void igmp_source_forward_reevaluate_all(struct pim_instance
*pim
)
848 struct interface
*ifp
;
850 FOR_ALL_INTERFACES (pim
->vrf
, ifp
) {
851 struct pim_interface
*pim_ifp
= ifp
->info
;
852 struct listnode
*sock_node
;
853 struct igmp_sock
*igmp
;
858 /* scan igmp sockets */
859 for (ALL_LIST_ELEMENTS_RO(pim_ifp
->igmp_socket_list
, sock_node
,
861 struct listnode
*grpnode
;
862 struct igmp_group
*grp
;
864 /* scan igmp groups */
865 for (ALL_LIST_ELEMENTS_RO(igmp
->igmp_group_list
,
867 struct listnode
*srcnode
;
868 struct igmp_source
*src
;
870 /* scan group sources */
871 for (ALL_LIST_ELEMENTS_RO(
872 grp
->group_source_list
, srcnode
,
874 igmp_source_forward_reevaluate_one(pim
,
876 } /* scan group sources */
877 } /* scan igmp groups */
878 } /* scan igmp sockets */
879 } /* scan interfaces */
882 void igmp_source_forward_start(struct pim_instance
*pim
,
883 struct igmp_source
*source
)
885 struct pim_interface
*pim_oif
;
886 struct igmp_group
*group
;
889 int input_iface_vif_index
= 0;
891 memset(&sg
, 0, sizeof(struct prefix_sg
));
892 sg
.src
= source
->source_addr
;
893 sg
.grp
= source
->source_group
->group_addr
;
895 if (PIM_DEBUG_IGMP_TRACE
) {
897 "%s: (S,G)=%s igmp_sock=%d oif=%s fwd=%d",
898 __PRETTY_FUNCTION__
, pim_str_sg_dump(&sg
),
899 source
->source_group
->group_igmp_sock
->fd
,
900 source
->source_group
->group_igmp_sock
->interface
->name
,
901 IGMP_SOURCE_TEST_FORWARDING(source
->source_flags
));
904 /* Prevent IGMP interface from installing multicast route multiple
906 if (IGMP_SOURCE_TEST_FORWARDING(source
->source_flags
)) {
910 group
= source
->source_group
;
911 pim_oif
= group
->group_igmp_sock
->interface
->info
;
913 if (PIM_DEBUG_IGMP_TRACE
) {
915 "%s: multicast not enabled on oif=%s ?",
917 source
->source_group
->group_igmp_sock
923 if (!source
->source_channel_oil
) {
924 struct in_addr vif_source
;
925 struct prefix nht_p
, src
, grp
;
926 struct pim_nexthop_cache out_pnc
;
927 struct pim_nexthop nexthop
;
928 struct pim_upstream
*up
= NULL
;
930 if (!pim_rp_set_upstream_addr(pim
, &vif_source
,
931 source
->source_addr
, sg
.grp
))
934 /* Register addr with Zebra NHT */
935 nht_p
.family
= AF_INET
;
936 nht_p
.prefixlen
= IPV4_MAX_BITLEN
;
937 nht_p
.u
.prefix4
= vif_source
;
938 memset(&out_pnc
, 0, sizeof(struct pim_nexthop_cache
));
940 src
.family
= AF_INET
;
941 src
.prefixlen
= IPV4_MAX_BITLEN
;
942 src
.u
.prefix4
= vif_source
; // RP or Src address
943 grp
.family
= AF_INET
;
944 grp
.prefixlen
= IPV4_MAX_BITLEN
;
945 grp
.u
.prefix4
= sg
.grp
;
947 if (pim_find_or_track_nexthop(pim
, &nht_p
, NULL
, NULL
,
949 if (out_pnc
.nexthop_num
) {
950 up
= pim_upstream_find(pim
, &sg
);
951 memset(&nexthop
, 0, sizeof(nexthop
));
954 &up
->rpf
.source_nexthop
,
955 sizeof(struct pim_nexthop
));
956 pim_ecmp_nexthop_search(pim
, &out_pnc
, &nexthop
,
958 if (nexthop
.interface
)
959 input_iface_vif_index
=
960 pim_if_find_vifindex_by_ifindex(
962 nexthop
.interface
->ifindex
);
964 if (PIM_DEBUG_ZEBRA
) {
965 char buf1
[INET_ADDRSTRLEN
];
966 char buf2
[INET_ADDRSTRLEN
];
967 pim_inet4_dump("<source?>",
968 nht_p
.u
.prefix4
, buf1
,
970 pim_inet4_dump("<source?>",
974 "%s: NHT Nexthop not found for addr %s grp %s",
975 __PRETTY_FUNCTION__
, buf1
,
980 input_iface_vif_index
=
981 pim_ecmp_fib_lookup_if_vif_index(pim
, &src
,
984 if (PIM_DEBUG_ZEBRA
) {
985 char buf2
[INET_ADDRSTRLEN
];
986 pim_inet4_dump("<source?>", vif_source
, buf2
,
988 zlog_debug("%s: NHT %s vif_source %s vif_index:%d ",
989 __PRETTY_FUNCTION__
, pim_str_sg_dump(&sg
),
990 buf2
, input_iface_vif_index
);
993 if (input_iface_vif_index
< 1) {
994 if (PIM_DEBUG_IGMP_TRACE
) {
995 char source_str
[INET_ADDRSTRLEN
];
996 pim_inet4_dump("<source?>", source
->source_addr
,
997 source_str
, sizeof(source_str
));
999 "%s %s: could not find input interface for source %s",
1000 __FILE__
, __PRETTY_FUNCTION__
,
1007 Protect IGMP against adding looped MFC entries created by both
1008 source and receiver attached to the same interface. See TODO
1011 if (input_iface_vif_index
== pim_oif
->mroute_vif_index
) {
1012 /* ignore request for looped MFC entry */
1013 if (PIM_DEBUG_IGMP_TRACE
) {
1015 "%s: ignoring request for looped MFC entry (S,G)=%s: igmp_sock=%d oif=%s vif_index=%d",
1016 __PRETTY_FUNCTION__
,
1017 pim_str_sg_dump(&sg
),
1018 source
->source_group
->group_igmp_sock
1020 source
->source_group
->group_igmp_sock
1022 input_iface_vif_index
);
1027 source
->source_channel_oil
=
1028 pim_channel_oil_add(pim
, &sg
, input_iface_vif_index
);
1029 if (!source
->source_channel_oil
) {
1030 if (PIM_DEBUG_IGMP_TRACE
) {
1032 "%s %s: could not create OIL for channel (S,G)=%s",
1033 __FILE__
, __PRETTY_FUNCTION__
,
1034 pim_str_sg_dump(&sg
));
1040 result
= pim_channel_add_oif(source
->source_channel_oil
,
1041 group
->group_igmp_sock
->interface
,
1042 PIM_OIF_FLAG_PROTO_IGMP
);
1044 if (PIM_DEBUG_MROUTE
) {
1045 zlog_warn("%s: add_oif() failed with return=%d",
1051 if (!(PIM_I_am_DR(pim_oif
))) {
1052 if (PIM_DEBUG_IGMP_TRACE
)
1053 zlog_debug("%s: %s was received on %s interface but we are not DR for that interface",
1054 __PRETTY_FUNCTION__
,
1055 pim_str_sg_dump(&sg
),
1056 group
->group_igmp_sock
->interface
->name
);
1058 pim_channel_del_oif(source
->source_channel_oil
,
1059 group
->group_igmp_sock
->interface
,
1060 PIM_OIF_FLAG_PROTO_IGMP
);
1064 Feed IGMPv3-gathered local membership information into PIM
1065 per-interface (S,G) state.
1067 if (!pim_ifchannel_local_membership_add(
1068 group
->group_igmp_sock
->interface
, &sg
)) {
1069 if (PIM_DEBUG_MROUTE
)
1070 zlog_warn("%s: Failure to add local membership for %s",
1071 __PRETTY_FUNCTION__
, pim_str_sg_dump(&sg
));
1073 pim_channel_del_oif(source
->source_channel_oil
,
1074 group
->group_igmp_sock
->interface
,
1075 PIM_OIF_FLAG_PROTO_IGMP
);
1079 IGMP_SOURCE_DO_FORWARDING(source
->source_flags
);
1083 igmp_source_forward_stop: stop fowarding, but keep the source
1084 igmp_source_delete: stop fowarding, and delete the source
1086 void igmp_source_forward_stop(struct igmp_source
*source
)
1088 struct igmp_group
*group
;
1089 struct prefix_sg sg
;
1092 memset(&sg
, 0, sizeof(struct prefix_sg
));
1093 sg
.src
= source
->source_addr
;
1094 sg
.grp
= source
->source_group
->group_addr
;
1096 if (PIM_DEBUG_IGMP_TRACE
) {
1098 "%s: (S,G)=%s igmp_sock=%d oif=%s fwd=%d",
1099 __PRETTY_FUNCTION__
, pim_str_sg_dump(&sg
),
1100 source
->source_group
->group_igmp_sock
->fd
,
1101 source
->source_group
->group_igmp_sock
->interface
->name
,
1102 IGMP_SOURCE_TEST_FORWARDING(source
->source_flags
));
1105 /* Prevent IGMP interface from removing multicast route multiple
1107 if (!IGMP_SOURCE_TEST_FORWARDING(source
->source_flags
)) {
1111 group
= source
->source_group
;
1114 It appears that in certain circumstances that
1115 igmp_source_forward_stop is called when IGMP forwarding
1116 was not enabled in oif_flags for this outgoing interface.
1117 Possibly because of multiple calls. When that happens, we
1118 enter the below if statement and this function returns early
1119 which in turn triggers the calling function to assert.
1120 Making the call to pim_channel_del_oif and ignoring the return code
1121 fixes the issue without ill effect, similar to
1122 pim_forward_stop below.
1124 result
= pim_channel_del_oif(source
->source_channel_oil
,
1125 group
->group_igmp_sock
->interface
,
1126 PIM_OIF_FLAG_PROTO_IGMP
);
1128 if (PIM_DEBUG_IGMP_TRACE
)
1130 "%s: pim_channel_del_oif() failed with return=%d",
1136 Feed IGMPv3-gathered local membership information into PIM
1137 per-interface (S,G) state.
1139 pim_ifchannel_local_membership_del(group
->group_igmp_sock
->interface
,
1142 IGMP_SOURCE_DONT_FORWARDING(source
->source_flags
);
1145 void pim_forward_start(struct pim_ifchannel
*ch
)
1147 struct pim_upstream
*up
= ch
->upstream
;
1148 uint32_t mask
= PIM_OIF_FLAG_PROTO_PIM
;
1149 int input_iface_vif_index
= 0;
1150 struct pim_instance
*pim
;
1151 struct pim_interface
*pim_ifp
;
1153 pim_ifp
= ch
->interface
->info
;
1156 if (PIM_DEBUG_PIM_TRACE
) {
1157 char source_str
[INET_ADDRSTRLEN
];
1158 char group_str
[INET_ADDRSTRLEN
];
1159 char upstream_str
[INET_ADDRSTRLEN
];
1161 pim_inet4_dump("<source?>", ch
->sg
.src
, source_str
,
1162 sizeof(source_str
));
1163 pim_inet4_dump("<group?>", ch
->sg
.grp
, group_str
,
1165 pim_inet4_dump("<upstream?>", up
->upstream_addr
, upstream_str
,
1166 sizeof(upstream_str
));
1167 zlog_debug("%s: (S,G)=(%s,%s) oif=%s (%s)", __PRETTY_FUNCTION__
,
1168 source_str
, group_str
, ch
->interface
->name
,
1172 /* Resolve IIF for upstream as mroute_del sets mfcc_parent to MAXVIFS,
1173 as part of mroute_del called by pim_forward_stop.
1175 if (!up
->channel_oil
1177 && up
->channel_oil
->oil
.mfcc_parent
>= MAXVIFS
)) {
1178 struct prefix nht_p
, src
, grp
;
1179 struct pim_nexthop_cache out_pnc
;
1181 /* Register addr with Zebra NHT */
1182 nht_p
.family
= AF_INET
;
1183 nht_p
.prefixlen
= IPV4_MAX_BITLEN
;
1184 nht_p
.u
.prefix4
= up
->upstream_addr
;
1185 grp
.family
= AF_INET
;
1186 grp
.prefixlen
= IPV4_MAX_BITLEN
;
1187 grp
.u
.prefix4
= up
->sg
.grp
;
1188 memset(&out_pnc
, 0, sizeof(struct pim_nexthop_cache
));
1190 if (pim_find_or_track_nexthop(pim
, &nht_p
, NULL
, NULL
,
1192 if (out_pnc
.nexthop_num
) {
1193 src
.family
= AF_INET
;
1194 src
.prefixlen
= IPV4_MAX_BITLEN
;
1196 up
->upstream_addr
; // RP or Src address
1197 grp
.family
= AF_INET
;
1198 grp
.prefixlen
= IPV4_MAX_BITLEN
;
1199 grp
.u
.prefix4
= up
->sg
.grp
;
1200 // Compute PIM RPF using Cached nexthop
1201 if (pim_ecmp_nexthop_search(
1203 &up
->rpf
.source_nexthop
, &src
, &grp
,
1205 input_iface_vif_index
=
1206 pim_if_find_vifindex_by_ifindex(
1208 up
->rpf
.source_nexthop
1209 .interface
->ifindex
);
1211 if (PIM_DEBUG_TRACE
)
1213 "%s: Nexthop selection failed for %s ",
1214 __PRETTY_FUNCTION__
,
1218 if (PIM_DEBUG_ZEBRA
) {
1219 char buf1
[INET_ADDRSTRLEN
];
1220 char buf2
[INET_ADDRSTRLEN
];
1221 pim_inet4_dump("<source?>",
1222 nht_p
.u
.prefix4
, buf1
,
1224 pim_inet4_dump("<source?>",
1225 grp
.u
.prefix4
, buf2
,
1228 "%s: NHT pnc is NULL for addr %s grp %s",
1229 __PRETTY_FUNCTION__
, buf1
,
1234 input_iface_vif_index
=
1235 pim_ecmp_fib_lookup_if_vif_index(pim
, &src
,
1238 if (input_iface_vif_index
< 1) {
1239 if (PIM_DEBUG_PIM_TRACE
) {
1240 char source_str
[INET_ADDRSTRLEN
];
1241 pim_inet4_dump("<source?>", up
->sg
.src
,
1242 source_str
, sizeof(source_str
));
1244 "%s %s: could not find input interface for source %s",
1245 __FILE__
, __PRETTY_FUNCTION__
,
1250 if (PIM_DEBUG_TRACE
) {
1251 struct interface
*in_intf
= pim_if_find_by_vif_index(
1252 pim
, input_iface_vif_index
);
1254 "%s: Update channel_oil IIF %s VIFI %d entry %s ",
1255 __PRETTY_FUNCTION__
,
1256 in_intf
? in_intf
->name
: "NIL",
1257 input_iface_vif_index
, up
->sg_str
);
1259 up
->channel_oil
= pim_channel_oil_add(pim
, &up
->sg
,
1260 input_iface_vif_index
);
1261 if (!up
->channel_oil
) {
1262 if (PIM_DEBUG_PIM_TRACE
)
1264 "%s %s: could not create OIL for channel (S,G)=%s",
1265 __FILE__
, __PRETTY_FUNCTION__
,
1271 if (up
->flags
& PIM_UPSTREAM_FLAG_MASK_SRC_IGMP
)
1272 mask
= PIM_OIF_FLAG_PROTO_IGMP
;
1274 pim_channel_add_oif(up
->channel_oil
, ch
->interface
, mask
);
1277 void pim_forward_stop(struct pim_ifchannel
*ch
, bool install_it
)
1279 struct pim_upstream
*up
= ch
->upstream
;
1281 if (PIM_DEBUG_PIM_TRACE
) {
1282 zlog_debug("%s: (S,G)=%s oif=%s install_it: %d installed: %d",
1283 __PRETTY_FUNCTION__
, ch
->sg_str
, ch
->interface
->name
,
1284 install_it
, up
->channel_oil
->installed
);
1287 pim_channel_del_oif(up
->channel_oil
, ch
->interface
,
1288 PIM_OIF_FLAG_PROTO_PIM
);
1290 if (install_it
&& !up
->channel_oil
->installed
)
1291 pim_mroute_add(up
->channel_oil
, __PRETTY_FUNCTION__
);
1294 void pim_zebra_zclient_update(struct vty
*vty
)
1296 vty_out(vty
, "Zclient update socket: ");
1299 vty_out(vty
, "%d failures=%d\n", zclient
->sock
, zclient
->fail
);
1301 vty_out(vty
, "<null zclient>\n");
1305 struct zclient
*pim_zebra_zclient_get(void)