]> git.proxmox.com Git - mirror_frr.git/blobdiff - pimd/pim_ifchannel.c
Merge pull request #5767 from ton31337/fix/replace_s_addr_0_to_INADDR_ANY
[mirror_frr.git] / pimd / pim_ifchannel.c
index 66e64cefa0bfce83ecf94bb2a1a11300100cc78c..d9c9bb37dd2048171c25b8ce883ca1a7cb6cec2b 100644 (file)
@@ -147,10 +147,11 @@ void pim_ifchannel_delete(struct pim_ifchannel *ch)
                                        ch->upstream, ch, ch->parent))
                        pim_channel_add_oif(ch->upstream->channel_oil,
                                        ch->interface,
-                                       PIM_OIF_FLAG_PROTO_STAR);
+                                       PIM_OIF_FLAG_PROTO_STAR,
+                                       __func__);
 
                pim_channel_del_oif(ch->upstream->channel_oil,
-                                       ch->interface, mask);
+                                       ch->interface, mask, __func__);
                /*
                 * Do we have any S,G's that are inheriting?
                 * Nuke from on high too.
@@ -161,9 +162,10 @@ void pim_ifchannel_delete(struct pim_ifchannel *ch)
 
                        for (ALL_LIST_ELEMENTS_RO(ch->upstream->sources,
                                                  up_node, child))
-                               pim_channel_del_oif(child->channel_oil,
-                                                   ch->interface,
-                                                   PIM_OIF_FLAG_PROTO_STAR);
+                               pim_channel_del_inherited_oif(
+                                               child->channel_oil,
+                                               ch->interface,
+                                               __func__);
                }
        }
 
@@ -179,9 +181,7 @@ void pim_ifchannel_delete(struct pim_ifchannel *ch)
 
        listnode_delete(ch->upstream->ifchannels, ch);
 
-       if (ch->ifjoin_state != PIM_IFJOIN_NOINFO) {
-               pim_upstream_update_join_desired(pim_ifp->pim, ch->upstream);
-       }
+       pim_upstream_update_join_desired(pim_ifp->pim, ch->upstream);
 
        /* upstream is common across ifchannels, check if upstream's
           ifchannel list is empty before deleting upstream_del
@@ -191,11 +191,13 @@ void pim_ifchannel_delete(struct pim_ifchannel *ch)
                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);
+       else {
+               if (PIM_DEBUG_PIM_TRACE)
+                       zlog_debug("%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;
 
@@ -248,6 +250,7 @@ void pim_ifchannel_ifjoin_switch(const char *caller, struct pim_ifchannel *ch,
 {
        enum pim_ifjoin_state old_state = ch->ifjoin_state;
        struct pim_interface *pim_ifp = ch->interface->info;
+       struct pim_ifchannel *child_ch;
 
        if (PIM_DEBUG_PIM_EVENTS)
                zlog_debug(
@@ -291,28 +294,18 @@ void pim_ifchannel_ifjoin_switch(const char *caller, struct pim_ifchannel *ch,
                                        if (!c_oil)
                                                continue;
 
-                                       if (!pim_upstream_evaluate_join_desired(
-                                                   pim_ifp->pim, child)) {
-                                               pim_channel_del_oif(
-                                                       c_oil, ch->interface,
-                                                       PIM_OIF_FLAG_PROTO_STAR);
-                                               pim_upstream_update_join_desired(
-                                                       pim_ifp->pim, child);
-                                       }
-
                                        /*
                                         * If the S,G has no if channel and the
                                         * c_oil still
                                         * has output here then the *,G was
                                         * supplying the implied
                                         * if channel.  So remove it.
-                                        * I think this is dead code now. is it?
                                         */
                                        if (c_oil->oil.mfcc_ttls
                                                    [pim_ifp->mroute_vif_index])
