]> git.proxmox.com Git - mirror_frr.git/blobdiff - pimd/pim_upstream.c
ospf6d: Make 'struct zebra_privs_t' available
[mirror_frr.git] / pimd / pim_upstream.c
index 9d462067581a20f91e6c7b50fee716737c57ecb9..fdd37f2b91bf17c5dfab3b165572870d29f17acb 100644 (file)
@@ -82,8 +82,7 @@ static void pim_upstream_remove_children(struct pim_instance *pim,
                if (child)
                        child->parent = NULL;
        }
-       list_delete(up->sources);
-       up->sources = NULL;
+       list_delete_and_null(&up->sources);
 }
 
 /*
@@ -153,6 +152,7 @@ static void upstream_channel_oil_detach(struct pim_upstream *up)
                /* Detaching from channel_oil, channel_oil may exist post del,
                   but upstream would not keep reference of it
                 */
+               up->channel_oil->up = NULL;
                pim_channel_oil_del(up->channel_oil);
                up->channel_oil = NULL;
        }
@@ -166,8 +166,9 @@ struct pim_upstream *pim_upstream_del(struct pim_instance *pim,
 
        if (PIM_DEBUG_TRACE)
                zlog_debug(
-                       "%s(%s): Delete %s ref count: %d , flags: %d c_oil ref count %d (Pre decrement)",
-                       __PRETTY_FUNCTION__, name, up->sg_str, up->ref_count,
+                       "%s(%s): Delete %s[%s] ref count: %d , flags: %d c_oil ref count %d (Pre decrement)",
+                       __PRETTY_FUNCTION__, name, up->sg_str,
+                       pim->vrf->name, up->ref_count,
                        up->flags, up->channel_oil->oil_ref_count);
 
        --up->ref_count;
@@ -201,13 +202,12 @@ struct pim_upstream *pim_upstream_del(struct pim_instance *pim,
 
        pim_upstream_remove_children(pim, up);
        if (up->sources)
-               list_delete(up->sources);
-       up->sources = NULL;
+               list_delete_and_null(&up->sources);
+
        pim_mroute_del(up->channel_oil, __PRETTY_FUNCTION__);
        upstream_channel_oil_detach(up);
 
-       list_delete(up->ifchannels);
-       up->ifchannels = NULL;
+       list_delete_and_null(&up->ifchannels);
 
        /*
          notice that listnode_delete() can't be moved
@@ -222,7 +222,7 @@ struct pim_upstream *pim_upstream_del(struct pim_instance *pim,
        hash_release(pim->upstream_hash, up);
 
        if (notify_msdp) {
-               pim_msdp_up_del(&up->sg);
+               pim_msdp_up_del(pim, &up->sg);
        }
 
        /* Deregister addr with Zebra NHT */
@@ -443,7 +443,7 @@ static void forward_off(struct pim_upstream *up)
        /* scan per-interface (S,G) state */
        for (ALL_LIST_ELEMENTS(up->ifchannels, chnode, chnextnode, ch)) {
 
-               pim_forward_stop(ch);
+               pim_forward_stop(ch, false);
 
        } /* scan iface channel list */
 }
@@ -483,7 +483,7 @@ void pim_upstream_register_reevaluate(struct pim_instance *pim)
                if (!PIM_UPSTREAM_FLAG_TEST_FHR(up->flags) || !up->t_ka_timer)
                        continue;
 
-               if (pim_is_grp_ssm(up->sg.grp)) {
+               if (pim_is_grp_ssm(pim, up->sg.grp)) {
                        /* clear the register state  for SSM groups */
                        if (up->reg_state != PIM_REG_NOINFO) {
                                if (PIM_DEBUG_PIM_EVENTS)
@@ -512,7 +512,7 @@ void pim_upstream_register_reevaluate(struct pim_instance *pim)
        }
 }
 
-void pim_upstream_switch(struct pim_upstream *up,
+void pim_upstream_switch(struct pim_instance *pim, struct pim_upstream *up,
                         enum pim_upstream_state new_state)
 {
        enum pim_upstream_state old_state = up->join_state;
@@ -534,14 +534,14 @@ void pim_upstream_switch(struct pim_upstream *up,
                if (old_state != PIM_UPSTREAM_JOINED) {
                        int old_fhr = PIM_UPSTREAM_FLAG_TEST_FHR(up->flags);
                        forward_on(up);
-                       pim_msdp_up_join_state_changed(up);
+                       pim_msdp_up_join_state_changed(pim, up);
                        if (pim_upstream_could_register(up)) {
                                PIM_UPSTREAM_FLAG_SET_FHR(up->flags);
                                if (!old_fhr
                                    && PIM_UPSTREAM_FLAG_TEST_SRC_STREAM(
                                               up->flags)) {
                                        pim_upstream_keep_alive_timer_start(
-                                               up, qpim_keep_alive_time);
+                                               up, pim->keep_alive_time);
                                        pim_register_join(up);
                                }
                        } else {
@@ -555,13 +555,13 @@ void pim_upstream_switch(struct pim_upstream *up,
 
                forward_off(up);
                if (old_state == PIM_UPSTREAM_JOINED)
-                       pim_msdp_up_join_state_changed(up);
+                       pim_msdp_up_join_state_changed(pim, up);
 
                /* IHR, Trigger SGRpt on *,G IIF to prune S,G from RPT towards
                   RP.
                   If I am RP for G then send S,G prune to its IIF. */
                if (pim_upstream_is_sg_rpt(up) && up->parent
-                   && !I_am_RP(up->channel_oil->pim, up->sg.grp)) {
+                   && !I_am_RP(pim, up->sg.grp)) {
                        if (PIM_DEBUG_PIM_TRACE_DETAIL)
                                zlog_debug(
                                        "%s: *,G IIF %s S,G IIF %s ",
@@ -599,12 +599,14 @@ int pim_upstream_compare(void *arg1, void *arg2)
        return 0;
 }
 
-static struct pim_upstream *
-pim_upstream_new(struct prefix_sg *sg, struct interface *incoming, int flags)
+static struct pim_upstream *pim_upstream_new(struct pim_instance *pim,
+                                            struct prefix_sg *sg,
+                                            struct interface *incoming,
+                                            int flags,
+                                            struct pim_ifchannel *ch)
 {
        enum pim_rpf_result rpf_result;
        struct pim_interface *pim_ifp;
-       struct pim_instance *pim;
        struct pim_upstream *up;
 
        up = XCALLOC(MTYPE_PIM_UPSTREAM, sizeof(*up));
@@ -614,10 +616,11 @@ pim_upstream_new(struct prefix_sg *sg, struct interface *incoming, int flags)
                return NULL;
        }
 
-       pim_ifp = incoming->info;
-       pim = pim_ifp->pim;
        up->sg = *sg;
        pim_str_sg_set(sg, up->sg_str);
+       if (ch)
+               ch->upstream = up;
+
        up = hash_get(pim->upstream_hash, up, hash_alloc_intern);
        if (!pim_rp_set_upstream_addr(pim, &up->upstream_addr, sg->src,
                                      sg->grp)) {
@@ -667,7 +670,7 @@ pim_upstream_new(struct prefix_sg *sg, struct interface *incoming, int flags)
        if (up->sg.src.s_addr != INADDR_ANY)
                wheel_add_item(pim->upstream_sg_wheel, up);
 
-       rpf_result = pim_rpf_update(up, NULL, 1);
+       rpf_result = pim_rpf_update(pim, up, NULL, 1);
        if (rpf_result == PIM_RPF_FAILURE) {
                struct prefix nht_p;
 
@@ -679,7 +682,7 @@ pim_upstream_new(struct prefix_sg *sg, struct interface *incoming, int flags)
                nht_p.family = AF_INET;
                nht_p.prefixlen = IPV4_MAX_BITLEN;
                nht_p.u.prefix4 = up->upstream_addr;
-               pim_delete_tracked_nexthop(pim_ifp->pim, &nht_p, up, NULL);
+               pim_delete_tracked_nexthop(pim, &nht_p, up, NULL);
 
                if (up->parent) {
                        listnode_delete(up->parent->sources, up);
@@ -691,7 +694,9 @@ pim_upstream_new(struct prefix_sg *sg, struct interface *incoming, int flags)
 
                pim_upstream_remove_children(pim, up);
                if (up->sources)
-                       list_delete(up->sources);
+                       list_delete_and_null(&up->sources);
+
+               list_delete_and_null(&up->ifchannels);
 
                hash_release(pim->upstream_hash, up);
                XFREE(MTYPE_PIM_UPSTREAM, up);
@@ -749,7 +754,8 @@ struct pim_upstream *pim_upstream_find_or_add(struct prefix_sg *sg,
                                        up->ref_count);
                }
        } else
-               up = pim_upstream_add(sg, incoming, flags, name);
+               up = pim_upstream_add(pim_ifp->pim, sg, incoming, flags, name,
+                                     NULL);
 
        return up;
 }
@@ -764,21 +770,21 @@ void pim_upstream_ref(struct pim_upstream *up, int flags, const char *name)
                           up->ref_count);
 }
 
-struct pim_upstream *pim_upstream_add(struct prefix_sg *sg,
+struct pim_upstream *pim_upstream_add(struct pim_instance *pim,
+                                     struct prefix_sg *sg,
                                      struct interface *incoming, int flags,
-                                     const char *name)
+                                     const char *name,
+                                     struct pim_ifchannel *ch)
 {
        struct pim_upstream *up = NULL;
-       struct pim_interface *pim_ifp;
        int found = 0;
 
-       pim_ifp = incoming->info;
-       up = pim_upstream_find(pim_ifp->pim, sg);
+       up = pim_upstream_find(pim, sg);
        if (up) {
                pim_upstream_ref(up, flags, name);
                found = 1;
        } else {
-               up = pim_upstream_new(sg, incoming, flags);
+               up = pim_upstream_new(pim, sg, incoming, flags, ch);
        }
 
        if (PIM_DEBUG_TRACE) {
@@ -858,12 +864,11 @@ int pim_upstream_evaluate_join_desired(struct pim_instance *pim,
                                       struct pim_upstream *up)
 {
        struct interface *ifp;
-       struct listnode *node;
        struct pim_ifchannel *ch, *starch;
        struct pim_upstream *starup = up->parent;
        int ret = 0;
 
-       for (ALL_LIST_ELEMENTS_RO(vrf_iflist(pim->vrf_id), node, ifp)) {
+       FOR_ALL_INTERFACES (pim->vrf, ifp) {
                if (!ifp->info)
                        continue;
 
@@ -903,13 +908,13 @@ void pim_upstream_update_join_desired(struct pim_instance *pim,
 
        /* switched from false to true */
        if (is_join_desired && !was_join_desired) {
-               pim_upstream_switch(up, PIM_UPSTREAM_JOINED);
+               pim_upstream_switch(pim, up, PIM_UPSTREAM_JOINED);
                return;
        }
 
        /* switched from true to false */
        if (!is_join_desired && was_join_desired) {
-               pim_upstream_switch(up, PIM_UPSTREAM_NOTJOINED);
+               pim_upstream_switch(pim, up, PIM_UPSTREAM_NOTJOINED);
                return;
        }
 }
@@ -943,8 +948,8 @@ void pim_upstream_rpf_genid_changed(struct pim_instance *pim,
                        pim_addr_dump("<rpf?>", &up->rpf.rpf_addr, rpf_addr_str,
                                      sizeof(rpf_addr_str));
                        zlog_debug(
-                               "%s: matching neigh=%s against upstream (S,G)=%s joined=%d rpf_addr=%s",
-                               __PRETTY_FUNCTION__, neigh_str, up->sg_str,
+                               "%s: matching neigh=%s against upstream (S,G)=%s[%s] joined=%d rpf_addr=%s",
+                               __PRETTY_FUNCTION__, neigh_str, up->sg_str, pim->vrf->name,
                                up->join_state == PIM_UPSTREAM_JOINED,
                                rpf_addr_str);
                }
@@ -1081,10 +1086,12 @@ static void pim_upstream_fhr_kat_start(struct pim_upstream *up)
 static int pim_upstream_keep_alive_timer(struct thread *t)
 {
        struct pim_upstream *up;
+       struct pim_instance *pim;
 
        up = THREAD_ARG(t);
+       pim = up->channel_oil->pim;
 
-       if (I_am_RP(pimg, up->sg.grp)) {
+       if (I_am_RP(pim, up->sg.grp)) {
                pim_br_clear_pmbr(&up->sg);
                /*
                 * We need to do more here :)
@@ -1093,19 +1100,26 @@ static int pim_upstream_keep_alive_timer(struct thread *t)
        }
 
        /* source is no longer active - pull the SA from MSDP's cache */
-       pim_msdp_sa_local_del(&up->sg);
+       pim_msdp_sa_local_del(pim, &up->sg);
 
        /* if entry was created because of activity we need to deref it */
        if (PIM_UPSTREAM_FLAG_TEST_SRC_STREAM(up->flags)) {
-               pim_upstream_fhr_kat_expiry(pimg, up);
+               pim_upstream_fhr_kat_expiry(pim, up);
                if (PIM_DEBUG_TRACE)
-                       zlog_debug("kat expired on %s; remove stream reference",
-                                  up->sg_str);
+                       zlog_debug("kat expired on %s[%s]; remove stream reference",
+                                  up->sg_str, pim->vrf->name);
                PIM_UPSTREAM_FLAG_UNSET_SRC_STREAM(up->flags);
-               pim_upstream_del(pimg, up, __PRETTY_FUNCTION__);
+               pim_upstream_del(pim, up, __PRETTY_FUNCTION__);
        } else if (PIM_UPSTREAM_FLAG_TEST_SRC_LHR(up->flags)) {
+               struct pim_upstream *parent = up->parent;
+
                PIM_UPSTREAM_FLAG_UNSET_SRC_LHR(up->flags);
-               pim_upstream_del(pimg, up, __PRETTY_FUNCTION__);
+               pim_upstream_del(pim, up, __PRETTY_FUNCTION__);
+
+               if (parent) {
+                       pim_jp_agg_single_upstream_send(&parent->rpf,
+                                                       parent, true);
+               }
        }
 
        return 0;
@@ -1130,12 +1144,11 @@ void pim_upstream_keep_alive_timer_start(struct pim_upstream *up, uint32_t time)
 /* MSDP on RP needs to know if a source is registerable to this RP */
 static int pim_upstream_msdp_reg_timer(struct thread *t)
 {
-       struct pim_upstream *up;
-
-       up = THREAD_ARG(t);
+       struct pim_upstream *up = THREAD_ARG(t);
+       struct pim_instance *pim = up->channel_oil->pim;
 
        /* source is no longer active - pull the SA from MSDP's cache */
-       pim_msdp_sa_local_del(&up->sg);
+       pim_msdp_sa_local_del(pim, &up->sg);
        return 1;
 }
 void pim_upstream_msdp_reg_timer_start(struct pim_upstream *up)
@@ -1175,9 +1188,10 @@ void pim_upstream_msdp_reg_timer_start(struct pim_upstream *up)
  *  SwitchToSptDesired(S,G) return true once a single packet has been
  *  received for the source and group.
  */
-int pim_upstream_switch_to_spt_desired(struct prefix_sg *sg)
+int pim_upstream_switch_to_spt_desired(struct pim_instance *pim,
+                                      struct prefix_sg *sg)
 {
-       if (I_am_RP(pimg, sg->grp))
+       if (I_am_RP(pim, sg->grp))
                return 1;
 
        return 0;
@@ -1311,22 +1325,24 @@ const char *pim_reg_state2str(enum pim_reg_state reg_state, char *state_str)
 static int pim_upstream_register_stop_timer(struct thread *t)
 {
        struct pim_interface *pim_ifp;
+       struct pim_instance *pim;
        struct pim_upstream *up;
        struct pim_rpf *rpg;
        struct ip ip_hdr;
        up = THREAD_ARG(t);
+       pim = up->channel_oil->pim;
 
        if (PIM_DEBUG_TRACE) {
                char state_str[PIM_REG_STATE_STR_LEN];
-               zlog_debug("%s: (S,G)=%s upstream register stop timer %s",
-                          __PRETTY_FUNCTION__, up->sg_str,
+               zlog_debug("%s: (S,G)=%s[%s] upstream register stop timer %s",
+                          __PRETTY_FUNCTION__, up->sg_str, pim->vrf->name,
                           pim_reg_state2str(up->reg_state, state_str));
        }
 
        switch (up->reg_state) {
        case PIM_REG_JOIN_PENDING:
                up->reg_state = PIM_REG_JOIN;
-               pim_channel_add_oif(up->channel_oil, pimg->regiface,
+               pim_channel_add_oif(up->channel_oil, pim->regiface,
                                    PIM_OIF_FLAG_PROTO_PIM);
                break;
        case PIM_REG_JOIN:
@@ -1345,7 +1361,7 @@ static int pim_upstream_register_stop_timer(struct thread *t)
                pim_upstream_start_register_stop_timer(up, 1);
 
                if (((up->channel_oil->cc.lastused / 100)
-                    > PIM_KEEPALIVE_PERIOD)
+                    > pim->keep_alive_time)
                    && (I_am_RP(pim_ifp->pim, up->sg.grp))) {
                        if (PIM_DEBUG_TRACE)
                                zlog_debug(
@@ -1354,6 +1370,13 @@ static int pim_upstream_register_stop_timer(struct thread *t)
                        return 0;
                }
                rpg = RP(pim_ifp->pim, up->sg.grp);
+               if (!rpg) {
+                       if (PIM_DEBUG_TRACE)
+                               zlog_debug(
+                                       "%s: Cannot send register for %s no RPF to the RP",
+                                       __PRETTY_FUNCTION__, up->sg_str);
+                       return 0;
+               }
                memset(&ip_hdr, 0, sizeof(struct ip));
                ip_hdr.ip_p = PIM_IP_PROTO_PIM;
                ip_hdr.ip_hl = 5;
@@ -1402,7 +1425,6 @@ int pim_upstream_inherited_olist_decide(struct pim_instance *pim,
        struct interface *ifp;
        struct pim_interface *pim_ifp = NULL;
        struct pim_ifchannel *ch, *starch;
-       struct listnode *node;
        struct pim_upstream *starup = up->parent;
        int output_intf = 0;
 
@@ -1417,7 +1439,7 @@ int pim_upstream_inherited_olist_decide(struct pim_instance *pim,
                up->channel_oil = pim_channel_oil_add(
                        pim, &up->sg, pim_ifp->mroute_vif_index);
 
-       for (ALL_LIST_ELEMENTS_RO(vrf_iflist(pim->vrf_id), node, ifp)) {
+       FOR_ALL_INTERFACES (pim->vrf, ifp) {
                if (!ifp->info)
                        continue;
 
@@ -1474,7 +1496,7 @@ int pim_upstream_inherited_olist(struct pim_instance *pim,
         * incoming packets so we don't bother the other stuff!
         */
        if (output_intf)
-               pim_upstream_switch(up, PIM_UPSTREAM_JOINED);
+               pim_upstream_switch(pim, up, PIM_UPSTREAM_JOINED);
        else
                forward_on(up);
 
@@ -1507,12 +1529,12 @@ void pim_upstream_find_new_rpf(struct pim_instance *pim)
                                zlog_debug(
                                        "Upstream %s without a path to send join, checking",
                                        up->sg_str);
-                       pim_rpf_update(up, NULL, 1);
+                       pim_rpf_update(pim, up, NULL, 1);
                }
        }
 }
 
-static unsigned int pim_upstream_hash_key(void *arg)
+unsigned int pim_upstream_hash_key(void *arg)
 {
        struct pim_upstream *up = (struct pim_upstream *)arg;
 
@@ -1522,15 +1544,14 @@ static unsigned int pim_upstream_hash_key(void *arg)
 void pim_upstream_terminate(struct pim_instance *pim)
 {
        if (pim->upstream_list)
-               list_delete(pim->upstream_list);
-       pim->upstream_list = NULL;
+               list_delete_and_null(&pim->upstream_list);
 
        if (pim->upstream_hash)
                hash_free(pim->upstream_hash);
        pim->upstream_hash = NULL;
 }
 
-static int pim_upstream_equal(const void *arg1, const void *arg2)
+int pim_upstream_equal(const void *arg1, const void *arg2)
 {
        const struct pim_upstream *up1 = (const struct pim_upstream *)arg1;
        const struct pim_upstream *up2 = (const struct pim_upstream *)arg2;
@@ -1558,6 +1579,8 @@ static int pim_upstream_equal(const void *arg1, const void *arg2)
  */
 static bool pim_upstream_kat_start_ok(struct pim_upstream *up)
 {
+       struct pim_instance *pim = up->channel_oil->pim;
+
        /* "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,
@@ -1577,7 +1600,7 @@ static bool pim_upstream_kat_start_ok(struct pim_upstream *up)
                 * MUST be
                 * removed to handle spt turn-arounds correctly in a 3-tier clos
                 */
-               if (I_am_RP(pimg, up->sg.grp))
+               if (I_am_RP(pim, up->sg.grp))
                        return true;
        }
 
@@ -1591,12 +1614,14 @@ static bool pim_upstream_kat_start_ok(struct pim_upstream *up)
 static void pim_upstream_sg_running(void *arg)
 {
        struct pim_upstream *up = (struct pim_upstream *)arg;
+       struct pim_instance *pim = up->channel_oil->pim;
 
        // No packet can have arrived here if this is the case
-       if (!up->channel_oil || !up->channel_oil->installed) {
+       if (!up->channel_oil->installed) {
                if (PIM_DEBUG_TRACE)
-                       zlog_debug("%s: %s is not installed in mroute",
-                                  __PRETTY_FUNCTION__, up->sg_str);
+                       zlog_debug("%s: %s[%s] is not installed in mroute",
+                                  __PRETTY_FUNCTION__,
+                                  up->sg_str, pim->vrf->name);
                return;
        }
 
@@ -1611,9 +1636,9 @@ static void pim_upstream_sg_running(void *arg)
        if (up->channel_oil->oil_inherited_rescan) {
                if (PIM_DEBUG_TRACE)
                        zlog_debug(
-                               "%s: Handling unscanned inherited_olist for %s",
-                               __PRETTY_FUNCTION__, up->sg_str);
-               pim_upstream_inherited_olist_decide(pimg, up);
+                               "%s: Handling unscanned inherited_olist for %s[%s]",
+                               __PRETTY_FUNCTION__, up->sg_str, pim->vrf->name);
+               pim_upstream_inherited_olist_decide(pim, up);
                up->channel_oil->oil_inherited_rescan = 0;
        }
        pim_mroute_update_counters(up->channel_oil);
@@ -1623,8 +1648,8 @@ static void pim_upstream_sg_running(void *arg)
            && (up->channel_oil->cc.lastused / 100 > 30)) {
                if (PIM_DEBUG_TRACE) {
                        zlog_debug(
-                               "%s: %s old packet count is equal or lastused is greater than 30, (%ld,%ld,%lld)",
-                               __PRETTY_FUNCTION__, up->sg_str,
+                               "%s[%s]: %s old packet count is equal or lastused is greater than 30, (%ld,%ld,%lld)",
+                               __PRETTY_FUNCTION__, up->sg_str, pim->vrf->name,
                                up->channel_oil->cc.oldpktcnt,
                                up->channel_oil->cc.pktcnt,
                                up->channel_oil->cc.lastused / 100);
@@ -1638,17 +1663,17 @@ static void pim_upstream_sg_running(void *arg)
                if (!PIM_UPSTREAM_FLAG_TEST_SRC_STREAM(up->flags)) {
                        if (PIM_DEBUG_TRACE)
                                zlog_debug(
-                                       "source reference created on kat restart %s",
-                                       up->sg_str);
+                                       "source reference created on kat restart %s[%s]",
+                                       up->sg_str, pim->vrf->name);
 
                        pim_upstream_ref(up, PIM_UPSTREAM_FLAG_MASK_SRC_STREAM,
                                         __PRETTY_FUNCTION__);
                        PIM_UPSTREAM_FLAG_SET_SRC_STREAM(up->flags);
                        pim_upstream_fhr_kat_start(up);
                }
-               pim_upstream_keep_alive_timer_start(up, qpim_keep_alive_time);
+               pim_upstream_keep_alive_timer_start(up, pim->keep_alive_time);
        } else if (PIM_UPSTREAM_FLAG_TEST_SRC_LHR(up->flags))
-               pim_upstream_keep_alive_timer_start(up, qpim_keep_alive_time);
+               pim_upstream_keep_alive_timer_start(up, pim->keep_alive_time);
 
        if (up->sptbit != PIM_UPSTREAM_SPTBIT_TRUE) {
                pim_upstream_set_sptbit(up, up->rpf.source_nexthop.interface);
@@ -1734,11 +1759,16 @@ void pim_upstream_remove_lhr_star_pimreg(struct pim_instance *pim,
 
 void pim_upstream_init(struct pim_instance *pim)
 {
+       char hash_name[64];
+
        pim->upstream_sg_wheel =
                wheel_init(master, 31000, 100, pim_upstream_hash_key,
                           pim_upstream_sg_running);
+
+       snprintf(hash_name, 64, "PIM %s Upstream Hash",
+                pim->vrf->name);
        pim->upstream_hash = hash_create_size(8192, pim_upstream_hash_key,
-                                             pim_upstream_equal, NULL);
+                                             pim_upstream_equal, hash_name);
 
        pim->upstream_list = list_new();
        pim->upstream_list->del = (void (*)(void *))pim_upstream_free;