]> git.puffer.fish Git - mirror/frr.git/commitdiff
pimd: Fix code to not send joins when SGRPT Prune is received
authorDonald Sharp <sharpd@cumulusnetworks.com>
Thu, 22 Jun 2017 15:05:03 +0000 (11:05 -0400)
committerDonald Sharp <sharpd@cumulusnetworks.com>
Mon, 24 Jul 2017 17:51:40 +0000 (13:51 -0400)
When we receive a SGRPT Prune we were switching the upstream
to JOINED and immediately sending a join.  This was not
the right thing to do.

This was happening because we were making decisions about the
new ifchannel before it was fully formed.

Rework ifchannel startup to provide enough information to
the pim upstream data structure to make the right decisions

Ticket: CM-16425
Signed-off-by: Donald Sharp <sharpd@cumulusnetworks.com>
pimd/pim_assert.c
pimd/pim_ifchannel.c
pimd/pim_ifchannel.h
pimd/pim_mroute.c
pimd/pim_msdp.c
pimd/pim_register.c
pimd/pim_upstream.c
pimd/pim_upstream.h

index 6af52bbf4d1e4a810650bbb2b358597c4de65728..934fea5a9e1a9a038aae4f3ce5e2c3d453e5088e 100644 (file)
@@ -147,7 +147,7 @@ static int dispatch_assert(struct interface *ifp, struct in_addr source_addr,
        memset(&sg, 0, sizeof(struct prefix_sg));
        sg.src = source_addr;
        sg.grp = group_addr;
-       ch = pim_ifchannel_add(ifp, &sg, 0);
+       ch = pim_ifchannel_add(ifp, &sg, 0, 0);
        if (!ch) {
                zlog_warn(
                        "%s: (S,G)=%s failure creating channel on interface %s",
index 5f3901e49b264e8bcb9c968385211d0d0a7f4e4c..922ee647a5bc350056826f7297aab5c1a267d725 100644 (file)
@@ -509,7 +509,8 @@ static struct pim_ifchannel *pim_ifchannel_find_parent(struct pim_ifchannel *ch)
 }
 
 struct pim_ifchannel *pim_ifchannel_add(struct interface *ifp,
-                                       struct prefix_sg *sg, int flags)
+                                       struct prefix_sg *sg,
+                                       uint8_t source_flags, int up_flags)
 {
        struct pim_interface *pim_ifp;
        struct pim_ifchannel *ch;
@@ -521,27 +522,19 @@ struct pim_ifchannel *pim_ifchannel_add(struct interface *ifp,
 
        pim_ifp = ifp->info;
 
-       up = pim_upstream_add(pim_ifp->pim, sg, NULL, flags,
-                             __PRETTY_FUNCTION__);
-       if (!up) {
-               zlog_err(
-                       "%s: could not attach upstream (S,G)=%s on interface %s",
-                       __PRETTY_FUNCTION__, pim_str_sg_dump(sg), ifp->name);
-               return NULL;
-       }
-
        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__, up->sg_str, ifp->name);
-
-               pim_upstream_del(pim_ifp->pim, up, __PRETTY_FUNCTION__);
                return NULL;
        }
 
        ch->flags = 0;
-       ch->upstream = up;
+       if ((source_flags & PIM_ENCODE_RPT_BIT)
+           && !(source_flags & PIM_ENCODE_WC_BIT))
+               PIM_IF_FLAG_SET_S_G_RPT(ch->flags);
+
        ch->interface = ifp;
        ch->sg = *sg;
        pim_str_sg_set(sg, ch->sg_str);
@@ -561,6 +554,32 @@ struct pim_ifchannel *pim_ifchannel_add(struct interface *ifp,
        ch->t_ifjoin_prune_pending_timer = NULL;
        ch->ifjoin_creation = 0;
 
+       /* Attach to list */
+       listnode_add_sort(pim_ifp->pim_ifchannel_list, ch);
+       ch = hash_get(pim_ifp->pim_ifchannel_hash, ch, hash_alloc_intern);
+       listnode_add_sort(pim_ifp->pim->ifchannel_list, ch);
+
+       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);
+
+               pim_ifchannel_remove_children(ch);
+               if (ch)
+                       list_delete(ch->sources);
+
+               listnode_delete(pim_ifp->pim_ifchannel_list, ch);
+               hash_release(pim_ifp->pim_ifchannel_hash, ch);
+               listnode_delete(pim_ifp->pim->ifchannel_list, ch);
+               XFREE(MTYPE_PIM_IFCHANNEL, ch);
+               return NULL;
+       }
+
+       listnode_add_sort(up->ifchannels, ch);
+
        ch->ifassert_my_metric = pim_macro_ch_my_assert_metric_eval(ch);
        ch->ifassert_winner_metric = pim_macro_ch_my_assert_metric_eval(ch);
 
