]> git.proxmox.com Git - mirror_frr.git/blobdiff - zebra/zebra_pbr.c
Merge pull request #5789 from donaldsharp/bgp_ebgp_reason
[mirror_frr.git] / zebra / zebra_pbr.c
index f95a4ff950e72738ed3ecc254940ca4a76896417..ff3907451b4808c6d274af1736d1a3ed06efaa21 100644 (file)
@@ -144,17 +144,12 @@ uint32_t zebra_pbr_rules_hash_key(const void *arg)
        key = jhash_3words(rule->rule.seq, rule->rule.priority,
                           rule->rule.action.table,
                           prefix_hash_key(&rule->rule.filter.src_ip));
-       if (rule->ifp)
-               key = jhash_1word(rule->ifp->ifindex, key);
-       else
-               key = jhash_1word(0, key);
 
        if (rule->rule.filter.fwmark)
-               key = jhash_1word(rule->rule.filter.fwmark, key);
+               key = jhash_3words(rule->rule.filter.fwmark, rule->vrf_id,
+                                  rule->rule.ifindex, key);
        else
-               key = jhash_1word(0, key);
-
-       key = jhash_1word(rule->vrf_id, key);
+               key = jhash_2words(rule->vrf_id, rule->rule.ifindex, key);
 
        return jhash_3words(rule->rule.filter.src_port,
                            rule->rule.filter.dst_port,
@@ -196,7 +191,7 @@ bool zebra_pbr_rules_hash_equal(const void *arg1, const void *arg2)
        if (!prefix_same(&r1->rule.filter.dst_ip, &r2->rule.filter.dst_ip))
                return false;
 
-       if (r1->ifp != r2->ifp)
+       if (r1->rule.ifindex != r2->rule.ifindex)
                return false;
 
        if (r1->vrf_id != r2->vrf_id)
@@ -208,7 +203,7 @@ bool zebra_pbr_rules_hash_equal(const void *arg1, const void *arg2)
 struct pbr_rule_unique_lookup {
        struct zebra_pbr_rule *rule;
        uint32_t unique;
-       struct interface *ifp;
+       ifindex_t ifindex;
        vrf_id_t vrf_id;
 };
 
@@ -218,7 +213,7 @@ static int pbr_rule_lookup_unique_walker(struct hash_bucket *b, void *data)
        struct zebra_pbr_rule *rule = b->data;
 
        if (pul->unique == rule->rule.unique
-           && pul->ifp == rule->ifp
+           && pul->ifindex == rule->rule.ifindex
            && pul->vrf_id == rule->vrf_id) {
                pul->rule = rule;
                return HASHWALK_ABORT;
@@ -233,7 +228,7 @@ pbr_rule_lookup_unique(struct zebra_pbr_rule *zrule)
        struct pbr_rule_unique_lookup pul;
 
        pul.unique = zrule->rule.unique;
-       pul.ifp = zrule->ifp;
+       pul.ifindex = zrule->rule.ifindex;
        pul.rule = NULL;
        pul.vrf_id = zrule->vrf_id;
        hash_walk(zrouter.rules_hash, &pbr_rule_lookup_unique_walker, &pul);
@@ -350,11 +345,13 @@ void zebra_pbr_iptable_free(void *arg)
        iptable = (struct zebra_pbr_iptable *)arg;
        hook_call(zebra_pbr_iptable_update, 0, iptable);
 
-       for (ALL_LIST_ELEMENTS(iptable->interface_name_list,
-                                       node, nnode, name)) {
-               XFREE(MTYPE_PBR_IPTABLE_IFNAME, name);
-               list_delete_node(iptable->interface_name_list,
-                                node);
+       if (iptable->interface_name_list) {
+               for (ALL_LIST_ELEMENTS(iptable->interface_name_list, node,
+                                      nnode, name)) {
+                       XFREE(MTYPE_PBR_IPTABLE_IFNAME, name);
+                       list_delete_node(iptable->interface_name_list, node);
+               }
+               list_delete(&iptable->interface_name_list);
        }
        XFREE(MTYPE_TMP, iptable);
 }
@@ -471,8 +468,12 @@ static void zebra_pbr_cleanup_rules(struct hash_bucket *b, void *data)
 
        if (rule->sock == *sock) {
                (void)kernel_del_pbr_rule(rule);
-               hash_release(zrouter.rules_hash, rule);
-               XFREE(MTYPE_TMP, rule);
+               if (hash_release(zrouter.rules_hash, rule))
+                       XFREE(MTYPE_TMP, rule);
+               else
+                       zlog_debug(
+                               "%s: Rule seq: %u is being cleaned but we can't find it in our tables",
+                               __func__, rule->rule.seq);
        }
 }
 
@@ -482,8 +483,10 @@ static void zebra_pbr_cleanup_ipset(struct hash_bucket *b, void *data)
        int *sock = data;
 
        if (ipset->sock == *sock) {
-               hook_call(zebra_pbr_ipset_update, 0, ipset);
-               hash_release(zrouter.ipset_hash, ipset);
+               if (hash_release(zrouter.ipset_hash, ipset))
+                       zebra_pbr_ipset_free(ipset);
+               else
+                       hook_call(zebra_pbr_ipset_update, 0, ipset);
        }
 }
 
@@ -493,8 +496,10 @@ static void zebra_pbr_cleanup_ipset_entry(struct hash_bucket *b, void *data)
        int *sock = data;
 
        if (ipset->sock == *sock) {
-               hook_call(zebra_pbr_ipset_entry_update, 0, ipset);
-               hash_release(zrouter.ipset_entry_hash, ipset);
+               if (hash_release(zrouter.ipset_entry_hash, ipset))
+                       zebra_pbr_ipset_entry_free(ipset);
+               else
+                       hook_call(zebra_pbr_ipset_entry_update, 0, ipset);
        }
 }
 
@@ -504,8 +509,10 @@ static void zebra_pbr_cleanup_iptable(struct hash_bucket *b, void *data)
        int *sock = data;
 
        if (iptable->sock == *sock) {
-               hook_call(zebra_pbr_iptable_update, 0, iptable);
-               hash_release(zrouter.iptable_hash, iptable);
+               if (hash_release(zrouter.iptable_hash, iptable))
+                       zebra_pbr_iptable_free(iptable);
+               else
+                       hook_call(zebra_pbr_iptable_update, 0, iptable);
        }
 }
 
@@ -651,12 +658,22 @@ static void *pbr_iptable_alloc_intern(void *arg)
 {
        struct zebra_pbr_iptable *zpi;
        struct zebra_pbr_iptable *new;
+       struct listnode *ln;
+       char *ifname;
 
        zpi = (struct zebra_pbr_iptable *)arg;
 
        new = XCALLOC(MTYPE_TMP, sizeof(struct zebra_pbr_iptable));
 
+       /* Deep structure copy */
        memcpy(new, zpi, sizeof(*zpi));
+       new->interface_name_list = list_new();
+
+       if (zpi->interface_name_list) {
+               for (ALL_LIST_ELEMENTS_RO(zpi->interface_name_list, ln, ifname))
+                       listnode_add(new->interface_name_list,
+                                    XSTRDUP(MTYPE_PBR_IPTABLE_IFNAME, ifname));
+       }
 
        return new;
 }
@@ -689,6 +706,7 @@ void zebra_pbr_del_iptable(struct zebra_pbr_iptable *iptable)
                        list_delete_node(iptable->interface_name_list,
                                         node);
                }
+               list_delete(&iptable->interface_name_list);
                XFREE(MTYPE_TMP, lookup);
        } else
                zlog_debug("%s: IPTable being deleted we know nothing about",