-                                               pim_channel_del_oif(
+                                               pim_channel_del_inherited_oif(
                                                        c_oil, ch->interface,
-                                                       PIM_OIF_FLAG_PROTO_STAR);
+                                                       __func__);
                                }
                        }
                        if (ch->ifjoin_state == PIM_IFJOIN_JOIN) {
@@ -326,12 +319,19 @@ void pim_ifchannel_ifjoin_switch(const char *caller, struct pim_ifchannel *ch,
                                                        child->sg_str,
                                                        up->sg_str);
 
-                                       if (pim_upstream_evaluate_join_desired(
-                                                   pim_ifp->pim, child)) {
+                                       /* check if the channel can be
+                                        * inherited into the SG's OIL
+                                        */
+                                       child_ch = pim_ifchannel_find(
+                                                       ch->interface,
+                                                       &child->sg);
+                                       if (pim_upstream_eval_inherit_if(
+                                                   child, child_ch, ch)) {
                                                pim_channel_add_oif(
                                                        child->channel_oil,
                                                        ch->interface,
-                                                       PIM_OIF_FLAG_PROTO_STAR);
+                                                       PIM_OIF_FLAG_PROTO_STAR,
+                                                       __func__);
                                                pim_upstream_update_join_desired(
                                                        pim_ifp->pim, child);
                                        }
@@ -580,7 +580,7 @@ struct pim_ifchannel *pim_ifchannel_add(struct interface *ifp,
        ch->ifassert_my_metric = pim_macro_ch_my_assert_metric_eval(ch);
        ch->ifassert_winner_metric = pim_macro_ch_my_assert_metric_eval(ch);
 
-       ch->ifassert_winner.s_addr = 0;
+       ch->ifassert_winner.s_addr = INADDR_ANY;
 
        /* Assert state */
        ch->t_ifassert_timer = NULL;
@@ -617,7 +617,7 @@ static int on_ifjoin_expiry_timer(struct thread *t)
 
        ch = THREAD_ARG(t);
 
-       if (PIM_DEBUG_TRACE)
+       if (PIM_DEBUG_PIM_TRACE)
                zlog_debug("%s: ifchannel %s expiry timer", __PRETTY_FUNCTION__,
                           ch->sg_str);
 
@@ -636,7 +636,7 @@ static int on_ifjoin_prune_pending_timer(struct thread *t)
 
        ch = THREAD_ARG(t);
 
-       if (PIM_DEBUG_TRACE)
+       if (PIM_DEBUG_PIM_TRACE)
                zlog_debug(
                        "%s: IFCHANNEL%s %s Prune Pending Timer Popped",
                        __PRETTY_FUNCTION__, pim_str_sg_dump(&ch->sg),
@@ -781,6 +781,28 @@ static int nonlocal_upstream(int is_join, struct interface *recv_ifp,
        return 1; /* non-local */
 }
 
+static void pim_ifchannel_ifjoin_handler(struct pim_ifchannel *ch,
+               struct pim_interface *pim_ifp)
+{
+       pim_ifchannel_ifjoin_switch(__PRETTY_FUNCTION__, ch,
+                       PIM_IFJOIN_JOIN);
+       PIM_IF_FLAG_UNSET_S_G_RPT(ch->flags);
+       /* check if the interface qualifies as an immediate
+        * OIF
+        */
+       if (pim_upstream_evaluate_join_desired_interface(
+                               ch->upstream, ch,
+                               NULL /*starch*/)) {
+               pim_channel_add_oif(ch->upstream->channel_oil,
+                               ch->interface,
+                               PIM_OIF_FLAG_PROTO_PIM,
+                               __func__);
+               pim_upstream_update_join_desired(pim_ifp->pim,
+                               ch->upstream);
+       }
+}
+
+
 void pim_ifchannel_join_add(struct interface *ifp, struct in_addr neigh_addr,
                            struct in_addr upstream, struct prefix_sg *sg,
                            uint8_t source_flags, uint16_t holdtime)
@@ -888,25 +910,8 @@ void pim_ifchannel_join_add(struct interface *ifp, struct in_addr neigh_addr,
                if (source_flags & PIM_ENCODE_RPT_BIT)
                        pim_ifchannel_ifjoin_switch(__PRETTY_FUNCTION__, ch,
                                                    PIM_IFJOIN_NOINFO);
-               else {
-                       /*
-                        * We have received a S,G join and we are in
-                        * S,G RPT Prune state.  Which means we need
-                        * to transition to Join state and setup
-                        * state as appropriate.
-                        */
-                       pim_ifchannel_ifjoin_switch(__PRETTY_FUNCTION__, ch,
-                                                   PIM_IFJOIN_JOIN);
-                       PIM_IF_FLAG_UNSET_S_G_RPT(ch->flags);
-                       if (pim_upstream_evaluate_join_desired(pim_ifp->pim,
-                                                              ch->upstream)) {
-                               pim_channel_add_oif(ch->upstream->channel_oil,
-                                                   ch->interface,
-                                                   PIM_OIF_FLAG_PROTO_PIM);
-                               pim_upstream_update_join_desired(pim_ifp->pim,
-                                                                ch->upstream);
-                       }
-               }
+               else
+                       pim_ifchannel_ifjoin_handler(ch, pim_ifp);
                break;
        case PIM_IFJOIN_PRUNE_PENDING:
                THREAD_OFF(ch->t_ifjoin_prune_pending_timer);
@@ -914,9 +919,9 @@ void pim_ifchannel_join_add(struct interface *ifp, struct in_addr neigh_addr,
                        THREAD_OFF(ch->t_ifjoin_expiry_timer);
                        pim_ifchannel_ifjoin_switch(__PRETTY_FUNCTION__, ch,
                                                    PIM_IFJOIN_NOINFO);
-               } else
-                       pim_ifchannel_ifjoin_switch(__PRETTY_FUNCTION__, ch,
-                                                   PIM_IFJOIN_JOIN);
+               } else {
+                       pim_ifchannel_ifjoin_handler(ch, pim_ifp);
+               }
                break;
        case PIM_IFJOIN_PRUNE_TMP:
                break;
@@ -945,7 +950,7 @@ void pim_ifchannel_prune(struct interface *ifp, struct in_addr upstream,
 
        ch = pim_ifchannel_find(ifp, sg);
        if (!ch && !(source_flags & PIM_ENCODE_RPT_BIT)) {
-               if (PIM_DEBUG_TRACE)
+               if (PIM_DEBUG_PIM_TRACE)
                        zlog_debug(
                                "%s: Received prune with no relevant ifchannel %s%s state: %d",
                                __PRETTY_FUNCTION__, ifp->name,
@@ -1103,9 +1108,9 @@ int pim_ifchannel_local_membership_add(struct interface *ifp,
                        if (pim_upstream_evaluate_join_desired_interface(
                                    child, ch, starch)) {
                                pim_channel_add_oif(child->channel_oil, ifp,
-                                                   PIM_OIF_FLAG_PROTO_STAR);
-                               pim_upstream_switch(pim, child,
-                                                   PIM_UPSTREAM_JOINED);
+                                                   PIM_OIF_FLAG_PROTO_STAR,
+                                                       __func__);
+                               pim_upstream_update_join_desired(pim, child);
                        }
                }
 
@@ -1122,12 +1127,14 @@ int pim_ifchannel_local_membership_add(struct interface *ifp,
                                    == PREFIX_DENY) {
                                        pim_channel_add_oif(
                                                up->channel_oil, pim->regiface,
-                                               PIM_OIF_FLAG_PROTO_IGMP);
+                                               PIM_OIF_FLAG_PROTO_IGMP,
+                                               __func__);
                                }
                        }
                } else
                        pim_channel_add_oif(up->channel_oil, pim->regiface,
-                                           PIM_OIF_FLAG_PROTO_IGMP);
+                                       PIM_OIF_FLAG_PROTO_IGMP,
+                                       __func__);
        }
 
        return 1;
