]> git.proxmox.com Git - mirror_frr.git/blobdiff - pimd/pim_ifchannel.c
zebra: Allow ns delete to happen after under/over flow checks
[mirror_frr.git] / pimd / pim_ifchannel.c
index bb56379c14a2ec0585f8ffcc08470b7e6cf3dd04..8f6a9ece5316ab7943202337cb167127faea32a2 100644 (file)
@@ -124,11 +124,6 @@ static void pim_ifchannel_find_new_children(struct pim_ifchannel *ch)
        }
 }
 
-void pim_ifchannel_free(struct pim_ifchannel *ch)
-{
-       XFREE(MTYPE_PIM_IFCHANNEL, ch);
-}
-
 void pim_ifchannel_delete(struct pim_ifchannel *ch)
 {
        struct pim_interface *pim_ifp;
@@ -141,9 +136,8 @@ void pim_ifchannel_delete(struct pim_ifchannel *ch)
                        mask = PIM_OIF_FLAG_PROTO_IGMP;
 
                /* SGRpt entry could have empty oil */
-               if (ch->upstream->channel_oil)
-                       pim_channel_del_oif(ch->upstream->channel_oil,
-                                           ch->interface, mask);
+               pim_channel_del_oif(ch->upstream->channel_oil, ch->interface,
+                                   mask);
                /*
                 * Do we have any S,G's that are inheriting?
                 * Nuke from on high too.
@@ -168,7 +162,7 @@ void pim_ifchannel_delete(struct pim_ifchannel *ch)
        pim_ifchannel_remove_children(ch);
 
        if (ch->sources)
-               list_delete_and_null(&ch->sources);
+               list_delete(&ch->sources);
 
        listnode_delete(ch->upstream->ifchannels, ch);
 
@@ -180,7 +174,16 @@ void pim_ifchannel_delete(struct pim_ifchannel *ch)
           ifchannel list is empty before deleting upstream_del
           ref count will take care of it.
        */
-       pim_upstream_del(pim_ifp->pim, ch->upstream, __PRETTY_FUNCTION__);
+       if (ch->upstream->ref_count > 0)
+               pim_upstream_del(pim_ifp->pim, ch->upstream,
+                       __PRETTY_FUNCTION__);
+
+       else
+               zlog_warn("%s: Avoiding deletion of upstream with ref_count %d "
+                       "from ifchannel(%s): %s", __PRETTY_FUNCTION__,
+                       ch->upstream->ref_count, ch->interface->name,
+                       ch->sg_str);
+
        ch->upstream = NULL;
 
        THREAD_OFF(ch->t_ifjoin_expiry_timer);
@@ -198,7 +201,7 @@ void pim_ifchannel_delete(struct pim_ifchannel *ch)
                zlog_debug("%s: ifchannel entry %s is deleted ",
                           __PRETTY_FUNCTION__, ch->sg_str);
 
-       pim_ifchannel_free(ch);
+       XFREE(MTYPE_PIM_IFCHANNEL, ch);
 }
 
 void pim_ifchannel_delete_all(struct interface *ifp)
@@ -525,12 +528,6 @@ struct pim_ifchannel *pim_ifchannel_add(struct interface *ifp,
        pim_ifp = ifp->info;
 
        ch = XCALLOC(MTYPE_PIM_IFCHANNEL, sizeof(*ch));
-       if (!ch) {
-               zlog_warn(
-                       "%s: pim_ifchannel_new() failure for (S,G)=%s on interface %s",
-                       __PRETTY_FUNCTION__, pim_str_sg_dump(sg), ifp->name);
-               return NULL;
-       }
 
        ch->flags = 0;
        if ((source_flags & PIM_ENCODE_RPT_BIT)
@@ -561,26 +558,6 @@ struct pim_ifchannel *pim_ifchannel_add(struct interface *ifp,
        up = pim_upstream_add(pim_ifp->pim, sg, NULL, up_flags,
                              __PRETTY_FUNCTION__, ch);
 
-       if (!up) {
-               zlog_err(
-                       "%s: could not attach upstream (S,G)=%s on interface %s",
-                       __PRETTY_FUNCTION__, pim_str_sg_dump(sg), ifp->name);
-
-               if (ch->parent)
-                       listnode_delete(ch->parent->sources, ch);
-
-               pim_ifchannel_remove_children(ch);
-               if (ch->sources)
-                       list_delete_and_null(&ch->sources);
-
-               THREAD_OFF(ch->t_ifjoin_expiry_timer);
-               THREAD_OFF(ch->t_ifjoin_prune_pending_timer);
-               THREAD_OFF(ch->t_ifassert_timer);
-
-               RB_REMOVE(pim_ifchannel_rb, &pim_ifp->ifchannel_rb, ch);
-               XFREE(MTYPE_PIM_IFCHANNEL, ch);
-               return NULL;
-       }
        ch->upstream = up;
 
        listnode_add_sort(up->ifchannels, ch);
@@ -1035,10 +1012,21 @@ int pim_ifchannel_local_membership_add(struct interface *ifp,
 
        /* PIM enabled on interface? */
        pim_ifp = ifp->info;
-       if (!pim_ifp)
+       if (!pim_ifp) {
+               if (PIM_DEBUG_EVENTS)
+                       zlog_debug("%s:%s Expected pim interface setup for %s",
+                                  __PRETTY_FUNCTION__,
+                                  pim_str_sg_dump(sg), ifp->name);
                return 0;
-       if (!PIM_IF_TEST_PIM(pim_ifp->options))
+       }
+
+       if (!PIM_IF_TEST_PIM(pim_ifp->options)) {
+               if (PIM_DEBUG_EVENTS)
+                       zlog_debug("%s:%s PIM is not configured on this interface %s",
+                                  __PRETTY_FUNCTION__,
+                                  pim_str_sg_dump(sg), ifp->name);
                return 0;
+       }
 
        pim = pim_ifp->pim;
 
@@ -1056,6 +1044,10 @@ int pim_ifchannel_local_membership_add(struct interface *ifp,
 
        ch = pim_ifchannel_add(ifp, sg, 0, PIM_UPSTREAM_FLAG_MASK_SRC_IGMP);
        if (!ch) {
+               if (PIM_DEBUG_EVENTS)
+                       zlog_debug("%s:%s Unable to add ifchannel",
+                                  __PRETTY_FUNCTION__,
+                                  pim_str_sg_dump(sg));
                return 0;
        }
 
@@ -1138,7 +1130,8 @@ void pim_ifchannel_local_membership_del(struct interface *ifp,
                        struct channel_oil *c_oil = child->channel_oil;
                        struct pim_ifchannel *chchannel =
                                pim_ifchannel_find(ifp, &child->sg);
-                       struct pim_interface *pim_ifp = ifp->info;
+
+                       pim_ifp = ifp->info;
 
                        if (PIM_DEBUG_EVENTS)
                                zlog_debug("%s %s: Prune(S,G)=%s(%s) from %s",