]> git.puffer.fish Git - mirror/frr.git/commitdiff
zebra: Keep track of rules written
authorDonald Sharp <sharpd@cumulusnetworks.com>
Fri, 16 Feb 2018 02:34:04 +0000 (21:34 -0500)
committerDonald Sharp <sharpd@cumulusnetworks.com>
Fri, 9 Mar 2018 16:07:41 +0000 (11:07 -0500)
Keep track of rules written into the kernel.  This will
allow us to delete them on shutdown if we are not cleaned
up properly.

Signed-off-by: Donald Sharp <sharpd@cumulusnetworks.com>
zebra/rule_netlink.c
zebra/zebra_ns.c
zebra/zebra_ns.h
zebra/zebra_pbr.c
zebra/zebra_pbr.h
zebra/zserv.c

index 3228d0e4bd535ed240faefaab5d240cac8825c9f..c64d9f6ab2d8c7cde50d6406af77bc84362ef0b5 100644 (file)
@@ -85,8 +85,9 @@ static int netlink_rule_update(int cmd, struct zebra_pbr_rule *rule,
        addattr32(&req.n, sizeof(req), FRA_PRIORITY, rule->priority);
 
        /* interface on which applied */
-       addattr_l(&req.n, sizeof(req), FRA_IFNAME, ifp->name,
-                 strlen(ifp->name)+1);
+       if (ifp)
+               addattr_l(&req.n, sizeof(req), FRA_IFNAME, ifp->name,
+                         strlen(ifp->name) + 1);
 
        /* source IP, if specified */
        if (IS_RULE_FILTERING_ON_SRC_IP(rule)) {
@@ -114,7 +115,8 @@ static int netlink_rule_update(int cmd, struct zebra_pbr_rule *rule,
                zlog_debug(
                        "Tx %s family %s IF %s(%u) Pref %u Src %s Dst %s Table %u",
                        nl_msg_type_to_str(cmd), nl_family_to_str(family),
-                       ifp->name, ifp->ifindex, rule->priority,
+                       ifp ? ifp->name : "Unknown", ifp ? ifp->ifindex : 0,
+                       rule->priority,
                        prefix2str(&rule->filter.src_ip, buf1, sizeof(buf1)),
                        prefix2str(&rule->filter.dst_ip, buf2, sizeof(buf2)),
                        rule->action.table);
index 580ff3eec1a5f21c8ca2410e0fb32c94307d804a..192e8ad4137e39ed505b20930dfd3b54cd0d6ba7 100644 (file)
@@ -36,6 +36,7 @@
 #include "debug.h"
 #include "zebra_netns_notify.h"
 #include "zebra_netns_id.h"
+#include "zebra_pbr.h"
 
 extern struct zebra_privs_t zserv_privs;
 
@@ -211,12 +212,15 @@ int zebra_ns_disable(ns_id_t ns_id, void **info)
        struct zebra_ns_table *znst;
        struct zebra_ns *zns = (struct zebra_ns *)(*info);
 
+       hash_clean(zns->rules_hash, zebra_pbr_rules_free);
+       hash_free(zns->rules_hash);
        while (!RB_EMPTY(zebra_ns_table_head, &zns->ns_tables)) {
                znst = RB_ROOT(zebra_ns_table_head, &zns->ns_tables);
 
                RB_REMOVE(zebra_ns_table_head, &zns->ns_tables, znst);
                zebra_ns_free_table(znst);
        }
+
        route_table_finish(zns->if_table);
        zebra_vxlan_ns_disable(zns);
 #if defined(HAVE_RTADV)
@@ -257,6 +261,9 @@ int zebra_ns_init(void)
        /* Default NS is activated */
        zebra_ns_enable(ns_id, (void **)&dzns);
 
+       dzns->rules_hash =
+               hash_create_size(8, zebra_pbr_rules_hash_key,
+                                zebra_pbr_rules_hash_equal, "Rules Hash");
        if (vrf_is_backend_netns()) {
                ns_add_hook(NS_NEW_HOOK, zebra_ns_new);
                ns_add_hook(NS_ENABLE_HOOK, zebra_ns_enabled);
index 1d7b6f725e07a5b970434bcf95fbb6735337de35..19ecba1f0e764cab1a8c937a6aa8b8eef35aa66b 100644 (file)
@@ -71,6 +71,8 @@ struct zebra_ns {
 
        struct zebra_ns_table_head ns_tables;
 
+       struct hash *rules_hash;
+
        /* Back pointer */
        struct ns *ns;
 };
index 8a7e693bbfe6b526518a68aae3d57dbbf79eb183..3f8655552b3997359f38751526a387688688644b 100644 (file)
@@ -21,6 +21,9 @@
 
 #include <zebra.h>
 
+#include <jhash.h>
+#include <hash.h>
+
 #include "zebra/zebra_pbr.h"
 #include "zebra/rt.h"
 
 /* Private functions */
 
 /* Public functions */
-void zebra_pbr_add_rule(struct zebra_pbr_rule *rule, struct interface *ifp)
+void zebra_pbr_rules_free(void *arg)
 {
+       struct zebra_pbr_rule *rule;
+
+       rule = (struct zebra_pbr_rule *)arg;
+
+       kernel_del_pbr_rule(rule, NULL);
+       XFREE(MTYPE_TMP, rule);
+}
+
+uint32_t zebra_pbr_rules_hash_key(void *arg)
+{
+       struct zebra_pbr_rule *rule;
+       uint32_t key;
+
+       rule = (struct zebra_pbr_rule *)arg;
+       key = jhash_3words(rule->seq, rule->priority, rule->action.table,
+                          prefix_hash_key(&rule->filter.src_ip));
+       return jhash_3words(rule->filter.src_port, rule->filter.dst_port,
+                           prefix_hash_key(&rule->filter.dst_ip), key);
+}
+
+int zebra_pbr_rules_hash_equal(const void *arg1, const void *arg2)
+{
+       const struct zebra_pbr_rule *r1, *r2;
+
+       r1 = (const struct zebra_pbr_rule *)arg1;
+       r2 = (const struct zebra_pbr_rule *)arg2;
+
+       if (r1->seq != r2->seq)
+               return 0;
+
+       if (r1->priority != r2->priority)
+               return 0;
+
+       if (r1->action.table != r2->action.table)
+               return 0;
+
+       if (r1->filter.src_port != r2->filter.src_port)
+               return 0;
+
+       if (r1->filter.dst_port != r2->filter.dst_port)
+               return 0;
+
+       if (!prefix_same(&r1->filter.src_ip, &r2->filter.src_ip))
+               return 0;
+
+       if (!prefix_same(&r1->filter.dst_ip, &r2->filter.dst_ip))
+               return 0;
+
+       return 1;
+}
+
+static void *pbr_rule_alloc_intern(void *arg)
+{
+       struct zebra_pbr_rule *zpr;
+       struct zebra_pbr_rule *new;
+
+       zpr = (struct zebra_pbr_rule *)arg;
+
+       new = XCALLOC(MTYPE_TMP, sizeof(*new));
+
+       memcpy(new, zpr, sizeof(*zpr));
+
+       return new;
+}
+
+void zebra_pbr_add_rule(struct zebra_ns *zns, struct zebra_pbr_rule *rule,
+                       struct interface *ifp)
+{
+       (void)hash_get(zns->rules_hash, rule, pbr_rule_alloc_intern);
        kernel_add_pbr_rule(rule, ifp);
 }
 
-void zebra_pbr_del_rule(struct zebra_pbr_rule *rule, struct interface *ifp)
+void zebra_pbr_del_rule(struct zebra_ns *zns, struct zebra_pbr_rule *rule,
+                       struct interface *ifp)
 {
+       struct zebra_pbr_rule *lookup;
+
+       lookup = hash_lookup(zns->rules_hash, rule);
        kernel_del_pbr_rule(rule, ifp);
+
+       if (lookup)
+               XFREE(MTYPE_TMP, lookup);
+       else
+               zlog_warn("%s: Rule being deleted we know nothing about",
+                         __PRETTY_FUNCTION__);
 }
 
 /*
@@ -57,5 +139,3 @@ int kernel_pbr_rule_del(struct zebra_pbr_rule *rule, struct interface *ifp)
 {
        return 0;
 }
-
-
index 6a97ef55ed64ecb0f547faf4627c9cb18e639a5c..f5f139cbda3d9c9aa2eeaad7436dd7a34fc6418f 100644 (file)
@@ -90,8 +90,10 @@ struct zebra_pbr_rule {
        struct zebra_pbr_action action;
 };
 
-void zebra_pbr_add_rule(struct zebra_pbr_rule *rule, struct interface *ifp);
-void zebra_pbr_del_rule(struct zebra_pbr_rule *rule, struct interface *ifp);
+void zebra_pbr_add_rule(struct zebra_ns *zns, struct zebra_pbr_rule *rule,
+                       struct interface *ifp);
+void zebra_pbr_del_rule(struct zebra_ns *zns, struct zebra_pbr_rule *rule,
+                       struct interface *ifp);
 
 /*
  * Install specified rule for a specific interface.
@@ -126,4 +128,7 @@ extern void kernel_pbr_rule_add_del_status(struct zebra_pbr_rule *rule,
 extern int kernel_pbr_rule_del(struct zebra_pbr_rule *rule,
                               struct interface *ifp);
 
+extern void zebra_pbr_rules_free(void *arg);
+extern uint32_t zebra_pbr_rules_hash_key(void *arg);
+extern int zebra_pbr_rules_hash_equal(const void *arg1, const void *arg2);
 #endif /* _ZEBRA_PBR_H */
index 7ec8525f49552c5f739f62e9a1604711292ffe39..a56b388ec9a3f25476f6d0051ece0be1d95fccc8 100644 (file)
@@ -2636,7 +2636,7 @@ static inline void zread_rule(uint16_t command, struct zserv *client,
                if (zpr.filter.dst_port)
                        zpr.filter.filter_bm |= PBR_FILTER_DST_PORT;
 
-               zebra_pbr_add_rule(&zpr, ifp);
+               zebra_pbr_add_rule(zvrf->zns, &zpr, ifp);
        }
 
 stream_failure: