]> git.proxmox.com Git - mirror_frr.git/blobdiff - zebra/zebra_routemap.c
Merge pull request #12798 from donaldsharp/rib_match_multicast
[mirror_frr.git] / zebra / zebra_routemap.c
index 908c13f3dfc567f5dc94eff81535e6f68f1f8bbf..c5bccd05a6c3952d2cc1b3a0f297379a32572f3b 100644 (file)
@@ -1,21 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
 /* zebra routemap.
  * Copyright (C) 2006 IBM Corporation
- *
- * This file is part of GNU Zebra.
- *
- * GNU Zebra is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2, or (at your option) any
- * later version.
- *
- * GNU Zebra is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; see the file COPYING; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
 #include <zebra.h>
@@ -40,9 +25,7 @@
 #include "zebra/zebra_rnh.h"
 #include "zebra/zebra_routemap.h"
 
-#ifndef VTYSH_EXTRACT_PL
 #include "zebra/zebra_routemap_clippy.c"
-#endif
 
 static uint32_t zebra_rmap_update_timer = ZEBRA_RMAP_DEFAULT_UPDATE_TIMER;
 static struct thread *zebra_t_rmap_update = NULL;
@@ -145,26 +128,48 @@ static void show_vrf_proto_rm(struct vty *vty, struct zebra_vrf *zvrf,
 }
 
 static void show_vrf_nht_rm(struct vty *vty, struct zebra_vrf *zvrf,
-                           int af_type)
+                           int af_type, json_object *json)
 {
        int i;
 
-       vty_out(vty, "Protocol                  : route-map\n");
-       vty_out(vty, "-------------------------------------\n");
+       if (!json) {
+               vty_out(vty, "Protocol                  : route-map\n");
+               vty_out(vty, "-------------------------------------\n");
+       }
 
        for (i = 0; i < ZEBRA_ROUTE_MAX; i++) {
+               if (json) {
+                       if (NHT_RM_NAME(zvrf, af_type, i))
+                               json_object_string_add(
+                                       json, zebra_route_string(i),
+                                       NHT_RM_NAME(zvrf, af_type, i));
+                       else
+                               json_object_string_add(
+                                       json, zebra_route_string(i), "none");
+               } else {
+                       if (NHT_RM_NAME(zvrf, af_type, i))
+                               vty_out(vty, "%-24s  : %-10s\n",
+                                       zebra_route_string(i),
+                                       NHT_RM_NAME(zvrf, af_type, i));
+                       else
+                               vty_out(vty, "%-24s  : none\n",
+                                       zebra_route_string(i));
+               }
+       }
+
+       if (json) {
                if (NHT_RM_NAME(zvrf, af_type, i))
-                       vty_out(vty, "%-24s  : %-10s\n", zebra_route_string(i),
+                       json_object_string_add(json, "any",
+                                              NHT_RM_NAME(zvrf, af_type, i));
+               else
+                       json_object_string_add(json, "any", "none");
+       } else {
+               if (NHT_RM_NAME(zvrf, af_type, i))
+                       vty_out(vty, "%-24s  : %-10s\n", "any",
                                NHT_RM_NAME(zvrf, af_type, i));
                else
-                       vty_out(vty, "%-24s  : none\n", zebra_route_string(i));
+                       vty_out(vty, "%-24s  : none\n", "any");
        }
-
-       if (NHT_RM_NAME(zvrf, af_type, i))
-               vty_out(vty, "%-24s  : %-10s\n", "any",
-                       NHT_RM_NAME(zvrf, af_type, i));
-       else
-               vty_out(vty, "%-24s  : none\n", "any");
 }
 
 static int show_proto_rm(struct vty *vty, int af_type, const char *vrf_all,
@@ -200,35 +205,78 @@ static int show_proto_rm(struct vty *vty, int af_type, const char *vrf_all,
 }
 
 static int show_nht_rm(struct vty *vty, int af_type, const char *vrf_all,
-                      const char *vrf_name)
+                      const char *vrf_name, bool use_json)
 {
        struct zebra_vrf *zvrf;
+       json_object *json = NULL;
+       json_object *json_vrfs = NULL;
+
+       if (use_json) {
+               json = json_object_new_object();
+               json_vrfs = json_object_new_object();
+               json_object_string_add(json, "afi",
+                                      (af_type == AFI_IP) ? "ipv4" : "ipv6");
+       }
 
        if (vrf_all) {
                struct vrf *vrf;
 
+               if (use_json)
+                       json_object_object_add(json, "vrfs", json_vrfs);
+
                RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
                        zvrf = (struct zebra_vrf *)vrf->info;
                        if (zvrf == NULL)
                                continue;
 
-                       vty_out(vty, "VRF: %s\n", zvrf->vrf->name);
-                       show_vrf_nht_rm(vty, zvrf, af_type);
+                       if (use_json) {
+                               json_object *json_proto = NULL;
+                               json_object *json_vrf = NULL;
+                               json_vrf = json_object_new_object();
+                               json_object_object_add(
+                                       json_vrfs, zvrf->vrf->name, json_vrf);
+                               json_proto = json_object_new_object();
+                               json_object_object_add(json_vrf, "protocols",
+                                                      json_proto);
+                               show_vrf_nht_rm(vty, zvrf, af_type, json_proto);
+                       } else {
+                               vty_out(vty, "VRF: %s\n", zvrf->vrf->name);
+                               show_vrf_nht_rm(vty, zvrf, af_type, NULL);
+                       }
                }
        } else {
+               json_object *json_proto = NULL;
+               json_object *json_vrf = NULL;
                vrf_id_t vrf_id = VRF_DEFAULT;
 
                if (vrf_name)
                        VRF_GET_ID(vrf_id, vrf_name, false);
 
                zvrf = zebra_vrf_lookup_by_id(vrf_id);
-               if (!zvrf)
+               if (!zvrf) {
+                       json_object_free(json);
+                       json_object_free(json_vrfs);
                        return CMD_SUCCESS;
+               }
 
-               vty_out(vty, "VRF: %s\n", zvrf->vrf->name);
-               show_vrf_nht_rm(vty, zvrf, af_type);
+               if (use_json) {
+                       json_object_object_add(json, "vrfs", json_vrfs);
+                       json_vrf = json_object_new_object();
+                       json_object_object_add(json_vrfs, zvrf->vrf->name,
+                                              json_vrf);
+                       json_proto = json_object_new_object();
+                       json_object_object_add(json_vrf, "protocols",
+                                              json_proto);
+                       show_vrf_nht_rm(vty, zvrf, af_type, json_proto);
+               } else {
+                       vty_out(vty, "VRF: %s\n", zvrf->vrf->name);
+                       show_vrf_nht_rm(vty, zvrf, af_type, NULL);
+               }
        }
 
+       if (use_json)
+               vty_json(vty, json);
+
        return CMD_SUCCESS;
 }
 
@@ -638,7 +686,7 @@ DEFPY_YANG (ip_protocol,
        assert(proto);
        assert(rmap);
 
-       ZEBRA_DECLVAR_CONTEXT(vrf, zvrf);
+       ZEBRA_DECLVAR_CONTEXT_VRF(vrf, zvrf);
 
        if (!zvrf)
                return CMD_WARNING;
@@ -672,7 +720,7 @@ DEFPY_YANG (no_ip_protocol,
 
        assert(proto);
 
-       ZEBRA_DECLVAR_CONTEXT(vrf, zvrf);
+       ZEBRA_DECLVAR_CONTEXT_VRF(vrf, zvrf);
 
        if (!zvrf)
                return CMD_WARNING;
@@ -719,7 +767,7 @@ DEFPY_YANG (ipv6_protocol,
        assert(rmap);
        assert(proto);
 
-       ZEBRA_DECLVAR_CONTEXT(vrf, zvrf);
+       ZEBRA_DECLVAR_CONTEXT_VRF(vrf, zvrf);
 
        if (!zvrf)
                return CMD_WARNING;
@@ -753,7 +801,7 @@ DEFPY_YANG (no_ipv6_protocol,
 
        assert(proto);
 
-       ZEBRA_DECLVAR_CONTEXT(vrf, zvrf);
+       ZEBRA_DECLVAR_CONTEXT_VRF(vrf, zvrf);
 
        if (!zvrf)
                return CMD_WARNING;
@@ -801,7 +849,7 @@ DEFPY_YANG (ip_protocol_nht_rmap,
        assert(proto);
        assert(rmap);
 
-       ZEBRA_DECLVAR_CONTEXT(vrf, zvrf);
+       ZEBRA_DECLVAR_CONTEXT_VRF(vrf, zvrf);
 
        if (!zvrf)
                return CMD_WARNING;
@@ -835,7 +883,7 @@ DEFPY_YANG (no_ip_protocol_nht_rmap,
 
        assert(proto);
 
-       ZEBRA_DECLVAR_CONTEXT(vrf, zvrf);
+       ZEBRA_DECLVAR_CONTEXT_VRF(vrf, zvrf);
 
        if (!zvrf)
                return CMD_WARNING;
@@ -856,14 +904,19 @@ DEFPY_YANG (no_ip_protocol_nht_rmap,
 
 DEFPY_YANG (show_ip_protocol_nht,
        show_ip_protocol_nht_cmd,
-       "show ip nht route-map [vrf <NAME$vrf_name|all$vrf_all>]",
+       "show ip nht route-map [vrf <NAME$vrf_name|all$vrf_all>] [json]",
        SHOW_STR
        IP_STR
-       "IP nexthop tracking table\n"
-       "IP Next Hop tracking filtering status\n"
-       VRF_FULL_CMD_HELP_STR)
+       "IPv4 nexthop tracking table\n"
+       "IPv4 Next Hop tracking filtering status\n"
+       VRF_CMD_HELP_STR
+       "All VRFs\n"
+       JSON_STR)
 {
-       int ret = show_nht_rm(vty, AFI_IP, vrf_all, vrf_name);
+       int ret;
+       bool uj = use_json(argc, argv);
+
+       ret = show_nht_rm(vty, AFI_IP, vrf_all, vrf_name, uj);
 
        return ret;
 }
@@ -883,7 +936,7 @@ DEFPY_YANG (ipv6_protocol_nht_rmap,
        assert(rmap);
        assert(proto);
 
-       ZEBRA_DECLVAR_CONTEXT(vrf, zvrf);
+       ZEBRA_DECLVAR_CONTEXT_VRF(vrf, zvrf);
 
        if (!zvrf)
                return CMD_WARNING;
@@ -917,7 +970,7 @@ DEFPY_YANG (no_ipv6_protocol_nht_rmap,
 
        assert(proto);
 
-       ZEBRA_DECLVAR_CONTEXT(vrf, zvrf);
+       ZEBRA_DECLVAR_CONTEXT_VRF(vrf, zvrf);
 
        if (!zvrf)
                return CMD_WARNING;
@@ -938,14 +991,19 @@ DEFPY_YANG (no_ipv6_protocol_nht_rmap,
 
 DEFPY_YANG (show_ipv6_protocol_nht,
        show_ipv6_protocol_nht_cmd,
-       "show ipv6 nht route-map [vrf <NAME$vrf_name|all$vrf_all>]",
+       "show ipv6 nht route-map [vrf <NAME$vrf_name|all$vrf_all>] [json]",
        SHOW_STR
        IP6_STR
-       "Next Hop filtering status\n"
-       "Route-map\n"
-       VRF_FULL_CMD_HELP_STR)
+       "IPv6 nexthop tracking table\n"
+       "IPv6 Next Hop tracking filtering status\n"
+       VRF_CMD_HELP_STR
+       "All VRFs\n"
+       JSON_STR)
 {
-       int ret = show_nht_rm(vty, AFI_IP6, vrf_all, vrf_name);
+       int ret;
+       bool uj = use_json(argc, argv);
+
+       ret = show_nht_rm(vty, AFI_IP6, vrf_all, vrf_name, uj);
 
        return ret;
 }
@@ -976,12 +1034,19 @@ route_match_ip_next_hop(void *rule, const struct prefix *prefix, void *object)
                p.prefix = nh_data->nexthop->gate.ipv4;
                p.prefixlen = IPV4_MAX_BITLEN;
                break;
-       default:
+       case NEXTHOP_TYPE_IPV6:
+       case NEXTHOP_TYPE_IPV6_IFINDEX:
+       case NEXTHOP_TYPE_BLACKHOLE:
                return RMAP_NOMATCH;
        }
        alist = access_list_lookup(AFI_IP, (char *)rule);
-       if (alist == NULL)
+       if (alist == NULL) {
+               if (CHECK_FLAG(rmap_debug, DEBUG_ROUTEMAP_DETAIL))
+                       zlog_debug(
+                               "%s: Access-List Specified: %s does not exist defaulting to NO_MATCH",
+                               __func__, (char *)rule);
                return RMAP_NOMATCH;
+       }
 
        return (access_list_apply(alist, &p) == FILTER_DENY ? RMAP_NOMATCH
                                                            : RMAP_MATCH);
@@ -1032,12 +1097,19 @@ route_match_ip_next_hop_prefix_list(void *rule, const struct prefix *prefix,
                p.prefix = nh_data->nexthop->gate.ipv4;
                p.prefixlen = IPV4_MAX_BITLEN;
                break;
-       default:
+       case NEXTHOP_TYPE_IPV6:
+       case NEXTHOP_TYPE_IPV6_IFINDEX:
+       case NEXTHOP_TYPE_BLACKHOLE:
                return RMAP_NOMATCH;
        }
        plist = prefix_list_lookup(AFI_IP, (char *)rule);
-       if (plist == NULL)
+       if (plist == NULL) {
+               if (CHECK_FLAG(rmap_debug, DEBUG_ROUTEMAP_DETAIL))
+                       zlog_debug(
+                               "%s: Prefix List %s specified does not exist defaulting to NO_MATCH",
+                               __func__, (char *)rule);
                return RMAP_NOMATCH;
+       }
 
        return (prefix_list_apply(plist, &p) == PREFIX_DENY ? RMAP_NOMATCH
                                                            : RMAP_MATCH);
@@ -1072,8 +1144,13 @@ route_match_address(afi_t afi, void *rule, const struct prefix *prefix,
        struct access_list *alist;
 
        alist = access_list_lookup(afi, (char *)rule);
-       if (alist == NULL)
+       if (alist == NULL) {
+               if (CHECK_FLAG(rmap_debug, DEBUG_ROUTEMAP_DETAIL))
+                       zlog_debug(
+                               "%s: Access-List Specified: %s does not exist defaulting to NO_MATCH",
+                               __func__, (char *)rule);
                return RMAP_NOMATCH;
+       }
 
        return (access_list_apply(alist, prefix) == FILTER_DENY ? RMAP_NOMATCH
                                                                : RMAP_MATCH);
@@ -1129,8 +1206,13 @@ route_match_address_prefix_list(void *rule, const struct prefix *prefix,
        struct prefix_list *plist;
 
        plist = prefix_list_lookup(afi, (char *)rule);
-       if (plist == NULL)
+       if (plist == NULL) {
+               if (CHECK_FLAG(rmap_debug, DEBUG_ROUTEMAP_DETAIL))
+                       zlog_debug(
+                               "%s: Prefix List %s specified does not exist defaulting to NO_MATCH",
+                               __func__, (char *)rule);
                return RMAP_NOMATCH;
+       }
 
        return (prefix_list_apply(plist, prefix) == PREFIX_DENY ? RMAP_NOMATCH
                                                                : RMAP_MATCH);
@@ -1291,7 +1373,9 @@ route_match_ip_nexthop_prefix_len(void *rule, const struct prefix *prefix,
                p.prefix = nh_data->nexthop->gate.ipv4;
                p.prefixlen = IPV4_MAX_BITLEN;
                break;
-       default:
+       case NEXTHOP_TYPE_IPV6:
+       case NEXTHOP_TYPE_IPV6_IFINDEX:
+       case NEXTHOP_TYPE_BLACKHOLE:
                return RMAP_NOMATCH;
        }
        return ((p.prefixlen == *prefixlen) ? RMAP_MATCH : RMAP_NOMATCH);
@@ -1638,7 +1722,7 @@ static void zebra_route_map_process_update_cb(char *rmap_name)
        zebra_nht_rm_update(rmap_name);
 }
 
-static int zebra_route_map_update_timer(struct thread *thread)
+static void zebra_route_map_update_timer(struct thread *thread)
 {
        if (IS_ZEBRA_DEBUG_EVENT)
                zlog_debug("Event driven route-map update triggered");
@@ -1655,7 +1739,6 @@ static int zebra_route_map_update_timer(struct thread *thread)
         * 1) VRF Aware <sigh>
         * 2) Route-map aware
         */
-       return 0;
 }
 
 static void zebra_route_map_set_delay_timer(uint32_t value)
@@ -1821,6 +1904,23 @@ static void zebra_route_map_event(const char *rmap_name)
        route_map_notify_dependencies(rmap_name, RMAP_EVENT_MATCH_ADDED);
 }
 
+void zebra_routemap_vrf_delete(struct zebra_vrf *zvrf)
+{
+       afi_t afi;
+       uint8_t type;
+
+       for (afi = AFI_IP; afi < AFI_MAX; afi++) {
+               for (type = 0; type <= ZEBRA_ROUTE_MAX; type++) {
+                       if (PROTO_RM_NAME(zvrf, afi, type))
+                               XFREE(MTYPE_ROUTE_MAP_NAME,
+                                     PROTO_RM_NAME(zvrf, afi, type));
+                       if (NHT_RM_NAME(zvrf, afi, type))
+                               XFREE(MTYPE_ROUTE_MAP_NAME,
+                                     NHT_RM_NAME(zvrf, afi, type));
+               }
+       }
+}
+
 /* ip protocol configuration write function */
 void zebra_routemap_config_write_protocol(struct vty *vty,
                                          struct zebra_vrf *zvrf)