diff options
author | David Lamparter <equinox@opensourcerouting.org> | 2022-02-28 11:42:48 +0100 |
---|---|---|
committer | David Lamparter <equinox@opensourcerouting.org> | 2022-03-12 22:47:08 +0100 |
commit | cd6d285855954039624f115a9fad7d4abbb4574d (patch) | |
tree | ee7c2288a648ae032b552577759040daa8c7b1d3 /pimd | |
parent | pimd: add safety check to OIL add/del (diff) | |
download | frr-cd6d285855954039624f115a9fad7d4abbb4574d.tar.xz frr-cd6d285855954039624f115a9fad7d4abbb4574d.zip |
pimd: refactor/split IGMP integration
Try to untangle some spaghetti...
This is an 1:1 change that should not result in any functional
difference.
Signed-off-by: David Lamparter <equinox@opensourcerouting.org>
Diffstat (limited to 'pimd')
-rw-r--r-- | pimd/pim_igmp.c | 171 | ||||
-rw-r--r-- | pimd/pim_igmp.h | 11 | ||||
-rw-r--r-- | pimd/pim_ssm.c | 2 | ||||
-rw-r--r-- | pimd/pim_tib.c | 178 | ||||
-rw-r--r-- | pimd/pim_tib.h | 33 | ||||
-rw-r--r-- | pimd/pim_zebra.c | 329 | ||||
-rw-r--r-- | pimd/pim_zebra.h | 10 | ||||
-rw-r--r-- | pimd/subdir.am | 2 |
8 files changed, 395 insertions, 341 deletions
diff --git a/pimd/pim_igmp.c b/pimd/pim_igmp.c index 5cdefd282..289e8e457 100644 --- a/pimd/pim_igmp.c +++ b/pimd/pim_igmp.c @@ -37,11 +37,180 @@ #include "pim_str.h" #include "pim_util.h" #include "pim_time.h" -#include "pim_zebra.h" +#include "pim_ssm.h" +#include "pim_tib.h" static void group_timer_off(struct gm_group *group); static void pim_igmp_general_query(struct thread *t); +void igmp_anysource_forward_start(struct pim_instance *pim, + struct gm_group *group) +{ + struct gm_source *source; + struct in_addr src_addr = {.s_addr = 0}; + /* Any source (*,G) is forwarded only if mode is EXCLUDE {empty} */ + assert(group->group_filtermode_isexcl); + assert(listcount(group->group_source_list) < 1); + + source = igmp_get_source_by_addr(group, src_addr, NULL); + if (!source) { + zlog_warn("%s: Failure to create * source", __func__); + return; + } + + igmp_source_forward_start(pim, source); +} + +void igmp_anysource_forward_stop(struct gm_group *group) +{ + struct gm_source *source; + struct in_addr star = {.s_addr = 0}; + + source = igmp_find_source_by_addr(group, star); + if (source) + igmp_source_forward_stop(source); +} + +static void igmp_source_forward_reevaluate_one(struct pim_instance *pim, + struct gm_source *source) +{ + pim_sgaddr sg; + struct gm_group *group = source->source_group; + struct pim_ifchannel *ch; + + if ((source->source_addr.s_addr != INADDR_ANY) || + !IGMP_SOURCE_TEST_FORWARDING(source->source_flags)) + return; + + memset(&sg, 0, sizeof(sg)); + sg.src = source->source_addr; + sg.grp = group->group_addr; + + ch = pim_ifchannel_find(group->interface, &sg); + if (pim_is_grp_ssm(pim, group->group_addr)) { + /* If SSM group withdraw local membership */ + if (ch && + (ch->local_ifmembership == PIM_IFMEMBERSHIP_INCLUDE)) { + if (PIM_DEBUG_PIM_EVENTS) + zlog_debug( + "local membership del for %pSG as G is now SSM", + &sg); + pim_ifchannel_local_membership_del(group->interface, + &sg); + } + } else { + /* If ASM group add local membership */ + if (!ch || + (ch->local_ifmembership == PIM_IFMEMBERSHIP_NOINFO)) { + if (PIM_DEBUG_PIM_EVENTS) + zlog_debug( + "local membership add for %pSG as G is now ASM", + &sg); + pim_ifchannel_local_membership_add( + group->interface, &sg, false /*is_vxlan*/); + } + } +} + +void igmp_source_forward_reevaluate_all(struct pim_instance *pim) +{ + struct interface *ifp; + + FOR_ALL_INTERFACES (pim->vrf, ifp) { + struct pim_interface *pim_ifp = ifp->info; + struct listnode *grpnode; + struct gm_group *grp; + struct pim_ifchannel *ch, *ch_temp; + + if (!pim_ifp) + continue; + + /* scan igmp groups */ + for (ALL_LIST_ELEMENTS_RO(pim_ifp->gm_group_list, grpnode, + grp)) { + struct listnode *srcnode; + struct gm_source *src; + + /* scan group sources */ + for (ALL_LIST_ELEMENTS_RO(grp->group_source_list, + srcnode, src)) { + igmp_source_forward_reevaluate_one(pim, src); + } /* scan group sources */ + } /* scan igmp groups */ + + RB_FOREACH_SAFE (ch, pim_ifchannel_rb, &pim_ifp->ifchannel_rb, + ch_temp) { + if (pim_is_grp_ssm(pim, ch->sg.grp)) { + if (pim_addr_is_any(ch->sg.src)) + pim_ifchannel_delete(ch); + } + } + } /* scan interfaces */ +} + +void igmp_source_forward_start(struct pim_instance *pim, + struct gm_source *source) +{ + struct gm_group *group; + pim_sgaddr sg; + + memset(&sg, 0, sizeof(sg)); + sg.src = source->source_addr; + sg.grp = source->source_group->group_addr; + + if (PIM_DEBUG_IGMP_TRACE) { + zlog_debug("%s: (S,G)=%pSG oif=%s fwd=%d", __func__, &sg, + source->source_group->interface->name, + IGMP_SOURCE_TEST_FORWARDING(source->source_flags)); + } + + /* Prevent IGMP interface from installing multicast route multiple + times */ + if (IGMP_SOURCE_TEST_FORWARDING(source->source_flags)) { + return; + } + + group = source->source_group; + + if (tib_sg_gm_join(pim, sg, group->interface, + &source->source_channel_oil)) + IGMP_SOURCE_DO_FORWARDING(source->source_flags); +} + +/* + igmp_source_forward_stop: stop fowarding, but keep the source + igmp_source_delete: stop fowarding, and delete the source + */ +void igmp_source_forward_stop(struct gm_source *source) +{ + struct pim_interface *pim_oif; + struct gm_group *group; + pim_sgaddr sg; + + memset(&sg, 0, sizeof(sg)); + sg.src = source->source_addr; + sg.grp = source->source_group->group_addr; + + if (PIM_DEBUG_IGMP_TRACE) { + zlog_debug("%s: (S,G)=%pSG oif=%s fwd=%d", __func__, &sg, + source->source_group->interface->name, + IGMP_SOURCE_TEST_FORWARDING(source->source_flags)); + } + + /* Prevent IGMP interface from removing multicast route multiple + times */ + if (!IGMP_SOURCE_TEST_FORWARDING(source->source_flags)) { + return; + } + + group = source->source_group; + pim_oif = group->interface->info; + + tib_sg_gm_prune(pim_oif->pim, sg, group->interface, + &source->source_channel_oil); + IGMP_SOURCE_DONT_FORWARDING(source->source_flags); +} + /* This socket is used for TXing IGMP packets only, IGMP RX happens * in pim_mroute_msg() */ diff --git a/pimd/pim_igmp.h b/pimd/pim_igmp.h index 5c3599663..d1490fddf 100644 --- a/pimd/pim_igmp.h +++ b/pimd/pim_igmp.h @@ -204,6 +204,17 @@ struct gm_group { }; #if PIM_IPV == 4 +struct pim_instance; + +void igmp_anysource_forward_start(struct pim_instance *pim, + struct gm_group *group); +void igmp_anysource_forward_stop(struct gm_group *group); + +void igmp_source_forward_start(struct pim_instance *pim, + struct gm_source *source); +void igmp_source_forward_stop(struct gm_source *source); +void igmp_source_forward_reevaluate_all(struct pim_instance *pim); + struct gm_group *find_group_by_addr(struct gm_sock *igmp, struct in_addr group_addr); struct gm_group *igmp_add_group_by_addr(struct gm_sock *igmp, diff --git a/pimd/pim_ssm.c b/pimd/pim_ssm.c index 688d38c84..74310474d 100644 --- a/pimd/pim_ssm.c +++ b/pimd/pim_ssm.c @@ -28,7 +28,7 @@ #include "pimd.h" #include "pim_ssm.h" -#include "pim_zebra.h" +#include "pim_igmp.h" static void pim_ssm_range_reevaluate(struct pim_instance *pim) { diff --git a/pimd/pim_tib.c b/pimd/pim_tib.c new file mode 100644 index 000000000..838f11211 --- /dev/null +++ b/pimd/pim_tib.c @@ -0,0 +1,178 @@ +/* + * TIB (Tree Information Base) - just PIM <> IGMP/MLD glue for now + * Copyright (C) 2022 David Lamparter for NetDEF, Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include <zebra.h> + +#include "pim_tib.h" + +#include "pimd.h" +#include "pim_iface.h" +#include "pim_upstream.h" +#include "pim_oil.h" +#include "pim_nht.h" + +static struct channel_oil * +tib_sg_oil_setup(struct pim_instance *pim, pim_sgaddr sg, struct interface *oif) +{ + struct pim_interface *pim_oif = oif->info; + int input_iface_vif_index = 0; + pim_addr vif_source; + struct prefix src, grp; + struct pim_nexthop nexthop; + struct pim_upstream *up = NULL; + + if (!pim_rp_set_upstream_addr(pim, &vif_source, sg.src, sg.grp)) { + /* no PIM RP - create a dummy channel oil */ + return pim_channel_oil_add(pim, &sg, __func__); + } + + pim_addr_to_prefix(&src, vif_source); // RP or Src addr + pim_addr_to_prefix(&grp, sg.grp); + + up = pim_upstream_find(pim, &sg); + if (up) { + memcpy(&nexthop, &up->rpf.source_nexthop, + sizeof(struct pim_nexthop)); + pim_ecmp_nexthop_lookup(pim, &nexthop, &src, &grp, 0); + if (nexthop.interface) + input_iface_vif_index = pim_if_find_vifindex_by_ifindex( + pim, nexthop.interface->ifindex); + } else + input_iface_vif_index = + pim_ecmp_fib_lookup_if_vif_index(pim, &src, &grp); + + if (PIM_DEBUG_ZEBRA) + zlog_debug("%s: NHT %pSG vif_source %pPAs vif_index:%d", + __func__, &sg, &vif_source, input_iface_vif_index); + + if (input_iface_vif_index < 1) { + if (PIM_DEBUG_IGMP_TRACE) + zlog_debug( + "%s %s: could not find input interface for %pSG", + __FILE__, __func__, &sg); + + return pim_channel_oil_add(pim, &sg, __func__); + } + + /* + * Protect IGMP against adding looped MFC entries created by both + * source and receiver attached to the same interface. See TODO T22. + * Block only when the intf is non DR DR must create upstream. + */ + if ((input_iface_vif_index == pim_oif->mroute_vif_index) && + !(PIM_I_am_DR(pim_oif))) { + /* ignore request for looped MFC entry */ + if (PIM_DEBUG_IGMP_TRACE) + zlog_debug( + "%s: ignoring request for looped MFC entry (S,G)=%pSG: oif=%s vif_index=%d", + __func__, &sg, oif->name, + input_iface_vif_index); + + return NULL; + } + + return pim_channel_oil_add(pim, &sg, __func__); +} + +bool tib_sg_gm_join(struct pim_instance *pim, pim_sgaddr sg, + struct interface *oif, struct channel_oil **oilp) +{ + struct pim_interface *pim_oif = oif->info; + + if (!pim_oif) { + if (PIM_DEBUG_IGMP_TRACE) + zlog_debug("%s: multicast not enabled on oif=%s?", + __func__, oif->name); + return false; + } + + if (!*oilp) + *oilp = tib_sg_oil_setup(pim, sg, oif); + if (!*oilp) + return false; + + if (PIM_I_am_DR(pim_oif) || PIM_I_am_DualActive(pim_oif)) { + int result; + + result = pim_channel_add_oif(*oilp, oif, + PIM_OIF_FLAG_PROTO_IGMP, __func__); + if (result) { + if (PIM_DEBUG_MROUTE) + zlog_warn("%s: add_oif() failed with return=%d", + __func__, result); + return false; + } + } else { + if (PIM_DEBUG_IGMP_TRACE) + zlog_debug( + "%s: %pSG was received on %s interface but we are not DR for that interface", + __func__, &sg, oif->name); + + return false; + } + /* + Feed IGMPv3-gathered local membership information into PIM + per-interface (S,G) state. + */ + if (!pim_ifchannel_local_membership_add(oif, &sg, false /*is_vxlan*/)) { + if (PIM_DEBUG_MROUTE) + zlog_warn( + "%s: Failure to add local membership for %pSG", + __func__, &sg); + + pim_channel_del_oif(*oilp, oif, PIM_OIF_FLAG_PROTO_IGMP, + __func__); + return false; + } + + return true; +} + +void tib_sg_gm_prune(struct pim_instance *pim, pim_sgaddr sg, + struct interface *oif, struct channel_oil **oilp) +{ + int result; + + /* + It appears that in certain circumstances that + igmp_source_forward_stop is called when IGMP forwarding + was not enabled in oif_flags for this outgoing interface. + Possibly because of multiple calls. When that happens, we + enter the below if statement and this function returns early + which in turn triggers the calling function to assert. + Making the call to pim_channel_del_oif and ignoring the return code + fixes the issue without ill effect, similar to + pim_forward_stop below. + */ + result = pim_channel_del_oif(*oilp, oif, PIM_OIF_FLAG_PROTO_IGMP, + __func__); + if (result) { + if (PIM_DEBUG_IGMP_TRACE) + zlog_debug( + "%s: pim_channel_del_oif() failed with return=%d", + __func__, result); + return; + } + + /* + Feed IGMPv3-gathered local membership information into PIM + per-interface (S,G) state. + */ + pim_ifchannel_local_membership_del(oif, &sg); +} diff --git a/pimd/pim_tib.h b/pimd/pim_tib.h new file mode 100644 index 000000000..b320f4cde --- /dev/null +++ b/pimd/pim_tib.h @@ -0,0 +1,33 @@ +/* + * TIB (Tree Information Base) - just PIM <> IGMP/MLD glue for now + * Copyright (C) 2022 David Lamparter for NetDEF, Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the Free + * Software Foundation; either version 2 of the License, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; see the file COPYING; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef _FRR_PIM_GLUE_H +#define _FRR_PIM_GLUE_H + +#include "pim_addr.h" + +struct pim_instance; +struct channel_oil; + +extern bool tib_sg_gm_join(struct pim_instance *pim, pim_sgaddr sg, + struct interface *oif, struct channel_oil **oilp); +extern void tib_sg_gm_prune(struct pim_instance *pim, pim_sgaddr sg, + struct interface *oif, struct channel_oil **oilp); + +#endif /* _FRR_PIM_GLUE_H */ diff --git a/pimd/pim_zebra.c b/pimd/pim_zebra.c index 526fdcbc2..91d4a479c 100644 --- a/pimd/pim_zebra.c +++ b/pimd/pim_zebra.c @@ -486,335 +486,6 @@ void pim_zebra_init(void) zclient_lookup_new(); } -#if PIM_IPV == 4 -void igmp_anysource_forward_start(struct pim_instance *pim, - struct gm_group *group) -{ - struct gm_source *source; - struct in_addr src_addr = {.s_addr = 0}; - /* Any source (*,G) is forwarded only if mode is EXCLUDE {empty} */ - assert(group->group_filtermode_isexcl); - assert(listcount(group->group_source_list) < 1); - - source = igmp_get_source_by_addr(group, src_addr, NULL); - if (!source) { - zlog_warn("%s: Failure to create * source", __func__); - return; - } - - igmp_source_forward_start(pim, source); -} - -void igmp_anysource_forward_stop(struct gm_group *group) -{ - struct gm_source *source; - struct in_addr star = {.s_addr = 0}; - - source = igmp_find_source_by_addr(group, star); - if (source) - igmp_source_forward_stop(source); -} - -static void igmp_source_forward_reevaluate_one(struct pim_instance *pim, - struct gm_source *source) -{ - pim_sgaddr sg; - struct gm_group *group = source->source_group; - struct pim_ifchannel *ch; - - if ((source->source_addr.s_addr != INADDR_ANY) - || !IGMP_SOURCE_TEST_FORWARDING(source->source_flags)) - return; - - memset(&sg, 0, sizeof(sg)); - sg.src = source->source_addr; - sg.grp = group->group_addr; - - ch = pim_ifchannel_find(group->interface, &sg); - if (pim_is_grp_ssm(pim, group->group_addr)) { - /* If SSM group withdraw local membership */ - if (ch - && (ch->local_ifmembership == PIM_IFMEMBERSHIP_INCLUDE)) { - if (PIM_DEBUG_PIM_EVENTS) - zlog_debug("local membership del for %pSG as G is now SSM", - &sg); - pim_ifchannel_local_membership_del(group->interface, - &sg); - } - } else { - /* If ASM group add local membership */ - if (!ch - || (ch->local_ifmembership == PIM_IFMEMBERSHIP_NOINFO)) { - if (PIM_DEBUG_PIM_EVENTS) - zlog_debug("local membership add for %pSG as G is now ASM", - &sg); - pim_ifchannel_local_membership_add( - group->interface, &sg, false /*is_vxlan*/); - } - } -} - -void igmp_source_forward_reevaluate_all(struct pim_instance *pim) -{ - struct interface *ifp; - - FOR_ALL_INTERFACES (pim->vrf, ifp) { - struct pim_interface *pim_ifp = ifp->info; - struct listnode *grpnode; - struct gm_group *grp; - struct pim_ifchannel *ch, *ch_temp; - - if (!pim_ifp) - continue; - - /* scan igmp groups */ - for (ALL_LIST_ELEMENTS_RO(pim_ifp->gm_group_list, grpnode, - grp)) { - struct listnode *srcnode; - struct gm_source *src; - - /* scan group sources */ - for (ALL_LIST_ELEMENTS_RO(grp->group_source_list, - srcnode, src)) { - igmp_source_forward_reevaluate_one(pim, src); - } /* scan group sources */ - } /* scan igmp groups */ - - RB_FOREACH_SAFE (ch, pim_ifchannel_rb, &pim_ifp->ifchannel_rb, - ch_temp) { - if (pim_is_grp_ssm(pim, ch->sg.grp)) { - if (pim_addr_is_any(ch->sg.src)) - pim_ifchannel_delete(ch); - } - } - } /* scan interfaces */ -} - -void igmp_source_forward_start(struct pim_instance *pim, - struct gm_source *source) -{ - struct pim_interface *pim_oif; - struct gm_group *group; - pim_sgaddr sg; - int result; - int input_iface_vif_index = 0; - - memset(&sg, 0, sizeof(sg)); - sg.src = source->source_addr; - sg.grp = source->source_group->group_addr; - - if (PIM_DEBUG_IGMP_TRACE) { - zlog_debug("%s: (S,G)=%pSG oif=%s fwd=%d", __func__, &sg, - source->source_group->interface->name, - IGMP_SOURCE_TEST_FORWARDING(source->source_flags)); - } - - /* Prevent IGMP interface from installing multicast route multiple - times */ - if (IGMP_SOURCE_TEST_FORWARDING(source->source_flags)) { - return; - } - - group = source->source_group; - pim_oif = group->interface->info; - if (!pim_oif) { - if (PIM_DEBUG_IGMP_TRACE) { - zlog_debug("%s: multicast not enabled on oif=%s ?", - __func__, - source->source_group->interface->name); - } - return; - } - - if (!source->source_channel_oil) { - pim_addr vif_source; - struct prefix src, grp; - struct pim_nexthop nexthop; - struct pim_upstream *up = NULL; - - if (!pim_rp_set_upstream_addr(pim, &vif_source, - source->source_addr, sg.grp)) { - /*Create a dummy channel oil */ - source->source_channel_oil = - pim_channel_oil_add(pim, &sg, __func__); - } - - else { - pim_addr_to_prefix(&src, vif_source); // RP or Src addr - pim_addr_to_prefix(&grp, sg.grp); - - up = pim_upstream_find(pim, &sg); - if (up) { - memcpy(&nexthop, &up->rpf.source_nexthop, - sizeof(struct pim_nexthop)); - pim_ecmp_nexthop_lookup(pim, &nexthop, &src, - &grp, 0); - if (nexthop.interface) - input_iface_vif_index = - pim_if_find_vifindex_by_ifindex( - pim, - nexthop.interface->ifindex); - } else - input_iface_vif_index = - pim_ecmp_fib_lookup_if_vif_index( - pim, &src, &grp); - - if (PIM_DEBUG_ZEBRA) - zlog_debug( - "%s: NHT %pSG vif_source %pPAs vif_index:%d ", - __func__, &sg, &vif_source, - input_iface_vif_index); - - if (input_iface_vif_index < 1) { - if (PIM_DEBUG_IGMP_TRACE) { - char source_str[INET_ADDRSTRLEN]; - pim_inet4_dump("<source?>", - source->source_addr, - source_str, sizeof(source_str)); - zlog_debug( - "%s %s: could not find input interface for source %s", - __FILE__, __func__, source_str); - } - source->source_channel_oil = - pim_channel_oil_add(pim, &sg, __func__); - } - - else { - /* - * Protect IGMP against adding looped MFC - * entries created by both source and receiver - * attached to the same interface. See TODO - * T22. Block only when the intf is non DR - * DR must create upstream. - */ - if ((input_iface_vif_index == - pim_oif->mroute_vif_index) && - !(PIM_I_am_DR(pim_oif))) { - /* ignore request for looped MFC entry - */ - if (PIM_DEBUG_IGMP_TRACE) { - zlog_debug("%s: ignoring request for looped MFC entry (S,G)=%pSG: oif=%s vif_index=%d", - __func__, - &sg, - source->source_group - ->interface->name, - input_iface_vif_index); - } - return; - } - - source->source_channel_oil = - pim_channel_oil_add(pim, &sg, __func__); - if (!source->source_channel_oil) { - if (PIM_DEBUG_IGMP_TRACE) { - zlog_debug("%s %s: could not create OIL for channel (S,G)=%pSG", - __FILE__, __func__, - &sg); - } - return; - } - } - } - } - - if (PIM_I_am_DR(pim_oif) || PIM_I_am_DualActive(pim_oif)) { - result = pim_channel_add_oif(source->source_channel_oil, - group->interface, - PIM_OIF_FLAG_PROTO_IGMP, __func__); - if (result) { - if (PIM_DEBUG_MROUTE) { - zlog_warn("%s: add_oif() failed with return=%d", - __func__, result); - } - return; - } - } else { - if (PIM_DEBUG_IGMP_TRACE) - zlog_debug("%s: %pSG was received on %s interface but we are not DR for that interface", - __func__, &sg, - group->interface->name); - - return; - } - /* - Feed IGMPv3-gathered local membership information into PIM - per-interface (S,G) state. - */ - if (!pim_ifchannel_local_membership_add(group->interface, &sg, - false /*is_vxlan*/)) { - if (PIM_DEBUG_MROUTE) - zlog_warn("%s: Failure to add local membership for %pSG", - __func__, &sg); - - pim_channel_del_oif(source->source_channel_oil, - group->interface, PIM_OIF_FLAG_PROTO_IGMP, - __func__); - return; - } - - IGMP_SOURCE_DO_FORWARDING(source->source_flags); -} - -/* - igmp_source_forward_stop: stop fowarding, but keep the source - igmp_source_delete: stop fowarding, and delete the source - */ -void igmp_source_forward_stop(struct gm_source *source) -{ - struct gm_group *group; - pim_sgaddr sg; - int result; - - memset(&sg, 0, sizeof(sg)); - sg.src = source->source_addr; - sg.grp = source->source_group->group_addr; - - if (PIM_DEBUG_IGMP_TRACE) { - zlog_debug("%s: (S,G)=%pSG oif=%s fwd=%d", __func__, &sg, - source->source_group->interface->name, - IGMP_SOURCE_TEST_FORWARDING(source->source_flags)); - } - - /* Prevent IGMP interface from removing multicast route multiple - times */ - if (!IGMP_SOURCE_TEST_FORWARDING(source->source_flags)) { - return; - } - - group = source->source_group; - - /* - It appears that in certain circumstances that - igmp_source_forward_stop is called when IGMP forwarding - was not enabled in oif_flags for this outgoing interface. - Possibly because of multiple calls. When that happens, we - enter the below if statement and this function returns early - which in turn triggers the calling function to assert. - Making the call to pim_channel_del_oif and ignoring the return code - fixes the issue without ill effect, similar to - pim_forward_stop below. - */ - result = pim_channel_del_oif(source->source_channel_oil, - group->interface, PIM_OIF_FLAG_PROTO_IGMP, - __func__); - if (result) { - if (PIM_DEBUG_IGMP_TRACE) - zlog_debug( - "%s: pim_channel_del_oif() failed with return=%d", - __func__, result); - return; - } - - /* - Feed IGMPv3-gathered local membership information into PIM - per-interface (S,G) state. - */ - pim_ifchannel_local_membership_del(group->interface, &sg); - - IGMP_SOURCE_DONT_FORWARDING(source->source_flags); -} -#endif /* PIM_IPV == 4 */ - void pim_forward_start(struct pim_ifchannel *ch) { struct pim_upstream *up = ch->upstream; diff --git a/pimd/pim_zebra.h b/pimd/pim_zebra.h index 8656d7563..5879cdefb 100644 --- a/pimd/pim_zebra.h +++ b/pimd/pim_zebra.h @@ -23,7 +23,6 @@ #include <zebra.h> #include "zclient.h" -#include "pim_igmp.h" #include "pim_ifchannel.h" void pim_zebra_init(void); @@ -32,15 +31,6 @@ void pim_zebra_zclient_update(struct vty *vty); void pim_scan_individual_oil(struct channel_oil *c_oil, int in_vif_index); void pim_scan_oil(struct pim_instance *pim_matcher); -void igmp_anysource_forward_start(struct pim_instance *pim, - struct gm_group *group); -void igmp_anysource_forward_stop(struct gm_group *group); - -void igmp_source_forward_start(struct pim_instance *pim, - struct gm_source *source); -void igmp_source_forward_stop(struct gm_source *source); -void igmp_source_forward_reevaluate_all(struct pim_instance *pim); - void pim_forward_start(struct pim_ifchannel *ch); void pim_forward_stop(struct pim_ifchannel *ch); diff --git a/pimd/subdir.am b/pimd/subdir.am index d617be3cb..cda5acb00 100644 --- a/pimd/subdir.am +++ b/pimd/subdir.am @@ -47,6 +47,7 @@ pim_common = \ pimd/pim_ssmpingd.c \ pimd/pim_static.c \ pimd/pim_str.c \ + pimd/pim_tib.c \ pimd/pim_time.c \ pimd/pim_tlv.c \ pimd/pim_upstream.c \ @@ -141,6 +142,7 @@ noinst_HEADERS += \ pimd/pim_ssmpingd.h \ pimd/pim_static.h \ pimd/pim_str.h \ + pimd/pim_tib.h \ pimd/pim_time.h \ pimd/pim_tlv.h \ pimd/pim_upstream.h \ |