zebra: PBR config and monitor IPSET/IPTABLE hooks declared

The following PBR handlers: ipset, and iptables will prioritary
call the hook from a possible plugin.
If a plugin is attached, then it will return a positive value.
That is why the return status is tested against 0 value, since that
means that there are no plugin module plugged

Signed-off-by: Philippe Guibert <philippe.guibert@6wind.com>
This commit is contained in:
Philippe Guibert 2018-05-04 13:57:31 +02:00
parent 8cda910629
commit 73a829f709
2 changed files with 125 additions and 24 deletions

View File

@ -24,12 +24,12 @@
#include <jhash.h>
#include <hash.h>
#include <memory.h>
#include <hook.h>
#include "zebra/zebra_pbr.h"
#include "zebra/rt.h"
#include "zebra/zapi_msg.h"
#include "zebra/zebra_memory.h"
#include "zebra_pbr.h"
/* definitions */
DEFINE_MTYPE_STATIC(ZEBRA, PBR_IPTABLE_IFNAME, "PBR interface list")
@ -44,6 +44,30 @@ static const struct message ipset_type_msg[] = {
};
/* static function declarations */
DEFINE_HOOK(zebra_pbr_ipset_entry_wrap_script_get_stat, (struct zebra_ns *zns,
struct zebra_pbr_ipset_entry *ipset,
uint64_t *pkts, uint64_t *bytes),
(zns, ipset, pkts, bytes))
DEFINE_HOOK(zebra_pbr_iptable_wrap_script_get_stat, (struct zebra_ns *zns,
struct zebra_pbr_iptable *iptable,
uint64_t *pkts, uint64_t *bytes),
(zns, iptable, pkts, bytes))
DEFINE_HOOK(zebra_pbr_iptable_wrap_script_update, (struct zebra_ns *zns,
int cmd,
struct zebra_pbr_iptable *iptable),
(zns, cmd, iptable));
DEFINE_HOOK(zebra_pbr_ipset_entry_wrap_script_update, (struct zebra_ns *zns,
int cmd,
struct zebra_pbr_ipset_entry *ipset),
(zns, cmd, ipset));
DEFINE_HOOK(zebra_pbr_ipset_wrap_script_update, (struct zebra_ns *zns,
int cmd,
struct zebra_pbr_ipset *ipset),
(zns, cmd, ipset));
/* Private functions */
@ -158,9 +182,15 @@ static struct zebra_pbr_rule *pbr_rule_lookup_unique(struct zebra_ns *zns,
void zebra_pbr_ipset_free(void *arg)
{
struct zebra_pbr_ipset *ipset;
struct zebra_ns *zns;
ipset = (struct zebra_pbr_ipset *)arg;
if (vrf_is_backend_netns())
zns = zebra_ns_lookup(ipset->vrf_id);
else
zns = zebra_ns_lookup(NS_DEFAULT);
hook_call(zebra_pbr_ipset_wrap_script_update,
zns, 0, ipset);
XFREE(MTYPE_TMP, ipset);
}
@ -192,8 +222,17 @@ int zebra_pbr_ipset_hash_equal(const void *arg1, const void *arg2)
void zebra_pbr_ipset_entry_free(void *arg)
{
struct zebra_pbr_ipset_entry *ipset;
struct zebra_ns *zns;
ipset = (struct zebra_pbr_ipset_entry *)arg;
if (ipset->backpointer && vrf_is_backend_netns()) {
struct zebra_pbr_ipset *ips = ipset->backpointer;
zns = zebra_ns_lookup((ns_id_t)ips->vrf_id);
} else
zns = zebra_ns_lookup(NS_DEFAULT);
hook_call(zebra_pbr_ipset_entry_wrap_script_update,
zns, 0, ipset);
XFREE(MTYPE_TMP, ipset);
}
@ -254,8 +293,15 @@ void zebra_pbr_iptable_free(void *arg)
struct zebra_pbr_iptable *iptable;
struct listnode *node, *nnode;
char *name;
struct zebra_ns *zns;
iptable = (struct zebra_pbr_iptable *)arg;
if (vrf_is_backend_netns())
zns = zebra_ns_lookup((ns_id_t)iptable->vrf_id);
else
zns = zebra_ns_lookup(NS_DEFAULT);
hook_call(zebra_pbr_iptable_wrap_script_update,
zns, 0, iptable);
for (ALL_LIST_ELEMENTS(iptable->interface_name_list,
node, nnode, name)) {
@ -323,7 +369,6 @@ void zebra_pbr_add_rule(struct zebra_ns *zns, struct zebra_pbr_rule *rule)
(void)hash_get(zns->rules_hash, rule, pbr_rule_alloc_intern);
kernel_add_pbr_rule(rule);
/*
* Rule Replace semantics, if we have an old, install the
* new rule, look above, and then delete the old
@ -366,8 +411,11 @@ static void zebra_pbr_cleanup_ipset(struct hash_backet *b, void *data)
struct zebra_pbr_ipset *ipset = b->data;
int *sock = data;
if (ipset->sock == *sock)
if (ipset->sock == *sock) {
hook_call(zebra_pbr_ipset_wrap_script_update,
zns, 0, ipset);
hash_release(zns->ipset_hash, ipset);
}
}
static void zebra_pbr_cleanup_ipset_entry(struct hash_backet *b, void *data)
@ -376,8 +424,11 @@ static void zebra_pbr_cleanup_ipset_entry(struct hash_backet *b, void *data)
struct zebra_pbr_ipset_entry *ipset = b->data;
int *sock = data;
if (ipset->sock == *sock)
if (ipset->sock == *sock) {
hook_call(zebra_pbr_ipset_entry_wrap_script_update,
zns, 0, ipset);
hash_release(zns->ipset_entry_hash, ipset);
}
}
static void zebra_pbr_cleanup_iptable(struct hash_backet *b, void *data)
@ -386,8 +437,11 @@ static void zebra_pbr_cleanup_iptable(struct hash_backet *b, void *data)
struct zebra_pbr_iptable *iptable = b->data;
int *sock = data;
if (iptable->sock == *sock)
if (iptable->sock == *sock) {
hook_call(zebra_pbr_iptable_wrap_script_update,
zns, 0, iptable);
hash_release(zns->iptable_hash, iptable);
}
}
static int zebra_pbr_client_close_cleanup(struct zserv *client)
@ -429,10 +483,14 @@ static void *pbr_ipset_alloc_intern(void *arg)
void zebra_pbr_create_ipset(struct zebra_ns *zns,
struct zebra_pbr_ipset *ipset)
{
int ret;
(void)hash_get(zns->ipset_hash, ipset, pbr_ipset_alloc_intern);
/* TODO:
* - Netlink call
*/
ret = hook_call(zebra_pbr_ipset_wrap_script_update,
zns, 1, ipset);
kernel_pbr_ipset_add_del_status(ipset,
ret ? SOUTHBOUND_INSTALL_SUCCESS
: SOUTHBOUND_INSTALL_FAILURE);
}
void zebra_pbr_destroy_ipset(struct zebra_ns *zns,
@ -441,9 +499,8 @@ void zebra_pbr_destroy_ipset(struct zebra_ns *zns,
struct zebra_pbr_ipset *lookup;
lookup = hash_lookup(zns->ipset_hash, ipset);
/* TODO:
* - Netlink destroy from kernel
*/
hook_call(zebra_pbr_ipset_wrap_script_update,
zns, 0, ipset);
if (lookup) {
hash_release(zns->ipset_hash, lookup);
XFREE(MTYPE_TMP, lookup);
@ -509,11 +566,15 @@ static void *pbr_ipset_entry_alloc_intern(void *arg)
void zebra_pbr_add_ipset_entry(struct zebra_ns *zns,
struct zebra_pbr_ipset_entry *ipset)
{
int ret;
(void)hash_get(zns->ipset_entry_hash, ipset,
pbr_ipset_entry_alloc_intern);
/* TODO:
* - Netlink add to kernel
*/
ret = hook_call(zebra_pbr_ipset_entry_wrap_script_update,
zns, 1, ipset);
kernel_pbr_ipset_entry_add_del_status(ipset,
ret ? SOUTHBOUND_INSTALL_SUCCESS
: SOUTHBOUND_INSTALL_FAILURE);
}
void zebra_pbr_del_ipset_entry(struct zebra_ns *zns,
@ -522,9 +583,8 @@ void zebra_pbr_del_ipset_entry(struct zebra_ns *zns,
struct zebra_pbr_ipset_entry *lookup;
lookup = hash_lookup(zns->ipset_entry_hash, ipset);
/* TODO:
* - Netlink destroy
*/
hook_call(zebra_pbr_ipset_entry_wrap_script_update,
zns, 0, ipset);
if (lookup) {
hash_release(zns->ipset_entry_hash, lookup);
XFREE(MTYPE_TMP, lookup);
@ -550,9 +610,14 @@ static void *pbr_iptable_alloc_intern(void *arg)
void zebra_pbr_add_iptable(struct zebra_ns *zns,
struct zebra_pbr_iptable *iptable)
{
int ret;
(void)hash_get(zns->iptable_hash, iptable,
pbr_iptable_alloc_intern);
/* TODO call ioctl layer */
ret = hook_call(zebra_pbr_iptable_wrap_script_update, zns, 1, iptable);
kernel_pbr_iptable_add_del_status(iptable,
ret ? SOUTHBOUND_INSTALL_SUCCESS
: SOUTHBOUND_INSTALL_FAILURE);
}
void zebra_pbr_del_iptable(struct zebra_ns *zns,
@ -561,9 +626,7 @@ void zebra_pbr_del_iptable(struct zebra_ns *zns,
struct zebra_pbr_iptable *lookup;
lookup = hash_lookup(zns->iptable_hash, iptable);
/* TODO:
* - call ioctl layer
*/
hook_call(zebra_pbr_iptable_wrap_script_update, zns, 0, iptable);
if (lookup) {
struct listnode *node, *nnode;
char *name;
@ -687,6 +750,7 @@ int kernel_pbr_rule_del(struct zebra_pbr_rule *rule)
struct zebra_pbr_ipset_entry_unique_display {
struct zebra_pbr_ipset *zpi;
struct vty *vty;
struct zebra_ns *zns;
};
struct zebra_pbr_env_display {
@ -738,6 +802,9 @@ static int zebra_pbr_show_ipset_entry_walkcb(struct hash_backet *backet,
struct vty *vty = unique->vty;
struct zebra_pbr_ipset_entry *zpie =
(struct zebra_pbr_ipset_entry *)backet->data;
uint64_t pkts = 0, bytes = 0;
struct zebra_ns *zns = unique->zns;
int ret = 0;
if (zpie->backpointer != zpi)
return HASHWALK_CONTINUE;
@ -786,6 +853,11 @@ static int zebra_pbr_show_ipset_entry_walkcb(struct hash_backet *backet,
}
vty_out(vty, " (%u)\n", zpie->unique);
ret = hook_call(zebra_pbr_ipset_entry_wrap_script_get_stat,
zns, zpie, &pkts, &bytes);
if (ret && pkts > 0)
vty_out(vty, "\t pkts %" PRIu64 ", bytes %" PRIu64"\n",
pkts, bytes);
return HASHWALK_CONTINUE;
}
@ -802,7 +874,7 @@ static int zebra_pbr_show_ipset_walkcb(struct hash_backet *backet, void *arg)
zebra_pbr_ipset_type2str(zpi->type));
unique.vty = vty;
unique.zpi = zpi;
unique.zns = zns;
hash_walk(zns->ipset_entry_hash, zebra_pbr_show_ipset_entry_walkcb,
&unique);
vty_out(vty, "\n");
@ -829,7 +901,7 @@ void zebra_pbr_show_ipset_list(struct vty *vty, char *ipsetname)
unique.vty = vty;
unique.zpi = zpi;
unique.zns = zns;
hash_walk(zns->ipset_entry_hash,
zebra_pbr_show_ipset_entry_walkcb,
&unique);
@ -867,11 +939,18 @@ static int zebra_pbr_show_iptable_walkcb(struct hash_backet *backet, void *arg)
struct zebra_pbr_env_display *env = (struct zebra_pbr_env_display *)arg;
struct vty *vty = env->vty;
struct zebra_ns *zns = env->zns;
int ret;
uint64_t pkts = 0, bytes = 0;
vty_out(vty, "IPtable %s action %s (%u)\n", iptable->ipset_name,
iptable->action == ZEBRA_IPTABLES_DROP ? "drop" : "redirect",
iptable->unique);
ret = hook_call(zebra_pbr_iptable_wrap_script_get_stat,
zns, iptable, &pkts, &bytes);
if (ret && pkts > 0)
vty_out(vty, "\t pkts %" PRIu64 ", bytes %" PRIu64"\n",
pkts, bytes);
if (iptable->action != ZEBRA_IPTABLES_DROP) {
struct pbr_rule_fwmark_lookup prfl;

View File

@ -226,4 +226,26 @@ extern void zebra_pbr_show_iptable(struct vty *vty);
extern void zebra_pbr_iptable_update_interfacelist(struct stream *s,
struct zebra_pbr_iptable *zpi);
DECLARE_HOOK(zebra_pbr_ipset_entry_wrap_script_get_stat, (struct zebra_ns *zns,
struct zebra_pbr_ipset_entry *ipset,
uint64_t *pkts, uint64_t *bytes),
(zns, ipset, pkts, bytes))
DECLARE_HOOK(zebra_pbr_iptable_wrap_script_get_stat, (struct zebra_ns *zns,
struct zebra_pbr_iptable *iptable,
uint64_t *pkts, uint64_t *bytes),
(zns, iptable, pkts, bytes))
DECLARE_HOOK(zebra_pbr_iptable_wrap_script_update, (struct zebra_ns *zns,
int cmd,
struct zebra_pbr_iptable *iptable),
(zns, cmd, iptable));
DECLARE_HOOK(zebra_pbr_ipset_entry_wrap_script_update, (struct zebra_ns *zns,
int cmd,
struct zebra_pbr_ipset_entry *ipset),
(zns, cmd, ipset));
DECLARE_HOOK(zebra_pbr_ipset_wrap_script_update, (struct zebra_ns *zns,
int cmd,
struct zebra_pbr_ipset *ipset),
(zns, cmd, ipset));
#endif /* _ZEBRA_PBR_H */