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
);
153 if_set_index(ifp
, IFINDEX_INTERNAL
);
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 static int pim_zebra_interface_vrf_update(int command
, struct zclient
*zclient
,
273 zebra_size_t length
, vrf_id_t vrf_id
)
275 struct interface
*ifp
;
278 ifp
= zebra_interface_vrf_update_read(zclient
->ibuf
, vrf_id
,
284 zlog_debug("%s: %s updating from %u to %u",
286 ifp
->name
, vrf_id
, new_vrf_id
);
288 if_update_to_new_vrf(ifp
, new_vrf_id
);
293 #ifdef PIM_DEBUG_IFADDR_DUMP
294 static void dump_if_address(struct interface
*ifp
)
296 struct connected
*ifc
;
297 struct listnode
*node
;
299 zlog_debug("%s %s: interface %s addresses:", __FILE__
,
300 __PRETTY_FUNCTION__
, ifp
->name
);
302 for (ALL_LIST_ELEMENTS_RO(ifp
->connected
, node
, ifc
)) {
303 struct prefix
*p
= ifc
->address
;
305 if (p
->family
!= AF_INET
)
308 zlog_debug("%s %s: interface %s address %s %s", __FILE__
,
309 __PRETTY_FUNCTION__
, ifp
->name
,
310 inet_ntoa(p
->u
.prefix4
),
311 CHECK_FLAG(ifc
->flags
, ZEBRA_IFA_SECONDARY
)
318 static int pim_zebra_if_address_add(int command
, struct zclient
*zclient
,
319 zebra_size_t length
, vrf_id_t vrf_id
)
323 struct pim_interface
*pim_ifp
;
324 struct pim_instance
*pim
;
327 zebra api notifies address adds/dels events by using the same call
328 interface_add_read below, see comments in lib/zclient.c
330 zebra_interface_address_read(ZEBRA_INTERFACE_ADDRESS_ADD, ...)
331 will add address to interface list by calling
332 connected_add_by_prefix()
334 c
= zebra_interface_address_read(command
, zclient
->ibuf
, vrf_id
);
338 pim_ifp
= c
->ifp
->info
;
341 if (PIM_DEBUG_ZEBRA
) {
343 prefix2str(p
, buf
, BUFSIZ
);
344 zlog_debug("%s: %s(%u) connected IP address %s flags %u %s",
345 __PRETTY_FUNCTION__
, c
->ifp
->name
, vrf_id
, buf
,
347 CHECK_FLAG(c
->flags
, ZEBRA_IFA_SECONDARY
)
351 #ifdef PIM_DEBUG_IFADDR_DUMP
352 dump_if_address(c
->ifp
);
356 if (!CHECK_FLAG(c
->flags
, ZEBRA_IFA_SECONDARY
)) {
357 /* trying to add primary address */
359 struct in_addr primary_addr
= pim_find_primary_addr(c
->ifp
);
360 if (p
->family
!= AF_INET
361 || primary_addr
.s_addr
!= p
->u
.prefix4
.s_addr
) {
362 if (PIM_DEBUG_ZEBRA
) {
363 /* but we had a primary address already */
367 prefix2str(p
, buf
, BUFSIZ
);
370 "%s: %s : forcing secondary flag on %s",
371 __PRETTY_FUNCTION__
, c
->ifp
->name
, buf
);
373 SET_FLAG(c
->flags
, ZEBRA_IFA_SECONDARY
);
379 pim
= pim_get_pim_instance(vrf_id
);
382 pim_rp_check_on_if_add(pim_ifp
);
385 if (if_is_loopback(c
->ifp
)) {
386 struct vrf
*vrf
= vrf_lookup_by_id(VRF_DEFAULT
);
387 struct interface
*ifp
;
389 FOR_ALL_INTERFACES (vrf
, ifp
) {
390 if (!if_is_loopback(ifp
) && if_is_operative(ifp
))
391 pim_if_addr_add_all(ifp
);
398 static int pim_zebra_if_address_del(int command
, struct zclient
*client
,
399 zebra_size_t length
, vrf_id_t vrf_id
)
403 struct vrf
*vrf
= vrf_lookup_by_id(vrf_id
);
404 struct pim_instance
*pim
;
411 zebra api notifies address adds/dels events by using the same call
412 interface_add_read below, see comments in lib/zclient.c
414 zebra_interface_address_read(ZEBRA_INTERFACE_ADDRESS_DELETE, ...)
415 will remove address from interface list by calling
416 connected_delete_by_prefix()
418 c
= zebra_interface_address_read(command
, client
->ibuf
, vrf_id
);
423 if (p
->family
== AF_INET
) {
424 if (PIM_DEBUG_ZEBRA
) {
426 prefix2str(p
, buf
, BUFSIZ
);
428 "%s: %s(%u) disconnected IP address %s flags %u %s",
429 __PRETTY_FUNCTION__
, c
->ifp
->name
, vrf_id
, buf
,
431 CHECK_FLAG(c
->flags
, ZEBRA_IFA_SECONDARY
)
435 #ifdef PIM_DEBUG_IFADDR_DUMP
436 dump_if_address(c
->ifp
);
440 pim_if_addr_del(c
, 0);
442 pim_i_am_rp_re_evaluate(pim
);
449 void pim_zebra_update_all_interfaces(struct pim_instance
*pim
)
451 struct interface
*ifp
;
453 FOR_ALL_INTERFACES (pim
->vrf
, ifp
) {
454 struct pim_interface
*pim_ifp
= ifp
->info
;
455 struct pim_iface_upstream_switch
*us
;
456 struct listnode
*node
;
461 for (ALL_LIST_ELEMENTS_RO(pim_ifp
->upstream_switch_list
, node
,
465 rpf
.source_nexthop
.interface
= ifp
;
466 rpf
.rpf_addr
.u
.prefix4
= us
->address
;
467 pim_joinprune_send(&rpf
, us
->us
);
468 pim_jp_agg_clear_group(us
->us
);
473 void pim_zebra_upstream_rpf_changed(struct pim_instance
*pim
,
474 struct pim_upstream
*up
,
477 if (old
->source_nexthop
.interface
) {
478 struct pim_neighbor
*nbr
;
480 nbr
= pim_neighbor_find(old
->source_nexthop
.interface
,
481 old
->rpf_addr
.u
.prefix4
);
483 pim_jp_agg_remove_group(nbr
->upstream_jp_agg
, up
);
486 * We have detected a case where we might need
487 * to rescan the inherited o_list so do it.
489 if (up
->channel_oil
->oil_inherited_rescan
) {
490 pim_upstream_inherited_olist_decide(pim
, up
);
491 up
->channel_oil
->oil_inherited_rescan
= 0;
494 if (up
->join_state
== PIM_UPSTREAM_JOINED
) {
496 * If we come up real fast we can be here
497 * where the mroute has not been installed
500 if (!up
->channel_oil
->installed
)
501 pim_mroute_add(up
->channel_oil
,
502 __PRETTY_FUNCTION__
);
505 * RFC 4601: 4.5.7. Sending (S,G)
506 * Join/Prune Messages
508 * Transitions from Joined State
510 * RPF'(S,G) changes not due to an Assert
512 * The upstream (S,G) state machine remains
513 * in Joined state. Send Join(S,G) to the new
514 * upstream neighbor, which is the new value
515 * of RPF'(S,G). Send Prune(S,G) to the old
516 * upstream neighbor, which is the old value
517 * of RPF'(S,G). Set the Join Timer (JT) to
518 * expire after t_periodic seconds.
520 pim_jp_agg_switch_interface(old
, &up
->rpf
, up
);
522 pim_upstream_join_timer_restart(up
, old
);
523 } /* up->join_state == PIM_UPSTREAM_JOINED */
528 * We have detected a case where we might need
529 * to rescan the inherited o_list so do it.
531 if (up
->channel_oil
->oil_inherited_rescan
) {
532 pim_upstream_inherited_olist_decide(pim
, up
);
533 up
->channel_oil
->oil_inherited_rescan
= 0;
536 if (!up
->channel_oil
->installed
)
537 pim_mroute_add(up
->channel_oil
, __PRETTY_FUNCTION__
);
540 /* FIXME can join_desired actually be changed by pim_rpf_update()
541 * returning PIM_RPF_CHANGED ?
543 pim_upstream_update_join_desired(pim
, up
);
546 void pim_scan_individual_oil(struct channel_oil
*c_oil
, int in_vif_index
)
548 struct in_addr vif_source
;
549 int input_iface_vif_index
;
552 pim_rp_set_upstream_addr(c_oil
->pim
, &vif_source
,
553 c_oil
->oil
.mfcc_origin
,
554 c_oil
->oil
.mfcc_mcastgrp
);
557 input_iface_vif_index
= in_vif_index
;
559 struct prefix src
, grp
;
561 src
.family
= AF_INET
;
562 src
.prefixlen
= IPV4_MAX_BITLEN
;
563 src
.u
.prefix4
= vif_source
;
564 grp
.family
= AF_INET
;
565 grp
.prefixlen
= IPV4_MAX_BITLEN
;
566 grp
.u
.prefix4
= c_oil
->oil
.mfcc_mcastgrp
;
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: channel_oil (%s,%s) upstream info is not present.",
577 __PRETTY_FUNCTION__
, source_str
, group_str
);
579 input_iface_vif_index
= pim_ecmp_fib_lookup_if_vif_index(
580 c_oil
->pim
, &src
, &grp
);
583 if (input_iface_vif_index
< 1) {
584 if (PIM_DEBUG_ZEBRA
) {
585 char source_str
[INET_ADDRSTRLEN
];
586 char group_str
[INET_ADDRSTRLEN
];
587 pim_inet4_dump("<source?>", c_oil
->oil
.mfcc_origin
,
588 source_str
, sizeof(source_str
));
589 pim_inet4_dump("<group?>", c_oil
->oil
.mfcc_mcastgrp
,
590 group_str
, sizeof(group_str
));
592 "%s %s: could not find input interface(%d) for (S,G)=(%s,%s)",
593 __FILE__
, __PRETTY_FUNCTION__
,
594 c_oil
->oil
.mfcc_parent
, source_str
, group_str
);
596 pim_mroute_del(c_oil
, __PRETTY_FUNCTION__
);
600 if (input_iface_vif_index
== c_oil
->oil
.mfcc_parent
) {
601 if (!c_oil
->installed
)
602 pim_mroute_add(c_oil
, __PRETTY_FUNCTION__
);
608 if (PIM_DEBUG_ZEBRA
) {
609 struct interface
*old_iif
= pim_if_find_by_vif_index(
610 c_oil
->pim
, c_oil
->oil
.mfcc_parent
);
611 struct interface
*new_iif
= pim_if_find_by_vif_index(
612 c_oil
->pim
, input_iface_vif_index
);
613 char source_str
[INET_ADDRSTRLEN
];
614 char group_str
[INET_ADDRSTRLEN
];
615 pim_inet4_dump("<source?>", c_oil
->oil
.mfcc_origin
, source_str
,
617 pim_inet4_dump("<group?>", c_oil
->oil
.mfcc_mcastgrp
, group_str
,
620 "%s %s: (S,G)=(%s,%s) input interface changed from %s vif_index=%d to %s vif_index=%d",
621 __FILE__
, __PRETTY_FUNCTION__
, source_str
, group_str
,
622 (old_iif
) ? old_iif
->name
: "<old_iif?>",
623 c_oil
->oil
.mfcc_parent
,
624 (new_iif
) ? new_iif
->name
: "<new_iif?>",
625 input_iface_vif_index
);
628 /* new iif loops to existing oif ? */
629 if (c_oil
->oil
.mfcc_ttls
[input_iface_vif_index
]) {
630 struct interface
*new_iif
= pim_if_find_by_vif_index(
631 c_oil
->pim
, input_iface_vif_index
);
633 if (PIM_DEBUG_ZEBRA
) {
634 char source_str
[INET_ADDRSTRLEN
];
635 char group_str
[INET_ADDRSTRLEN
];
636 pim_inet4_dump("<source?>", c_oil
->oil
.mfcc_origin
,
637 source_str
, sizeof(source_str
));
638 pim_inet4_dump("<group?>", c_oil
->oil
.mfcc_mcastgrp
,
639 group_str
, sizeof(group_str
));
641 "%s %s: (S,G)=(%s,%s) new iif loops to existing oif: %s vif_index=%d",
642 __FILE__
, __PRETTY_FUNCTION__
, source_str
,
644 (new_iif
) ? new_iif
->name
: "<new_iif?>",
645 input_iface_vif_index
);
649 /* update iif vif_index */
650 old_vif_index
= c_oil
->oil
.mfcc_parent
;
651 c_oil
->oil
.mfcc_parent
= input_iface_vif_index
;
653 /* update kernel multicast forwarding cache (MFC) */
654 if (pim_mroute_add(c_oil
, __PRETTY_FUNCTION__
)) {
655 if (PIM_DEBUG_MROUTE
) {
656 /* just log warning */
657 struct interface
*old_iif
= pim_if_find_by_vif_index(
658 c_oil
->pim
, old_vif_index
);
659 struct interface
*new_iif
= pim_if_find_by_vif_index(
660 c_oil
->pim
, input_iface_vif_index
);
661 char source_str
[INET_ADDRSTRLEN
];
662 char group_str
[INET_ADDRSTRLEN
];
663 pim_inet4_dump("<source?>", c_oil
->oil
.mfcc_origin
,
664 source_str
, sizeof(source_str
));
665 pim_inet4_dump("<group?>", c_oil
->oil
.mfcc_mcastgrp
,
666 group_str
, sizeof(group_str
));
668 "%s %s: (S,G)=(%s,%s) failure updating input interface from %s vif_index=%d to %s vif_index=%d",
669 __FILE__
, __PRETTY_FUNCTION__
, source_str
,
671 old_iif
? old_iif
->name
: "<old_iif?>",
672 c_oil
->oil
.mfcc_parent
,
673 new_iif
? new_iif
->name
: "<new_iif?>",
674 input_iface_vif_index
);
679 void pim_scan_oil(struct pim_instance
*pim
)
681 struct listnode
*node
;
682 struct listnode
*nextnode
;
683 struct channel_oil
*c_oil
;
687 pim
->scan_oil_last
= pim_time_monotonic_sec();
688 ++pim
->scan_oil_events
;
690 for (ALL_LIST_ELEMENTS(pim
->channel_oil_list
, node
, nextnode
, c_oil
)) {
691 if (c_oil
->up
&& c_oil
->up
->rpf
.source_nexthop
.interface
) {
692 ifindex
= c_oil
->up
->rpf
.source_nexthop
695 pim_if_find_vifindex_by_ifindex(pim
, ifindex
);
696 /* Pass Current selected NH vif index to mroute
699 pim_scan_individual_oil(c_oil
, vif_index
);
701 pim_scan_individual_oil(c_oil
, 0);
705 static int on_rpf_cache_refresh(struct thread
*t
)
707 struct pim_instance
*pim
= THREAD_ARG(t
);
709 /* update kernel multicast forwarding cache (MFC) */
712 pim
->rpf_cache_refresh_last
= pim_time_monotonic_sec();
713 ++pim
->rpf_cache_refresh_events
;
715 // It is called as part of pim_neighbor_add
720 void sched_rpf_cache_refresh(struct pim_instance
*pim
)
722 ++pim
->rpf_cache_refresh_requests
;
724 pim_rpf_set_refresh_time(pim
);
726 if (pim
->rpf_cache_refresher
) {
727 /* Refresh timer is already running */
731 /* Start refresh timer */
733 if (PIM_DEBUG_ZEBRA
) {
734 zlog_debug("%s: triggering %ld msec timer", __PRETTY_FUNCTION__
,
735 router
->rpf_cache_refresh_delay_msec
);
738 thread_add_timer_msec(router
->master
, on_rpf_cache_refresh
, pim
,
739 router
->rpf_cache_refresh_delay_msec
,
740 &pim
->rpf_cache_refresher
);
743 static void pim_zebra_connected(struct zclient
*zclient
)
745 /* Send the client registration */
746 bfd_client_sendmsg(zclient
, ZEBRA_BFD_CLIENT_REGISTER
);
748 zclient_send_reg_requests(zclient
, router
->vrf_id
);
751 static void pim_zebra_capabilities(struct zclient_capabilities
*cap
)
753 router
->role
= cap
->role
;
756 void pim_zebra_init(void)
758 /* Socket for receiving updates from Zebra daemon */
759 zclient
= zclient_new(router
->master
, &zclient_options_default
);
761 zclient
->zebra_capabilities
= pim_zebra_capabilities
;
762 zclient
->zebra_connected
= pim_zebra_connected
;
763 zclient
->router_id_update
= pim_router_id_update_zebra
;
764 zclient
->interface_add
= pim_zebra_if_add
;
765 zclient
->interface_delete
= pim_zebra_if_del
;
766 zclient
->interface_up
= pim_zebra_if_state_up
;
767 zclient
->interface_down
= pim_zebra_if_state_down
;
768 zclient
->interface_address_add
= pim_zebra_if_address_add
;
769 zclient
->interface_address_delete
= pim_zebra_if_address_del
;
770 zclient
->interface_vrf_update
= pim_zebra_interface_vrf_update
;
771 zclient
->nexthop_update
= pim_parse_nexthop_update
;
773 zclient_init(zclient
, ZEBRA_ROUTE_PIM
, 0, &pimd_privs
);
774 if (PIM_DEBUG_PIM_TRACE
) {
775 zlog_notice("%s: zclient socket initialized",
776 __PRETTY_FUNCTION__
);
779 zclient_lookup_new();
782 void igmp_anysource_forward_start(struct pim_instance
*pim
,
783 struct igmp_group
*group
)
785 struct igmp_source
*source
;
786 struct in_addr src_addr
= {.s_addr
= 0};
787 /* Any source (*,G) is forwarded only if mode is EXCLUDE {empty} */
788 zassert(group
->group_filtermode_isexcl
);
789 zassert(listcount(group
->group_source_list
) < 1);
791 source
= source_new(group
, src_addr
);
793 zlog_warn("%s: Failure to create * source",
794 __PRETTY_FUNCTION__
);
798 igmp_source_forward_start(pim
, source
);
801 void igmp_anysource_forward_stop(struct igmp_group
*group
)
803 struct igmp_source
*source
;
804 struct in_addr star
= {.s_addr
= 0};
806 source
= igmp_find_source_by_addr(group
, star
);
808 igmp_source_forward_stop(source
);
811 static void igmp_source_forward_reevaluate_one(struct pim_instance
*pim
,
812 struct igmp_source
*source
)
815 struct igmp_group
*group
= source
->source_group
;
816 struct pim_ifchannel
*ch
;
818 if ((source
->source_addr
.s_addr
!= INADDR_ANY
)
819 || !IGMP_SOURCE_TEST_FORWARDING(source
->source_flags
))
822 memset(&sg
, 0, sizeof(struct prefix_sg
));
823 sg
.src
= source
->source_addr
;
824 sg
.grp
= group
->group_addr
;
826 ch
= pim_ifchannel_find(group
->group_igmp_sock
->interface
, &sg
);
827 if (pim_is_grp_ssm(pim
, group
->group_addr
)) {
828 /* If SSM group withdraw local membership */
830 && (ch
->local_ifmembership
== PIM_IFMEMBERSHIP_INCLUDE
)) {
831 if (PIM_DEBUG_PIM_EVENTS
)
833 "local membership del for %s as G is now SSM",
834 pim_str_sg_dump(&sg
));
835 pim_ifchannel_local_membership_del(
836 group
->group_igmp_sock
->interface
, &sg
);
839 /* If ASM group add local membership */
841 || (ch
->local_ifmembership
== PIM_IFMEMBERSHIP_NOINFO
)) {
842 if (PIM_DEBUG_PIM_EVENTS
)
844 "local membership add for %s as G is now ASM",
845 pim_str_sg_dump(&sg
));
846 pim_ifchannel_local_membership_add(
847 group
->group_igmp_sock
->interface
, &sg
);
852 void igmp_source_forward_reevaluate_all(struct pim_instance
*pim
)
854 struct interface
*ifp
;
856 FOR_ALL_INTERFACES (pim
->vrf
, ifp
) {
857 struct pim_interface
*pim_ifp
= ifp
->info
;
858 struct listnode
*sock_node
;
859 struct igmp_sock
*igmp
;
864 /* scan igmp sockets */
865 for (ALL_LIST_ELEMENTS_RO(pim_ifp
->igmp_socket_list
, sock_node
,
867 struct listnode
*grpnode
;
868 struct igmp_group
*grp
;
870 /* scan igmp groups */
871 for (ALL_LIST_ELEMENTS_RO(igmp
->igmp_group_list
,
873 struct listnode
*srcnode
;
874 struct igmp_source
*src
;
876 /* scan group sources */
877 for (ALL_LIST_ELEMENTS_RO(
878 grp
->group_source_list
, srcnode
,
880 igmp_source_forward_reevaluate_one(pim
,
882 } /* scan group sources */
883 } /* scan igmp groups */
884 } /* scan igmp sockets */
885 } /* scan interfaces */
888 void igmp_source_forward_start(struct pim_instance
*pim
,
889 struct igmp_source
*source
)
891 struct pim_interface
*pim_oif
;
892 struct igmp_group
*group
;
895 int input_iface_vif_index
= 0;
897 memset(&sg
, 0, sizeof(struct prefix_sg
));
898 sg
.src
= source
->source_addr
;
899 sg
.grp
= source
->source_group
->group_addr
;
901 if (PIM_DEBUG_IGMP_TRACE
) {
903 "%s: (S,G)=%s igmp_sock=%d oif=%s fwd=%d",
904 __PRETTY_FUNCTION__
, pim_str_sg_dump(&sg
),
905 source
->source_group
->group_igmp_sock
->fd
,
906 source
->source_group
->group_igmp_sock
->interface
->name
,
907 IGMP_SOURCE_TEST_FORWARDING(source
->source_flags
));
910 /* Prevent IGMP interface from installing multicast route multiple
912 if (IGMP_SOURCE_TEST_FORWARDING(source
->source_flags
)) {
916 group
= source
->source_group
;
917 pim_oif
= group
->group_igmp_sock
->interface
->info
;
919 if (PIM_DEBUG_IGMP_TRACE
) {
921 "%s: multicast not enabled on oif=%s ?",
923 source
->source_group
->group_igmp_sock
929 if (!source
->source_channel_oil
) {
930 struct in_addr vif_source
;
931 struct prefix nht_p
, src
, grp
;
932 struct pim_nexthop nexthop
;
933 struct pim_upstream
*up
= NULL
;
935 if (!pim_rp_set_upstream_addr(pim
, &vif_source
,
936 source
->source_addr
, sg
.grp
)) {
937 /*Create a dummy channel oil */
938 source
->source_channel_oil
=
939 pim_channel_oil_add(pim
, &sg
, MAXVIFS
);
941 if (!source
->source_channel_oil
) {
942 if (PIM_DEBUG_IGMP_TRACE
) {
944 "%s %s: could not create OIL for channel (S,G)=%s",
945 __FILE__
, __PRETTY_FUNCTION__
,
946 pim_str_sg_dump(&sg
));
953 /* Register addr with Zebra NHT */
954 nht_p
.family
= AF_INET
;
955 nht_p
.prefixlen
= IPV4_MAX_BITLEN
;
956 nht_p
.u
.prefix4
= vif_source
;
958 src
.family
= AF_INET
;
959 src
.prefixlen
= IPV4_MAX_BITLEN
;
960 src
.u
.prefix4
= vif_source
; // RP or Src address
961 grp
.family
= AF_INET
;
962 grp
.prefixlen
= IPV4_MAX_BITLEN
;
963 grp
.u
.prefix4
= sg
.grp
;
965 up
= pim_upstream_find(pim
, &sg
);
967 memcpy(&nexthop
, &up
->rpf
.source_nexthop
,
968 sizeof(struct pim_nexthop
));
969 pim_ecmp_nexthop_lookup(pim
, &nexthop
, &src
,
971 if (nexthop
.interface
)
972 input_iface_vif_index
=
973 pim_if_find_vifindex_by_ifindex(
975 nexthop
.interface
->ifindex
);
977 input_iface_vif_index
=
978 pim_ecmp_fib_lookup_if_vif_index(
981 if (PIM_DEBUG_ZEBRA
) {
982 char buf2
[INET_ADDRSTRLEN
];
984 pim_inet4_dump("<source?>", vif_source
, buf2
,
986 zlog_debug("%s: NHT %s vif_source %s vif_index:%d ",
988 pim_str_sg_dump(&sg
),
989 buf2
, input_iface_vif_index
);
992 if (input_iface_vif_index
< 1) {
993 if (PIM_DEBUG_IGMP_TRACE
) {
994 char source_str
[INET_ADDRSTRLEN
];
995 pim_inet4_dump("<source?>",
997 source_str
, sizeof(source_str
));
999 "%s %s: could not find input interface for source %s",
1000 __FILE__
, __PRETTY_FUNCTION__
,
1003 source
->source_channel_oil
=
1004 pim_channel_oil_add(pim
, &sg
, MAXVIFS
);
1009 * Protect IGMP against adding looped MFC
1010 * entries created by both source and receiver
1011 * attached to the same interface. See TODO
1014 if (input_iface_vif_index
==
1015 pim_oif
->mroute_vif_index
) {
1016 /* ignore request for looped MFC entry
1018 if (PIM_DEBUG_IGMP_TRACE
) {
1020 "%s: ignoring request for looped MFC entry (S,G)=%s: igmp_sock=%d oif=%s vif_index=%d",
1021 __PRETTY_FUNCTION__
,
1022 pim_str_sg_dump(&sg
),
1023 source
->source_group
1024 ->group_igmp_sock
->fd
,
1025 source
->source_group
1028 input_iface_vif_index
);
1033 source
->source_channel_oil
=
1034 pim_channel_oil_add(pim
, &sg
,
1035 input_iface_vif_index
);
1036 if (!source
->source_channel_oil
) {
1037 if (PIM_DEBUG_IGMP_TRACE
) {
1039 "%s %s: could not create OIL for channel (S,G)=%s",
1041 __PRETTY_FUNCTION__
,
1042 pim_str_sg_dump(&sg
));
1050 result
= pim_channel_add_oif(source
->source_channel_oil
,
1051 group
->group_igmp_sock
->interface
,
1052 PIM_OIF_FLAG_PROTO_IGMP
);
1054 if (PIM_DEBUG_MROUTE
) {
1055 zlog_warn("%s: add_oif() failed with return=%d",
1061 if (!(PIM_I_am_DR(pim_oif
))) {
1062 if (PIM_DEBUG_IGMP_TRACE
)
1063 zlog_debug("%s: %s was received on %s interface but we are not DR for that interface",
1064 __PRETTY_FUNCTION__
,
1065 pim_str_sg_dump(&sg
),
1066 group
->group_igmp_sock
->interface
->name
);
1068 pim_channel_del_oif(source
->source_channel_oil
,
1069 group
->group_igmp_sock
->interface
,
1070 PIM_OIF_FLAG_PROTO_IGMP
);
1074 Feed IGMPv3-gathered local membership information into PIM
1075 per-interface (S,G) state.
1077 if (!pim_ifchannel_local_membership_add(
1078 group
->group_igmp_sock
->interface
, &sg
)) {
1079 if (PIM_DEBUG_MROUTE
)
1080 zlog_warn("%s: Failure to add local membership for %s",
1081 __PRETTY_FUNCTION__
, pim_str_sg_dump(&sg
));
1083 pim_channel_del_oif(source
->source_channel_oil
,
1084 group
->group_igmp_sock
->interface
,
1085 PIM_OIF_FLAG_PROTO_IGMP
);
1089 IGMP_SOURCE_DO_FORWARDING(source
->source_flags
);
1093 igmp_source_forward_stop: stop fowarding, but keep the source
1094 igmp_source_delete: stop fowarding, and delete the source
1096 void igmp_source_forward_stop(struct igmp_source
*source
)
1098 struct igmp_group
*group
;
1099 struct prefix_sg sg
;
1102 memset(&sg
, 0, sizeof(struct prefix_sg
));
1103 sg
.src
= source
->source_addr
;
1104 sg
.grp
= source
->source_group
->group_addr
;
1106 if (PIM_DEBUG_IGMP_TRACE
) {
1108 "%s: (S,G)=%s igmp_sock=%d oif=%s fwd=%d",
1109 __PRETTY_FUNCTION__
, pim_str_sg_dump(&sg
),
1110 source
->source_group
->group_igmp_sock
->fd
,
1111 source
->source_group
->group_igmp_sock
->interface
->name
,
1112 IGMP_SOURCE_TEST_FORWARDING(source
->source_flags
));
1115 /* Prevent IGMP interface from removing multicast route multiple
1117 if (!IGMP_SOURCE_TEST_FORWARDING(source
->source_flags
)) {
1121 group
= source
->source_group
;
1124 It appears that in certain circumstances that
1125 igmp_source_forward_stop is called when IGMP forwarding
1126 was not enabled in oif_flags for this outgoing interface.
1127 Possibly because of multiple calls. When that happens, we
1128 enter the below if statement and this function returns early
1129 which in turn triggers the calling function to assert.
1130 Making the call to pim_channel_del_oif and ignoring the return code
1131 fixes the issue without ill effect, similar to
1132 pim_forward_stop below.
1134 result
= pim_channel_del_oif(source
->source_channel_oil
,
1135 group
->group_igmp_sock
->interface
,
1136 PIM_OIF_FLAG_PROTO_IGMP
);
1138 if (PIM_DEBUG_IGMP_TRACE
)
1140 "%s: pim_channel_del_oif() failed with return=%d",
1146 Feed IGMPv3-gathered local membership information into PIM
1147 per-interface (S,G) state.
1149 pim_ifchannel_local_membership_del(group
->group_igmp_sock
->interface
,
1152 IGMP_SOURCE_DONT_FORWARDING(source
->source_flags
);
1155 void pim_forward_start(struct pim_ifchannel
*ch
)
1157 struct pim_upstream
*up
= ch
->upstream
;
1158 uint32_t mask
= PIM_OIF_FLAG_PROTO_PIM
;
1159 int input_iface_vif_index
= 0;
1160 struct pim_instance
*pim
;
1161 struct pim_interface
*pim_ifp
;
1163 pim_ifp
= ch
->interface
->info
;
1166 if (PIM_DEBUG_PIM_TRACE
) {
1167 char source_str
[INET_ADDRSTRLEN
];
1168 char group_str
[INET_ADDRSTRLEN
];
1169 char upstream_str
[INET_ADDRSTRLEN
];
1171 pim_inet4_dump("<source?>", ch
->sg
.src
, source_str
,
1172 sizeof(source_str
));
1173 pim_inet4_dump("<group?>", ch
->sg
.grp
, group_str
,
1175 pim_inet4_dump("<upstream?>", up
->upstream_addr
, upstream_str
,
1176 sizeof(upstream_str
));
1177 zlog_debug("%s: (S,G)=(%s,%s) oif=%s (%s)", __PRETTY_FUNCTION__
,
1178 source_str
, group_str
, ch
->interface
->name
,
1179 inet_ntoa(up
->upstream_addr
));
1182 /* Resolve IIF for upstream as mroute_del sets mfcc_parent to MAXVIFS,
1183 as part of mroute_del called by pim_forward_stop.
1185 if ((up
->upstream_addr
.s_addr
!= INADDR_ANY
) && (!up
->channel_oil
)) {
1186 struct prefix nht_p
, src
, grp
;
1188 /* Register addr with Zebra NHT */
1189 nht_p
.family
= AF_INET
;
1190 nht_p
.prefixlen
= IPV4_MAX_BITLEN
;
1191 nht_p
.u
.prefix4
= up
->upstream_addr
;
1192 grp
.family
= AF_INET
;
1193 grp
.prefixlen
= IPV4_MAX_BITLEN
;
1194 grp
.u
.prefix4
= up
->sg
.grp
;
1195 src
.family
= AF_INET
;
1196 src
.prefixlen
= IPV4_MAX_BITLEN
;
1197 src
.u
.prefix4
= up
->sg
.src
;
1199 if (pim_ecmp_nexthop_lookup(pim
, &up
->rpf
.source_nexthop
, &src
,
1201 input_iface_vif_index
= pim_if_find_vifindex_by_ifindex(
1202 pim
, up
->rpf
.source_nexthop
.interface
->ifindex
);
1204 if (input_iface_vif_index
< 1) {
1205 if (PIM_DEBUG_PIM_TRACE
) {
1206 char source_str
[INET_ADDRSTRLEN
];
1207 pim_inet4_dump("<source?>", up
->sg
.src
,
1208 source_str
, sizeof(source_str
));
1210 "%s %s: could not find input interface for source %s",
1211 __FILE__
, __PRETTY_FUNCTION__
,
1214 up
->channel_oil
= pim_channel_oil_add(pim
, &up
->sg
,
1219 up
->channel_oil
= pim_channel_oil_add(pim
, &up
->sg
,
1220 input_iface_vif_index
);
1221 if (!up
->channel_oil
) {
1222 if (PIM_DEBUG_PIM_TRACE
)
1224 "%s %s: could not create OIL for channel (S,G)=%s",
1225 __FILE__
, __PRETTY_FUNCTION__
,
1231 if (PIM_DEBUG_TRACE
) {
1232 struct interface
*in_intf
= pim_if_find_by_vif_index(
1233 pim
, input_iface_vif_index
);
1235 "%s: Update channel_oil IIF %s VIFI %d entry %s ",
1236 __PRETTY_FUNCTION__
,
1237 in_intf
? in_intf
->name
: "Unknown",
1238 input_iface_vif_index
, up
->sg_str
);
1241 up
->channel_oil
= pim_channel_oil_add(pim
, &up
->sg
,
1242 input_iface_vif_index
);
1243 if (!up
->channel_oil
) {
1244 if (PIM_DEBUG_PIM_TRACE
)
1246 "%s %s: could not create OIL for channel (S,G)=%s",
1247 __FILE__
, __PRETTY_FUNCTION__
,
1253 if (up
->flags
& PIM_UPSTREAM_FLAG_MASK_SRC_IGMP
)
1254 mask
= PIM_OIF_FLAG_PROTO_IGMP
;
1256 pim_channel_add_oif(up
->channel_oil
, ch
->interface
, mask
);
1259 void pim_forward_stop(struct pim_ifchannel
*ch
, bool install_it
)
1261 struct pim_upstream
*up
= ch
->upstream
;
1263 if (PIM_DEBUG_PIM_TRACE
) {
1264 zlog_debug("%s: (S,G)=%s oif=%s install_it: %d installed: %d",
1265 __PRETTY_FUNCTION__
, ch
->sg_str
, ch
->interface
->name
,
1266 install_it
, up
->channel_oil
->installed
);
1269 pim_channel_del_oif(up
->channel_oil
, ch
->interface
,
1270 PIM_OIF_FLAG_PROTO_PIM
);
1272 if (install_it
&& !up
->channel_oil
->installed
)
1273 pim_mroute_add(up
->channel_oil
, __PRETTY_FUNCTION__
);
1276 void pim_zebra_zclient_update(struct vty
*vty
)
1278 vty_out(vty
, "Zclient update socket: ");
1281 vty_out(vty
, "%d failures=%d\n", zclient
->sock
, zclient
->fail
);
1283 vty_out(vty
, "<null zclient>\n");
1287 struct zclient
*pim_zebra_zclient_get(void)