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"
35 #include "pim_zebra.h"
36 #include "pim_iface.h"
42 #include "pim_zlookup.h"
43 #include "pim_ifchannel.h"
45 #include "pim_igmpv3.h"
46 #include "pim_jp_agg.h"
50 #undef PIM_DEBUG_IFADDR_DUMP
51 #define PIM_DEBUG_IFADDR_DUMP
53 static struct zclient
*zclient
= NULL
;
56 /* Router-id update message from zebra. */
57 static int pim_router_id_update_zebra(int command
, struct zclient
*zclient
,
58 zebra_size_t length
, vrf_id_t vrf_id
)
60 struct prefix router_id
;
62 zebra_router_id_update_read(zclient
->ibuf
, &router_id
);
67 static int pim_zebra_if_add(int command
, struct zclient
*zclient
,
68 zebra_size_t length
, vrf_id_t vrf_id
)
70 struct interface
*ifp
;
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 if (PIM_DEBUG_ZEBRA
) {
81 zlog_debug("%s: %s index %d flags %ld metric %d mtu %d operative %d",
83 ifp
->name
, ifp
->ifindex
, (long)ifp
->flags
, ifp
->metric
,
84 ifp
->mtu
, if_is_operative(ifp
));
87 if (if_is_operative(ifp
))
88 pim_if_addr_add_all(ifp
);
93 static int pim_zebra_if_del(int command
, struct zclient
*zclient
,
94 zebra_size_t length
, vrf_id_t vrf_id
)
96 struct interface
*ifp
;
99 zebra api adds/dels interfaces using the same call
100 interface_add_read below, see comments in lib/zclient.c
102 comments in lib/zclient.c seem to indicate that calling
103 zebra_interface_add_read is the correct call, but that
104 results in an attemted out of bounds read which causes
105 pimd to assert. Other clients use zebra_interface_state_read
106 and it appears to work just fine.
108 ifp
= zebra_interface_state_read(zclient
->ibuf
, vrf_id
);
112 if (PIM_DEBUG_ZEBRA
) {
113 zlog_debug("%s: %s index %d flags %ld metric %d mtu %d operative %d",
115 ifp
->name
, ifp
->ifindex
, (long)ifp
->flags
, ifp
->metric
,
116 ifp
->mtu
, if_is_operative(ifp
));
119 if (!if_is_operative(ifp
))
120 pim_if_addr_del_all(ifp
);
125 static int pim_zebra_if_state_up(int command
, struct zclient
*zclient
,
126 zebra_size_t length
, vrf_id_t vrf_id
)
128 struct interface
*ifp
;
131 zebra api notifies interface up/down events by using the same call
132 zebra_interface_state_read below, see comments in lib/zclient.c
134 ifp
= zebra_interface_state_read(zclient
->ibuf
, vrf_id
);
138 if (PIM_DEBUG_ZEBRA
) {
139 zlog_debug("%s: %s index %d flags %ld metric %d mtu %d operative %d",
141 ifp
->name
, ifp
->ifindex
, (long)ifp
->flags
, ifp
->metric
,
142 ifp
->mtu
, if_is_operative(ifp
));
145 if (if_is_operative(ifp
)) {
147 pim_if_addr_add_all() suffices for bringing up both IGMP and PIM
149 pim_if_addr_add_all(ifp
);
155 static int pim_zebra_if_state_down(int command
, struct zclient
*zclient
,
156 zebra_size_t length
, vrf_id_t vrf_id
)
158 struct interface
*ifp
;
161 zebra api notifies interface up/down events by using the same call
162 zebra_interface_state_read below, see comments in lib/zclient.c
164 ifp
= zebra_interface_state_read(zclient
->ibuf
, vrf_id
);
168 if (PIM_DEBUG_ZEBRA
) {
169 zlog_debug("%s: %s index %d flags %ld metric %d mtu %d operative %d",
171 ifp
->name
, ifp
->ifindex
, (long)ifp
->flags
, ifp
->metric
,
172 ifp
->mtu
, if_is_operative(ifp
));
175 if (!if_is_operative(ifp
)) {
176 pim_ifchannel_delete_all(ifp
);
178 pim_if_addr_del_all() suffices for shutting down IGMP,
179 but not for shutting down PIM
181 pim_if_addr_del_all(ifp
);
184 pim_sock_delete() closes the socket, stops read and timer threads,
185 and kills all neighbors.
188 pim_sock_delete(ifp
, "link down");
198 #ifdef PIM_DEBUG_IFADDR_DUMP
199 static void dump_if_address(struct interface
*ifp
)
201 struct connected
*ifc
;
202 struct listnode
*node
;
204 zlog_debug("%s %s: interface %s addresses:",
205 __FILE__
, __PRETTY_FUNCTION__
,
208 for (ALL_LIST_ELEMENTS_RO(ifp
->connected
, node
, ifc
)) {
209 struct prefix
*p
= ifc
->address
;
211 if (p
->family
!= AF_INET
)
214 zlog_debug("%s %s: interface %s address %s %s",
215 __FILE__
, __PRETTY_FUNCTION__
,
217 inet_ntoa(p
->u
.prefix4
),
218 CHECK_FLAG(ifc
->flags
, ZEBRA_IFA_SECONDARY
) ?
219 "secondary" : "primary");
224 static int pim_zebra_if_address_add(int command
, struct zclient
*zclient
,
225 zebra_size_t length
, vrf_id_t vrf_id
)
229 struct pim_interface
*pim_ifp
;
232 zebra api notifies address adds/dels events by using the same call
233 interface_add_read below, see comments in lib/zclient.c
235 zebra_interface_address_read(ZEBRA_INTERFACE_ADDRESS_ADD, ...)
236 will add address to interface list by calling
237 connected_add_by_prefix()
239 c
= zebra_interface_address_read(command
, zclient
->ibuf
, vrf_id
);
243 pim_ifp
= c
->ifp
->info
;
246 if (PIM_DEBUG_ZEBRA
) {
248 prefix2str(p
, buf
, BUFSIZ
);
249 zlog_debug("%s: %s connected IP address %s flags %u %s",
251 c
->ifp
->name
, buf
, c
->flags
,
252 CHECK_FLAG(c
->flags
, ZEBRA_IFA_SECONDARY
) ? "secondary" : "primary");
254 #ifdef PIM_DEBUG_IFADDR_DUMP
255 dump_if_address(c
->ifp
);
259 if (!CHECK_FLAG(c
->flags
, ZEBRA_IFA_SECONDARY
)) {
260 /* trying to add primary address */
262 struct in_addr primary_addr
= pim_find_primary_addr(c
->ifp
);
263 if (p
->family
!= AF_INET
|| primary_addr
.s_addr
!= p
->u
.prefix4
.s_addr
) {
264 if (PIM_DEBUG_ZEBRA
) {
265 /* but we had a primary address already */
269 prefix2str(p
, buf
, BUFSIZ
);
271 zlog_warn("%s: %s : forcing secondary flag on %s",
275 SET_FLAG(c
->flags
, ZEBRA_IFA_SECONDARY
);
281 pim_rp_check_on_if_add(pim_ifp
);
283 if (if_is_loopback (c
->ifp
))
285 struct listnode
*ifnode
;
286 struct interface
*ifp
;
288 for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT
), ifnode
, ifp
))
290 if (!if_is_loopback (ifp
) && if_is_operative (ifp
))
291 pim_if_addr_add_all (ifp
);
298 static int pim_zebra_if_address_del(int command
, struct zclient
*client
,
299 zebra_size_t length
, vrf_id_t vrf_id
)
305 zebra api notifies address adds/dels events by using the same call
306 interface_add_read below, see comments in lib/zclient.c
308 zebra_interface_address_read(ZEBRA_INTERFACE_ADDRESS_DELETE, ...)
309 will remove address from interface list by calling
310 connected_delete_by_prefix()
312 c
= zebra_interface_address_read(command
, client
->ibuf
, vrf_id
);
317 if (p
->family
== AF_INET
)
319 if (PIM_DEBUG_ZEBRA
) {
321 prefix2str(p
, buf
, BUFSIZ
);
322 zlog_debug("%s: %s disconnected IP address %s flags %u %s",
324 c
->ifp
->name
, buf
, c
->flags
,
325 CHECK_FLAG(c
->flags
, ZEBRA_IFA_SECONDARY
) ? "secondary" : "primary");
327 #ifdef PIM_DEBUG_IFADDR_DUMP
328 dump_if_address(c
->ifp
);
332 pim_if_addr_del(c
, 0);
334 pim_i_am_rp_re_evaluate();
341 static void scan_upstream_rpf_cache()
343 struct listnode
*up_node
;
344 struct listnode
*ifnode
;
345 struct listnode
*up_nextnode
;
346 struct listnode
*node
;
347 struct pim_upstream
*up
;
348 struct interface
*ifp
;
350 for (ALL_LIST_ELEMENTS(pim_upstream_list
, up_node
, up_nextnode
, up
)) {
351 enum pim_rpf_result rpf_result
;
355 nht_p
.family
= AF_INET
;
356 nht_p
.prefixlen
= IPV4_MAX_BITLEN
;
357 nht_p
.u
.prefix4
.s_addr
= up
->upstream_addr
.s_addr
;
358 pim_resolve_upstream_nh (&nht_p
);
360 old
.source_nexthop
.interface
= up
->rpf
.source_nexthop
.interface
;
361 old
.source_nexthop
.nbr
= up
->rpf
.source_nexthop
.nbr
;
362 rpf_result
= pim_rpf_update(up
, &old
, 0);
364 if (rpf_result
== PIM_RPF_FAILURE
)
367 if (rpf_result
== PIM_RPF_CHANGED
) {
368 struct pim_neighbor
*nbr
;
370 nbr
= pim_neighbor_find (old
.source_nexthop
.interface
,
371 old
.rpf_addr
.u
.prefix4
);
373 pim_jp_agg_remove_group (nbr
->upstream_jp_agg
, up
);
376 * We have detected a case where we might need to rescan
377 * the inherited o_list so do it.
379 if (up
->channel_oil
->oil_inherited_rescan
)
381 pim_upstream_inherited_olist_decide (up
);
382 up
->channel_oil
->oil_inherited_rescan
= 0;
385 if (up
->join_state
== PIM_UPSTREAM_JOINED
) {
387 * If we come up real fast we can be here
388 * where the mroute has not been installed
391 if (!up
->channel_oil
->installed
)
392 pim_mroute_add (up
->channel_oil
, __PRETTY_FUNCTION__
);
395 * RFC 4601: 4.5.7. Sending (S,G) Join/Prune Messages
397 * Transitions from Joined State
399 * RPF'(S,G) changes not due to an Assert
401 * The upstream (S,G) state machine remains in Joined
402 * state. Send Join(S,G) to the new upstream neighbor, which is
403 * the new value of RPF'(S,G). Send Prune(S,G) to the old
404 * upstream neighbor, which is the old value of RPF'(S,G). Set
405 * the Join Timer (JT) to expire after t_periodic seconds.
407 pim_jp_agg_switch_interface (&old
, &up
->rpf
, up
);
409 pim_upstream_join_timer_restart(up
, &old
);
410 } /* up->join_state == PIM_UPSTREAM_JOINED */
412 /* FIXME can join_desired actually be changed by pim_rpf_update()
413 returning PIM_RPF_CHANGED ? */
414 pim_upstream_update_join_desired(up
);
416 } /* PIM_RPF_CHANGED */
418 } /* for (qpim_upstream_list) */
420 for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT
), ifnode
, ifp
))
423 struct pim_interface
*pim_ifp
= ifp
->info
;
424 struct pim_iface_upstream_switch
*us
;
426 for (ALL_LIST_ELEMENTS_RO(pim_ifp
->upstream_switch_list
, node
, us
))
429 rpf
.source_nexthop
.interface
= ifp
;
430 rpf
.rpf_addr
.u
.prefix4
= us
->address
;
431 pim_joinprune_send(&rpf
, us
->us
);
432 pim_jp_agg_clear_group(us
->us
);
438 pim_scan_individual_oil (struct channel_oil
*c_oil
, int in_vif_index
)
440 struct in_addr vif_source
;
441 int input_iface_vif_index
;
444 if (!pim_rp_set_upstream_addr (&vif_source
, c_oil
->oil
.mfcc_origin
, c_oil
->oil
.mfcc_mcastgrp
))
448 input_iface_vif_index
= in_vif_index
;
451 struct prefix src
, grp
;
453 src
.family
= AF_INET
;
454 src
.prefixlen
= IPV4_MAX_BITLEN
;
455 src
.u
.prefix4
= vif_source
;
456 grp
.family
= AF_INET
;
457 grp
.prefixlen
= IPV4_MAX_BITLEN
;
458 grp
.u
.prefix4
= c_oil
->oil
.mfcc_mcastgrp
;
462 char source_str
[INET_ADDRSTRLEN
];
463 char group_str
[INET_ADDRSTRLEN
];
464 pim_inet4_dump("<source?>", c_oil
->oil
.mfcc_origin
, source_str
, sizeof(source_str
));
465 pim_inet4_dump("<group?>", c_oil
->oil
.mfcc_mcastgrp
, group_str
, sizeof(group_str
));
466 zlog_debug ("%s: channel_oil (%s, %s) upstream info is not present.",
467 __PRETTY_FUNCTION__
, source_str
, group_str
);
469 input_iface_vif_index
= pim_ecmp_fib_lookup_if_vif_index(vif_source
, &src
, &grp
);
472 if (input_iface_vif_index
< 1)
476 char source_str
[INET_ADDRSTRLEN
];
477 char group_str
[INET_ADDRSTRLEN
];
478 pim_inet4_dump("<source?>", c_oil
->oil
.mfcc_origin
, source_str
, sizeof(source_str
));
479 pim_inet4_dump("<group?>", c_oil
->oil
.mfcc_mcastgrp
, group_str
, sizeof(group_str
));
480 zlog_debug("%s %s: could not find input interface(%d) for (S,G)=(%s,%s)",
481 __FILE__
, __PRETTY_FUNCTION__
, c_oil
->oil
.mfcc_parent
,
482 source_str
, group_str
);
484 pim_mroute_del (c_oil
, __PRETTY_FUNCTION__
);
488 if (input_iface_vif_index
== c_oil
->oil
.mfcc_parent
)
490 if (!c_oil
->installed
)
491 pim_mroute_add (c_oil
, __PRETTY_FUNCTION__
);
499 struct interface
*old_iif
= pim_if_find_by_vif_index(c_oil
->oil
.mfcc_parent
);
500 struct interface
*new_iif
= pim_if_find_by_vif_index(input_iface_vif_index
);
501 char source_str
[INET_ADDRSTRLEN
];
502 char group_str
[INET_ADDRSTRLEN
];
503 pim_inet4_dump("<source?>", c_oil
->oil
.mfcc_origin
, source_str
, sizeof(source_str
));
504 pim_inet4_dump("<group?>", c_oil
->oil
.mfcc_mcastgrp
, group_str
, sizeof(group_str
));
505 zlog_debug("%s %s: (S,G)=(%s,%s) input interface changed from %s vif_index=%d to %s vif_index=%d",
506 __FILE__
, __PRETTY_FUNCTION__
,
507 source_str
, group_str
,
508 old_iif
->name
, c_oil
->oil
.mfcc_parent
,
509 new_iif
->name
, input_iface_vif_index
);
512 /* new iif loops to existing oif ? */
513 if (c_oil
->oil
.mfcc_ttls
[input_iface_vif_index
])
515 struct interface
*new_iif
= pim_if_find_by_vif_index(input_iface_vif_index
);
517 if (PIM_DEBUG_ZEBRA
) {
518 char source_str
[INET_ADDRSTRLEN
];
519 char group_str
[INET_ADDRSTRLEN
];
520 pim_inet4_dump("<source?>", c_oil
->oil
.mfcc_origin
, source_str
, sizeof(source_str
));
521 pim_inet4_dump("<group?>", c_oil
->oil
.mfcc_mcastgrp
, group_str
, sizeof(group_str
));
522 zlog_debug("%s %s: (S,G)=(%s,%s) new iif loops to existing oif: %s vif_index=%d",
523 __FILE__
, __PRETTY_FUNCTION__
,
524 source_str
, group_str
,
525 new_iif
->name
, input_iface_vif_index
);
529 /* update iif vif_index */
530 old_vif_index
= c_oil
->oil
.mfcc_parent
;
531 c_oil
->oil
.mfcc_parent
= input_iface_vif_index
;
533 /* update kernel multicast forwarding cache (MFC) */
534 if (pim_mroute_add(c_oil
, __PRETTY_FUNCTION__
))
536 if (PIM_DEBUG_MROUTE
)
538 /* just log warning */
539 struct interface
*old_iif
= pim_if_find_by_vif_index(old_vif_index
);
540 struct interface
*new_iif
= pim_if_find_by_vif_index(input_iface_vif_index
);
541 char source_str
[INET_ADDRSTRLEN
];
542 char group_str
[INET_ADDRSTRLEN
];
543 pim_inet4_dump("<source?>", c_oil
->oil
.mfcc_origin
, source_str
, sizeof(source_str
));
544 pim_inet4_dump("<group?>", c_oil
->oil
.mfcc_mcastgrp
, group_str
, sizeof(group_str
));
545 zlog_debug("%s %s: (S,G)=(%s,%s) failure updating input interface from %s vif_index=%d to %s vif_index=%d",
546 __FILE__
, __PRETTY_FUNCTION__
,
547 source_str
, group_str
,
548 old_iif
? old_iif
->name
: "<old_iif?>", c_oil
->oil
.mfcc_parent
,
549 new_iif
? new_iif
->name
: "<new_iif?>", input_iface_vif_index
);
556 struct listnode
*node
;
557 struct listnode
*nextnode
;
558 struct channel_oil
*c_oil
;
562 qpim_scan_oil_last
= pim_time_monotonic_sec();
563 ++qpim_scan_oil_events
;
565 for (ALL_LIST_ELEMENTS(pim_channel_oil_list
, node
, nextnode
, c_oil
))
567 if (c_oil
->up
&& c_oil
->up
->rpf
.source_nexthop
.interface
)
569 ifindex
= c_oil
->up
->rpf
.source_nexthop
.interface
->ifindex
;
570 vif_index
= pim_if_find_vifindex_by_ifindex (ifindex
);
571 /* Pass Current selected NH vif index to mroute download */
573 pim_scan_individual_oil (c_oil
, vif_index
);
576 pim_scan_individual_oil (c_oil
, 0);
580 static int on_rpf_cache_refresh(struct thread
*t
)
582 zassert(qpim_rpf_cache_refresher
);
584 qpim_rpf_cache_refresher
= 0;
586 /* update PIM protocol state */
587 scan_upstream_rpf_cache();
589 /* update kernel multicast forwarding cache (MFC) */
592 qpim_rpf_cache_refresh_last
= pim_time_monotonic_sec();
593 ++qpim_rpf_cache_refresh_events
;
595 //It is called as part of pim_neighbor_add
600 void sched_rpf_cache_refresh(void)
602 ++qpim_rpf_cache_refresh_requests
;
604 pim_rpf_set_refresh_time ();
606 if (qpim_rpf_cache_refresher
) {
607 /* Refresh timer is already running */
611 /* Start refresh timer */
613 if (PIM_DEBUG_ZEBRA
) {
614 zlog_debug("%s: triggering %ld msec timer",
616 qpim_rpf_cache_refresh_delay_msec
);
619 thread_add_timer_msec(master
, on_rpf_cache_refresh
, 0,
620 qpim_rpf_cache_refresh_delay_msec
,
621 &qpim_rpf_cache_refresher
);
625 pim_zebra_connected (struct zclient
*zclient
)
627 zclient_send_reg_requests (zclient
, VRF_DEFAULT
);
630 void pim_zebra_init(void)
634 #ifdef HAVE_TCP_ZEBRA
635 zlog_notice("zclient update contacting ZEBRA daemon at socket TCP %s,%d", "127.0.0.1", ZEBRA_PORT
);
637 zlog_notice("zclient update contacting ZEBRA daemon at socket UNIX %s", zclient_serv_path_get());
640 /* Socket for receiving updates from Zebra daemon */
641 zclient
= zclient_new (master
);
643 zclient
->zebra_connected
= pim_zebra_connected
;
644 zclient
->router_id_update
= pim_router_id_update_zebra
;
645 zclient
->interface_add
= pim_zebra_if_add
;
646 zclient
->interface_delete
= pim_zebra_if_del
;
647 zclient
->interface_up
= pim_zebra_if_state_up
;
648 zclient
->interface_down
= pim_zebra_if_state_down
;
649 zclient
->interface_address_add
= pim_zebra_if_address_add
;
650 zclient
->interface_address_delete
= pim_zebra_if_address_del
;
651 zclient
->nexthop_update
= pim_parse_nexthop_update
;
653 zclient_init(zclient
, ZEBRA_ROUTE_PIM
, 0);
654 if (PIM_DEBUG_PIM_TRACE
) {
655 zlog_info("zclient_init cleared redistribution request");
658 zassert(zclient
->redist_default
== ZEBRA_ROUTE_PIM
);
660 /* Request all redistribution */
661 for (i
= 0; i
< ZEBRA_ROUTE_MAX
; i
++) {
662 if (i
== zclient
->redist_default
)
664 vrf_bitmap_set (zclient
->redist
[AFI_IP
][i
], VRF_DEFAULT
);;
665 if (PIM_DEBUG_PIM_TRACE
) {
666 zlog_debug("%s: requesting redistribution for %s (%i)",
667 __PRETTY_FUNCTION__
, zebra_route_string(i
), i
);
671 /* Request default information */
672 zclient_redistribute_default (ZEBRA_REDISTRIBUTE_DEFAULT_ADD
,
673 zclient
, VRF_DEFAULT
);
675 if (PIM_DEBUG_PIM_TRACE
) {
676 zlog_info("%s: requesting default information redistribution",
677 __PRETTY_FUNCTION__
);
679 zlog_notice("%s: zclient update socket initialized",
680 __PRETTY_FUNCTION__
);
683 zclient_lookup_new();
686 void igmp_anysource_forward_start(struct igmp_group
*group
)
688 struct igmp_source
*source
;
689 struct in_addr src_addr
= { .s_addr
= 0 };
690 /* Any source (*,G) is forwarded only if mode is EXCLUDE {empty} */
691 zassert(group
->group_filtermode_isexcl
);
692 zassert(listcount(group
->group_source_list
) < 1);
694 source
= source_new (group
, src_addr
);
697 zlog_warn ("%s: Failure to create * source", __PRETTY_FUNCTION__
);
701 igmp_source_forward_start (source
);
704 void igmp_anysource_forward_stop(struct igmp_group
*group
)
706 struct igmp_source
*source
;
707 struct in_addr star
= { .s_addr
= 0 };
709 source
= igmp_find_source_by_addr (group
, star
);
711 igmp_source_forward_stop (source
);
715 igmp_source_forward_reevaluate_one(struct igmp_source
*source
)
718 struct igmp_group
*group
= source
->source_group
;
719 struct pim_ifchannel
*ch
;
721 if ((source
->source_addr
.s_addr
!= INADDR_ANY
) ||
722 !IGMP_SOURCE_TEST_FORWARDING (source
->source_flags
))
725 memset (&sg
, 0, sizeof (struct prefix_sg
));
726 sg
.src
= source
->source_addr
;
727 sg
.grp
= group
->group_addr
;
729 ch
= pim_ifchannel_find (group
->group_igmp_sock
->interface
, &sg
);
730 if (pim_is_grp_ssm (group
->group_addr
))
732 /* If SSM group withdraw local membership */
733 if (ch
&& (ch
->local_ifmembership
== PIM_IFMEMBERSHIP_INCLUDE
))
735 if (PIM_DEBUG_PIM_EVENTS
)
736 zlog_debug ("local membership del for %s as G is now SSM",
737 pim_str_sg_dump (&sg
));
738 pim_ifchannel_local_membership_del (group
->group_igmp_sock
->interface
, &sg
);
743 /* If ASM group add local membership */
744 if (!ch
|| (ch
->local_ifmembership
== PIM_IFMEMBERSHIP_NOINFO
))
746 if (PIM_DEBUG_PIM_EVENTS
)
747 zlog_debug ("local membership add for %s as G is now ASM",
748 pim_str_sg_dump (&sg
));
749 pim_ifchannel_local_membership_add (group
->group_igmp_sock
->interface
, &sg
);
755 igmp_source_forward_reevaluate_all(void)
757 struct listnode
*ifnode
;
758 struct interface
*ifp
;
760 for (ALL_LIST_ELEMENTS_RO (vrf_iflist (VRF_DEFAULT
), ifnode
, ifp
))
762 struct pim_interface
*pim_ifp
= ifp
->info
;
763 struct listnode
*sock_node
;
764 struct igmp_sock
*igmp
;
769 /* scan igmp sockets */
770 for (ALL_LIST_ELEMENTS_RO (pim_ifp
->igmp_socket_list
, sock_node
, igmp
))
772 struct listnode
*grpnode
;
773 struct igmp_group
*grp
;
775 /* scan igmp groups */
776 for (ALL_LIST_ELEMENTS_RO (igmp
->igmp_group_list
, grpnode
, grp
))
778 struct listnode
*srcnode
;
779 struct igmp_source
*src
;
781 /* scan group sources */
782 for (ALL_LIST_ELEMENTS_RO (grp
->group_source_list
,
785 igmp_source_forward_reevaluate_one (src
);
786 } /* scan group sources */
787 } /* scan igmp groups */
788 } /* scan igmp sockets */
789 } /* scan interfaces */
792 void igmp_source_forward_start(struct igmp_source
*source
)
794 struct igmp_group
*group
;
797 int input_iface_vif_index
= 0;
799 memset (&sg
, 0, sizeof (struct prefix_sg
));
800 sg
.src
= source
->source_addr
;
801 sg
.grp
= source
->source_group
->group_addr
;
803 if (PIM_DEBUG_IGMP_TRACE
) {
804 zlog_debug("%s: (S,G)=%s igmp_sock=%d oif=%s fwd=%d",
806 pim_str_sg_dump (&sg
),
807 source
->source_group
->group_igmp_sock
->fd
,
808 source
->source_group
->group_igmp_sock
->interface
->name
,
809 IGMP_SOURCE_TEST_FORWARDING(source
->source_flags
));
812 /* Prevent IGMP interface from installing multicast route multiple
814 if (IGMP_SOURCE_TEST_FORWARDING(source
->source_flags
)) {
818 group
= source
->source_group
;
820 if (!source
->source_channel_oil
) {
821 struct in_addr vif_source
;
822 struct pim_interface
*pim_oif
;
823 struct prefix nht_p
, src
, grp
;
825 struct pim_nexthop_cache out_pnc
;
826 struct pim_nexthop nexthop
;
827 struct pim_upstream
*up
= NULL
;
829 if (!pim_rp_set_upstream_addr (&vif_source
, source
->source_addr
, sg
.grp
))
832 /* Register addr with Zebra NHT */
833 nht_p
.family
= AF_INET
;
834 nht_p
.prefixlen
= IPV4_MAX_BITLEN
;
835 nht_p
.u
.prefix4
= vif_source
;
836 memset (&out_pnc
, 0, sizeof (struct pim_nexthop_cache
));
838 src
.family
= AF_INET
;
839 src
.prefixlen
= IPV4_MAX_BITLEN
;
840 src
.u
.prefix4
= vif_source
; //RP or Src address
841 grp
.family
= AF_INET
;
842 grp
.prefixlen
= IPV4_MAX_BITLEN
;
843 grp
.u
.prefix4
= sg
.grp
;
845 if ((ret
= pim_find_or_track_nexthop (&nht_p
, NULL
, NULL
, &out_pnc
)) == 1)
847 if (out_pnc
.nexthop_num
)
849 up
= pim_upstream_find (&sg
);
850 memset (&nexthop
, 0, sizeof (struct pim_nexthop
));
852 memcpy (&nexthop
, &up
->rpf
.source_nexthop
, sizeof (struct pim_nexthop
));
853 //Compute PIM RPF using Cached nexthop
854 pim_ecmp_nexthop_search (&out_pnc
, &nexthop
, &src
, &grp
, 0);
855 if (nexthop
.interface
)
856 input_iface_vif_index
= pim_if_find_vifindex_by_ifindex (nexthop
.interface
->ifindex
);
862 char buf1
[INET_ADDRSTRLEN
];
863 char buf2
[INET_ADDRSTRLEN
];
864 pim_inet4_dump("<source?>", nht_p
.u
.prefix4
, buf1
, sizeof(buf1
));
865 pim_inet4_dump("<source?>", grp
.u
.prefix4
, buf2
, sizeof(buf2
));
866 zlog_debug ("%s: NHT Nexthop not found for addr %s grp %s" ,
867 __PRETTY_FUNCTION__
, buf1
, buf2
);
872 input_iface_vif_index
= pim_ecmp_fib_lookup_if_vif_index(vif_source
, &src
, &grp
);
876 char buf2
[INET_ADDRSTRLEN
];
877 pim_inet4_dump("<source?>", vif_source
, buf2
, sizeof(buf2
));
878 zlog_debug ("%s: NHT %s vif_source %s vif_index:%d ", __PRETTY_FUNCTION__
,
879 pim_str_sg_dump (&sg
), buf2
, input_iface_vif_index
);
882 if (input_iface_vif_index
< 1) {
883 if (PIM_DEBUG_IGMP_TRACE
)
885 char source_str
[INET_ADDRSTRLEN
];
886 pim_inet4_dump("<source?>", source
->source_addr
, source_str
, sizeof(source_str
));
887 zlog_debug("%s %s: could not find input interface for source %s",
888 __FILE__
, __PRETTY_FUNCTION__
,
895 Protect IGMP against adding looped MFC entries created by both
896 source and receiver attached to the same interface. See TODO
899 pim_oif
= source
->source_group
->group_igmp_sock
->interface
->info
;
901 if (PIM_DEBUG_IGMP_TRACE
)
903 zlog_debug("%s: multicast not enabled on oif=%s ?",
905 source
->source_group
->group_igmp_sock
->interface
->name
);
910 if (input_iface_vif_index
== pim_oif
->mroute_vif_index
) {
911 /* ignore request for looped MFC entry */
912 if (PIM_DEBUG_IGMP_TRACE
) {
913 zlog_debug("%s: ignoring request for looped MFC entry (S,G)=%s: igmp_sock=%d oif=%s vif_index=%d",
915 pim_str_sg_dump (&sg
),
916 source
->source_group
->group_igmp_sock
->fd
,
917 source
->source_group
->group_igmp_sock
->interface
->name
,
918 input_iface_vif_index
);
923 source
->source_channel_oil
= pim_channel_oil_add(&sg
,
924 input_iface_vif_index
);
925 if (!source
->source_channel_oil
) {
926 if (PIM_DEBUG_IGMP_TRACE
)
928 zlog_debug("%s %s: could not create OIL for channel (S,G)=%s",
929 __FILE__
, __PRETTY_FUNCTION__
,
930 pim_str_sg_dump (&sg
));
936 result
= pim_channel_add_oif(source
->source_channel_oil
,
937 group
->group_igmp_sock
->interface
,
938 PIM_OIF_FLAG_PROTO_IGMP
);
940 if (PIM_DEBUG_MROUTE
)
942 zlog_warn("%s: add_oif() failed with return=%d",
949 Feed IGMPv3-gathered local membership information into PIM
950 per-interface (S,G) state.
952 if (!pim_ifchannel_local_membership_add(group
->group_igmp_sock
->interface
, &sg
))
954 if (PIM_DEBUG_MROUTE
)
955 zlog_warn ("%s: Failure to add local membership for %s",
956 __PRETTY_FUNCTION__
, pim_str_sg_dump (&sg
));
960 IGMP_SOURCE_DO_FORWARDING(source
->source_flags
);
964 igmp_source_forward_stop: stop fowarding, but keep the source
965 igmp_source_delete: stop fowarding, and delete the source
967 void igmp_source_forward_stop(struct igmp_source
*source
)
969 struct igmp_group
*group
;
973 memset (&sg
, 0, sizeof (struct prefix_sg
));
974 sg
.src
= source
->source_addr
;
975 sg
.grp
= source
->source_group
->group_addr
;
977 if (PIM_DEBUG_IGMP_TRACE
) {
978 zlog_debug("%s: (S,G)=%s igmp_sock=%d oif=%s fwd=%d",
980 pim_str_sg_dump (&sg
),
981 source
->source_group
->group_igmp_sock
->fd
,
982 source
->source_group
->group_igmp_sock
->interface
->name
,
983 IGMP_SOURCE_TEST_FORWARDING(source
->source_flags
));
986 /* Prevent IGMP interface from removing multicast route multiple
988 if (!IGMP_SOURCE_TEST_FORWARDING(source
->source_flags
)) {
992 group
= source
->source_group
;
995 It appears that in certain circumstances that
996 igmp_source_forward_stop is called when IGMP forwarding
997 was not enabled in oif_flags for this outgoing interface.
998 Possibly because of multiple calls. When that happens, we
999 enter the below if statement and this function returns early
1000 which in turn triggers the calling function to assert.
1001 Making the call to pim_channel_del_oif and ignoring the return code
1002 fixes the issue without ill effect, similar to
1003 pim_forward_stop below.
1005 result
= pim_channel_del_oif(source
->source_channel_oil
,
1006 group
->group_igmp_sock
->interface
,
1007 PIM_OIF_FLAG_PROTO_IGMP
);
1009 if (PIM_DEBUG_IGMP_TRACE
)
1010 zlog_debug("%s: pim_channel_del_oif() failed with return=%d",
1016 Feed IGMPv3-gathered local membership information into PIM
1017 per-interface (S,G) state.
1019 pim_ifchannel_local_membership_del(group
->group_igmp_sock
->interface
,
1022 IGMP_SOURCE_DONT_FORWARDING(source
->source_flags
);
1025 void pim_forward_start(struct pim_ifchannel
*ch
)
1027 struct pim_upstream
*up
= ch
->upstream
;
1028 uint32_t mask
= PIM_OIF_FLAG_PROTO_PIM
;
1029 int input_iface_vif_index
= 0;
1031 if (PIM_DEBUG_PIM_TRACE
) {
1032 char source_str
[INET_ADDRSTRLEN
];
1033 char group_str
[INET_ADDRSTRLEN
];
1034 char upstream_str
[INET_ADDRSTRLEN
];
1036 pim_inet4_dump("<source?>", ch
->sg
.src
, source_str
, sizeof(source_str
));
1037 pim_inet4_dump("<group?>", ch
->sg
.grp
, group_str
, sizeof(group_str
));
1038 pim_inet4_dump("<upstream?>", up
->upstream_addr
, upstream_str
, sizeof(upstream_str
));
1039 zlog_debug("%s: (S,G)=(%s,%s) oif=%s (%s)",
1040 __PRETTY_FUNCTION__
,
1041 source_str
, group_str
, ch
->interface
->name
, upstream_str
);
1044 /* Resolve IIF for upstream as mroute_del sets mfcc_parent to MAXVIFS,
1045 as part of mroute_del called by pim_forward_stop.
1047 if (!up
->channel_oil
||
1048 (up
->channel_oil
&& up
->channel_oil
->oil
.mfcc_parent
>= MAXVIFS
))
1050 struct prefix nht_p
, src
, grp
;
1052 struct pim_nexthop_cache out_pnc
;
1054 /* Register addr with Zebra NHT */
1055 nht_p
.family
= AF_INET
;
1056 nht_p
.prefixlen
= IPV4_MAX_BITLEN
;
1057 nht_p
.u
.prefix4
.s_addr
= up
->upstream_addr
.s_addr
;
1058 grp
.family
= AF_INET
;
1059 grp
.prefixlen
= IPV4_MAX_BITLEN
;
1060 grp
.u
.prefix4
= up
->sg
.grp
;
1061 memset (&out_pnc
, 0, sizeof (struct pim_nexthop_cache
));
1063 if ((ret
= pim_find_or_track_nexthop (&nht_p
, NULL
, NULL
, &out_pnc
)) == 1)
1065 if (out_pnc
.nexthop_num
)
1067 src
.family
= AF_INET
;
1068 src
.prefixlen
= IPV4_MAX_BITLEN
;
1069 src
.u
.prefix4
= up
->upstream_addr
; //RP or Src address
1070 grp
.family
= AF_INET
;
1071 grp
.prefixlen
= IPV4_MAX_BITLEN
;
1072 grp
.u
.prefix4
= up
->sg
.grp
;
1073 //Compute PIM RPF using Cached nexthop
1074 if (pim_ecmp_nexthop_search (&out_pnc
, &up
->rpf
.source_nexthop
, &src
, &grp
, 0) == 0)
1075 input_iface_vif_index
= pim_if_find_vifindex_by_ifindex (up
->rpf
.source_nexthop
.interface
->ifindex
);
1078 if (PIM_DEBUG_TRACE
)
1079 zlog_debug ("%s: Nexthop selection failed for %s ", __PRETTY_FUNCTION__
, up
->sg_str
);
1084 if (PIM_DEBUG_ZEBRA
)
1086 char buf1
[INET_ADDRSTRLEN
];
1087 char buf2
[INET_ADDRSTRLEN
];
1088 pim_inet4_dump("<source?>", nht_p
.u
.prefix4
, buf1
, sizeof(buf1
));
1089 pim_inet4_dump("<source?>", grp
.u
.prefix4
, buf2
, sizeof(buf2
));
1090 zlog_debug ("%s: NHT pnc is NULL for addr %s grp %s" ,
1091 __PRETTY_FUNCTION__
, buf1
, buf2
);
1096 input_iface_vif_index
= pim_ecmp_fib_lookup_if_vif_index(up
->upstream_addr
, &src
, &grp
);
1098 if (input_iface_vif_index
< 1)
1100 if (PIM_DEBUG_PIM_TRACE
)
1102 char source_str
[INET_ADDRSTRLEN
];
1103 pim_inet4_dump("<source?>", up
->sg
.src
, source_str
, sizeof(source_str
));
1104 zlog_debug("%s %s: could not find input interface for source %s",
1105 __FILE__
, __PRETTY_FUNCTION__
,
1110 if (PIM_DEBUG_TRACE
)
1112 struct interface
*in_intf
= pim_if_find_by_vif_index (input_iface_vif_index
);
1113 zlog_debug ("%s: Update channel_oil IIF %s VIFI %d entry %s ",
1114 __PRETTY_FUNCTION__
, in_intf
? in_intf
->name
: "NIL",
1115 input_iface_vif_index
, up
->sg_str
);
1117 up
->channel_oil
= pim_channel_oil_add (&up
->sg
, input_iface_vif_index
);
1118 if (!up
->channel_oil
)
1120 if (PIM_DEBUG_PIM_TRACE
)
1121 zlog_debug ("%s %s: could not create OIL for channel (S,G)=%s",
1122 __FILE__
, __PRETTY_FUNCTION__
, up
->sg_str
);
1127 if (up
->flags
& PIM_UPSTREAM_FLAG_MASK_SRC_IGMP
)
1128 mask
= PIM_OIF_FLAG_PROTO_IGMP
;
1130 pim_channel_add_oif (up
->channel_oil
, ch
->interface
, mask
);
1133 void pim_forward_stop(struct pim_ifchannel
*ch
)
1135 struct pim_upstream
*up
= ch
->upstream
;
1137 if (PIM_DEBUG_PIM_TRACE
) {
1138 zlog_debug("%s: (S,G)=%s oif=%s",
1139 __PRETTY_FUNCTION__
,
1140 ch
->sg_str
, ch
->interface
->name
);
1143 pim_channel_del_oif(up
->channel_oil
,
1145 PIM_OIF_FLAG_PROTO_PIM
);
1149 pim_zebra_zclient_update (struct vty
*vty
)
1151 vty_out(vty
, "Zclient update socket: ");
1154 vty_out(vty
, "%d failures=%d%s", zclient
->sock
,
1155 zclient
->fail
, VTY_NEWLINE
);
1158 vty_out(vty
, "<null zclient>%s", VTY_NEWLINE
);
1162 struct zclient
*pim_zebra_zclient_get (void)