]> git.proxmox.com Git - mirror_frr.git/blobdiff - pimd/pim_oil.c
Merge pull request #5767 from ton31337/fix/replace_s_addr_0_to_INADDR_ANY
[mirror_frr.git] / pimd / pim_oil.c
index 979bc669fe99f0c3ebcc52cabbdbb033f36ec64c..598988f88f7704f9a8ee8cbe4f46db09903154d7 100644 (file)
@@ -64,8 +64,8 @@ char *pim_channel_oil_dump(struct channel_oil *c_oil, char *buf, size_t size)
        return buf;
 }
 
-static int pim_channel_oil_compare(struct channel_oil *c1,
-                                  struct channel_oil *c2)
+int pim_channel_oil_compare(const struct channel_oil *c1,
+                           const struct channel_oil *c2)
 {
        if (ntohl(c1->oil.mfcc_mcastgrp.s_addr)
            < ntohl(c2->oil.mfcc_mcastgrp.s_addr))
@@ -86,48 +86,19 @@ static int pim_channel_oil_compare(struct channel_oil *c1,
        return 0;
 }
 
-static bool pim_oil_equal(const void *arg1, const void *arg2)
-{
-       const struct channel_oil *c1 = (const struct channel_oil *)arg1;
-       const struct channel_oil *c2 = (const struct channel_oil *)arg2;
-
-       if ((c1->oil.mfcc_mcastgrp.s_addr == c2->oil.mfcc_mcastgrp.s_addr)
-           && (c1->oil.mfcc_origin.s_addr == c2->oil.mfcc_origin.s_addr))
-               return true;
-
-       return false;
-}
-
-static unsigned int pim_oil_hash_key(const void *arg)
-{
-       const struct channel_oil *oil = arg;
-
-       return jhash_2words(oil->oil.mfcc_mcastgrp.s_addr,
-                           oil->oil.mfcc_origin.s_addr, 0);
-}
-
 void pim_oil_init(struct pim_instance *pim)
 {
-       char hash_name[64];
-
-       snprintf(hash_name, 64, "PIM %s Oil Hash", pim->vrf->name);
-       pim->channel_oil_hash = hash_create_size(8192, pim_oil_hash_key,
-                                                pim_oil_equal, hash_name);
-
-       pim->channel_oil_list = list_new();
-       pim->channel_oil_list->del = (void (*)(void *))pim_channel_oil_free;
-       pim->channel_oil_list->cmp =
-               (int (*)(void *, void *))pim_channel_oil_compare;
+       rb_pim_oil_init(&pim->channel_oil_head);
 }
 
 void pim_oil_terminate(struct pim_instance *pim)
 {
-       if (pim->channel_oil_list)
-               list_delete(&pim->channel_oil_list);
+       struct channel_oil *c_oil;
+
+       while ((c_oil = rb_pim_oil_pop(&pim->channel_oil_head)))
+               pim_channel_oil_free(c_oil);
 
-       if (pim->channel_oil_hash)
-               hash_free(pim->channel_oil_hash);
-       pim->channel_oil_hash = NULL;
+       rb_pim_oil_fini(&pim->channel_oil_head);
 }
 
 void pim_channel_oil_free(struct channel_oil *c_oil)
@@ -144,7 +115,7 @@ struct channel_oil *pim_find_channel_oil(struct pim_instance *pim,
        lookup.oil.mfcc_mcastgrp = sg->grp;
        lookup.oil.mfcc_origin = sg->src;
 
-       c_oil = hash_lookup(pim->channel_oil_hash, &lookup);
+       c_oil = rb_pim_oil_find(&pim->channel_oil_head, &lookup);
 
        return c_oil;
 }
@@ -187,7 +158,6 @@ struct channel_oil *pim_channel_oil_add(struct pim_instance *pim,
 
        c_oil->oil.mfcc_mcastgrp = sg->grp;
        c_oil->oil.mfcc_origin = sg->src;
-       c_oil = hash_get(pim->channel_oil_hash, c_oil, hash_alloc_intern);
 
        c_oil->oil.mfcc_parent = MAXVIFS;
        c_oil->oil_ref_count = 1;
@@ -195,7 +165,7 @@ struct channel_oil *pim_channel_oil_add(struct pim_instance *pim,
        c_oil->up = pim_upstream_find(pim, sg);
        c_oil->pim = pim;
 
-       listnode_add_sort(pim->channel_oil_list, c_oil);
+       rb_pim_oil_add(&pim->channel_oil_head, c_oil);
 
        if (PIM_DEBUG_MROUTE)
                zlog_debug("%s(%s): c_oil %s add",
@@ -224,8 +194,7 @@ struct channel_oil *pim_channel_oil_del(struct channel_oil *c_oil,
                 * called by list_delete_all_node()
                 */
                c_oil->up = NULL;
-               listnode_delete(c_oil->pim->channel_oil_list, c_oil);
-               hash_release(c_oil->pim->channel_oil_hash, c_oil);
+               rb_pim_oil_del(&c_oil->pim->channel_oil_head, c_oil);
 
                pim_channel_oil_free(c_oil);
                return NULL;
@@ -352,6 +321,21 @@ int pim_channel_del_oif(struct channel_oil *channel_oil, struct interface *oif,
        return 0;
 }
 
+void pim_channel_del_inherited_oif(struct channel_oil *c_oil,
+               struct interface *oif, const char *caller)
+{
+       struct pim_upstream *up = c_oil->up;
+
+       pim_channel_del_oif(c_oil, oif, PIM_OIF_FLAG_PROTO_STAR,
+                       caller);
+
+       /* if an inherited OIF is being removed join-desired can change
+        * if the inherited OIL is now empty and KAT is running
+        */
+       if (up && up->sg.src.s_addr != INADDR_ANY &&
+                       pim_upstream_empty_inherited_olist(up))
+               pim_upstream_update_join_desired(up->pim, up);
+}
 
 static bool pim_channel_eval_oif_mute(struct channel_oil *c_oil,
                struct pim_interface *pim_ifp)
@@ -445,7 +429,6 @@ int pim_channel_add_oif(struct channel_oil *channel_oil, struct interface *oif,
 {
        struct pim_interface *pim_ifp;
        int old_ttl;
-       bool allow_iif_in_oil = false;
 
        /*
         * If we've gotten here we've gone bad, but let's
@@ -458,48 +441,6 @@ int pim_channel_add_oif(struct channel_oil *channel_oil, struct interface *oif,
 
        pim_ifp = oif->info;
 
-#ifdef PIM_ENFORCE_LOOPFREE_MFC
-       /*
-         Prevent creating MFC entry with OIF=IIF.
-
-         This is a protection against implementation mistakes.
-
-         PIM protocol implicitely ensures loopfree multicast topology.
-
-         IGMP must be protected against adding looped MFC entries created
-         by both source and receiver attached to the same interface. See
-         TODO T22.
-         We shall allow igmp to create upstream when it is DR for the intf.
-         Assume RP reachable via non DR.
-       */
-       if ((channel_oil->up &&
-           PIM_UPSTREAM_FLAG_TEST_ALLOW_IIF_IN_OIL(channel_oil->up->flags)) ||
-           ((proto_mask == PIM_OIF_FLAG_PROTO_IGMP) && PIM_I_am_DR(pim_ifp))) {
-               allow_iif_in_oil = true;
-       }
-
-       if (!allow_iif_in_oil &&
-               pim_ifp->mroute_vif_index == channel_oil->oil.mfcc_parent) {
-               channel_oil->oil_inherited_rescan = 1;
-               if (PIM_DEBUG_MROUTE) {
-                       char group_str[INET_ADDRSTRLEN];
-                       char source_str[INET_ADDRSTRLEN];
-                       pim_inet4_dump("<group?>",
-                                      channel_oil->oil.mfcc_mcastgrp,
-                                      group_str, sizeof(group_str));
-                       pim_inet4_dump("<source?>",
-                                      channel_oil->oil.mfcc_origin, source_str,
-                                      sizeof(source_str));
-                       zlog_debug(
-                               "%s %s: refusing protocol mask %u request for IIF=OIF=%s (vif_index=%d) for channel (S,G)=(%s,%s)",
-                               __FILE__, __PRETTY_FUNCTION__, proto_mask,
-                               oif->name, pim_ifp->mroute_vif_index,
-                               source_str, group_str);
-               }
-               return -2;
-       }
-#endif
-
        /* Prevent single protocol from subscribing same interface to
           channel (S,G) multiple times */
        if (channel_oil->oif_flags[pim_ifp->mroute_vif_index] & proto_mask) {
@@ -646,19 +587,15 @@ int pim_channel_add_oif(struct channel_oil *channel_oil, struct interface *oif,
 
 int pim_channel_oil_empty(struct channel_oil *c_oil)
 {
-       static uint32_t zero[MAXVIFS];
-       static int inited = 0;
+       static struct mfcctl null_oil;
 
        if (!c_oil)
                return 1;
-       /*
-        * Not sure that this is necessary, but I would rather ensure
-        * that this works.
-        */
-       if (!inited) {
-               memset(&zero, 0, sizeof(uint32_t) * MAXVIFS);
-               inited = 1;
-       }
 
-       return !memcmp(c_oil->oil.mfcc_ttls, zero, MAXVIFS * sizeof(uint32_t));
+       /* exclude pimreg from the OIL when checking if the inherited_oil is
+        * non-NULL.
+        * pimreg device (in all vrfs) uses a vifi of
+        * 0 (PIM_OIF_PIM_REGISTER_VIF) so we simply mfcc_ttls[0] */
+       return !memcmp(&c_oil->oil.mfcc_ttls[1], &null_oil.mfcc_ttls[1],
+               sizeof(null_oil.mfcc_ttls) - sizeof(null_oil.mfcc_ttls[0]));
 }