@@ -1172,22 +1179,19 @@ void pim_ifchannel_local_membership_del(struct interface *ifp,
                                           child->sg_str);
 
                        ch = pim_ifchannel_find(ifp, &child->sg);
-                       if (c_oil
-                           && !pim_upstream_evaluate_join_desired_interface(
-                                      child, ch, starch))
-                               pim_channel_del_oif(c_oil, ifp,
-                                                   PIM_OIF_FLAG_PROTO_STAR);
-
                        /*
                         * If the S,G has no if channel and the c_oil still
                         * has output here then the *,G was supplying the
                         * implied
                         * if channel.  So remove it.
                         */
-                       if (!chchannel && c_oil
-                           && c_oil->oil.mfcc_ttls[pim_ifp->mroute_vif_index])
-                               pim_channel_del_oif(c_oil, ifp,
-                                                   PIM_OIF_FLAG_PROTO_STAR);
+                       if (!pim_upstream_evaluate_join_desired_interface(
+                               child, ch, starch) ||
+                               (!chchannel &&
+                                c_oil->oil.mfcc_ttls[pim_ifp->mroute_vif_index])) {
+                               pim_channel_del_inherited_oif(c_oil, ifp,
+                                               __func__);
+                       }
 
                        /* Child node removal/ref count-- will happen as part of
                         * parent' delete_no_info */
@@ -1406,12 +1410,10 @@ void pim_ifchannel_set_star_g_join_state(struct pim_ifchannel *ch, int eom,
                                child->upstream))) {
                                pim_channel_add_oif(
                                        child->upstream->channel_oil,
-                                       ch->interface, PIM_OIF_FLAG_PROTO_STAR);
-                               pim_upstream_switch(pim, child->upstream,
-                                                   PIM_UPSTREAM_JOINED);
-                               pim_jp_agg_single_upstream_send(
-                                       &child->upstream->rpf, child->upstream,
-                                       true);
+                                       ch->interface, PIM_OIF_FLAG_PROTO_STAR,
+                                       __func__);
+                               pim_upstream_update_join_desired(pim,
+                                               child->upstream);
                        }
                        send_upstream_starg = true;