zebra: Keep track of rules written

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>
This commit is contained in:
Donald Sharp 2018-02-15 21:34:04 -05:00
parent 1fbfe5a572
commit 43fe6a2a73
6 changed files with 106 additions and 10 deletions

View 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);

View 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);

View File

@ -71,6 +71,8 @@ struct zebra_ns {
struct zebra_ns_table_head ns_tables;
struct hash *rules_hash;
/* Back pointer */
struct ns *ns;
};

View File

@ -21,6 +21,9 @@
#include <zebra.h>
#include <jhash.h>
#include <hash.h>
#include "zebra/zebra_pbr.h"
#include "zebra/rt.h"
@ -31,14 +34,93 @@
/* 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;
}

View 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 */

View 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: