]> 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 ed404ba4989ff462a48c964a409405016071a270..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;
@@ -460,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
@@ -473,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) {
@@ -666,6 +592,10 @@ int pim_channel_oil_empty(struct channel_oil *c_oil)
        if (!c_oil)
                return 1;
 
-       return !memcmp(c_oil->oil.mfcc_ttls,
-                       null_oil.mfcc_ttls, sizeof(null_oil.mfcc_ttls));
+       /* 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]));
 }