From 732c209c985da005791fcc3ecd88c443c7c74cd6 Mon Sep 17 00:00:00 2001 From: Sarita Patra Date: Fri, 22 Feb 2019 03:05:29 -0800 Subject: [PATCH] pimd: create dummy (*,G) upstream when RP not configured/reachable In this commit, we are creating a dummy upstream & dummy channel_oil for (*, G) when RP is not configured or not reachable. Dummy upstream: Dummy channel oil: Signed-off-by: Sarita Patra --- pimd/pim_oil.c | 20 ++-- pimd/pim_rp.c | 3 +- pimd/pim_upstream.c | 64 +++++------- pimd/pim_zebra.c | 232 ++++++++++++++++++++++++++------------------ 4 files changed, 178 insertions(+), 141 deletions(-) diff --git a/pimd/pim_oil.c b/pimd/pim_oil.c index 2e12d728cf..5042db8e57 100644 --- a/pimd/pim_oil.c +++ b/pimd/pim_oil.c @@ -168,13 +168,15 @@ struct channel_oil *pim_channel_oil_add(struct pim_instance *pim, return c_oil; } - ifp = pim_if_find_by_vif_index(pim, input_vif_index); - if (!ifp) { - /* warning only */ - zlog_warn( - "%s: (S,G)=%s could not find input interface for input_vif_index=%d", - __PRETTY_FUNCTION__, pim_str_sg_dump(sg), - input_vif_index); + if (input_vif_index != MAXVIFS) { + ifp = pim_if_find_by_vif_index(pim, input_vif_index); + if (!ifp) { + /* warning only */ + zlog_warn( + "%s: (S,G)=%s could not find input interface for input_vif_index=%d", + __PRETTY_FUNCTION__, pim_str_sg_dump(sg), + input_vif_index); + } } c_oil = XCALLOC(MTYPE_PIM_CHANNEL_OIL, sizeof(*c_oil)); @@ -188,6 +190,10 @@ struct channel_oil *pim_channel_oil_add(struct pim_instance *pim, c_oil->installed = 0; c_oil->up = pim_upstream_find(pim, sg); c_oil->pim = pim; + if (input_vif_index != MAXVIFS) + c_oil->is_valid = 1; + else + c_oil->is_valid = 0; listnode_add_sort(pim->channel_oil_list, c_oil); diff --git a/pimd/pim_rp.c b/pimd/pim_rp.c index 08f2ffc4ea..d46f3d853f 100644 --- a/pimd/pim_rp.c +++ b/pimd/pim_rp.c @@ -870,7 +870,7 @@ struct pim_rpf *pim_rp_g(struct pim_instance *pim, struct in_addr group) * the rp configured and the source address * * If we have don't have a RP configured and the source address is * - * then return failure. + * then set the upstream addr as INADDR_ANY and return failure. * */ int pim_rp_set_upstream_addr(struct pim_instance *pim, struct in_addr *up, @@ -891,6 +891,7 @@ int pim_rp_set_upstream_addr(struct pim_instance *pim, struct in_addr *up, if (PIM_DEBUG_PIM_NHT_RP) zlog_debug("%s: Received a (*,G) with no RP configured", __PRETTY_FUNCTION__); + up->s_addr = INADDR_ANY; return 0; } diff --git a/pimd/pim_upstream.c b/pimd/pim_upstream.c index cd0610eb82..2a2b944354 100644 --- a/pimd/pim_upstream.c +++ b/pimd/pim_upstream.c @@ -668,15 +668,14 @@ static struct pim_upstream *pim_upstream_new(struct pim_instance *pim, ch->upstream = up; up = hash_get(pim->upstream_hash, up, hash_alloc_intern); + /* Set up->upstream_addr as INADDR_ANY, if RP is not + * configured and retain the upstream data structure + */ if (!pim_rp_set_upstream_addr(pim, &up->upstream_addr, sg->src, sg->grp)) { if (PIM_DEBUG_TRACE) zlog_debug("%s: Received a (*,G) with no RP configured", __PRETTY_FUNCTION__); - - hash_release(pim->upstream_hash, up); - XFREE(MTYPE_PIM_UPSTREAM, up); - return NULL; } up->parent = pim_upstream_find_parent(pim, up); @@ -716,45 +715,34 @@ static struct pim_upstream *pim_upstream_new(struct pim_instance *pim, if (up->sg.src.s_addr != INADDR_ANY) wheel_add_item(pim->upstream_sg_wheel, up); - rpf_result = pim_rpf_update(pim, up, NULL, 1); - if (rpf_result == PIM_RPF_FAILURE) { - struct prefix nht_p; - - if (PIM_DEBUG_TRACE) - zlog_debug( - "%s: Attempting to create upstream(%s), Unable to RPF for source", - __PRETTY_FUNCTION__, up->sg_str); - - nht_p.family = AF_INET; - nht_p.prefixlen = IPV4_MAX_BITLEN; - nht_p.u.prefix4 = up->upstream_addr; - pim_delete_tracked_nexthop(pim, &nht_p, up, NULL); + if (up->upstream_addr.s_addr == INADDR_ANY) + /* Create a dummmy channel oil with incoming ineterface MAXVIFS, + * since RP is not configured + */ + up->channel_oil = pim_channel_oil_add(pim, &up->sg, MAXVIFS); - if (up->parent) { - listnode_delete(up->parent->sources, up); - up->parent = NULL; + else { + rpf_result = pim_rpf_update(pim, up, NULL, 1); + if (rpf_result == PIM_RPF_FAILURE) { + if (PIM_DEBUG_TRACE) + zlog_debug( + "%s: Attempting to create upstream(%s), Unable to RPF for source", + __PRETTY_FUNCTION__, up->sg_str); + /* Create a dummmy channel oil with incoming ineterface + * MAXVIFS, since RP is not reachable + */ + up->channel_oil = pim_channel_oil_add( + pim, &up->sg, MAXVIFS); } - if (up->sg.src.s_addr != INADDR_ANY) - wheel_remove_item(pim->upstream_sg_wheel, up); - - pim_upstream_remove_children(pim, up); - if (up->sources) - list_delete(&up->sources); - - list_delete(&up->ifchannels); - - hash_release(pim->upstream_hash, up); - XFREE(MTYPE_PIM_UPSTREAM, up); - return NULL; + if (up->rpf.source_nexthop.interface) { + pim_ifp = up->rpf.source_nexthop.interface->info; + if (pim_ifp) + up->channel_oil = pim_channel_oil_add(pim, + &up->sg, pim_ifp->mroute_vif_index); + } } - if (up->rpf.source_nexthop.interface) { - pim_ifp = up->rpf.source_nexthop.interface->info; - if (pim_ifp) - up->channel_oil = pim_channel_oil_add( - pim, &up->sg, pim_ifp->mroute_vif_index); - } listnode_add_sort(pim->upstream_list, up); if (PIM_DEBUG_TRACE) { diff --git a/pimd/pim_zebra.c b/pimd/pim_zebra.c index 2c5c7f6174..6a5e6e726f 100644 --- a/pimd/pim_zebra.c +++ b/pimd/pim_zebra.c @@ -569,10 +569,9 @@ void pim_scan_individual_oil(struct channel_oil *c_oil, int in_vif_index) int input_iface_vif_index; int old_vif_index; - if (!pim_rp_set_upstream_addr(c_oil->pim, &vif_source, + pim_rp_set_upstream_addr(c_oil->pim, &vif_source, c_oil->oil.mfcc_origin, - c_oil->oil.mfcc_mcastgrp)) - return; + c_oil->oil.mfcc_mcastgrp); if (in_vif_index) input_iface_vif_index = in_vif_index; @@ -958,112 +957,141 @@ void igmp_source_forward_start(struct pim_instance *pim, struct pim_upstream *up = NULL; if (!pim_rp_set_upstream_addr(pim, &vif_source, - source->source_addr, sg.grp)) - return; - - /* Register addr with Zebra NHT */ - nht_p.family = AF_INET; - nht_p.prefixlen = IPV4_MAX_BITLEN; - nht_p.u.prefix4 = vif_source; - memset(&out_pnc, 0, sizeof(struct pim_nexthop_cache)); + source->source_addr, sg.grp)) { + /*Create a dummy channel oil */ + source->source_channel_oil = + pim_channel_oil_add(pim, &sg, MAXVIFS); - src.family = AF_INET; - src.prefixlen = IPV4_MAX_BITLEN; - src.u.prefix4 = vif_source; // RP or Src address - grp.family = AF_INET; - grp.prefixlen = IPV4_MAX_BITLEN; - grp.u.prefix4 = sg.grp; + if (!source->source_channel_oil) { + if (PIM_DEBUG_IGMP_TRACE) { + zlog_debug( + "%s %s: could not create OIL for channel (S,G)=%s", + __FILE__, __PRETTY_FUNCTION__, + pim_str_sg_dump(&sg)); + } + return; + } + } - if (pim_find_or_track_nexthop(pim, &nht_p, NULL, NULL, + else { + /* Register addr with Zebra NHT */ + nht_p.family = AF_INET; + nht_p.prefixlen = IPV4_MAX_BITLEN; + nht_p.u.prefix4 = vif_source; + memset(&out_pnc, 0, sizeof(struct pim_nexthop_cache)); + + src.family = AF_INET; + src.prefixlen = IPV4_MAX_BITLEN; + src.u.prefix4 = vif_source; // RP or Src address + grp.family = AF_INET; + grp.prefixlen = IPV4_MAX_BITLEN; + grp.u.prefix4 = sg.grp; + + if (pim_find_or_track_nexthop(pim, &nht_p, NULL, NULL, &out_pnc)) { - if (out_pnc.nexthop_num) { - up = pim_upstream_find(pim, &sg); - memset(&nexthop, 0, sizeof(nexthop)); - if (up) - memcpy(&nexthop, - &up->rpf.source_nexthop, - sizeof(struct pim_nexthop)); - pim_ecmp_nexthop_search(pim, &out_pnc, &nexthop, - &src, &grp, 0); - if (nexthop.interface) - input_iface_vif_index = + if (out_pnc.nexthop_num) { + up = pim_upstream_find(pim, &sg); + memset(&nexthop, 0, sizeof(nexthop)); + if (up) + memcpy(&nexthop, + &up->rpf.source_nexthop, + sizeof(struct pim_nexthop)); + pim_ecmp_nexthop_search(pim, &out_pnc, + &nexthop, + &src, &grp, 0); + if (nexthop.interface) + input_iface_vif_index = pim_if_find_vifindex_by_ifindex( - pim, - nexthop.interface->ifindex); - } else { - if (PIM_DEBUG_ZEBRA) { - char buf1[INET_ADDRSTRLEN]; - char buf2[INET_ADDRSTRLEN]; - pim_inet4_dump("", + pim, + nexthop.interface->ifindex); + } else { + if (PIM_DEBUG_ZEBRA) { + char buf1[INET_ADDRSTRLEN]; + char buf2[INET_ADDRSTRLEN]; + + pim_inet4_dump("", nht_p.u.prefix4, buf1, sizeof(buf1)); - pim_inet4_dump("", + pim_inet4_dump("", grp.u.prefix4, buf2, sizeof(buf2)); - zlog_debug( + zlog_debug( "%s: NHT Nexthop not found for addr %s grp %s", __PRETTY_FUNCTION__, buf1, buf2); + } } - } - } else - input_iface_vif_index = - pim_ecmp_fib_lookup_if_vif_index(pim, &src, + } else + input_iface_vif_index = + pim_ecmp_fib_lookup_if_vif_index(pim, &src, &grp); - if (PIM_DEBUG_ZEBRA) { - char buf2[INET_ADDRSTRLEN]; - pim_inet4_dump("", vif_source, buf2, - sizeof(buf2)); - zlog_debug("%s: NHT %s vif_source %s vif_index:%d ", - __PRETTY_FUNCTION__, pim_str_sg_dump(&sg), - buf2, 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_addr, - source_str, sizeof(source_str)); - zlog_debug( - "%s %s: could not find input interface for source %s", - __FILE__, __PRETTY_FUNCTION__, - source_str); - } - return; - } + if (PIM_DEBUG_ZEBRA) { + char buf2[INET_ADDRSTRLEN]; - /* - Protect IGMP against adding looped MFC entries created by both - source and receiver attached to the same interface. See TODO - T22. - */ - if (input_iface_vif_index == pim_oif->mroute_vif_index) { - /* ignore request for looped MFC entry */ - if (PIM_DEBUG_IGMP_TRACE) { - zlog_debug( - "%s: ignoring request for looped MFC entry (S,G)=%s: igmp_sock=%d oif=%s vif_index=%d", + pim_inet4_dump("", vif_source, buf2, + sizeof(buf2)); + zlog_debug("%s: NHT %s vif_source %s vif_index:%d ", __PRETTY_FUNCTION__, pim_str_sg_dump(&sg), - source->source_group->group_igmp_sock - ->fd, - source->source_group->group_igmp_sock - ->interface->name, - input_iface_vif_index); + buf2, input_iface_vif_index); } - return; - } - source->source_channel_oil = - pim_channel_oil_add(pim, &sg, input_iface_vif_index); - if (!source->source_channel_oil) { - if (PIM_DEBUG_IGMP_TRACE) { - zlog_debug( - "%s %s: could not create OIL for channel (S,G)=%s", - __FILE__, __PRETTY_FUNCTION__, - pim_str_sg_dump(&sg)); + if (input_iface_vif_index < 1) { + if (PIM_DEBUG_IGMP_TRACE) { + char source_str[INET_ADDRSTRLEN]; + pim_inet4_dump("", + source->source_addr, + source_str, sizeof(source_str)); + zlog_debug( + "%s %s: could not find input interface for source %s", + __FILE__, __PRETTY_FUNCTION__, + source_str); + } + source->source_channel_oil = + pim_channel_oil_add(pim, &sg, MAXVIFS); + } + + else { + /* + * Protect IGMP against adding looped MFC + * entries created by both source and receiver + * attached to the same interface. See TODO + * T22. + */ + if (input_iface_vif_index == + pim_oif->mroute_vif_index) { + /* ignore request for looped MFC entry + */ + if (PIM_DEBUG_IGMP_TRACE) { + zlog_debug( + "%s: ignoring request for looped MFC entry (S,G)=%s: igmp_sock=%d oif=%s vif_index=%d", + __PRETTY_FUNCTION__, + pim_str_sg_dump(&sg), + source->source_group + ->group_igmp_sock->fd, + source->source_group + ->group_igmp_sock + ->interface->name, + input_iface_vif_index); + } + return; + } + + source->source_channel_oil = + pim_channel_oil_add(pim, &sg, + input_iface_vif_index); + if (!source->source_channel_oil) { + if (PIM_DEBUG_IGMP_TRACE) { + zlog_debug( + "%s %s: could not create OIL for channel (S,G)=%s", + __FILE__, + __PRETTY_FUNCTION__, + pim_str_sg_dump(&sg)); + } + return; + } } - return; } } @@ -1196,15 +1224,13 @@ void pim_forward_start(struct pim_ifchannel *ch) sizeof(upstream_str)); zlog_debug("%s: (S,G)=(%s,%s) oif=%s (%s)", __PRETTY_FUNCTION__, source_str, group_str, ch->interface->name, - upstream_str); + inet_ntoa(up->upstream_addr)); } /* Resolve IIF for upstream as mroute_del sets mfcc_parent to MAXVIFS, as part of mroute_del called by pim_forward_stop. */ - if (!up->channel_oil - || (up->channel_oil - && up->channel_oil->oil.mfcc_parent >= MAXVIFS)) { + if ((up->upstream_addr.s_addr != INADDR_ANY) && (!up->channel_oil)) { struct prefix nht_p, src, grp; struct pim_nexthop_cache out_pnc; @@ -1275,17 +1301,33 @@ void pim_forward_start(struct pim_ifchannel *ch) __FILE__, __PRETTY_FUNCTION__, source_str); } - return; + up->channel_oil = pim_channel_oil_add(pim, &up->sg, + MAXVIFS); } + + else { + up->channel_oil = pim_channel_oil_add(pim, &up->sg, + input_iface_vif_index); + if (!up->channel_oil) { + if (PIM_DEBUG_PIM_TRACE) + zlog_debug( + "%s %s: could not create OIL for channel (S,G)=%s", + __FILE__, __PRETTY_FUNCTION__, + up->sg_str); + return; + } + } + if (PIM_DEBUG_TRACE) { struct interface *in_intf = pim_if_find_by_vif_index( pim, input_iface_vif_index); zlog_debug( "%s: Update channel_oil IIF %s VIFI %d entry %s ", __PRETTY_FUNCTION__, - in_intf ? in_intf->name : "NIL", + in_intf ? in_intf->name : "Unknown", input_iface_vif_index, up->sg_str); } + up->channel_oil = pim_channel_oil_add(pim, &up->sg, input_iface_vif_index); if (!up->channel_oil) { -- 2.39.5