@@ -580,13 +599,6 @@ struct pim_ifchannel *pim_ifchannel_add(struct interface *ifp,
        else
                PIM_IF_FLAG_UNSET_ASSERT_TRACKING_DESIRED(ch->flags);
 
-       /* Attach to list */
-       listnode_add_sort(pim_ifp->pim_ifchannel_list, ch);
-       ch = hash_get(pim_ifp->pim_ifchannel_hash, ch, hash_alloc_intern);
-       listnode_add_sort(pim_ifp->pim->ifchannel_list, ch);
-
-       listnode_add_sort(up->ifchannels, ch);
-
        if (PIM_DEBUG_PIM_TRACE)
                zlog_debug("%s: ifchannel %s is created ", __PRETTY_FUNCTION__,
                           ch->sg_str);
@@ -772,7 +784,8 @@ void pim_ifchannel_join_add(struct interface *ifp, struct in_addr neigh_addr,
                return;
        }
 
-       ch = pim_ifchannel_add(ifp, sg, PIM_UPSTREAM_FLAG_MASK_SRC_PIM);
+       ch = pim_ifchannel_add(ifp, sg, source_flags,
+                              PIM_UPSTREAM_FLAG_MASK_SRC_PIM);
        if (!ch)
                return;
 
@@ -914,7 +927,8 @@ void pim_ifchannel_prune(struct interface *ifp, struct in_addr upstream,
                return;
        }
 
-       ch = pim_ifchannel_add(ifp, sg, PIM_UPSTREAM_FLAG_MASK_SRC_PIM);
+       ch = pim_ifchannel_add(ifp, sg, source_flags,
+                              PIM_UPSTREAM_FLAG_MASK_SRC_PIM);
        if (!ch)
                return;
 
@@ -1027,7 +1041,7 @@ int pim_ifchannel_local_membership_add(struct interface *ifp,
                }
        }
 
-       ch = pim_ifchannel_add(ifp, sg, PIM_UPSTREAM_FLAG_MASK_SRC_IGMP);
+       ch = pim_ifchannel_add(ifp, sg, 0, PIM_UPSTREAM_FLAG_MASK_SRC_IGMP);
        if (!ch) {
                return 0;
        }
index 2260fd451b9b73182ef499e4b5382ca7a974978d..3fd717bec8d4c15a05d1a3f69d8e047b21126b57 100644 (file)
@@ -116,7 +116,8 @@ void pim_ifchannel_delete_on_noinfo(struct interface *ifp);
 struct pim_ifchannel *pim_ifchannel_find(struct interface *ifp,
                                         struct prefix_sg *sg);
 struct pim_ifchannel *pim_ifchannel_add(struct interface *ifp,
-                                       struct prefix_sg *sg, int flags);
+                                       struct prefix_sg *sg, uint8_t ch_flags,
+                                       int up_flags);
 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);
