]> git.puffer.fish Git - mirror/frr.git/commitdiff
pimd: Handling Null incoming interface of dummy upstream
authorSarita Patra <saritap@vmware.com>
Fri, 22 Feb 2019 09:59:07 +0000 (01:59 -0800)
committerSarita Patra <saritap@vmware.com>
Mon, 25 Feb 2019 05:26:58 +0000 (21:26 -0800)
When FRR receives IGMP/PIM (*, G) join and RP is not configured or not
reachable, then we are creating a dummy upstream with incoming interface
as NULL and upstream address as INADDR_ANY.

Added upstream address and incoming interface validation where it is necessary,
before doing any operation on the upstream.

Signed-off-by: Sarita Patra <saritap@vmware.com>
pimd/pim_igmp_mtrace.c
pimd/pim_join.c
pimd/pim_jp_agg.c
pimd/pim_mroute.c
pimd/pim_nht.c
pimd/pim_rpf.c
pimd/pim_upstream.c
pimd/pim_zebra.c

index 1fb624a6a0bde85f6542697ed8312eef70020c1f..f51e0c0d2f1a1e2be1a3c6df3032a89a17ee7766 100644 (file)
@@ -133,6 +133,13 @@ static bool mtrace_fwd_info(struct pim_instance *pim,
        if (!up)
                return false;
 
+       if (!up->rpf.source_nexthop.interface) {
+               if (PIM_DEBUG_TRACE)
+                       zlog_debug("%s: up %s RPF is not present",
+                       __PRETTY_FUNCTION__, up->sg_str);
+               return false;
+       }
+
        ifp_in = up->rpf.source_nexthop.interface;
        nh_addr = up->rpf.source_nexthop.mrib_nexthop_addr.u.prefix4;
        total = htonl(MTRACE_UNKNOWN_COUNT);
index ae5032be73f7d41088a7e19f54babc2f8351d8ef..cbacaf3ea872733b4c749c3875e2230cf6c68bb2 100644 (file)
@@ -439,9 +439,6 @@ int pim_joinprune_send(struct pim_rpf *rpf, struct list *groups)
        size_t packet_size = 0;
        size_t group_size = 0;
 
-       on_trace(__PRETTY_FUNCTION__, rpf->source_nexthop.interface,
-                rpf->rpf_addr.u.prefix4);
-
        if (rpf->source_nexthop.interface)
                pim_ifp = rpf->source_nexthop.interface->info;
        else {
@@ -450,6 +447,9 @@ int pim_joinprune_send(struct pim_rpf *rpf, struct list *groups)
                return -1;
        }
 
+       on_trace(__PRETTY_FUNCTION__, rpf->source_nexthop.interface,
+               rpf->rpf_addr.u.prefix4);
+
        if (!pim_ifp) {
                zlog_warn("%s: multicast not enabled on interface %s",
                          __PRETTY_FUNCTION__,
index 7726ffda576da4c1e982ffec1c0fe035f82fe2cd..06a9e6d0d646888b2d0bbca6b31b3b95cb6404b2 100644 (file)
@@ -213,8 +213,18 @@ void pim_jp_agg_upstream_verification(struct pim_upstream *up, bool ignore)
 {
 #ifdef PIM_JP_AGG_DEBUG
        struct interface *ifp;
-       struct pim_interface *pim_ifp = up->rpf.source_nexthop.interface->info;
-       struct pim_instance *pim = pim_ifp->pim;
+       struct pim_interface *pim_ifp;
+       struct pim_instance *pim;
+
+       if (!up->rpf.source_nexthop.interface) {
+               if (PIM_DEBUG_TRACE)
+                       zlog_debug("%s: up %s RPF is not present",
+                               __PRETTY_FUNCTION__, up->sg_str);
+               return;
+       }
+
+       pim_ifp = up->rpf.source_nexthop.interface->info;
+       pim = pim_ifp->pim;
 
        FOR_ALL_INTERFACES (pim->vrf, ifp) {
                pim_ifp = ifp->info;
index dd9e21cae8782a030f8e498376b4f918d91e8278..67b1a95f74789c8dac64d6f193c6e69a627e6279 100644 (file)
@@ -234,7 +234,8 @@ static int pim_mroute_msg_nocache(int fd, struct interface *ifp,
        up->channel_oil->cc.pktcnt++;
        PIM_UPSTREAM_FLAG_SET_FHR(up->flags);
        // resolve mfcc_parent prior to mroute_add in channel_add_oif
-       if (up->channel_oil->oil.mfcc_parent >= MAXVIFS) {
+       if (up->rpf.source_nexthop.interface &&
+           up->channel_oil->oil.mfcc_parent >= MAXVIFS) {
                int vif_index = 0;
                vif_index = pim_if_find_vifindex_by_ifindex(
                        pim_ifp->pim,
@@ -301,6 +302,13 @@ static int pim_mroute_msg_wholepkt(int fd, struct interface *ifp,
                return 0;
        }
 
+       if (!up->rpf.source_nexthop.interface) {
+               if (PIM_DEBUG_TRACE)
+                       zlog_debug("%s: up %s RPF is not present",
+                               __PRETTY_FUNCTION__, up->sg_str);
+               return 0;
+       }
+
        pim_ifp = up->rpf.source_nexthop.interface->info;
 
        rpg = pim_ifp ? RP(pim_ifp->pim, sg.grp) : NULL;
index 2d808639b553949b21d10ff80f34fc83b588ead9..8c24bcdaed361ebbb8e7359be572c58dc4ed088d 100644 (file)
@@ -283,7 +283,7 @@ static int pim_update_upstream_nh_helper(struct hash_backet *backet, void *arg)
        }
 
        /* update kernel multicast forwarding cache (MFC) */
-       if (up->channel_oil) {
+       if (up->rpf.source_nexthop.interface) {
                ifindex_t ifindex = up->rpf.source_nexthop.interface->ifindex;
 
                vif_index = pim_if_find_vifindex_by_ifindex(pim, ifindex);
@@ -306,9 +306,10 @@ static int pim_update_upstream_nh_helper(struct hash_backet *backet, void *arg)
 
        if (PIM_DEBUG_PIM_NHT) {
                zlog_debug("%s: NHT upstream %s(%s) old ifp %s new ifp %s",
-                          __PRETTY_FUNCTION__, up->sg_str, pim->vrf->name,
-                          old.source_nexthop.interface->name,
-                          up->rpf.source_nexthop.interface->name);
+                       __PRETTY_FUNCTION__, up->sg_str, pim->vrf->name,
+                       old.source_nexthop.interface
+                       ? old.source_nexthop.interface->name : "Unknwon",
+                       up->rpf.source_nexthop.interface->name);
        }
 
        return HASHWALK_CONTINUE;
index 814d2e076bb0f581d5d20770432aed962166b024..d689b276b786a15fd1319646960778169f329438 100644 (file)
@@ -205,6 +205,12 @@ enum pim_rpf_result pim_rpf_update(struct pim_instance *pim,
        struct prefix src, grp;
        bool neigh_needed = true;
 
+       if (up->upstream_addr.s_addr == INADDR_ANY) {
+               zlog_debug("%s: RP is not configured yet for %s",
+                       __PRETTY_FUNCTION__, up->sg_str);
+               return PIM_RPF_OK;
+       }
+
        saved.source_nexthop = rpf->source_nexthop;
        saved.rpf_addr = rpf->rpf_addr;
 
index c6ab8f5a2af117a1f65fc012921f0b20cb041e4b..cd0610eb829ad7b702f1f3b109d5242c00de77ae 100644 (file)
@@ -238,6 +238,13 @@ struct pim_upstream *pim_upstream_del(struct pim_instance *pim,
 
 void pim_upstream_send_join(struct pim_upstream *up)
 {
+       if (!up->rpf.source_nexthop.interface) {
+               if (PIM_DEBUG_TRACE)
+                       zlog_debug("%s: up %s RPF is not present",
+                               __PRETTY_FUNCTION__, up->sg_str);
+               return;
+       }
+
        if (PIM_DEBUG_TRACE) {
                char rpf_str[PREFIX_STRLEN];
                pim_addr_dump("<rpf?>", &up->rpf.rpf_addr, rpf_str,
@@ -263,6 +270,13 @@ static int on_join_timer(struct thread *t)
 
        up = THREAD_ARG(t);
 
+       if (!up->rpf.source_nexthop.interface) {
+               if (PIM_DEBUG_TRACE)
+                       zlog_debug("%s: up %s RPF is not present",
+                       __PRETTY_FUNCTION__, up->sg_str);
+               return 0;
+       }
+
        /*
         * In the case of a HFR we will not ahve anyone to send this to.
         */
@@ -286,6 +300,13 @@ static void join_timer_stop(struct pim_upstream *up)
 {
        struct pim_neighbor *nbr;
 
+       if (!up->rpf.source_nexthop.interface) {
+               if (PIM_DEBUG_TRACE)
+                       zlog_debug("%s: up %s RPF is not present",
+                               __PRETTY_FUNCTION__, up->sg_str);
+               return;
+       }
+
        THREAD_OFF(up->t_join_timer);
 
        nbr = pim_neighbor_find(up->rpf.source_nexthop.interface,
@@ -301,6 +322,13 @@ void join_timer_start(struct pim_upstream *up)
 {
        struct pim_neighbor *nbr = NULL;
 
+       if (!up->rpf.source_nexthop.interface) {
+               if (PIM_DEBUG_TRACE)
+                       zlog_debug("%s: up %s RPF is not present",
+                               __PRETTY_FUNCTION__, up->sg_str);
+               return;
+       }
+
        if (up->rpf.source_nexthop.interface) {
                nbr = pim_neighbor_find(up->rpf.source_nexthop.interface,
                                        up->rpf.rpf_addr.u.prefix4);
@@ -356,6 +384,13 @@ void pim_upstream_join_suppress(struct pim_upstream *up,
        long t_joinsuppress_msec;
        long join_timer_remain_msec;
 
+       if (!up->rpf.source_nexthop.interface) {
+               if (PIM_DEBUG_TRACE)
+                       zlog_debug("%s: up %s RPF is not present",
+                               __PRETTY_FUNCTION__, up->sg_str);
+               return;
+       }
+
        t_joinsuppress_msec =
                MIN(pim_if_t_suppressed_msec(up->rpf.source_nexthop.interface),
                    1000 * holdtime);
@@ -389,6 +424,13 @@ void pim_upstream_join_timer_decrease_to_t_override(const char *debug_label,
        long join_timer_remain_msec;
        int t_override_msec;
 
+       if (!up->rpf.source_nexthop.interface) {
+               if (PIM_DEBUG_TRACE)
+                       zlog_debug("%s: up %s RPF is not present",
+                               __PRETTY_FUNCTION__, up->sg_str);
+               return;
+       }
+
        join_timer_remain_msec = pim_time_timer_remain_msec(up->t_join_timer);
        t_override_msec =
                pim_if_t_override_msec(up->rpf.source_nexthop.interface);
@@ -511,6 +553,18 @@ void pim_upstream_switch(struct pim_instance *pim, struct pim_upstream *up,
 {
        enum pim_upstream_state old_state = up->join_state;
 
+       if (up->upstream_addr.s_addr == INADDR_ANY) {
+               zlog_debug("%s: RPF not configured for %s",
+                       __PRETTY_FUNCTION__, up->sg_str);
+               return;
+       }
+
+       if (!up->rpf.source_nexthop.interface)  {
+               zlog_debug("%s: RP not reachable for %s",
+                       __PRETTY_FUNCTION__, up->sg_str);
+               return;
+       }
+
        if (PIM_DEBUG_PIM_EVENTS) {
                zlog_debug("%s: PIM_UPSTREAM_%s: (S,G) old: %s new: %s",
                           __PRETTY_FUNCTION__, up->sg_str,
@@ -558,11 +612,14 @@ void pim_upstream_switch(struct pim_instance *pim, struct pim_upstream *up,
                    && !I_am_RP(pim, up->sg.grp)) {
                        if (PIM_DEBUG_PIM_TRACE_DETAIL)
                                zlog_debug(
-                                       "%s: *,G IIF %s S,G IIF %s ",
-                                       __PRETTY_FUNCTION__,
-                                       up->parent->rpf.source_nexthop
-                                               .interface->name,
-                                       up->rpf.source_nexthop.interface->name);
+                                 "%s: *,G IIF %s S,G IIF %s ",
+                                 __PRETTY_FUNCTION__,
+                                 up->parent->rpf.source_nexthop.interface ?
+                                 up->parent->rpf.source_nexthop.interface->name
+                                 : "Unknown",
+                                 up->rpf.source_nexthop.interface ?
+                                 up->rpf.source_nexthop.interface->name :
+                                 "Unknown");
                        pim_jp_agg_single_upstream_send(&up->parent->rpf,
                                                        up->parent,
                                                        1 /* (W,G) Join */);
@@ -783,7 +840,7 @@ struct pim_upstream *pim_upstream_add(struct pim_instance *pim,
                        zlog_debug("%s(%s): %s, iif %s (%s) found: %d: ref_count: %d",
                   __PRETTY_FUNCTION__, name,
                   up->sg_str, buf, up->rpf.source_nexthop.interface ?
-                   up->rpf.source_nexthop.interface->name : "NIL" ,
+                   up->rpf.source_nexthop.interface->name : "Unknown" ,
                   found, up->ref_count);
                } else
                        zlog_debug("%s(%s): (%s) failure to create",
@@ -973,7 +1030,9 @@ void pim_upstream_rpf_interface_changed(struct pim_upstream *up,
                                (old_rpf_ifp == ch->interface) &&
                                /* RPF_interface(S) stopped being I */
                                (ch->upstream->rpf.source_nexthop
-                                        .interface != ch->interface)) {
+                                       .interface) &&
+                               (ch->upstream->rpf.source_nexthop
+                                       .interface != ch->interface)) {
                                assert_action_a5(ch);
                        }
                } /* PIM_IFASSERT_I_AM_LOSER */
@@ -1339,6 +1398,13 @@ static int pim_upstream_register_stop_timer(struct thread *t)
        case PIM_REG_JOIN:
                break;
        case PIM_REG_PRUNE:
+               if (!up->rpf.source_nexthop.interface) {
+                       if (PIM_DEBUG_TRACE)
+                               zlog_debug("%s: up %s RPF is not present",
+                                       __PRETTY_FUNCTION__, up->sg_str);
+                       return 0;
+               }
+
                pim_ifp = up->rpf.source_nexthop.interface->info;
                if (!pim_ifp) {
                        if (PIM_DEBUG_TRACE)
@@ -1515,11 +1581,19 @@ void pim_upstream_find_new_rpf(struct pim_instance *pim)
         * Scan all (S,G) upstreams searching for RPF'(S,G)=neigh_addr
         */
        for (ALL_LIST_ELEMENTS(pim->upstream_list, up_node, up_nextnode, up)) {
+               if (up->upstream_addr.s_addr == INADDR_ANY) {
+                       if (PIM_DEBUG_TRACE)
+                               zlog_debug(
+                                   "%s: RP not configured for Upstream %s",
+                                   __PRETTY_FUNCTION__, up->sg_str);
+                       continue;
+               }
+
                if (pim_rpf_addr_is_inaddr_any(&up->rpf)) {
                        if (PIM_DEBUG_TRACE)
                                zlog_debug(
-                                       "Upstream %s without a path to send join, checking",
-                                       up->sg_str);
+                                       "%s: Upstream %s without a path to send join, checking",
+                                       __PRETTY_FUNCTION__, up->sg_str);
                        pim_rpf_update(pim, up, NULL, 1);
                }
        }
@@ -1586,7 +1660,8 @@ static bool pim_upstream_kat_start_ok(struct pim_upstream *up)
 
        /* "iif == RPF_interface(S)" check has to be done by the kernel or hw
         * so we will skip that here */
-       if (pim_if_connected_to_source(up->rpf.source_nexthop.interface,
+       if (up->rpf.source_nexthop.interface &&
+               pim_if_connected_to_source(up->rpf.source_nexthop.interface,
                                       up->sg.src)) {
                return true;
        }
@@ -1679,7 +1754,8 @@ static void pim_upstream_sg_running(void *arg)
        } else if (PIM_UPSTREAM_FLAG_TEST_SRC_LHR(up->flags))
                pim_upstream_keep_alive_timer_start(up, pim->keep_alive_time);
 
-       if (up->sptbit != PIM_UPSTREAM_SPTBIT_TRUE) {
+       if ((up->sptbit != PIM_UPSTREAM_SPTBIT_TRUE) &&
+           (up->rpf.source_nexthop.interface)) {
                pim_upstream_set_sptbit(up, up->rpf.source_nexthop.interface);
        }
        return;
index 11ca6e8a108010bba7a44ff19fca425c5b6af770..2c5c7f6174e1cc703f568e0940a9b3c810442d0d 100644 (file)
@@ -535,6 +535,14 @@ static void scan_upstream_rpf_cache(struct pim_instance *pim)
                struct pim_rpf old;
                struct prefix nht_p;
 
+               if (up->upstream_addr.s_addr == INADDR_ANY) {
+                       if (PIM_DEBUG_TRACE)
+                               zlog_debug(
+                                   "%s: RP not configured for Upstream %s",
+                                   __PRETTY_FUNCTION__, up->sg_str);
+                       continue;
+               }
+
                nht_p.family = AF_INET;
                nht_p.prefixlen = IPV4_MAX_BITLEN;
                nht_p.u.prefix4.s_addr = up->upstream_addr.s_addr;