]> git.proxmox.com Git - mirror_frr.git/commitdiff
zebra: pbr vty show command for ipset and iptables
authorPhilippe Guibert <philippe.guibert@6wind.com>
Mon, 23 Apr 2018 13:17:19 +0000 (15:17 +0200)
committerPhilippe Guibert <philippe.guibert@6wind.com>
Thu, 31 May 2018 15:44:39 +0000 (17:44 +0200)
Two new vty show functions available:
show pbr ipset <NAME>
show pbr iptables <NAME>

Those function dump the underlying "kernel" contexts. It relies on the
zebra pbr contexts. This helps then to know which zebra pbr
context has been configured since those contexts are mainly configured
by BGP Flowspec.

Signed-off-by: Philippe Guibert <philippe.guibert@6wind.com>
zebra/zebra_pbr.c
zebra/zebra_pbr.h
zebra/zebra_vty.c

index 166b04dc962a54414b8f380f50b8490844783f79..3dca072dc1c3ac5e48c46b9b69313262075c9a32 100644 (file)
 #include "zebra/zapi_msg.h"
 
 /* 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 */
 
@@ -416,6 +423,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 =
@@ -630,3 +643,178 @@ 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_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 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;
+
+       if (zpie->backpointer != zpi)
+               return HASHWALK_CONTINUE;
+
+       if (zpi->type == IPSET_NET_NET) {
+               char buf[PREFIX_STRLEN];
+
+               zebra_pbr_prefix2str(&(zpie->src), buf, sizeof(buf));
+               vty_out(vty, "\tfrom %s", buf);
+               vty_out(vty, " to ");
+               zebra_pbr_prefix2str(&(zpie->dst), buf, sizeof(buf));
+               vty_out(vty, "%s", buf);
+       } else if (zpi->type == IPSET_NET) {
+               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_DST_IP) {
+                       zebra_pbr_prefix2str(&(zpie->dst), buf, sizeof(buf));
+                       vty_out(vty, "\tto %s", buf);
+               }
+       }
+       vty_out(vty, " (%u)\n", zpie->unique);
+
+       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;
+
+       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;
+
+               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;
+
+       vty_out(vty, "IPtable %s action %s (%u)\n", iptable->ipset_name,
+               iptable->action == ZEBRA_IPTABLES_DROP ? "drop" : "redirect",
+               iptable->unique);
+
+       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);
+}
index 12678b210bdb0b93d3d820d2a8384757cef4e3c5..5d2e4a08e1b975066fde2e84eb0eeee3a3e5ba27 100644 (file)
@@ -209,4 +209,8 @@ extern void zebra_pbr_iptable_free(void *arg);
 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);
+
 #endif /* _ZEBRA_PBR_H */
index 16aece9747c0a2eba3efdb731bb4513c3023af6d..43d76a6574bfaf1dad05c952d75b146cdb2beb31 100644 (file)
@@ -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;
 
@@ -3247,6 +3248,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)
 {
@@ -3749,6 +3781,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);