index fa53e568f4cdd1fe178aa3b70237431c520366d8..0e0a275155d9231f1f2bad9d7e83cd809eb8f009 100644 (file)
@@ -248,7 +248,7 @@ static int pim_mroute_msg_wholepkt(int fd, struct interface *ifp,
                if (up && PIM_UPSTREAM_FLAG_TEST_SRC_IGMP(up->flags)) {
                        up = pim_upstream_add(pim_ifp->pim, &sg, ifp,
                                              PIM_UPSTREAM_FLAG_MASK_SRC_LHR,
-                                             __PRETTY_FUNCTION__);
+                                             __PRETTY_FUNCTION__, NULL);
                        if (!up) {
                                if (PIM_DEBUG_MROUTE)
                                        zlog_debug(
@@ -520,7 +520,7 @@ static int pim_mroute_msg_wrvifwhole(int fd, struct interface *ifp,
        if (pim_if_connected_to_source(ifp, sg.src)) {
                up = pim_upstream_add(pim_ifp->pim, &sg, ifp,
                                      PIM_UPSTREAM_FLAG_MASK_FHR,
-                                     __PRETTY_FUNCTION__);
+                                     __PRETTY_FUNCTION__, NULL);
                if (!up) {
                        if (PIM_DEBUG_MROUTE)
                                zlog_debug(
index 3578f005dd0a6bd887446a6b094f5aee3332377f..34962122a03a4ff90b42474ab262e731c6804a5b 100644 (file)
@@ -205,7 +205,7 @@ static void pim_msdp_sa_upstream_update(struct pim_msdp_sa *sa,
         * as if a JP message was rxed addressed to the RP itself." */
        up = pim_upstream_add(sa->pim, &sa->sg, NULL /* iif */,
                              PIM_UPSTREAM_FLAG_MASK_SRC_MSDP,
-                             __PRETTY_FUNCTION__);
+                             __PRETTY_FUNCTION__, NULL);
 
        sa->up = up;
        if (up) {
index 605dd43d5e7f8a9e443a2ab2a337e3506ee7e479..d0de91bb45ae83f797e83c4caa6de72f08386fb6 100644 (file)
@@ -370,7 +370,7 @@ int pim_register_recv(struct interface *ifp, struct in_addr dest_addr,
                        upstream = pim_upstream_add(
                                pim_ifp->pim, &sg, ifp,
                                PIM_UPSTREAM_FLAG_MASK_SRC_STREAM,
-                               __PRETTY_FUNCTION__);
+                               __PRETTY_FUNCTION__, NULL);
                        if (!upstream) {
                                zlog_warn("Failure to create upstream state");
                                return 1;
index 7880bfd491c32599a33eaa404d26686b4f4e0d32..e7987eb6e793a9a85a60f2e779278516013b0f57 100644 (file)
@@ -602,7 +602,8 @@ int pim_upstream_compare(void *arg1, void *arg2)
 static struct pim_upstream *pim_upstream_new(struct pim_instance *pim,
                                             struct prefix_sg *sg,
                                             struct interface *incoming,
-                                            int flags)
+                                            int flags,
+                                            struct pim_ifchannel *ch)
 {
        enum pim_rpf_result rpf_result;
        struct pim_interface *pim_ifp;
@@ -617,6 +618,9 @@ static struct pim_upstream *pim_upstream_new(struct pim_instance *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)) {
@@ -748,7 +752,8 @@ struct pim_upstream *pim_upstream_find_or_add(struct prefix_sg *sg,
                                        up->ref_count);
                }
        } else
-               up = pim_upstream_add(pim_ifp->pim, sg, incoming, flags, name);
+               up = pim_upstream_add(pim_ifp->pim, sg, incoming, flags, name,
+                                     NULL);
 
        return up;
 }
@@ -766,7 +771,8 @@ void pim_upstream_ref(struct pim_upstream *up, int flags, const char *name)
 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;
        int found = 0;
@@ -776,7 +782,7 @@ struct pim_upstream *pim_upstream_add(struct pim_instance *pim,
                pim_upstream_ref(up, flags, name);
                found = 1;
        } else {
-               up = pim_upstream_new(pim, sg, incoming, flags);
+               up = pim_upstream_new(pim, sg, incoming, flags, ch);
        }
 
        if (PIM_DEBUG_TRACE) {
index b261b8cbae73f7c8d455ff9333e23c54972b48d1..af4af2a369d51df6d210a09cb8acd46c659f3b5d 100644 (file)
@@ -146,7 +146,8 @@ struct pim_upstream *pim_upstream_find_or_add(struct prefix_sg *sg,
 struct pim_upstream *pim_upstream_add(struct pim_instance *pim,
                                      struct prefix_sg *sg,
                                      struct interface *ifp, int flags,
-                                     const char *name);
+                                     const char *name,
+                                     struct pim_ifchannel *ch);
 void pim_upstream_ref(struct pim_upstream *up, int flags, const char *name);
 struct pim_upstream *pim_upstream_del(struct pim_instance *pim,
                                      struct pim_upstream *up,