summaryrefslogtreecommitdiff
path: root/pimd/pim_zebra.c
diff options
context:
space:
mode:
authorDavid Lamparter <equinox@opensourcerouting.org>2022-02-28 11:42:48 +0100
committerDavid Lamparter <equinox@opensourcerouting.org>2022-03-12 22:47:08 +0100
commitcd6d285855954039624f115a9fad7d4abbb4574d (patch)
treeee7c2288a648ae032b552577759040daa8c7b1d3 /pimd/pim_zebra.c
parentd6890c49b2f689fd679cd845d0011eecb80c326a (diff)
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/pim_zebra.c')
-rw-r--r--pimd/pim_zebra.c329
1 files changed, 0 insertions, 329 deletions
diff --git a/pimd/pim_zebra.c b/pimd/pim_zebra.c
index 526fdcbc27..91d4a479cf 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;