summaryrefslogtreecommitdiffstats
path: root/zebra
diff options
context:
space:
mode:
authorDonald Sharp <sharpd@cumulusnetworks.com>2018-05-29 17:33:00 +0200
committerGitHub <noreply@github.com>2018-05-29 17:33:00 +0200
commit68542a6da651a4a3f5d280482313f14508618c43 (patch)
treedbbc3aa2f4b76ceb345df7896cbb1277e2e6372c /zebra
parentMerge pull request #2307 from opensourcerouting/master-isis-tlv-copy-fix (diff)
parentbgpd: attributes presence checked when mpreach is present (diff)
downloadfrr-68542a6da651a4a3f5d280482313f14508618c43.tar.xz
frr-68542a6da651a4a3f5d280482313f14508618c43.zip
Merge pull request #2142 from pguibert6WIND/fs_zebra_complement
Flowspec complement : port support and policy routing per interface and plugin wrapper
Diffstat (limited to 'zebra')
-rw-r--r--zebra/debug.c3
-rw-r--r--zebra/debug.h2
-rw-r--r--zebra/rule_netlink.c6
-rw-r--r--zebra/zapi_msg.c20
-rw-r--r--zebra/zebra_ns.c4
-rw-r--r--zebra/zebra_pbr.c485
-rw-r--r--zebra/zebra_pbr.h44
-rw-r--r--zebra/zebra_vty.c35
8 files changed, 562 insertions, 37 deletions
diff --git a/zebra/debug.c b/zebra/debug.c
index 14b36cb5f..85be620bf 100644
--- a/zebra/debug.c
+++ b/zebra/debug.c
@@ -34,6 +34,8 @@ unsigned long zebra_debug_mpls;
unsigned long zebra_debug_vxlan;
unsigned long zebra_debug_pw;
+DEFINE_HOOK(zebra_debug_show_debugging, (struct vty *vty), (vty));
+
DEFUN_NOSH (show_debugging_zebra,
show_debugging_zebra_cmd,
"show debugging [zebra]",
@@ -88,6 +90,7 @@ DEFUN_NOSH (show_debugging_zebra,
if (IS_ZEBRA_DEBUG_PW)
vty_out(vty, " Zebra pseudowire debugging is on\n");
+ hook_call(zebra_debug_show_debugging, vty);
return CMD_SUCCESS;
}
diff --git a/zebra/debug.h b/zebra/debug.h
index 987f9d012..1c08459e2 100644
--- a/zebra/debug.h
+++ b/zebra/debug.h
@@ -82,4 +82,6 @@ extern unsigned long zebra_debug_pw;
extern void zebra_debug_init(void);
+DECLARE_HOOK(zebra_debug_show_debugging, (struct vty *vty), (vty));
+
#endif /* _ZEBRA_DEBUG_H */
diff --git a/zebra/rule_netlink.c b/zebra/rule_netlink.c
index 5f7354585..f0ed8f2f5 100644
--- a/zebra/rule_netlink.c
+++ b/zebra/rule_netlink.c
@@ -98,6 +98,12 @@ static int netlink_rule_update(int cmd, struct zebra_pbr_rule *rule)
&rule->rule.filter.dst_ip.u.prefix, bytelen);
}
+ /* fwmark, if specified */
+ if (IS_RULE_FILTERING_ON_FWMARK(rule)) {
+ addattr32(&req.n, sizeof(req), FRA_FWMARK,
+ rule->rule.filter.fwmark);
+ }
+
/* Route table to use to forward, if filter criteria matches. */
if (rule->rule.action.table < 256)
req.frh.table = rule->rule.action.table;
diff --git a/zebra/zapi_msg.c b/zebra/zapi_msg.c
index 9a18cc22f..943329b19 100644
--- a/zebra/zapi_msg.c
+++ b/zebra/zapi_msg.c
@@ -2847,6 +2847,7 @@ static inline void zread_ipset(ZAPI_HANDLER_ARGS)
memset(&zpi, 0, sizeof(zpi));
zpi.sock = client->sock;
+ zpi.vrf_id = zvrf->vrf->vrf_id;
STREAM_GETL(s, zpi.unique);
STREAM_GETL(s, zpi.type);
STREAM_GET(&zpi.ipset_name, s, ZEBRA_IPSET_NAME_SIZE);
@@ -2885,11 +2886,26 @@ static inline void zread_ipset_entry(ZAPI_HANDLER_ARGS)
STREAM_GETC(s, zpi.dst.prefixlen);
STREAM_GET(&zpi.dst.u.prefix, s, prefix_blen(&zpi.dst));
+ STREAM_GETW(s, zpi.src_port_min);
+ STREAM_GETW(s, zpi.src_port_max);
+ STREAM_GETW(s, zpi.dst_port_min);
+ STREAM_GETW(s, zpi.dst_port_max);
+ STREAM_GETC(s, zpi.proto);
if (!is_default_prefix(&zpi.src))
zpi.filter_bm |= PBR_FILTER_SRC_IP;
if (!is_default_prefix(&zpi.dst))
zpi.filter_bm |= PBR_FILTER_DST_IP;
+ if (zpi.dst_port_min != 0)
+ zpi.filter_bm |= PBR_FILTER_DST_PORT;
+ if (zpi.src_port_min != 0)
+ zpi.filter_bm |= PBR_FILTER_SRC_PORT;
+ if (zpi.dst_port_max != 0)
+ zpi.filter_bm |= PBR_FILTER_DST_PORT_RANGE;
+ if (zpi.src_port_max != 0)
+ zpi.filter_bm |= PBR_FILTER_SRC_PORT_RANGE;
+ if (zpi.proto != 0)
+ zpi.filter_bm |= PBR_FILTER_PROTO;
/* calculate backpointer */
zpi.backpointer = zebra_pbr_lookup_ipset_pername(
@@ -2913,13 +2929,17 @@ static inline void zread_iptable(ZAPI_HANDLER_ARGS)
memset(&zpi, 0, sizeof(zpi));
+ zpi.interface_name_list = list_new();
zpi.sock = client->sock;
+ zpi.vrf_id = zvrf->vrf->vrf_id;
STREAM_GETL(s, zpi.unique);
STREAM_GETL(s, zpi.type);
STREAM_GETL(s, zpi.filter_bm);
STREAM_GETL(s, zpi.action);
STREAM_GETL(s, zpi.fwmark);
STREAM_GET(&zpi.ipset_name, s, ZEBRA_IPSET_NAME_SIZE);
+ STREAM_GETL(s, zpi.nb_interface);
+ zebra_pbr_iptable_update_interfacelist(s, &zpi);
if (hdr->command == ZEBRA_IPTABLE_ADD)
zebra_pbr_add_iptable(zvrf->zns, &zpi);
diff --git a/zebra/zebra_ns.c b/zebra/zebra_ns.c
index 5c62e366a..4526a1487 100644
--- a/zebra/zebra_ns.c
+++ b/zebra/zebra_ns.c
@@ -262,10 +262,10 @@ int zebra_ns_disable(ns_id_t ns_id, void **info)
hash_clean(zns->rules_hash, zebra_pbr_rules_free);
hash_free(zns->rules_hash);
- hash_clean(zns->ipset_hash, zebra_pbr_ipset_free);
- hash_free(zns->ipset_hash);
hash_clean(zns->ipset_entry_hash,
zebra_pbr_ipset_entry_free),
+ hash_clean(zns->ipset_hash, zebra_pbr_ipset_free);
+ hash_free(zns->ipset_hash);
hash_free(zns->ipset_entry_hash);
hash_clean(zns->iptable_hash,
zebra_pbr_iptable_free);
diff --git a/zebra/zebra_pbr.c b/zebra/zebra_pbr.c
index 54a9cdbc5..6a42aaecb 100644
--- a/zebra/zebra_pbr.c
+++ b/zebra/zebra_pbr.c
@@ -23,14 +23,51 @@
#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"
/* definitions */
+DEFINE_MTYPE_STATIC(ZEBRA, PBR_IPTABLE_IFNAME, "PBR interface list")
+
+/* definitions */
+static const struct message ipset_type_msg[] = {
+ {IPSET_NET_PORT_NET, "net,port,net"},
+ {IPSET_NET_PORT, "net,port"},
+ {IPSET_NET_NET, "net,net"},
+ {IPSET_NET, "net"},
+ {0}
+};
/* 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 */
@@ -145,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);
}
@@ -179,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);
}
@@ -194,6 +246,11 @@ uint32_t zebra_pbr_ipset_entry_hash_key(void *arg)
key = prefix_hash_key(&ipset->src);
key = jhash_1word(ipset->unique, key);
key = jhash_1word(prefix_hash_key(&ipset->dst), key);
+ key = jhash(&ipset->dst_port_min, 2, key);
+ key = jhash(&ipset->dst_port_max, 2, key);
+ key = jhash(&ipset->src_port_min, 2, key);
+ key = jhash(&ipset->src_port_max, 2, key);
+ key = jhash(&ipset->proto, 1, key);
return key;
}
@@ -214,15 +271,44 @@ int zebra_pbr_ipset_entry_hash_equal(const void *arg1, const void *arg2)
if (!prefix_same(&r1->dst, &r2->dst))
return 0;
+ if (r1->src_port_min != r2->src_port_min)
+ return 0;
+
+ if (r1->src_port_max != r2->src_port_max)
+ return 0;
+
+ if (r1->dst_port_min != r2->dst_port_min)
+ return 0;
+
+ if (r1->dst_port_max != r2->dst_port_max)
+ return 0;
+
+ if (r1->proto != r2->proto)
+ return 0;
return 1;
}
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)) {
+ XFREE(MTYPE_PBR_IPTABLE_IFNAME, name);
+ list_delete_node(iptable->interface_name_list,
+ node);
+ }
XFREE(MTYPE_TMP, iptable);
}
@@ -283,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
@@ -320,6 +405,45 @@ static void zebra_pbr_cleanup_rules(struct hash_backet *b, void *data)
}
}
+static void zebra_pbr_cleanup_ipset(struct hash_backet *b, void *data)
+{
+ struct zebra_ns *zns = zebra_ns_lookup(NS_DEFAULT);
+ struct zebra_pbr_ipset *ipset = b->data;
+ int *sock = data;
+
+ 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)
+{
+ struct zebra_ns *zns = zebra_ns_lookup(NS_DEFAULT);
+ struct zebra_pbr_ipset_entry *ipset = b->data;
+ int *sock = data;
+
+ 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)
+{
+ struct zebra_ns *zns = zebra_ns_lookup(NS_DEFAULT);
+ struct zebra_pbr_iptable *iptable = b->data;
+ int *sock = data;
+
+ 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)
{
int sock = client->sock;
@@ -328,6 +452,12 @@ static int zebra_pbr_client_close_cleanup(struct zserv *client)
if (!sock)
return 0;
hash_iterate(zns->rules_hash, zebra_pbr_cleanup_rules, &sock);
+ hash_iterate(zns->iptable_hash,
+ zebra_pbr_cleanup_iptable, &sock);
+ hash_iterate(zns->ipset_entry_hash,
+ zebra_pbr_cleanup_ipset_entry, &sock);
+ hash_iterate(zns->ipset_hash,
+ zebra_pbr_cleanup_ipset, &sock);
return 1;
}
@@ -353,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,
@@ -365,13 +499,12 @@ 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
- * - ?? destroy ipset entries before
- */
- if (lookup)
+ hook_call(zebra_pbr_ipset_wrap_script_update,
+ zns, 0, ipset);
+ if (lookup) {
+ hash_release(zns->ipset_hash, lookup);
XFREE(MTYPE_TMP, lookup);
- else
+ } else
zlog_warn("%s: IPSet Entry being deleted we know nothing about",
__PRETTY_FUNCTION__);
}
@@ -381,6 +514,12 @@ struct pbr_ipset_name_lookup {
char ipset_name[ZEBRA_IPSET_NAME_SIZE];
};
+static const char *zebra_pbr_ipset_type2str(uint32_t type)
+{
+ return lookup_msg(ipset_type_msg, type,
+ "Unrecognized IPset Type");
+}
+
static int zebra_pbr_ipset_pername_walkcb(struct hash_backet *backet, void *arg)
{
struct pbr_ipset_name_lookup *pinl =
@@ -427,12 +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:
- * - attach to ipset list
- * - 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,
@@ -441,14 +583,12 @@ 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
- * - detach from ipset list
- * - ?? if no more entres, delete ipset
- */
- if (lookup)
+ 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);
- else
+ } else
zlog_warn("%s: IPSet being deleted we know nothing about",
__PRETTY_FUNCTION__);
}
@@ -470,24 +610,36 @@ 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 netlink 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,
struct zebra_pbr_iptable *iptable)
{
- struct zebra_pbr_ipset_entry *lookup;
+ struct zebra_pbr_iptable *lookup;
lookup = hash_lookup(zns->iptable_hash, iptable);
- /* TODO:
- * - call netlink layer
- * - detach from iptable list
- */
- if (lookup)
+ hook_call(zebra_pbr_iptable_wrap_script_update, zns, 0, iptable);
+ if (lookup) {
+ struct listnode *node, *nnode;
+ char *name;
+
+ hash_release(zns->iptable_hash, lookup);
+ 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);
+ }
XFREE(MTYPE_TMP, lookup);
- else
+ } else
zlog_warn("%s: IPTable being deleted we know nothing about",
__PRETTY_FUNCTION__);
}
@@ -509,7 +661,7 @@ void kernel_pbr_rule_add_del_status(struct zebra_pbr_rule *rule,
zsend_rule_notify_owner(rule, ZAPI_RULE_REMOVED);
break;
case SOUTHBOUND_DELETE_FAILURE:
- zsend_rule_notify_owner(rule, ZAPI_RULE_REMOVED);
+ zsend_rule_notify_owner(rule, ZAPI_RULE_FAIL_REMOVE);
break;
}
}
@@ -528,8 +680,10 @@ void kernel_pbr_ipset_add_del_status(struct zebra_pbr_ipset *ipset,
zsend_ipset_notify_owner(ipset, ZAPI_IPSET_FAIL_INSTALL);
break;
case SOUTHBOUND_DELETE_SUCCESS:
+ zsend_ipset_notify_owner(ipset, ZAPI_IPSET_REMOVED);
+ break;
case SOUTHBOUND_DELETE_FAILURE:
- /* TODO : handling of delete event */
+ zsend_ipset_notify_owner(ipset, ZAPI_IPSET_FAIL_REMOVE);
break;
}
}
@@ -551,8 +705,12 @@ void kernel_pbr_ipset_entry_add_del_status(
ZAPI_IPSET_ENTRY_FAIL_INSTALL);
break;
case SOUTHBOUND_DELETE_SUCCESS:
+ zsend_ipset_entry_notify_owner(ipset,
+ ZAPI_IPSET_ENTRY_REMOVED);
+ break;
case SOUTHBOUND_DELETE_FAILURE:
- /* TODO : handling of delete event */
+ zsend_ipset_entry_notify_owner(ipset,
+ ZAPI_IPSET_ENTRY_FAIL_REMOVE);
break;
}
}
@@ -571,8 +729,12 @@ void kernel_pbr_iptable_add_del_status(struct zebra_pbr_iptable *iptable,
zsend_iptable_notify_owner(iptable, ZAPI_IPTABLE_FAIL_INSTALL);
break;
case SOUTHBOUND_DELETE_SUCCESS:
+ zsend_iptable_notify_owner(iptable,
+ ZAPI_IPTABLE_REMOVED);
+ break;
case SOUTHBOUND_DELETE_FAILURE:
- /* TODO : handling of delete event */
+ zsend_iptable_notify_owner(iptable,
+ ZAPI_IPTABLE_FAIL_REMOVE);
break;
}
}
@@ -584,3 +746,256 @@ int kernel_pbr_rule_del(struct zebra_pbr_rule *rule)
{
return 0;
}
+
+struct zebra_pbr_ipset_entry_unique_display {
+ struct zebra_pbr_ipset *zpi;
+ struct vty *vty;
+ struct zebra_ns *zns;
+};
+
+struct zebra_pbr_env_display {
+ struct zebra_ns *zns;
+ struct vty *vty;
+};
+
+static const char *zebra_pbr_prefix2str(union prefixconstptr pu,
+ char *str, int size)
+{
+ const struct prefix *p = pu.p;
+ char buf[PREFIX2STR_BUFFER];
+
+ if (p->family == AF_INET && p->prefixlen == IPV4_MAX_PREFIXLEN) {
+ snprintf(str, size, "%s", inet_ntop(p->family, &p->u.prefix,
+ buf, PREFIX2STR_BUFFER));
+ return str;
+ }
+ return prefix2str(pu, str, size);
+}
+
+static void zebra_pbr_display_port(struct vty *vty, uint32_t filter_bm,
+ uint16_t port_min, uint16_t port_max,
+ uint8_t proto)
+{
+ if (!(filter_bm & PBR_FILTER_PROTO)) {
+ if (port_max)
+ vty_out(vty, ":udp/tcp:%d-%d",
+ port_min, port_max);
+ else
+ vty_out(vty, ":udp/tcp:%d",
+ port_min);
+ } else {
+ if (port_max)
+ vty_out(vty, ":proto %d:%d-%d",
+ proto, port_min, port_max);
+ else
+ vty_out(vty, ":proto %d:%d",
+ proto, port_min);
+ }
+}
+
+static int zebra_pbr_show_ipset_entry_walkcb(struct hash_backet *backet,
+ void *arg)
+{
+ struct zebra_pbr_ipset_entry_unique_display *unique =
+ (struct zebra_pbr_ipset_entry_unique_display *)arg;
+ struct zebra_pbr_ipset *zpi = unique->zpi;
+ 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;
+
+ if ((zpi->type == IPSET_NET_NET) ||
+ (zpi->type == IPSET_NET_PORT_NET)) {
+ char buf[PREFIX_STRLEN];
+
+ zebra_pbr_prefix2str(&(zpie->src), buf, sizeof(buf));
+ vty_out(vty, "\tfrom %s", buf);
+ if (zpie->filter_bm & PBR_FILTER_SRC_PORT)
+ zebra_pbr_display_port(vty, zpie->filter_bm,
+ zpie->src_port_min,
+ zpie->src_port_max,
+ zpie->proto);
+ vty_out(vty, " to ");
+ zebra_pbr_prefix2str(&(zpie->dst), buf, sizeof(buf));
+ vty_out(vty, "%s", buf);
+ if (zpie->filter_bm & PBR_FILTER_DST_PORT)
+ zebra_pbr_display_port(vty, zpie->filter_bm,
+ zpie->dst_port_min,
+ zpie->dst_port_max,
+ zpie->proto);
+ } else if ((zpi->type == IPSET_NET) ||
+ (zpi->type == IPSET_NET_PORT)) {
+ char buf[PREFIX_STRLEN];
+
+ if (zpie->filter_bm & PBR_FILTER_SRC_IP) {
+ zebra_pbr_prefix2str(&(zpie->src), buf, sizeof(buf));
+ vty_out(vty, "\tfrom %s", buf);
+ }
+ if (zpie->filter_bm & PBR_FILTER_SRC_PORT)
+ zebra_pbr_display_port(vty, zpie->filter_bm,
+ zpie->src_port_min,
+ zpie->src_port_max,
+ zpie->proto);
+ if (zpie->filter_bm & PBR_FILTER_DST_IP) {
+ zebra_pbr_prefix2str(&(zpie->dst), buf, sizeof(buf));
+ vty_out(vty, "\tto %s", buf);
+ }
+ if (zpie->filter_bm & PBR_FILTER_DST_PORT)
+ zebra_pbr_display_port(vty, zpie->filter_bm,
+ zpie->dst_port_min,
+ zpie->dst_port_max,
+ zpie->proto);
+ }
+ 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;
+}
+
+static int zebra_pbr_show_ipset_walkcb(struct hash_backet *backet, void *arg)
+{
+ struct zebra_pbr_env_display *uniqueipset =
+ (struct zebra_pbr_env_display *)arg;
+ struct zebra_pbr_ipset *zpi = (struct zebra_pbr_ipset *)backet->data;
+ struct zebra_pbr_ipset_entry_unique_display unique;
+ struct vty *vty = uniqueipset->vty;
+ struct zebra_ns *zns = uniqueipset->zns;
+
+ vty_out(vty, "IPset %s type %s\n", zpi->ipset_name,
+ 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");
+ return HASHWALK_CONTINUE;
+}
+
+/*
+ */
+void zebra_pbr_show_ipset_list(struct vty *vty, char *ipsetname)
+{
+ struct zebra_pbr_ipset *zpi;
+ struct zebra_ns *zns = zebra_ns_lookup(NS_DEFAULT);
+ struct zebra_pbr_ipset_entry_unique_display unique;
+ struct zebra_pbr_env_display uniqueipset;
+
+ if (ipsetname) {
+ zpi = zebra_pbr_lookup_ipset_pername(zns, ipsetname);
+ if (!zpi) {
+ vty_out(vty, "No IPset %s found\n", ipsetname);
+ return;
+ }
+ vty_out(vty, "IPset %s type %s\n", ipsetname,
+ 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);
+ return;
+ }
+ uniqueipset.zns = zns;
+ uniqueipset.vty = vty;
+ hash_walk(zns->ipset_hash, zebra_pbr_show_ipset_walkcb,
+ &uniqueipset);
+}
+
+struct pbr_rule_fwmark_lookup {
+ struct zebra_pbr_rule *ptr;
+ uint32_t fwmark;
+};
+
+static int zebra_pbr_rule_lookup_fwmark_walkcb(struct hash_backet *backet,
+ void *arg)
+{
+ struct pbr_rule_fwmark_lookup *iprule =
+ (struct pbr_rule_fwmark_lookup *)arg;
+ struct zebra_pbr_rule *zpr = (struct zebra_pbr_rule *)backet->data;
+
+ if (iprule->fwmark == zpr->rule.filter.fwmark) {
+ iprule->ptr = zpr;
+ return HASHWALK_ABORT;
+ }
+ return HASHWALK_CONTINUE;
+}
+
+static int zebra_pbr_show_iptable_walkcb(struct hash_backet *backet, void *arg)
+{
+ struct zebra_pbr_iptable *iptable =
+ (struct zebra_pbr_iptable *)backet->data;
+ 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;
+
+ prfl.fwmark = iptable->fwmark;
+ prfl.ptr = NULL;
+ hash_walk(zns->rules_hash,
+ &zebra_pbr_rule_lookup_fwmark_walkcb, &prfl);
+ if (prfl.ptr) {
+ struct zebra_pbr_rule *zpr = prfl.ptr;
+
+ vty_out(vty, "\t table %u, fwmark %u\n",
+ zpr->rule.action.table,
+ prfl.fwmark);
+ }
+ }
+ return HASHWALK_CONTINUE;
+}
+
+void zebra_pbr_show_iptable(struct vty *vty)
+{
+ struct zebra_ns *zns = zebra_ns_lookup(NS_DEFAULT);
+ struct zebra_pbr_env_display env;
+
+ env.vty = vty;
+ env.zns = zns;
+
+ hash_walk(zns->iptable_hash, zebra_pbr_show_iptable_walkcb,
+ &env);
+}
+
+void zebra_pbr_iptable_update_interfacelist(struct stream *s,
+ struct zebra_pbr_iptable *zpi)
+{
+ uint32_t i = 0, index;
+ struct interface *ifp;
+ char *name;
+
+ for (i = 0; i < zpi->nb_interface; i++) {
+ STREAM_GETL(s, index);
+ ifp = if_lookup_by_index(index, zpi->vrf_id);
+ if (!ifp)
+ continue;
+ name = XSTRDUP(MTYPE_PBR_IPTABLE_IFNAME, ifp->name);
+ listnode_add(zpi->interface_name_list, name);
+ }
+stream_failure:
+ return;
+}
diff --git a/zebra/zebra_pbr.h b/zebra/zebra_pbr.h
index 6b5cd1e8d..31fc55358 100644
--- a/zebra/zebra_pbr.h
+++ b/zebra/zebra_pbr.h
@@ -48,6 +48,8 @@ struct zebra_pbr_rule {
(r->rule.filter.filter_bm & PBR_FILTER_SRC_PORT)
#define IS_RULE_FILTERING_ON_DST_PORT(r) \
(r->rule.filter.filter_bm & PBR_FILTER_DST_PORT)
+#define IS_RULE_FILTERING_ON_FWMARK(r) \
+ (r->rule.filter.filter_bm & PBR_FILTER_FWMARK)
/*
* An IPSet Entry Filter
@@ -61,6 +63,8 @@ struct zebra_pbr_ipset {
*/
int sock;
+ vrf_id_t vrf_id;
+
uint32_t unique;
/* type is encoded as uint32_t
@@ -87,6 +91,13 @@ struct zebra_pbr_ipset_entry {
struct prefix src;
struct prefix dst;
+ uint16_t src_port_min;
+ uint16_t src_port_max;
+ uint16_t dst_port_min;
+ uint16_t dst_port_max;
+
+ uint8_t proto;
+
uint32_t filter_bm;
struct zebra_pbr_ipset *backpointer;
@@ -104,6 +115,8 @@ struct zebra_pbr_iptable {
*/
int sock;
+ vrf_id_t vrf_id;
+
uint32_t unique;
/* include ipset type
@@ -118,6 +131,10 @@ struct zebra_pbr_iptable {
uint32_t action;
+ uint32_t nb_interface;
+
+ struct list *interface_name_list;
+
char ipset_name[ZEBRA_IPSET_NAME_SIZE];
};
@@ -204,4 +221,31 @@ extern uint32_t zebra_pbr_iptable_hash_key(void *arg);
extern int zebra_pbr_iptable_hash_equal(const void *arg1, const void *arg2);
extern void zebra_pbr_init(void);
+extern void zebra_pbr_show_ipset_list(struct vty *vty, char *ipsetname);
+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 */
diff --git a/zebra/zebra_vty.c b/zebra/zebra_vty.c
index e6f80f92a..a094ca585 100644
--- a/zebra/zebra_vty.c
+++ b/zebra/zebra_vty.c
@@ -51,6 +51,7 @@
#include "zebra/router-id.h"
#include "zebra/ipforward.h"
#include "zebra/zebra_vxlan_private.h"
+#include "zebra/zebra_pbr.h"
extern int allow_delete;
@@ -3260,6 +3261,37 @@ DEFUN (show_evpn_neigh_vni_vtep,
return CMD_SUCCESS;
}
+/* policy routing contexts */
+DEFUN (show_pbr_ipset,
+ show_pbr_ipset_cmd,
+ "show pbr ipset [WORD]",
+ SHOW_STR
+ "Policy-Based Routing\n"
+ "IPset Context information\n"
+ "IPset Name information\n")
+{
+ int idx = 0;
+ int found = 0;
+ found = argv_find(argv, argc, "WORD", &idx);
+ if (!found)
+ zebra_pbr_show_ipset_list(vty, NULL);
+ else
+ zebra_pbr_show_ipset_list(vty, argv[idx]->arg);
+ return CMD_SUCCESS;
+}
+
+/* policy routing contexts */
+DEFUN (show_pbr_iptable,
+ show_pbr_iptable_cmd,
+ "show pbr iptable",
+ SHOW_STR
+ "Policy-Based Routing\n"
+ "IPtable Context information\n")
+{
+ zebra_pbr_show_iptable(vty);
+ return CMD_SUCCESS;
+}
+
/* Static ip route configuration write function. */
static int zebra_ip_config(struct vty *vty)
{
@@ -3762,6 +3794,9 @@ void zebra_vty_init(void)
install_element(VIEW_NODE, &show_evpn_neigh_vni_neigh_cmd);
install_element(VIEW_NODE, &show_evpn_neigh_vni_vtep_cmd);
+ install_element(VIEW_NODE, &show_pbr_ipset_cmd);
+ install_element(VIEW_NODE, &show_pbr_iptable_cmd);
+
install_element(CONFIG_NODE, &default_vrf_vni_mapping_cmd);
install_element(CONFIG_NODE, &no_default_vrf_vni_mapping_cmd);
install_element(VRF_NODE, &vrf_vni_mapping_cmd);