back to topotato report
topotato coverage report
Current view: top level - zebra - zebra_routemap.c (source / functions) Hit Total Coverage
Test: test_bgp_set_aspath_replace.py::BGPSetAspathReplace Lines: 110 833 13.2 %
Date: 2023-02-24 18:37:49 Functions: 4 85 4.7 %

          Line data    Source code
       1             : /* zebra routemap.
       2             :  * Copyright (C) 2006 IBM Corporation
       3             :  *
       4             :  * This file is part of GNU Zebra.
       5             :  *
       6             :  * GNU Zebra is free software; you can redistribute it and/or modify it
       7             :  * under the terms of the GNU General Public License as published by the
       8             :  * Free Software Foundation; either version 2, or (at your option) any
       9             :  * later version.
      10             :  *
      11             :  * GNU Zebra is distributed in the hope that it will be useful, but
      12             :  * WITHOUT ANY WARRANTY; without even the implied warranty of
      13             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      14             :  * General Public License for more details.
      15             :  *
      16             :  * You should have received a copy of the GNU General Public License along
      17             :  * with this program; see the file COPYING; if not, write to the Free Software
      18             :  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
      19             :  */
      20             : 
      21             : #include <zebra.h>
      22             : 
      23             : #include "memory.h"
      24             : #include "prefix.h"
      25             : #include "rib.h"
      26             : #include "vty.h"
      27             : #include "routemap.h"
      28             : #include "command.h"
      29             : #include "filter.h"
      30             : #include "plist.h"
      31             : #include "nexthop.h"
      32             : #include "northbound_cli.h"
      33             : #include "lib/route_types.h"
      34             : #include "vrf.h"
      35             : #include "frrstr.h"
      36             : 
      37             : #include "zebra/zebra_router.h"
      38             : #include "zebra/redistribute.h"
      39             : #include "zebra/debug.h"
      40             : #include "zebra/zebra_rnh.h"
      41             : #include "zebra/zebra_routemap.h"
      42             : 
      43             : #include "zebra/zebra_routemap_clippy.c"
      44             : 
      45             : static uint32_t zebra_rmap_update_timer = ZEBRA_RMAP_DEFAULT_UPDATE_TIMER;
      46             : static struct thread *zebra_t_rmap_update = NULL;
      47             : char *zebra_import_table_routemap[AFI_MAX][ZEBRA_KERNEL_TABLE_MAX];
      48             : 
      49             : struct nh_rmap_obj {
      50             :         struct nexthop *nexthop;
      51             :         vrf_id_t vrf_id;
      52             :         uint32_t source_protocol;
      53             :         uint8_t instance;
      54             :         int metric;
      55             :         route_tag_t tag;
      56             : };
      57             : 
      58             : static void zebra_route_map_set_delay_timer(uint32_t value);
      59             : 
      60             : /* 'match tag TAG'
      61             :  * Match function return 1 if match is success else return 0
      62             :  */
      63             : static enum route_map_cmd_result_t
      64           0 : route_match_tag(void *rule, const struct prefix *prefix, void *object)
      65             : {
      66           0 :         route_tag_t *tag;
      67           0 :         struct nh_rmap_obj *nh_data;
      68             : 
      69           0 :         tag = rule;
      70           0 :         nh_data = object;
      71             : 
      72           0 :         if (nh_data->tag == *tag)
      73           0 :                 return RMAP_MATCH;
      74             : 
      75             :         return RMAP_NOMATCH;
      76             : }
      77             : 
      78             : /* Route map commands for tag matching */
      79             : static const struct route_map_rule_cmd route_match_tag_cmd = {
      80             :         "tag",
      81             :         route_match_tag,
      82             :         route_map_rule_tag_compile,
      83             :         route_map_rule_tag_free,
      84             : };
      85             : 
      86             : 
      87             : /* `match interface IFNAME' */
      88             : /* Match function return 1 if match is success else return zero. */
      89             : static enum route_map_cmd_result_t
      90           0 : route_match_interface(void *rule, const struct prefix *prefix, void *object)
      91             : {
      92           0 :         struct nh_rmap_obj *nh_data;
      93           0 :         char *ifname = rule;
      94           0 :         ifindex_t ifindex;
      95             : 
      96           0 :         if (strcasecmp(ifname, "any") == 0)
      97             :                 return RMAP_MATCH;
      98           0 :         nh_data = object;
      99           0 :         if (!nh_data || !nh_data->nexthop)
     100             :                 return RMAP_NOMATCH;
     101           0 :         ifindex = ifname2ifindex(ifname, nh_data->vrf_id);
     102           0 :         if (ifindex == 0)
     103             :                 return RMAP_NOMATCH;
     104           0 :         if (nh_data->nexthop->ifindex == ifindex)
     105             :                 return RMAP_MATCH;
     106             : 
     107             :         return RMAP_NOMATCH;
     108             : }
     109             : 
     110             : /* Route map `match interface' match statement. `arg' is IFNAME value */
     111           0 : static void *route_match_interface_compile(const char *arg)
     112             : {
     113           0 :         return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
     114             : }
     115             : 
     116             : /* Free route map's compiled `match interface' value. */
     117           0 : static void route_match_interface_free(void *rule)
     118             : {
     119           0 :         XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
     120           0 : }
     121             : 
     122           0 : static void show_vrf_proto_rm(struct vty *vty, struct zebra_vrf *zvrf,
     123             :                               int af_type)
     124             : {
     125           0 :         int i;
     126             : 
     127           0 :         vty_out(vty, "Protocol                  : route-map\n");
     128           0 :         vty_out(vty, "-------------------------------------\n");
     129             : 
     130           0 :         for (i = 0; i < ZEBRA_ROUTE_MAX; i++) {
     131           0 :                 if (PROTO_RM_NAME(zvrf, af_type, i))
     132           0 :                         vty_out(vty, "%-24s  : %-10s\n", zebra_route_string(i),
     133             :                                 PROTO_RM_NAME(zvrf, af_type, i));
     134             :                 else
     135           0 :                         vty_out(vty, "%-24s  : none\n", zebra_route_string(i));
     136             :         }
     137             : 
     138           0 :         if (PROTO_RM_NAME(zvrf, af_type, i))
     139           0 :                 vty_out(vty, "%-24s  : %-10s\n", "any",
     140             :                         PROTO_RM_NAME(zvrf, af_type, i));
     141             :         else
     142           0 :                 vty_out(vty, "%-24s  : none\n", "any");
     143           0 : }
     144             : 
     145           0 : static void show_vrf_nht_rm(struct vty *vty, struct zebra_vrf *zvrf,
     146             :                             int af_type, json_object *json)
     147             : {
     148           0 :         int i;
     149             : 
     150           0 :         if (!json) {
     151           0 :                 vty_out(vty, "Protocol                  : route-map\n");
     152           0 :                 vty_out(vty, "-------------------------------------\n");
     153             :         }
     154             : 
     155           0 :         for (i = 0; i < ZEBRA_ROUTE_MAX; i++) {
     156           0 :                 if (json) {
     157           0 :                         if (NHT_RM_NAME(zvrf, af_type, i))
     158           0 :                                 json_object_string_add(
     159             :                                         json, zebra_route_string(i),
     160             :                                         NHT_RM_NAME(zvrf, af_type, i));
     161             :                         else
     162           0 :                                 json_object_string_add(
     163             :                                         json, zebra_route_string(i), "none");
     164             :                 } else {
     165           0 :                         if (NHT_RM_NAME(zvrf, af_type, i))
     166           0 :                                 vty_out(vty, "%-24s  : %-10s\n",
     167             :                                         zebra_route_string(i),
     168             :                                         NHT_RM_NAME(zvrf, af_type, i));
     169             :                         else
     170           0 :                                 vty_out(vty, "%-24s  : none\n",
     171             :                                         zebra_route_string(i));
     172             :                 }
     173             :         }
     174             : 
     175           0 :         if (json) {
     176           0 :                 if (NHT_RM_NAME(zvrf, af_type, i))
     177           0 :                         json_object_string_add(json, "any",
     178             :                                                NHT_RM_NAME(zvrf, af_type, i));
     179             :                 else
     180           0 :                         json_object_string_add(json, "any", "none");
     181             :         } else {
     182           0 :                 if (NHT_RM_NAME(zvrf, af_type, i))
     183           0 :                         vty_out(vty, "%-24s  : %-10s\n", "any",
     184             :                                 NHT_RM_NAME(zvrf, af_type, i));
     185             :                 else
     186           0 :                         vty_out(vty, "%-24s  : none\n", "any");
     187             :         }
     188           0 : }
     189             : 
     190           0 : static int show_proto_rm(struct vty *vty, int af_type, const char *vrf_all,
     191             :                          const char *vrf_name)
     192             : {
     193           0 :         struct zebra_vrf *zvrf;
     194             : 
     195           0 :         if (vrf_all) {
     196           0 :                 struct vrf *vrf;
     197             : 
     198           0 :                 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
     199           0 :                         zvrf = (struct zebra_vrf *)vrf->info;
     200           0 :                         if (zvrf == NULL)
     201           0 :                                 continue;
     202           0 :                         vty_out(vty, "VRF: %s\n", zvrf->vrf->name);
     203           0 :                         show_vrf_proto_rm(vty, zvrf, af_type);
     204             :                 }
     205             :         } else {
     206           0 :                 vrf_id_t vrf_id = VRF_DEFAULT;
     207             : 
     208           0 :                 if (vrf_name)
     209           0 :                         VRF_GET_ID(vrf_id, vrf_name, false);
     210             : 
     211           0 :                 zvrf = zebra_vrf_lookup_by_id(vrf_id);
     212           0 :                 if (!zvrf)
     213             :                         return CMD_SUCCESS;
     214             : 
     215           0 :                 vty_out(vty, "VRF: %s\n", zvrf->vrf->name);
     216           0 :                 show_vrf_proto_rm(vty, zvrf, af_type);
     217             :         }
     218             : 
     219             :         return CMD_SUCCESS;
     220             : }
     221             : 
     222           0 : static int show_nht_rm(struct vty *vty, int af_type, const char *vrf_all,
     223             :                        const char *vrf_name, bool use_json)
     224             : {
     225           0 :         struct zebra_vrf *zvrf;
     226           0 :         json_object *json = NULL;
     227           0 :         json_object *json_vrfs = NULL;
     228             : 
     229           0 :         if (use_json) {
     230           0 :                 json = json_object_new_object();
     231           0 :                 json_vrfs = json_object_new_object();
     232           0 :                 json_object_string_add(json, "afi",
     233             :                                        (af_type == AFI_IP) ? "ipv4" : "ipv6");
     234             :         }
     235             : 
     236           0 :         if (vrf_all) {
     237           0 :                 struct vrf *vrf;
     238             : 
     239           0 :                 if (use_json)
     240           0 :                         json_object_object_add(json, "vrfs", json_vrfs);
     241             : 
     242           0 :                 RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
     243           0 :                         zvrf = (struct zebra_vrf *)vrf->info;
     244           0 :                         if (zvrf == NULL)
     245           0 :                                 continue;
     246             : 
     247           0 :                         if (use_json) {
     248           0 :                                 json_object *json_proto = NULL;
     249           0 :                                 json_object *json_vrf = NULL;
     250           0 :                                 json_vrf = json_object_new_object();
     251           0 :                                 json_object_object_add(
     252           0 :                                         json_vrfs, zvrf->vrf->name, json_vrf);
     253           0 :                                 json_proto = json_object_new_object();
     254           0 :                                 json_object_object_add(json_vrf, "protocols",
     255             :                                                        json_proto);
     256           0 :                                 show_vrf_nht_rm(vty, zvrf, af_type, json_proto);
     257             :                         } else {
     258           0 :                                 vty_out(vty, "VRF: %s\n", zvrf->vrf->name);
     259           0 :                                 show_vrf_nht_rm(vty, zvrf, af_type, NULL);
     260             :                         }
     261             :                 }
     262             :         } else {
     263           0 :                 json_object *json_proto = NULL;
     264           0 :                 json_object *json_vrf = NULL;
     265           0 :                 vrf_id_t vrf_id = VRF_DEFAULT;
     266             : 
     267           0 :                 if (vrf_name)
     268           0 :                         VRF_GET_ID(vrf_id, vrf_name, false);
     269             : 
     270           0 :                 zvrf = zebra_vrf_lookup_by_id(vrf_id);
     271           0 :                 if (!zvrf) {
     272           0 :                         json_object_free(json);
     273           0 :                         json_object_free(json_vrfs);
     274           0 :                         return CMD_SUCCESS;
     275             :                 }
     276             : 
     277           0 :                 if (use_json) {
     278           0 :                         json_object_object_add(json, "vrfs", json_vrfs);
     279           0 :                         json_vrf = json_object_new_object();
     280           0 :                         json_object_object_add(json_vrfs, zvrf->vrf->name,
     281             :                                                json_vrf);
     282           0 :                         json_proto = json_object_new_object();
     283           0 :                         json_object_object_add(json_vrf, "protocols",
     284             :                                                json_proto);
     285           0 :                         show_vrf_nht_rm(vty, zvrf, af_type, json_proto);
     286             :                 } else {
     287           0 :                         vty_out(vty, "VRF: %s\n", zvrf->vrf->name);
     288           0 :                         show_vrf_nht_rm(vty, zvrf, af_type, NULL);
     289             :                 }
     290             :         }
     291             : 
     292           0 :         if (use_json)
     293           0 :                 vty_json(vty, json);
     294             : 
     295             :         return CMD_SUCCESS;
     296             : }
     297             : 
     298             : /* Route map commands for interface matching */
     299             : static const struct route_map_rule_cmd route_match_interface_cmd = {
     300             :         "interface",
     301             :         route_match_interface,
     302             :         route_match_interface_compile,
     303             :         route_match_interface_free
     304             : };
     305             : 
     306           0 : static int ip_protocol_rm_add(struct zebra_vrf *zvrf, const char *rmap,
     307             :                               int rtype, afi_t afi, safi_t safi)
     308             : {
     309           0 :         struct route_table *table;
     310             : 
     311           0 :         if (PROTO_RM_NAME(zvrf, afi, rtype)) {
     312           0 :                 if (strcmp(PROTO_RM_NAME(zvrf, afi, rtype), rmap) == 0)
     313             :                         return CMD_SUCCESS;
     314             : 
     315           0 :                 XFREE(MTYPE_ROUTE_MAP_NAME, PROTO_RM_NAME(zvrf, afi, rtype));
     316             :         }
     317           0 :         route_map_counter_decrement(PROTO_RM_MAP(zvrf, afi, rtype));
     318           0 :         PROTO_RM_NAME(zvrf, afi, rtype) = XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
     319           0 :         PROTO_RM_MAP(zvrf, afi, rtype) =
     320           0 :                 route_map_lookup_by_name(PROTO_RM_NAME(zvrf, afi, rtype));
     321           0 :         route_map_counter_increment(PROTO_RM_MAP(zvrf, afi, rtype));
     322             : 
     323           0 :         if (PROTO_RM_MAP(zvrf, afi, rtype)) {
     324             : 
     325           0 :                 if (IS_ZEBRA_DEBUG_RIB_DETAILED)
     326           0 :                         zlog_debug(
     327             :                                 "%u: IPv4 Routemap config for protocol %d scheduling RIB processing",
     328             :                                 zvrf->vrf->vrf_id, rtype);
     329             :                 /* Process routes of interested address-families. */
     330           0 :                 table = zebra_vrf_table(afi, safi, zvrf->vrf->vrf_id);
     331           0 :                 if (table)
     332           0 :                         rib_update_table(table, RIB_UPDATE_RMAP_CHANGE,
     333             :                                          rtype);
     334             :         }
     335             : 
     336             :         return CMD_SUCCESS;
     337             : }
     338             : 
     339           0 : static int ip_protocol_rm_del(struct zebra_vrf *zvrf, const char *rmap,
     340             :                               int rtype, afi_t afi, safi_t safi)
     341             : {
     342           0 :         struct route_table *table;
     343             : 
     344           0 :         if (!PROTO_RM_NAME(zvrf, afi, rtype))
     345             :                 return CMD_SUCCESS;
     346             : 
     347           0 :         if (!rmap || strcmp(rmap, PROTO_RM_NAME(zvrf, afi, rtype)) == 0) {
     348             : 
     349           0 :                 route_map_counter_decrement(PROTO_RM_MAP(zvrf, afi, rtype));
     350           0 :                 if (PROTO_RM_MAP(zvrf, afi, rtype)) {
     351           0 :                         if (IS_ZEBRA_DEBUG_RIB_DETAILED)
     352           0 :                                 zlog_debug(
     353             :                                         "%u: IPv4 Routemap unconfig for protocol %d, scheduling RIB processing",
     354             :                                         zvrf->vrf->vrf_id, rtype);
     355           0 :                         PROTO_RM_MAP(zvrf, afi, rtype) = NULL;
     356             : 
     357             :                         /* Process routes of interested address-families. */
     358           0 :                         table = zebra_vrf_table(afi, safi, zvrf->vrf->vrf_id);
     359           0 :                         if (table)
     360           0 :                                 rib_update_table(table, RIB_UPDATE_RMAP_CHANGE,
     361             :                                                  rtype);
     362             :                 }
     363           0 :                 XFREE(MTYPE_ROUTE_MAP_NAME, PROTO_RM_NAME(zvrf, afi, rtype));
     364             :         }
     365             :         return CMD_SUCCESS;
     366             : }
     367             : 
     368           0 : static int ip_nht_rm_add(struct zebra_vrf *zvrf, const char *rmap, int rtype,
     369             :                          int afi)
     370             : {
     371             : 
     372           0 :         if (NHT_RM_NAME(zvrf, afi, rtype)) {
     373           0 :                 if (strcmp(NHT_RM_NAME(zvrf, afi, rtype), rmap) == 0)
     374             :                         return CMD_SUCCESS;
     375             : 
     376           0 :                 XFREE(MTYPE_ROUTE_MAP_NAME, NHT_RM_NAME(zvrf, afi, rtype));
     377             :         }
     378           0 :         route_map_counter_decrement(NHT_RM_MAP(zvrf, afi, rtype));
     379           0 :         NHT_RM_NAME(zvrf, afi, rtype) = XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap);
     380           0 :         NHT_RM_MAP(zvrf, afi, rtype) =
     381           0 :                 route_map_lookup_by_name(NHT_RM_NAME(zvrf, afi, rtype));
     382           0 :         route_map_counter_increment(NHT_RM_MAP(zvrf, afi, rtype));
     383             : 
     384           0 :         if (NHT_RM_MAP(zvrf, afi, rtype))
     385           0 :                 zebra_evaluate_rnh(zvrf, AFI_IP, 1, NULL, SAFI_UNICAST);
     386             : 
     387             :         return CMD_SUCCESS;
     388             : }
     389             : 
     390           0 : static int ip_nht_rm_del(struct zebra_vrf *zvrf, const char *rmap, int rtype,
     391             :                          int afi)
     392             : {
     393             : 
     394           0 :         if (!NHT_RM_NAME(zvrf, afi, rtype))
     395             :                 return CMD_SUCCESS;
     396             : 
     397           0 :         if (!rmap || strcmp(rmap, NHT_RM_NAME(zvrf, afi, rtype)) == 0) {
     398           0 :                 route_map_counter_decrement(NHT_RM_MAP(zvrf, afi, rtype));
     399           0 :                 if (NHT_RM_MAP(zvrf, afi, rtype)) {
     400           0 :                         if (IS_ZEBRA_DEBUG_RIB_DETAILED)
     401           0 :                                 zlog_debug(
     402             :                                         "%u: IPv4 Routemap unconfig for protocol %d, scheduling RIB processing",
     403             :                                         zvrf->vrf->vrf_id, rtype);
     404           0 :                         NHT_RM_MAP(zvrf, afi, rtype) = NULL;
     405             : 
     406           0 :                         zebra_evaluate_rnh(zvrf, AFI_IP, 1, NULL, SAFI_UNICAST);
     407             :                 }
     408           0 :                 XFREE(MTYPE_ROUTE_MAP_NAME, NHT_RM_NAME(zvrf, afi, rtype));
     409             :         }
     410             :         return CMD_SUCCESS;
     411             : }
     412             : 
     413           0 : DEFPY_YANG(
     414             :         match_ip_address_prefix_len, match_ip_address_prefix_len_cmd,
     415             :         "match ip address prefix-len (0-32)$length",
     416             :         MATCH_STR
     417             :         IP_STR
     418             :         "Match prefix length of IP address\n"
     419             :         "Match prefix length of IP address\n"
     420             :         "Prefix length\n")
     421             : {
     422           0 :         const char *xpath =
     423             :                 "./match-condition[condition='frr-zebra-route-map:ipv4-prefix-length']";
     424           0 :         char xpath_value[XPATH_MAXLEN];
     425             : 
     426           0 :         nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
     427           0 :         snprintf(
     428             :                 xpath_value, sizeof(xpath_value),
     429             :                 "%s/rmap-match-condition/frr-zebra-route-map:ipv4-prefix-length",
     430             :                 xpath);
     431           0 :         nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, length_str);
     432             : 
     433           0 :         return nb_cli_apply_changes(vty, NULL);
     434             : }
     435             : 
     436           0 : DEFPY_YANG(
     437             :         no_match_ip_address_prefix_len, no_match_ip_address_prefix_len_cmd,
     438             :         "no match ip address prefix-len [(0-32)]",
     439             :         NO_STR
     440             :         MATCH_STR
     441             :         IP_STR
     442             :         "Match prefix length of IP address\n"
     443             :         "Match prefix length of IP address\n"
     444             :         "Prefix length\n")
     445             : {
     446           0 :         const char *xpath =
     447             :                 "./match-condition[condition='frr-zebra-route-map:ipv4-prefix-length']";
     448             : 
     449           0 :         nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
     450             : 
     451           0 :         return nb_cli_apply_changes(vty, NULL);
     452             : }
     453             : 
     454           0 : DEFPY_YANG(
     455             :         match_ipv6_address_prefix_len, match_ipv6_address_prefix_len_cmd,
     456             :         "match ipv6 address prefix-len (0-128)$length",
     457             :         MATCH_STR
     458             :         IPV6_STR
     459             :         "Match prefix length of IPv6 address\n"
     460             :         "Match prefix length of IPv6 address\n"
     461             :         "Prefix length\n")
     462             : {
     463           0 :         const char *xpath =
     464             :                 "./match-condition[condition='frr-zebra-route-map:ipv6-prefix-length']";
     465           0 :         char xpath_value[XPATH_MAXLEN];
     466             : 
     467           0 :         nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
     468           0 :         snprintf(
     469             :                 xpath_value, sizeof(xpath_value),
     470             :                 "%s/rmap-match-condition/frr-zebra-route-map:ipv6-prefix-length",
     471             :                 xpath);
     472           0 :         nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, length_str);
     473             : 
     474           0 :         return nb_cli_apply_changes(vty, NULL);
     475             : }
     476             : 
     477           0 : DEFPY_YANG(
     478             :         no_match_ipv6_address_prefix_len, no_match_ipv6_address_prefix_len_cmd,
     479             :         "no match ipv6 address prefix-len [(0-128)]",
     480             :         NO_STR
     481             :         MATCH_STR
     482             :         IPV6_STR
     483             :         "Match prefix length of IPv6 address\n"
     484             :         "Match prefix length of IPv6 address\n"
     485             :         "Prefix length\n")
     486             : {
     487           0 :         const char *xpath =
     488             :                 "./match-condition[condition='frr-zebra-route-map:ipv6-prefix-length']";
     489             : 
     490           0 :         nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
     491             : 
     492           0 :         return nb_cli_apply_changes(vty, NULL);
     493             : }
     494             : 
     495           0 : DEFPY_YANG(
     496             :         match_ip_nexthop_prefix_len, match_ip_nexthop_prefix_len_cmd,
     497             :         "match ip next-hop prefix-len (0-32)$length",
     498             :         MATCH_STR
     499             :         IP_STR
     500             :         "Match prefixlen of nexthop IP address\n"
     501             :         "Match prefixlen of given nexthop\n"
     502             :         "Prefix length\n")
     503             : {
     504           0 :         const char *xpath =
     505             :                 "./match-condition[condition='frr-zebra-route-map:ipv4-next-hop-prefix-length']";
     506           0 :         char xpath_value[XPATH_MAXLEN];
     507             : 
     508           0 :         nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
     509           0 :         snprintf(
     510             :                 xpath_value, sizeof(xpath_value),
     511             :                 "%s/rmap-match-condition/frr-zebra-route-map:ipv4-prefix-length",
     512             :                 xpath);
     513           0 :         nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, length_str);
     514             : 
     515           0 :         return nb_cli_apply_changes(vty, NULL);
     516             : }
     517             : 
     518           0 : DEFPY_YANG(
     519             :         no_match_ip_nexthop_prefix_len, no_match_ip_nexthop_prefix_len_cmd,
     520             :         "no match ip next-hop prefix-len [(0-32)]",
     521             :         NO_STR
     522             :         MATCH_STR
     523             :         IP_STR
     524             :         "Match prefixlen of nexthop IP address\n"
     525             :         "Match prefix length of nexthop\n"
     526             :         "Prefix length\n")
     527             : {
     528           0 :         const char *xpath =
     529             :                 "./match-condition[condition='frr-zebra-route-map:ipv4-next-hop-prefix-length']";
     530             : 
     531           0 :         nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
     532             : 
     533           0 :         return nb_cli_apply_changes(vty, NULL);
     534             : }
     535             : 
     536           0 : DEFPY_YANG(
     537             :         match_source_protocol, match_source_protocol_cmd,
     538             :         "match source-protocol " FRR_REDIST_STR_ZEBRA "$proto",
     539             :         MATCH_STR
     540             :         "Match protocol via which the route was learnt\n"
     541             :         FRR_REDIST_HELP_STR_ZEBRA)
     542             : {
     543           0 :         const char *xpath =
     544             :                 "./match-condition[condition='frr-zebra-route-map:source-protocol']";
     545           0 :         char xpath_value[XPATH_MAXLEN];
     546             : 
     547           0 :         nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
     548           0 :         snprintf(xpath_value, sizeof(xpath_value),
     549             :                  "%s/rmap-match-condition/frr-zebra-route-map:source-protocol",
     550             :                  xpath);
     551           0 :         nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, proto);
     552             : 
     553           0 :         return nb_cli_apply_changes(vty, NULL);
     554             : }
     555             : 
     556           0 : DEFPY_YANG(
     557             :         no_match_source_protocol, no_match_source_protocol_cmd,
     558             :         "no match source-protocol [" FRR_REDIST_STR_ZEBRA "]",
     559             :         NO_STR
     560             :         MATCH_STR
     561             :         "Match protocol via which the route was learnt\n"
     562             :         FRR_REDIST_HELP_STR_ZEBRA)
     563             : {
     564           0 :         const char *xpath =
     565             :                 "./match-condition[condition='frr-zebra-route-map:source-protocol']";
     566             : 
     567           0 :         nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
     568             : 
     569           0 :         return nb_cli_apply_changes(vty, NULL);
     570             : }
     571             : 
     572           0 : DEFPY_YANG(
     573             :         match_source_instance, match_source_instance_cmd,
     574             :         "match source-instance (0-255)$instance",
     575             :         MATCH_STR
     576             :         "Match the protocol's instance number\n"
     577             :         "The instance number\n")
     578             : {
     579           0 :         const char *xpath =
     580             :                 "./match-condition[condition='frr-zebra-route-map:source-instance']";
     581           0 :         char xpath_value[XPATH_MAXLEN];
     582             : 
     583           0 :         nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
     584           0 :         snprintf(xpath_value, sizeof(xpath_value),
     585             :                  "%s/rmap-match-condition/frr-zebra-route-map:source-instance",
     586             :                  xpath);
     587           0 :         nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, instance_str);
     588             : 
     589           0 :         return nb_cli_apply_changes(vty, NULL);
     590             : }
     591             : 
     592           0 : DEFPY_YANG(
     593             :         no_match_source_instance, no_match_source_instance_cmd,
     594             :         "no match source-instance [(0-255)]",
     595             :         NO_STR MATCH_STR
     596             :         "Match the protocol's instance number\n"
     597             :         "The instance number\n")
     598             : {
     599           0 :         const char *xpath =
     600             :                 "./match-condition[condition='frr-zebra-route-map:source-instance']";
     601             : 
     602           0 :         nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
     603             : 
     604           0 :         return nb_cli_apply_changes(vty, NULL);
     605             : }
     606             : 
     607             : /* set functions */
     608             : 
     609           0 : DEFPY_YANG(
     610             :         set_src, set_src_cmd,
     611             :         "set src <A.B.C.D$addrv4|X:X::X:X$addrv6>",
     612             :         SET_STR
     613             :         "src address for route\n"
     614             :         "IPv4 src address\n"
     615             :         "IPv6 src address\n")
     616             : {
     617           0 :         const char *xpath =
     618             :                 "./set-action[action='frr-zebra-route-map:src-address']";
     619           0 :         char xpath_value[XPATH_MAXLEN];
     620             : 
     621           0 :         nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
     622           0 :         if (addrv4_str) {
     623           0 :                 snprintf(
     624             :                         xpath_value, sizeof(xpath_value),
     625             :                         "%s/rmap-set-action/frr-zebra-route-map:ipv4-src-address",
     626             :                         xpath);
     627           0 :                 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
     628             :                                       addrv4_str);
     629             :         } else {
     630           0 :                 snprintf(
     631             :                         xpath_value, sizeof(xpath_value),
     632             :                         "%s/rmap-set-action/frr-zebra-route-map:ipv6-src-address",
     633             :                         xpath);
     634           0 :                 nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
     635             :                                       addrv6_str);
     636             :         }
     637             : 
     638           0 :         return nb_cli_apply_changes(vty, NULL);
     639             : }
     640             : 
     641           0 : DEFPY_YANG(
     642             :         no_set_src, no_set_src_cmd,
     643             :         "no set src [<A.B.C.D|X:X::X:X>]",
     644             :         NO_STR
     645             :         SET_STR
     646             :         "Source address for route\n"
     647             :         "IPv4 address\n"
     648             :         "IPv6 address\n")
     649             : {
     650           0 :         const char *xpath =
     651             :                 "./set-action[action='frr-zebra-route-map:src-address']";
     652             : 
     653           0 :         nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
     654             : 
     655           0 :         return nb_cli_apply_changes(vty, NULL);
     656             : }
     657             : 
     658           0 : DEFUN_YANG (zebra_route_map_timer,
     659             :        zebra_route_map_timer_cmd,
     660             :        "zebra route-map delay-timer (0-600)",
     661             :        ZEBRA_STR
     662             :        "Set route-map parameters\n"
     663             :        "Time to wait before route-map updates are processed\n"
     664             :        "0 means route-map changes are run immediately instead of delaying\n")
     665             : {
     666           0 :         int idx_number = 3;
     667           0 :         uint32_t rmap_delay_timer;
     668             : 
     669           0 :         rmap_delay_timer = strtoul(argv[idx_number]->arg, NULL, 10);
     670           0 :         zebra_route_map_set_delay_timer(rmap_delay_timer);
     671             : 
     672           0 :         return (CMD_SUCCESS);
     673             : }
     674             : 
     675           0 : DEFUN_YANG (no_zebra_route_map_timer,
     676             :        no_zebra_route_map_timer_cmd,
     677             :        "no zebra route-map delay-timer [(0-600)]",
     678             :        NO_STR
     679             :        ZEBRA_STR
     680             :        "Set route-map parameters\n"
     681             :        "Reset delay-timer to default value, 30 secs\n"
     682             :        "0 means route-map changes are run immediately instead of delaying\n")
     683             : {
     684           0 :         zebra_route_map_set_delay_timer(ZEBRA_RMAP_DEFAULT_UPDATE_TIMER);
     685             : 
     686           0 :         return (CMD_SUCCESS);
     687             : }
     688             : 
     689           0 : DEFPY_YANG (ip_protocol,
     690             :        ip_protocol_cmd,
     691             :        "ip protocol " FRR_IP_PROTOCOL_MAP_STR_ZEBRA
     692             :        " $proto route-map ROUTE-MAP$rmap",
     693             :        IP_STR
     694             :        "Filter routing info exchanged between zebra and protocol\n"
     695             :        FRR_IP_PROTOCOL_MAP_HELP_STR_ZEBRA
     696             :        "Specify route-map\n"
     697             :        "Route map name\n")
     698             : {
     699           0 :         int ret, rtype;
     700             : 
     701           0 :         assert(proto);
     702           0 :         assert(rmap);
     703             : 
     704           0 :         ZEBRA_DECLVAR_CONTEXT_VRF(vrf, zvrf);
     705             : 
     706           0 :         if (!zvrf)
     707             :                 return CMD_WARNING;
     708             : 
     709           0 :         if (strcasecmp(proto, "any") == 0)
     710             :                 rtype = ZEBRA_ROUTE_MAX;
     711             :         else
     712           0 :                 rtype = proto_name2num(proto);
     713           0 :         if (rtype < 0) {
     714           0 :                 vty_out(vty, "invalid protocol name \"%s\"\n", proto);
     715           0 :                 return CMD_WARNING_CONFIG_FAILED;
     716             :         }
     717             : 
     718           0 :         ret = ip_protocol_rm_add(zvrf, rmap, rtype, AFI_IP, SAFI_UNICAST);
     719             : 
     720           0 :         return ret;
     721             : }
     722             : 
     723           0 : DEFPY_YANG (no_ip_protocol,
     724             :        no_ip_protocol_cmd,
     725             :        "no ip protocol " FRR_IP_PROTOCOL_MAP_STR_ZEBRA
     726             :        " $proto [route-map ROUTE-MAP$rmap]",
     727             :        NO_STR
     728             :        IP_STR
     729             :        "Stop filtering routing info between zebra and protocol\n"
     730             :        FRR_IP_PROTOCOL_MAP_HELP_STR_ZEBRA
     731             :        "Specify route-map\n"
     732             :        "Route map name\n")
     733             : {
     734           0 :         int ret, rtype;
     735             : 
     736           0 :         assert(proto);
     737             : 
     738           0 :         ZEBRA_DECLVAR_CONTEXT_VRF(vrf, zvrf);
     739             : 
     740           0 :         if (!zvrf)
     741             :                 return CMD_WARNING;
     742             : 
     743           0 :         if (strcasecmp(proto, "any") == 0)
     744             :                 rtype = ZEBRA_ROUTE_MAX;
     745             :         else
     746           0 :                 rtype = proto_name2num(proto);
     747           0 :         if (rtype < 0) {
     748           0 :                 vty_out(vty, "invalid protocol name \"%s\"\n", proto);
     749           0 :                 return CMD_WARNING_CONFIG_FAILED;
     750             :         }
     751             : 
     752           0 :         ret = ip_protocol_rm_del(zvrf, rmap, rtype, AFI_IP, SAFI_UNICAST);
     753             : 
     754           0 :         return ret;
     755             : }
     756             : 
     757           0 : DEFPY_YANG (show_ip_protocol,
     758             :        show_ip_protocol_cmd,
     759             :        "show ip protocol [vrf <NAME$vrf_name|all$vrf_all>]",
     760             :        SHOW_STR
     761             :        IP_STR
     762             :        "IP protocol filtering status\n"
     763             :        VRF_FULL_CMD_HELP_STR)
     764             : {
     765           0 :         int ret = show_proto_rm(vty, AFI_IP, vrf_all, vrf_name);
     766             : 
     767           0 :         return ret;
     768             : }
     769             : 
     770           0 : DEFPY_YANG (ipv6_protocol,
     771             :        ipv6_protocol_cmd,
     772             :        "ipv6 protocol " FRR_IP6_PROTOCOL_MAP_STR_ZEBRA
     773             :        " $proto route-map ROUTE-MAP$rmap",
     774             :        IP6_STR
     775             :        "Filter IPv6 routing info exchanged between zebra and protocol\n"
     776             :        FRR_IP6_PROTOCOL_MAP_HELP_STR_ZEBRA
     777             :        "Specify route-map\n"
     778             :        "Route map name\n")
     779             : {
     780           0 :         int ret, rtype;
     781             : 
     782           0 :         assert(rmap);
     783           0 :         assert(proto);
     784             : 
     785           0 :         ZEBRA_DECLVAR_CONTEXT_VRF(vrf, zvrf);
     786             : 
     787           0 :         if (!zvrf)
     788             :                 return CMD_WARNING;
     789             : 
     790           0 :         if (strcasecmp(proto, "any") == 0)
     791             :                 rtype = ZEBRA_ROUTE_MAX;
     792             :         else
     793           0 :                 rtype = proto_name2num(proto);
     794           0 :         if (rtype < 0) {
     795           0 :                 vty_out(vty, "invalid protocol name \"%s\"\n", proto);
     796           0 :                 return CMD_WARNING_CONFIG_FAILED;
     797             :         }
     798             : 
     799           0 :         ret = ip_protocol_rm_add(zvrf, rmap, rtype, AFI_IP6, SAFI_UNICAST);
     800             : 
     801           0 :         return ret;
     802             : }
     803             : 
     804           0 : DEFPY_YANG (no_ipv6_protocol,
     805             :        no_ipv6_protocol_cmd,
     806             :        "no ipv6 protocol " FRR_IP6_PROTOCOL_MAP_STR_ZEBRA
     807             :        " $proto [route-map ROUTE-MAP$rmap]",
     808             :        NO_STR
     809             :        IP6_STR
     810             :        "Stop filtering IPv6 routing info between zebra and protocol\n"
     811             :        FRR_IP6_PROTOCOL_MAP_HELP_STR_ZEBRA
     812             :        "Specify route-map\n"
     813             :        "Route map name\n")
     814             : {
     815           0 :         int ret, rtype;
     816             : 
     817           0 :         assert(proto);
     818             : 
     819           0 :         ZEBRA_DECLVAR_CONTEXT_VRF(vrf, zvrf);
     820             : 
     821           0 :         if (!zvrf)
     822             :                 return CMD_WARNING;
     823             : 
     824           0 :         if (strcasecmp(proto, "any") == 0)
     825             :                 rtype = ZEBRA_ROUTE_MAX;
     826             :         else
     827           0 :                 rtype = proto_name2num(proto);
     828           0 :         if (rtype < 0) {
     829           0 :                 vty_out(vty, "invalid protocol name \"%s\"\n", proto);
     830           0 :                 return CMD_WARNING_CONFIG_FAILED;
     831             :         }
     832             : 
     833           0 :         ret = ip_protocol_rm_del(zvrf, rmap, rtype, AFI_IP6, SAFI_UNICAST);
     834             : 
     835           0 :         return ret;
     836             : }
     837             : 
     838           0 : DEFPY_YANG (show_ipv6_protocol,
     839             :        show_ipv6_protocol_cmd,
     840             :        "show ipv6 protocol [vrf <NAME$vrf_name|all$vrf_all>]",
     841             :        SHOW_STR
     842             :        IP6_STR
     843             :        "IPv6 protocol filtering status\n"
     844             :        VRF_FULL_CMD_HELP_STR)
     845             : {
     846           0 :         int ret = show_proto_rm(vty, AFI_IP6, vrf_all, vrf_name);
     847             : 
     848           0 :         return ret;
     849             : }
     850             : 
     851           0 : DEFPY_YANG (ip_protocol_nht_rmap,
     852             :        ip_protocol_nht_rmap_cmd,
     853             :        "ip nht " FRR_IP_PROTOCOL_MAP_STR_ZEBRA
     854             :        " $proto route-map ROUTE-MAP$rmap",
     855             :        IP_STR
     856             :        "Filter Next Hop tracking route resolution\n"
     857             :        FRR_IP_PROTOCOL_MAP_HELP_STR_ZEBRA
     858             :        "Specify route map\n"
     859             :        "Route map name\n")
     860             : {
     861             : 
     862           0 :         int ret, rtype;
     863             : 
     864           0 :         assert(proto);
     865           0 :         assert(rmap);
     866             : 
     867           0 :         ZEBRA_DECLVAR_CONTEXT_VRF(vrf, zvrf);
     868             : 
     869           0 :         if (!zvrf)
     870             :                 return CMD_WARNING;
     871             : 
     872           0 :         if (strcasecmp(proto, "any") == 0)
     873             :                 rtype = ZEBRA_ROUTE_MAX;
     874             :         else
     875           0 :                 rtype = proto_name2num(proto);
     876           0 :         if (rtype < 0) {
     877           0 :                 vty_out(vty, "invalid protocol name \"%s\"\n", proto);
     878           0 :                 return CMD_WARNING_CONFIG_FAILED;
     879             :         }
     880             : 
     881           0 :         ret = ip_nht_rm_add(zvrf, rmap, rtype, AFI_IP);
     882             : 
     883           0 :         return ret;
     884             : }
     885             : 
     886           0 : DEFPY_YANG (no_ip_protocol_nht_rmap,
     887             :        no_ip_protocol_nht_rmap_cmd,
     888             :        "no ip nht " FRR_IP_PROTOCOL_MAP_STR_ZEBRA
     889             :        " $proto route-map [ROUTE-MAP$rmap]",
     890             :        NO_STR
     891             :        IP_STR
     892             :        "Filter Next Hop tracking route resolution\n"
     893             :        FRR_IP_PROTOCOL_MAP_HELP_STR_ZEBRA
     894             :        "Specify route map\n"
     895             :        "Route map name\n")
     896             : {
     897           0 :         int ret, rtype;
     898             : 
     899           0 :         assert(proto);
     900             : 
     901           0 :         ZEBRA_DECLVAR_CONTEXT_VRF(vrf, zvrf);
     902             : 
     903           0 :         if (!zvrf)
     904             :                 return CMD_WARNING;
     905             : 
     906           0 :         if (strcasecmp(proto, "any") == 0)
     907             :                 rtype = ZEBRA_ROUTE_MAX;
     908             :         else
     909           0 :                 rtype = proto_name2num(proto);
     910           0 :         if (rtype < 0) {
     911           0 :                 vty_out(vty, "invalid protocol name \"%s\"\n", proto);
     912           0 :                 return CMD_WARNING_CONFIG_FAILED;
     913             :         }
     914             : 
     915           0 :         ret = ip_nht_rm_del(zvrf, rmap, rtype, AFI_IP);
     916             : 
     917           0 :         return ret;
     918             : }
     919             : 
     920           0 : DEFPY_YANG (show_ip_protocol_nht,
     921             :        show_ip_protocol_nht_cmd,
     922             :        "show ip nht route-map [vrf <NAME$vrf_name|all$vrf_all>] [json]",
     923             :        SHOW_STR
     924             :        IP_STR
     925             :        "IPv4 nexthop tracking table\n"
     926             :        "IPv4 Next Hop tracking filtering status\n"
     927             :        VRF_CMD_HELP_STR
     928             :        "All VRFs\n"
     929             :        JSON_STR)
     930             : {
     931           0 :         int ret;
     932           0 :         bool uj = use_json(argc, argv);
     933             : 
     934           0 :         ret = show_nht_rm(vty, AFI_IP, vrf_all, vrf_name, uj);
     935             : 
     936           0 :         return ret;
     937             : }
     938             : 
     939           0 : DEFPY_YANG (ipv6_protocol_nht_rmap,
     940             :        ipv6_protocol_nht_rmap_cmd,
     941             :        "ipv6 nht " FRR_IP6_PROTOCOL_MAP_STR_ZEBRA
     942             :        " $proto route-map ROUTE-MAP$rmap",
     943             :        IP6_STR
     944             :        "Filter Next Hop tracking route resolution\n"
     945             :        FRR_IP6_PROTOCOL_MAP_HELP_STR_ZEBRA
     946             :        "Specify route map\n"
     947             :        "Route map name\n")
     948             : {
     949           0 :         int ret, rtype;
     950             : 
     951           0 :         assert(rmap);
     952           0 :         assert(proto);
     953             : 
     954           0 :         ZEBRA_DECLVAR_CONTEXT_VRF(vrf, zvrf);
     955             : 
     956           0 :         if (!zvrf)
     957             :                 return CMD_WARNING;
     958             : 
     959           0 :         if (strcasecmp(proto, "any") == 0)
     960             :                 rtype = ZEBRA_ROUTE_MAX;
     961             :         else
     962           0 :                 rtype = proto_name2num(proto);
     963           0 :         if (rtype < 0) {
     964           0 :                 vty_out(vty, "invalid protocol name \"%s\"\n", proto);
     965           0 :                 return CMD_WARNING_CONFIG_FAILED;
     966             :         }
     967             : 
     968           0 :         ret = ip_nht_rm_add(zvrf, rmap, rtype, AFI_IP6);
     969             : 
     970           0 :         return ret;
     971             : }
     972             : 
     973           0 : DEFPY_YANG (no_ipv6_protocol_nht_rmap,
     974             :        no_ipv6_protocol_nht_rmap_cmd,
     975             :        "no ipv6 nht " FRR_IP6_PROTOCOL_MAP_STR_ZEBRA
     976             :        " $proto [route-map ROUTE-MAP$rmap]",
     977             :        NO_STR
     978             :        IP6_STR
     979             :        "Filter Next Hop tracking route resolution\n"
     980             :        FRR_IP6_PROTOCOL_MAP_HELP_STR_ZEBRA
     981             :        "Specify route map\n"
     982             :        "Route map name\n")
     983             : {
     984           0 :         int ret, rtype;
     985             : 
     986           0 :         assert(proto);
     987             : 
     988           0 :         ZEBRA_DECLVAR_CONTEXT_VRF(vrf, zvrf);
     989             : 
     990           0 :         if (!zvrf)
     991             :                 return CMD_WARNING;
     992             : 
     993           0 :         if (strcasecmp(proto, "any") == 0)
     994             :                 rtype = ZEBRA_ROUTE_MAX;
     995             :         else
     996           0 :                 rtype = proto_name2num(proto);
     997           0 :         if (rtype < 0) {
     998           0 :                 vty_out(vty, "invalid protocol name \"%s\"\n", proto);
     999           0 :                 return CMD_WARNING_CONFIG_FAILED;
    1000             :         }
    1001             : 
    1002           0 :         ret = ip_nht_rm_del(zvrf, rmap, rtype, AFI_IP6);
    1003             : 
    1004           0 :         return ret;
    1005             : }
    1006             : 
    1007           0 : DEFPY_YANG (show_ipv6_protocol_nht,
    1008             :        show_ipv6_protocol_nht_cmd,
    1009             :        "show ipv6 nht route-map [vrf <NAME$vrf_name|all$vrf_all>] [json]",
    1010             :        SHOW_STR
    1011             :        IP6_STR
    1012             :        "IPv6 nexthop tracking table\n"
    1013             :        "IPv6 Next Hop tracking filtering status\n"
    1014             :        VRF_CMD_HELP_STR
    1015             :        "All VRFs\n"
    1016             :        JSON_STR)
    1017             : {
    1018           0 :         int ret;
    1019           0 :         bool uj = use_json(argc, argv);
    1020             : 
    1021           0 :         ret = show_nht_rm(vty, AFI_IP6, vrf_all, vrf_name, uj);
    1022             : 
    1023           0 :         return ret;
    1024             : }
    1025             : 
    1026             : /*XXXXXXXXXXXXXXXXXXXXXXXXXXXX*/
    1027             : 
    1028             : /* `match ip next-hop IP_ACCESS_LIST' */
    1029             : 
    1030             : /* Match function return 1 if match is success else return zero. */
    1031             : static enum route_map_cmd_result_t
    1032           0 : route_match_ip_next_hop(void *rule, const struct prefix *prefix, void *object)
    1033             : {
    1034           0 :         struct access_list *alist;
    1035           0 :         struct nh_rmap_obj *nh_data;
    1036           0 :         struct prefix_ipv4 p;
    1037             : 
    1038           0 :         nh_data = object;
    1039           0 :         if (!nh_data)
    1040             :                 return RMAP_NOMATCH;
    1041             : 
    1042           0 :         switch (nh_data->nexthop->type) {
    1043             :         case NEXTHOP_TYPE_IFINDEX:
    1044             :                 /* Interface routes can't match ip next-hop */
    1045             :                 return RMAP_NOMATCH;
    1046           0 :         case NEXTHOP_TYPE_IPV4_IFINDEX:
    1047             :         case NEXTHOP_TYPE_IPV4:
    1048           0 :                 p.family = AF_INET;
    1049           0 :                 p.prefix = nh_data->nexthop->gate.ipv4;
    1050           0 :                 p.prefixlen = IPV4_MAX_BITLEN;
    1051           0 :                 break;
    1052             :         case NEXTHOP_TYPE_IPV6:
    1053             :         case NEXTHOP_TYPE_IPV6_IFINDEX:
    1054             :         case NEXTHOP_TYPE_BLACKHOLE:
    1055             :                 return RMAP_NOMATCH;
    1056             :         }
    1057           0 :         alist = access_list_lookup(AFI_IP, (char *)rule);
    1058           0 :         if (alist == NULL)
    1059             :                 return RMAP_NOMATCH;
    1060             : 
    1061           0 :         return (access_list_apply(alist, &p) == FILTER_DENY ? RMAP_NOMATCH
    1062           0 :                                                             : RMAP_MATCH);
    1063             : }
    1064             : 
    1065             : /* Route map `ip next-hop' match statement.  `arg' should be
    1066             :    access-list name. */
    1067           0 : static void *route_match_ip_next_hop_compile(const char *arg)
    1068             : {
    1069           0 :         return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
    1070             : }
    1071             : 
    1072             : /* Free route map's compiled `. */
    1073           0 : static void route_match_ip_next_hop_free(void *rule)
    1074             : {
    1075           0 :         XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
    1076           0 : }
    1077             : 
    1078             : /* Route map commands for ip next-hop matching. */
    1079             : static const struct route_map_rule_cmd route_match_ip_next_hop_cmd = {
    1080             :         "ip next-hop",
    1081             :         route_match_ip_next_hop,
    1082             :         route_match_ip_next_hop_compile,
    1083             :         route_match_ip_next_hop_free
    1084             : };
    1085             : 
    1086             : /* `match ip next-hop prefix-list PREFIX_LIST' */
    1087             : 
    1088             : static enum route_map_cmd_result_t
    1089           0 : route_match_ip_next_hop_prefix_list(void *rule, const struct prefix *prefix,
    1090             :                                     void *object)
    1091             : {
    1092           0 :         struct prefix_list *plist;
    1093           0 :         struct nh_rmap_obj *nh_data;
    1094           0 :         struct prefix_ipv4 p;
    1095             : 
    1096           0 :         nh_data = (struct nh_rmap_obj *)object;
    1097           0 :         if (!nh_data)
    1098             :                 return RMAP_NOMATCH;
    1099             : 
    1100           0 :         switch (nh_data->nexthop->type) {
    1101             :         case NEXTHOP_TYPE_IFINDEX:
    1102             :                 /* Interface routes can't match ip next-hop */
    1103             :                 return RMAP_NOMATCH;
    1104           0 :         case NEXTHOP_TYPE_IPV4_IFINDEX:
    1105             :         case NEXTHOP_TYPE_IPV4:
    1106           0 :                 p.family = AF_INET;
    1107           0 :                 p.prefix = nh_data->nexthop->gate.ipv4;
    1108           0 :                 p.prefixlen = IPV4_MAX_BITLEN;
    1109           0 :                 break;
    1110             :         case NEXTHOP_TYPE_IPV6:
    1111             :         case NEXTHOP_TYPE_IPV6_IFINDEX:
    1112             :         case NEXTHOP_TYPE_BLACKHOLE:
    1113             :                 return RMAP_NOMATCH;
    1114             :         }
    1115           0 :         plist = prefix_list_lookup(AFI_IP, (char *)rule);
    1116           0 :         if (plist == NULL)
    1117             :                 return RMAP_NOMATCH;
    1118             : 
    1119           0 :         return (prefix_list_apply(plist, &p) == PREFIX_DENY ? RMAP_NOMATCH
    1120           0 :                                                             : RMAP_MATCH);
    1121             : }
    1122             : 
    1123           0 : static void *route_match_ip_next_hop_prefix_list_compile(const char *arg)
    1124             : {
    1125           0 :         return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
    1126             : }
    1127             : 
    1128           0 : static void route_match_ip_next_hop_prefix_list_free(void *rule)
    1129             : {
    1130           0 :         XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
    1131           0 : }
    1132             : 
    1133             : static const struct route_map_rule_cmd
    1134             :                 route_match_ip_next_hop_prefix_list_cmd = {
    1135             :         "ip next-hop prefix-list",
    1136             :         route_match_ip_next_hop_prefix_list,
    1137             :         route_match_ip_next_hop_prefix_list_compile,
    1138             :         route_match_ip_next_hop_prefix_list_free
    1139             : };
    1140             : 
    1141             : /* `match ip address IP_ACCESS_LIST' */
    1142             : 
    1143             : /* Match function should return 1 if match is success else return
    1144             :    zero. */
    1145             : static enum route_map_cmd_result_t
    1146           0 : route_match_address(afi_t afi, void *rule, const struct prefix *prefix,
    1147             :                     void *object)
    1148             : {
    1149           0 :         struct access_list *alist;
    1150             : 
    1151           0 :         alist = access_list_lookup(afi, (char *)rule);
    1152           0 :         if (alist == NULL)
    1153             :                 return RMAP_NOMATCH;
    1154             : 
    1155           0 :         return (access_list_apply(alist, prefix) == FILTER_DENY ? RMAP_NOMATCH
    1156           0 :                                                                 : RMAP_MATCH);
    1157             : }
    1158             : 
    1159             : static enum route_map_cmd_result_t
    1160           0 : route_match_ip_address(void *rule, const struct prefix *prefix, void *object)
    1161             : {
    1162           0 :         return route_match_address(AFI_IP, rule, prefix, object);
    1163             : }
    1164             : 
    1165             : static enum route_map_cmd_result_t
    1166           0 : route_match_ipv6_address(void *rule, const struct prefix *prefix, void *object)
    1167             : {
    1168           0 :         return route_match_address(AFI_IP6, rule, prefix, object);
    1169             : }
    1170             : 
    1171             : /* Route map `ip address' match statement.  `arg' should be
    1172             :    access-list name. */
    1173           0 : static void *route_match_address_compile(const char *arg)
    1174             : {
    1175           0 :         return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
    1176             : }
    1177             : 
    1178             : /* Free route map's compiled `ip address' value. */
    1179           0 : static void route_match_address_free(void *rule)
    1180             : {
    1181           0 :         XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
    1182           0 : }
    1183             : 
    1184             : /* Route map commands for ip address matching. */
    1185             : static const struct route_map_rule_cmd route_match_ip_address_cmd = {
    1186             :         "ip address",
    1187             :         route_match_ip_address,
    1188             :         route_match_address_compile,
    1189             :         route_match_address_free
    1190             : };
    1191             : 
    1192             : /* Route map commands for ipv6 address matching. */
    1193             : static const struct route_map_rule_cmd route_match_ipv6_address_cmd = {
    1194             :         "ipv6 address",
    1195             :         route_match_ipv6_address,
    1196             :         route_match_address_compile,
    1197             :         route_match_address_free
    1198             : };
    1199             : 
    1200             : /* `match ip address prefix-list PREFIX_LIST' */
    1201             : 
    1202             : static enum route_map_cmd_result_t
    1203           0 : route_match_address_prefix_list(void *rule, const struct prefix *prefix,
    1204             :                                 void *object, afi_t afi)
    1205             : {
    1206           0 :         struct prefix_list *plist;
    1207             : 
    1208           0 :         plist = prefix_list_lookup(afi, (char *)rule);
    1209           0 :         if (plist == NULL)
    1210             :                 return RMAP_NOMATCH;
    1211             : 
    1212           0 :         return (prefix_list_apply(plist, prefix) == PREFIX_DENY ? RMAP_NOMATCH
    1213           0 :                                                                 : RMAP_MATCH);
    1214             : }
    1215             : 
    1216             : static enum route_map_cmd_result_t
    1217           0 : route_match_ip_address_prefix_list(void *rule, const struct prefix *prefix,
    1218             :                                    void *object)
    1219             : {
    1220           0 :         return (route_match_address_prefix_list(rule, prefix, object, AFI_IP));
    1221             : }
    1222             : 
    1223           0 : static void *route_match_address_prefix_list_compile(const char *arg)
    1224             : {
    1225           0 :         return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
    1226             : }
    1227             : 
    1228           0 : static void route_match_address_prefix_list_free(void *rule)
    1229             : {
    1230           0 :         XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
    1231           0 : }
    1232             : 
    1233             : static const struct route_map_rule_cmd
    1234             :                 route_match_ip_address_prefix_list_cmd = {
    1235             :         "ip address prefix-list",
    1236             :         route_match_ip_address_prefix_list,
    1237             :         route_match_address_prefix_list_compile,
    1238             :         route_match_address_prefix_list_free
    1239             : };
    1240             : 
    1241             : static enum route_map_cmd_result_t
    1242           0 : route_match_ipv6_address_prefix_list(void *rule, const struct prefix *prefix,
    1243             :                                      void *object)
    1244             : {
    1245           0 :         return (route_match_address_prefix_list(rule, prefix, object, AFI_IP6));
    1246             : }
    1247             : 
    1248             : static const struct route_map_rule_cmd
    1249             :                 route_match_ipv6_address_prefix_list_cmd = {
    1250             :         "ipv6 address prefix-list",
    1251             :         route_match_ipv6_address_prefix_list,
    1252             :         route_match_address_prefix_list_compile,
    1253             :         route_match_address_prefix_list_free
    1254             : };
    1255             : 
    1256             : /* `match ipv6 next-hop type <TYPE>' */
    1257             : 
    1258             : static enum route_map_cmd_result_t
    1259           0 : route_match_ipv6_next_hop_type(void *rule, const struct prefix *prefix,
    1260             :                                void *object)
    1261             : {
    1262           0 :         struct nh_rmap_obj *nh_data;
    1263             : 
    1264           0 :         if (prefix->family == AF_INET6) {
    1265           0 :                 nh_data = (struct nh_rmap_obj *)object;
    1266           0 :                 if (!nh_data)
    1267             :                         return RMAP_NOMATCH;
    1268             : 
    1269           0 :                 if (nh_data->nexthop->type == NEXTHOP_TYPE_BLACKHOLE)
    1270           0 :                         return RMAP_MATCH;
    1271             :         }
    1272             : 
    1273             :         return RMAP_NOMATCH;
    1274             : }
    1275             : 
    1276           0 : static void *route_match_ipv6_next_hop_type_compile(const char *arg)
    1277             : {
    1278           0 :         return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
    1279             : }
    1280             : 
    1281           0 : static void route_match_ipv6_next_hop_type_free(void *rule)
    1282             : {
    1283           0 :         XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
    1284           0 : }
    1285             : 
    1286             : static const struct route_map_rule_cmd
    1287             :                 route_match_ipv6_next_hop_type_cmd = {
    1288             :         "ipv6 next-hop type",
    1289             :         route_match_ipv6_next_hop_type,
    1290             :         route_match_ipv6_next_hop_type_compile,
    1291             :         route_match_ipv6_next_hop_type_free
    1292             : };
    1293             : 
    1294             : /* `match ip address prefix-len PREFIXLEN' */
    1295             : 
    1296             : static enum route_map_cmd_result_t
    1297           0 : route_match_address_prefix_len(void *rule, const struct prefix *prefix,
    1298             :                                void *object)
    1299             : {
    1300           0 :         uint32_t *prefixlen = (uint32_t *)rule;
    1301             : 
    1302           0 :         return ((prefix->prefixlen == *prefixlen) ? RMAP_MATCH : RMAP_NOMATCH);
    1303             : }
    1304             : 
    1305           0 : static void *route_match_address_prefix_len_compile(const char *arg)
    1306             : {
    1307           0 :         uint32_t *prefix_len;
    1308           0 :         char *endptr = NULL;
    1309           0 :         unsigned long tmpval;
    1310             : 
    1311             :         /* prefix len value shoud be integer. */
    1312           0 :         if (!all_digit(arg))
    1313             :                 return NULL;
    1314             : 
    1315           0 :         errno = 0;
    1316           0 :         tmpval = strtoul(arg, &endptr, 10);
    1317           0 :         if (*endptr != '\0' || errno || tmpval > UINT32_MAX)
    1318             :                 return NULL;
    1319             : 
    1320           0 :         prefix_len = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(uint32_t));
    1321             : 
    1322           0 :         *prefix_len = tmpval;
    1323           0 :         return prefix_len;
    1324             : }
    1325             : 
    1326           0 : static void route_match_address_prefix_len_free(void *rule)
    1327             : {
    1328           0 :         XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
    1329           0 : }
    1330             : 
    1331             : static const struct route_map_rule_cmd
    1332             :                 route_match_ip_address_prefix_len_cmd = {
    1333             :         "ip address prefix-len",
    1334             :         route_match_address_prefix_len,
    1335             :         route_match_address_prefix_len_compile,
    1336             :         route_match_address_prefix_len_free
    1337             : };
    1338             : 
    1339             : static const struct route_map_rule_cmd
    1340             :                 route_match_ipv6_address_prefix_len_cmd = {
    1341             :         "ipv6 address prefix-len",
    1342             :         route_match_address_prefix_len,
    1343             :         route_match_address_prefix_len_compile,
    1344             :         route_match_address_prefix_len_free
    1345             : };
    1346             : 
    1347             : /* `match ip nexthop prefix-len PREFIXLEN' */
    1348             : 
    1349             : static enum route_map_cmd_result_t
    1350           0 : route_match_ip_nexthop_prefix_len(void *rule, const struct prefix *prefix,
    1351             :                                   void *object)
    1352             : {
    1353           0 :         uint32_t *prefixlen = (uint32_t *)rule;
    1354           0 :         struct nh_rmap_obj *nh_data;
    1355           0 :         struct prefix_ipv4 p;
    1356             : 
    1357           0 :         nh_data = (struct nh_rmap_obj *)object;
    1358           0 :         if (!nh_data || !nh_data->nexthop)
    1359             :                 return RMAP_NOMATCH;
    1360             : 
    1361           0 :         switch (nh_data->nexthop->type) {
    1362             :         case NEXTHOP_TYPE_IFINDEX:
    1363             :                 /* Interface routes can't match ip next-hop */
    1364             :                 return RMAP_NOMATCH;
    1365             :         case NEXTHOP_TYPE_IPV4_IFINDEX:
    1366             :         case NEXTHOP_TYPE_IPV4:
    1367             :                 p.family = AF_INET;
    1368             :                 p.prefix = nh_data->nexthop->gate.ipv4;
    1369           0 :                 p.prefixlen = IPV4_MAX_BITLEN;
    1370             :                 break;
    1371             :         case NEXTHOP_TYPE_IPV6:
    1372             :         case NEXTHOP_TYPE_IPV6_IFINDEX:
    1373             :         case NEXTHOP_TYPE_BLACKHOLE:
    1374             :                 return RMAP_NOMATCH;
    1375             :         }
    1376           0 :         return ((p.prefixlen == *prefixlen) ? RMAP_MATCH : RMAP_NOMATCH);
    1377             : }
    1378             : 
    1379             : static const struct route_map_rule_cmd
    1380             :                 route_match_ip_nexthop_prefix_len_cmd = {
    1381             :         "ip next-hop prefix-len",
    1382             :         route_match_ip_nexthop_prefix_len,
    1383             :         route_match_address_prefix_len_compile, /* reuse */
    1384             :         route_match_address_prefix_len_free     /* reuse */
    1385             : };
    1386             : 
    1387             : /* `match ip next-hop type <blackhole>' */
    1388             : 
    1389             : static enum route_map_cmd_result_t
    1390           0 : route_match_ip_next_hop_type(void *rule, const struct prefix *prefix,
    1391             :                              void *object)
    1392             : {
    1393           0 :         struct nh_rmap_obj *nh_data;
    1394             : 
    1395           0 :         if (prefix->family == AF_INET) {
    1396           0 :                 nh_data = (struct nh_rmap_obj *)object;
    1397           0 :                 if (!nh_data)
    1398             :                         return RMAP_NOMATCH;
    1399             : 
    1400           0 :                 if (nh_data->nexthop->type == NEXTHOP_TYPE_BLACKHOLE)
    1401           0 :                         return RMAP_MATCH;
    1402             :         }
    1403             : 
    1404             :         return RMAP_NOMATCH;
    1405             : }
    1406             : 
    1407           0 : static void *route_match_ip_next_hop_type_compile(const char *arg)
    1408             : {
    1409           0 :         return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
    1410             : }
    1411             : 
    1412           0 : static void route_match_ip_next_hop_type_free(void *rule)
    1413             : {
    1414           0 :         XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
    1415           0 : }
    1416             : 
    1417             : static const struct route_map_rule_cmd
    1418             :                 route_match_ip_next_hop_type_cmd = {
    1419             :         "ip next-hop type",
    1420             :         route_match_ip_next_hop_type,
    1421             :         route_match_ip_next_hop_type_compile,
    1422             :         route_match_ip_next_hop_type_free
    1423             : };
    1424             : 
    1425             : /* `match source-protocol PROTOCOL' */
    1426             : 
    1427             : static enum route_map_cmd_result_t
    1428           0 : route_match_source_protocol(void *rule, const struct prefix *p, void *object)
    1429             : {
    1430           0 :         uint32_t *rib_type = (uint32_t *)rule;
    1431           0 :         struct nh_rmap_obj *nh_data;
    1432             : 
    1433           0 :         nh_data = (struct nh_rmap_obj *)object;
    1434           0 :         if (!nh_data)
    1435             :                 return RMAP_NOMATCH;
    1436             : 
    1437           0 :         return ((nh_data->source_protocol == *rib_type) ? RMAP_MATCH
    1438           0 :                                                         : RMAP_NOMATCH);
    1439             : }
    1440             : 
    1441           0 : static void *route_match_source_protocol_compile(const char *arg)
    1442             : {
    1443           0 :         uint32_t *rib_type;
    1444           0 :         int i;
    1445             : 
    1446           0 :         i = proto_name2num(arg);
    1447           0 :         rib_type = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(uint32_t));
    1448             : 
    1449           0 :         *rib_type = i;
    1450             : 
    1451           0 :         return rib_type;
    1452             : }
    1453             : 
    1454           0 : static void route_match_source_protocol_free(void *rule)
    1455             : {
    1456           0 :         XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
    1457           0 : }
    1458             : 
    1459             : static const struct route_map_rule_cmd route_match_source_protocol_cmd = {
    1460             :         "source-protocol",
    1461             :         route_match_source_protocol,
    1462             :         route_match_source_protocol_compile,
    1463             :         route_match_source_protocol_free
    1464             : };
    1465             : 
    1466             : /* `source-instance` */
    1467             : static enum route_map_cmd_result_t
    1468           0 : route_match_source_instance(void *rule, const struct prefix *p, void *object)
    1469             : {
    1470           0 :         uint8_t *instance = (uint8_t *)rule;
    1471           0 :         struct nh_rmap_obj *nh_data;
    1472             : 
    1473           0 :         nh_data = (struct nh_rmap_obj *)object;
    1474           0 :         if (!nh_data)
    1475             :                 return RMAP_NOMATCH;
    1476             : 
    1477           0 :         return (nh_data->instance == *instance) ? RMAP_MATCH : RMAP_NOMATCH;
    1478             : }
    1479             : 
    1480           0 : static void *route_match_source_instance_compile(const char *arg)
    1481             : {
    1482           0 :         uint8_t *instance;
    1483           0 :         int i;
    1484             : 
    1485           0 :         i = atoi(arg);
    1486           0 :         instance = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(uint8_t));
    1487             : 
    1488           0 :         *instance = i;
    1489             : 
    1490           0 :         return instance;
    1491             : }
    1492             : 
    1493           0 : static void route_match_source_instance_free(void *rule)
    1494             : {
    1495           0 :         XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
    1496           0 : }
    1497             : 
    1498             : static const struct route_map_rule_cmd route_match_source_instance_cmd = {
    1499             :         "source-instance",
    1500             :         route_match_source_instance,
    1501             :         route_match_source_instance_compile,
    1502             :         route_match_source_instance_free
    1503             : };
    1504             : 
    1505             : /* `set src A.B.C.D' */
    1506             : 
    1507             : /* Set src. */
    1508             : static enum route_map_cmd_result_t
    1509           0 : route_set_src(void *rule, const struct prefix *prefix, void *object)
    1510             : {
    1511           0 :         struct nh_rmap_obj *nh_data;
    1512             : 
    1513           0 :         nh_data = (struct nh_rmap_obj *)object;
    1514           0 :         nh_data->nexthop->rmap_src = *(union g_addr *)rule;
    1515             : 
    1516           0 :         return RMAP_OKAY;
    1517             : }
    1518             : 
    1519             : /* set src compilation. */
    1520           0 : static void *route_set_src_compile(const char *arg)
    1521             : {
    1522           0 :         union g_addr src, *psrc;
    1523             : 
    1524           0 :         if ((inet_pton(AF_INET6, arg, &src.ipv6) == 1)
    1525           0 :             || (inet_pton(AF_INET, arg, &src.ipv4) == 1)) {
    1526           0 :                 psrc = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(union g_addr));
    1527           0 :                 *psrc = src;
    1528           0 :                 return psrc;
    1529             :         }
    1530             :         return NULL;
    1531             : }
    1532             : 
    1533             : /* Free route map's compiled `set src' value. */
    1534           0 : static void route_set_src_free(void *rule)
    1535             : {
    1536           0 :         XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
    1537           0 : }
    1538             : 
    1539             : /* Set src rule structure. */
    1540             : static const struct route_map_rule_cmd route_set_src_cmd = {
    1541             :         "src",
    1542             :         route_set_src,
    1543             :         route_set_src_compile,
    1544             :         route_set_src_free,
    1545             : };
    1546             : 
    1547             : /* The function checks if the changed routemap specified by parameter rmap
    1548             :  * matches the configured protocol routemaps in proto_rm table. If there is
    1549             :  * a match then rib_update_table() to process the routes.
    1550             :  */
    1551           0 : static void zebra_rib_table_rm_update(const char *rmap)
    1552             : {
    1553           0 :         int i = 0;
    1554           0 :         struct route_table *table;
    1555           0 :         struct vrf *vrf = NULL;
    1556           0 :         struct zebra_vrf *zvrf = NULL;
    1557           0 :         char *rmap_name;
    1558           0 :         struct route_map *old = NULL;
    1559             : 
    1560           0 :         RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
    1561           0 :                 zvrf = vrf->info;
    1562           0 :                 if (!zvrf)
    1563           0 :                         continue;
    1564           0 :                 for (i = 0; i <= ZEBRA_ROUTE_MAX; i++) {
    1565           0 :                         rmap_name = PROTO_RM_NAME(zvrf, AFI_IP, i);
    1566           0 :                         if (rmap_name && (strcmp(rmap_name, rmap) == 0)) {
    1567           0 :                                 if (IS_ZEBRA_DEBUG_EVENT)
    1568           0 :                                         zlog_debug(
    1569             :                                                 "%s : AFI_IP rmap %s, route type %s",
    1570             :                                                 __func__, rmap,
    1571             :                                                 zebra_route_string(i));
    1572             : 
    1573           0 :                                 old = PROTO_RM_MAP(zvrf, AFI_IP, i);
    1574             : 
    1575           0 :                                 PROTO_RM_MAP(zvrf, AFI_IP, i) =
    1576           0 :                                         route_map_lookup_by_name(rmap_name);
    1577             :                                 /* old is NULL. i.e Route map creation event.
    1578             :                                  * So update applied_counter.
    1579             :                                  * If Old is not NULL, i.e It may be routemap
    1580             :                                  * updation or deletion.
    1581             :                                  * So no need to update the counter.
    1582             :                                  */
    1583           0 :                                 if (!old)
    1584           0 :                                         route_map_counter_increment(
    1585             :                                                 PROTO_RM_MAP(zvrf, AFI_IP, i));
    1586             :                                 /* There is single rib table for all protocols
    1587             :                                  */
    1588           0 :                                 table = zvrf->table[AFI_IP][SAFI_UNICAST];
    1589           0 :                                 if (table) {
    1590           0 :                                         rib_update_table(
    1591             :                                                 table,
    1592             :                                                 RIB_UPDATE_RMAP_CHANGE,
    1593             :                                                 i);
    1594             :                                 }
    1595             :                         }
    1596           0 :                         rmap_name = PROTO_RM_NAME(zvrf, AFI_IP6, i);
    1597           0 :                         if (rmap_name && (strcmp(rmap_name, rmap) == 0)) {
    1598           0 :                                 if (IS_ZEBRA_DEBUG_EVENT)
    1599           0 :                                         zlog_debug(
    1600             :                                                 "%s : AFI_IP6 rmap %s, route type %s",
    1601             :                                                 __func__, rmap,
    1602             :                                                 zebra_route_string(i));
    1603             : 
    1604           0 :                                 old = PROTO_RM_MAP(zvrf, AFI_IP6, i);
    1605             : 
    1606           0 :                                 PROTO_RM_MAP(zvrf, AFI_IP6, i) =
    1607           0 :                                         route_map_lookup_by_name(rmap_name);
    1608           0 :                                 if (!old)
    1609           0 :                                         route_map_counter_increment(
    1610             :                                                 PROTO_RM_MAP(zvrf, AFI_IP6, i));
    1611             :                                 /* There is single rib table for all protocols
    1612             :                                  */
    1613           0 :                                 table = zvrf->table[AFI_IP6][SAFI_UNICAST];
    1614           0 :                                 if (table) {
    1615           0 :                                         rib_update_table(
    1616             :                                                 table,
    1617             :                                                 RIB_UPDATE_RMAP_CHANGE,
    1618             :                                                 i);
    1619             :                                 }
    1620             :                         }
    1621             :                 }
    1622             :         }
    1623           0 : }
    1624             : 
    1625             : /* The function checks if the changed routemap specified by parameter rmap
    1626             :  * matches the configured protocol routemaps in nht_rm table. If there is
    1627             :  * a match then zebra_evaluate_rnh() to process the nexthops.
    1628             :  */
    1629           0 : static void zebra_nht_rm_update(const char *rmap)
    1630             : {
    1631           0 :         int i = 0;
    1632           0 :         struct route_table *table;
    1633           0 :         struct vrf *vrf = NULL;
    1634           0 :         struct zebra_vrf *zvrf = NULL;
    1635           0 :         char *rmap_name;
    1636           0 :         char afi_ip = 0;
    1637           0 :         char afi_ipv6 = 0;
    1638           0 :         struct route_map *old = NULL;
    1639             : 
    1640           0 :         RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
    1641           0 :                 zvrf = vrf->info;
    1642           0 :                 if (!zvrf)
    1643           0 :                         continue;
    1644           0 :                 for (i = 0; i <= ZEBRA_ROUTE_MAX; i++) {
    1645           0 :                         rmap_name = NHT_RM_NAME(zvrf, AFI_IP, i);
    1646           0 :                         if (rmap_name && (strcmp(rmap_name, rmap) == 0)) {
    1647           0 :                                 if (IS_ZEBRA_DEBUG_EVENT)
    1648           0 :                                         zlog_debug(
    1649             :                                                 "%s : AFI_IP rmap %s, route type %s",
    1650             :                                                 __func__, rmap,
    1651             :                                                 zebra_route_string(i));
    1652             : 
    1653           0 :                                 old = NHT_RM_MAP(zvrf, AFI_IP, i);
    1654             : 
    1655           0 :                                 NHT_RM_MAP(zvrf, AFI_IP, i) =
    1656           0 :                                         route_map_lookup_by_name(rmap_name);
    1657           0 :                                 if (!old)
    1658           0 :                                         route_map_counter_increment(
    1659             :                                                 NHT_RM_MAP(zvrf, AFI_IP, i));
    1660             :                                 /* There is single rib table for all protocols
    1661             :                                  */
    1662           0 :                                 if (afi_ip == 0) {
    1663           0 :                                         table = zvrf->table[AFI_IP]
    1664             :                                                            [SAFI_UNICAST];
    1665           0 :                                         if (table) {
    1666             : 
    1667           0 :                                                 afi_ip = 1;
    1668             : 
    1669           0 :                                                 zebra_evaluate_rnh(
    1670             :                                                         zvrf, AFI_IP, 1, NULL,
    1671             :                                                         SAFI_UNICAST);
    1672             :                                         }
    1673             :                                 }
    1674             :                         }
    1675             : 
    1676           0 :                         rmap_name = NHT_RM_NAME(zvrf, AFI_IP6, i);
    1677           0 :                         if (rmap_name && (strcmp(rmap_name, rmap) == 0)) {
    1678           0 :                                 if (IS_ZEBRA_DEBUG_EVENT)
    1679           0 :                                         zlog_debug(
    1680             :                                                 "%s : AFI_IP6 rmap %s, route type %s",
    1681             :                                                 __func__, rmap,
    1682             :                                                 zebra_route_string(i));
    1683             : 
    1684           0 :                                 old = NHT_RM_MAP(zvrf, AFI_IP6, i);
    1685             : 
    1686           0 :                                 NHT_RM_MAP(zvrf, AFI_IP6, i) =
    1687           0 :                                         route_map_lookup_by_name(rmap_name);
    1688           0 :                                 if (!old)
    1689           0 :                                         route_map_counter_increment(
    1690             :                                                 NHT_RM_MAP(zvrf, AFI_IP6, i));
    1691             :                                 /* There is single rib table for all protocols
    1692             :                                  */
    1693           0 :                                 if (afi_ipv6 == 0) {
    1694           0 :                                         table = zvrf->table[AFI_IP6]
    1695             :                                                            [SAFI_UNICAST];
    1696           0 :                                         if (table) {
    1697             : 
    1698           0 :                                                 afi_ipv6 = 1;
    1699             : 
    1700           0 :                                                 zebra_evaluate_rnh(
    1701             :                                                         zvrf, AFI_IP, 1, NULL,
    1702             :                                                         SAFI_UNICAST);
    1703             :                                         }
    1704             :                                 }
    1705             :                         }
    1706             :                 }
    1707             :         }
    1708           0 : }
    1709             : 
    1710           0 : static void zebra_route_map_process_update_cb(char *rmap_name)
    1711             : {
    1712           0 :         if (IS_ZEBRA_DEBUG_EVENT)
    1713           0 :                 zlog_debug("Event handler for route-map: %s",
    1714             :                            rmap_name);
    1715           0 :         zebra_import_table_rm_update(rmap_name);
    1716           0 :         zebra_rib_table_rm_update(rmap_name);
    1717           0 :         zebra_nht_rm_update(rmap_name);
    1718           0 : }
    1719             : 
    1720           0 : static void zebra_route_map_update_timer(struct thread *thread)
    1721             : {
    1722           0 :         if (IS_ZEBRA_DEBUG_EVENT)
    1723           0 :                 zlog_debug("Event driven route-map update triggered");
    1724             : 
    1725           0 :         if (IS_ZEBRA_DEBUG_RIB_DETAILED)
    1726           0 :                 zlog_debug(
    1727             :                         "%u: Routemap update-timer fired, scheduling RIB processing",
    1728             :                         VRF_DEFAULT);
    1729             : 
    1730           0 :         route_map_walk_update_list(zebra_route_map_process_update_cb);
    1731             : 
    1732             :         /*
    1733             :          * This code needs to be updated to be:
    1734             :          * 1) VRF Aware <sigh>
    1735             :          * 2) Route-map aware
    1736             :          */
    1737           0 : }
    1738             : 
    1739           0 : static void zebra_route_map_set_delay_timer(uint32_t value)
    1740             : {
    1741           0 :         zebra_rmap_update_timer = value;
    1742           0 :         if (!value && zebra_t_rmap_update) {
    1743             :                 /* Event driven route map updates is being disabled */
    1744             :                 /* But there's a pending timer. Fire it off now */
    1745           0 :                 THREAD_OFF(zebra_t_rmap_update);
    1746           0 :                 zebra_route_map_update_timer(NULL);
    1747             :         }
    1748           0 : }
    1749             : 
    1750           3 : void zebra_routemap_finish(void)
    1751             : {
    1752             :         /* Set zebra_rmap_update_timer to 0 so that it wont schedule again */
    1753           3 :         zebra_rmap_update_timer = 0;
    1754             :         /* Thread off if any scheduled already */
    1755           3 :         THREAD_OFF(zebra_t_rmap_update);
    1756           3 :         route_map_finish();
    1757           3 : }
    1758             : 
    1759             : route_map_result_t
    1760           6 : zebra_route_map_check(afi_t family, int rib_type, uint8_t instance,
    1761             :                       const struct prefix *p, struct nexthop *nexthop,
    1762             :                       struct zebra_vrf *zvrf, route_tag_t tag)
    1763             : {
    1764           6 :         struct route_map *rmap = NULL;
    1765           6 :         char *rm_name;
    1766           6 :         route_map_result_t ret = RMAP_PERMITMATCH;
    1767           6 :         struct nh_rmap_obj nh_obj;
    1768             : 
    1769           6 :         nh_obj.nexthop = nexthop;
    1770           6 :         nh_obj.vrf_id = nexthop->vrf_id;
    1771           6 :         nh_obj.source_protocol = rib_type;
    1772           6 :         nh_obj.instance = instance;
    1773           6 :         nh_obj.metric = 0;
    1774           6 :         nh_obj.tag = tag;
    1775             : 
    1776           6 :         if (rib_type >= 0 && rib_type < ZEBRA_ROUTE_MAX) {
    1777           6 :                 rm_name = PROTO_RM_NAME(zvrf, family, rib_type);
    1778           6 :                 rmap = PROTO_RM_MAP(zvrf, family, rib_type);
    1779             : 
    1780           6 :                 if (rm_name && !rmap)
    1781             :                         return RMAP_DENYMATCH;
    1782             :         }
    1783           6 :         if (!rmap) {
    1784           6 :                 rm_name = PROTO_RM_NAME(zvrf, family, ZEBRA_ROUTE_MAX);
    1785           6 :                 rmap = PROTO_RM_MAP(zvrf, family, ZEBRA_ROUTE_MAX);
    1786             : 
    1787           6 :                 if (rm_name && !rmap)
    1788             :                         return RMAP_DENYMATCH;
    1789             :         }
    1790           6 :         if (rmap) {
    1791           0 :                 ret = route_map_apply(rmap, p, &nh_obj);
    1792             :         }
    1793             : 
    1794             :         return (ret);
    1795             : }
    1796             : 
    1797           0 : char *zebra_get_import_table_route_map(afi_t afi, uint32_t table)
    1798             : {
    1799           0 :         return zebra_import_table_routemap[afi][table];
    1800             : }
    1801             : 
    1802           0 : void zebra_add_import_table_route_map(afi_t afi, const char *rmap_name,
    1803             :                                       uint32_t table)
    1804             : {
    1805           0 :         zebra_import_table_routemap[afi][table] =
    1806           0 :                 XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmap_name);
    1807           0 : }
    1808             : 
    1809           0 : void zebra_del_import_table_route_map(afi_t afi, uint32_t table)
    1810             : {
    1811           0 :         XFREE(MTYPE_ROUTE_MAP_NAME, zebra_import_table_routemap[afi][table]);
    1812           0 : }
    1813             : 
    1814             : route_map_result_t
    1815           0 : zebra_import_table_route_map_check(int family, int re_type, uint8_t instance,
    1816             :                                    const struct prefix *p,
    1817             :                                    struct nexthop *nexthop,
    1818             :                                    vrf_id_t vrf_id, route_tag_t tag,
    1819             :                                    const char *rmap_name)
    1820             : {
    1821           0 :         struct route_map *rmap = NULL;
    1822           0 :         route_map_result_t ret = RMAP_DENYMATCH;
    1823           0 :         struct nh_rmap_obj nh_obj;
    1824             : 
    1825           0 :         nh_obj.nexthop = nexthop;
    1826           0 :         nh_obj.vrf_id = vrf_id;
    1827           0 :         nh_obj.source_protocol = re_type;
    1828           0 :         nh_obj.instance = instance;
    1829           0 :         nh_obj.metric = 0;
    1830           0 :         nh_obj.tag = tag;
    1831             : 
    1832           0 :         if (re_type >= 0 && re_type < ZEBRA_ROUTE_MAX)
    1833           0 :                 rmap = route_map_lookup_by_name(rmap_name);
    1834           0 :         if (rmap) {
    1835           0 :                 ret = route_map_apply(rmap, p, &nh_obj);
    1836             :         }
    1837             : 
    1838           0 :         return (ret);
    1839             : }
    1840             : 
    1841           0 : route_map_result_t zebra_nht_route_map_check(afi_t afi, int client_proto,
    1842             :                                              const struct prefix *p,
    1843             :                                              struct zebra_vrf *zvrf,
    1844             :                                              struct route_entry *re,
    1845             :                                              struct nexthop *nexthop)
    1846             : {
    1847           0 :         struct route_map *rmap = NULL;
    1848           0 :         route_map_result_t ret = RMAP_PERMITMATCH;
    1849           0 :         struct nh_rmap_obj nh_obj;
    1850             : 
    1851           0 :         nh_obj.nexthop = nexthop;
    1852           0 :         nh_obj.vrf_id = nexthop->vrf_id;
    1853           0 :         nh_obj.source_protocol = re->type;
    1854           0 :         nh_obj.instance = re->instance;
    1855           0 :         nh_obj.metric = re->metric;
    1856           0 :         nh_obj.tag = re->tag;
    1857             : 
    1858           0 :         if (client_proto >= 0 && client_proto < ZEBRA_ROUTE_MAX)
    1859           0 :                 rmap = NHT_RM_MAP(zvrf, afi, client_proto);
    1860           0 :         if (!rmap && NHT_RM_MAP(zvrf, afi, ZEBRA_ROUTE_MAX))
    1861             :                 rmap = NHT_RM_MAP(zvrf, afi, ZEBRA_ROUTE_MAX);
    1862           0 :         if (rmap)
    1863           0 :                 ret = route_map_apply(rmap, p, &nh_obj);
    1864             : 
    1865           0 :         return ret;
    1866             : }
    1867             : 
    1868           0 : static void zebra_route_map_mark_update(const char *rmap_name)
    1869             : {
    1870             :         /* rmap_update_timer of 0 means don't do route updates */
    1871           0 :         if (zebra_rmap_update_timer)
    1872           0 :                 THREAD_OFF(zebra_t_rmap_update);
    1873             : 
    1874           0 :         thread_add_timer(zrouter.master, zebra_route_map_update_timer,
    1875             :                          NULL, zebra_rmap_update_timer, &zebra_t_rmap_update);
    1876           0 : }
    1877             : 
    1878           0 : static void zebra_route_map_add(const char *rmap_name)
    1879             : {
    1880           0 :         if (route_map_mark_updated(rmap_name) == 0)
    1881           0 :                 zebra_route_map_mark_update(rmap_name);
    1882             : 
    1883           0 :         route_map_notify_dependencies(rmap_name, RMAP_EVENT_MATCH_ADDED);
    1884           0 : }
    1885             : 
    1886           0 : static void zebra_route_map_delete(const char *rmap_name)
    1887             : {
    1888           0 :         if (route_map_mark_updated(rmap_name) == 0)
    1889           0 :                 zebra_route_map_mark_update(rmap_name);
    1890             : 
    1891           0 :         route_map_notify_dependencies(rmap_name, RMAP_EVENT_MATCH_DELETED);
    1892           0 : }
    1893             : 
    1894           0 : static void zebra_route_map_event(const char *rmap_name)
    1895             : {
    1896           0 :         if (route_map_mark_updated(rmap_name) == 0)
    1897           0 :                 zebra_route_map_mark_update(rmap_name);
    1898             : 
    1899           0 :         route_map_notify_dependencies(rmap_name, RMAP_EVENT_MATCH_ADDED);
    1900           0 : }
    1901             : 
    1902           3 : void zebra_routemap_vrf_delete(struct zebra_vrf *zvrf)
    1903             : {
    1904           3 :         afi_t afi;
    1905           3 :         uint8_t type;
    1906             : 
    1907          12 :         for (afi = AFI_IP; afi < AFI_MAX; afi++) {
    1908         297 :                 for (type = 0; type <= ZEBRA_ROUTE_MAX; type++) {
    1909         288 :                         if (PROTO_RM_NAME(zvrf, afi, type))
    1910           0 :                                 XFREE(MTYPE_ROUTE_MAP_NAME,
    1911             :                                       PROTO_RM_NAME(zvrf, afi, type));
    1912         288 :                         if (NHT_RM_NAME(zvrf, afi, type))
    1913         288 :                                 XFREE(MTYPE_ROUTE_MAP_NAME,
    1914             :                                       NHT_RM_NAME(zvrf, afi, type));
    1915             :                 }
    1916             :         }
    1917           3 : }
    1918             : 
    1919             : /* ip protocol configuration write function */
    1920           0 : void zebra_routemap_config_write_protocol(struct vty *vty,
    1921             :                                           struct zebra_vrf *zvrf)
    1922             : {
    1923           0 :         int i;
    1924           0 :         char space[2];
    1925             : 
    1926           0 :         memset(space, 0, sizeof(space));
    1927             : 
    1928           0 :         if (zvrf_id(zvrf) != VRF_DEFAULT)
    1929           0 :                 snprintf(space, sizeof(space), "%s", " ");
    1930             : 
    1931           0 :         for (i = 0; i < ZEBRA_ROUTE_MAX; i++) {
    1932           0 :                 if (PROTO_RM_NAME(zvrf, AFI_IP, i))
    1933           0 :                         vty_out(vty, "%sip protocol %s route-map %s\n", space,
    1934             :                                 zebra_route_string(i),
    1935             :                                 PROTO_RM_NAME(zvrf, AFI_IP, i));
    1936             : 
    1937           0 :                 if (PROTO_RM_NAME(zvrf, AFI_IP6, i))
    1938           0 :                         vty_out(vty, "%sipv6 protocol %s route-map %s\n", space,
    1939             :                                 zebra_route_string(i),
    1940             :                                 PROTO_RM_NAME(zvrf, AFI_IP6, i));
    1941             : 
    1942           0 :                 if (NHT_RM_NAME(zvrf, AFI_IP, i))
    1943           0 :                         vty_out(vty, "%sip nht %s route-map %s\n", space,
    1944             :                                 zebra_route_string(i),
    1945             :                                 NHT_RM_NAME(zvrf, AFI_IP, i));
    1946             : 
    1947           0 :                 if (NHT_RM_NAME(zvrf, AFI_IP6, i))
    1948           0 :                         vty_out(vty, "%sipv6 nht %s route-map %s\n", space,
    1949             :                                 zebra_route_string(i),
    1950             :                                 NHT_RM_NAME(zvrf, AFI_IP6, i));
    1951             :         }
    1952             : 
    1953           0 :         if (PROTO_RM_NAME(zvrf, AFI_IP, ZEBRA_ROUTE_MAX))
    1954           0 :                 vty_out(vty, "%sip protocol %s route-map %s\n", space, "any",
    1955             :                         PROTO_RM_NAME(zvrf, AFI_IP, ZEBRA_ROUTE_MAX));
    1956             : 
    1957           0 :         if (PROTO_RM_NAME(zvrf, AFI_IP6, ZEBRA_ROUTE_MAX))
    1958           0 :                 vty_out(vty, "%sipv6 protocol %s route-map %s\n", space, "any",
    1959             :                         PROTO_RM_NAME(zvrf, AFI_IP6, ZEBRA_ROUTE_MAX));
    1960             : 
    1961           0 :         if (NHT_RM_NAME(zvrf, AFI_IP, ZEBRA_ROUTE_MAX))
    1962           0 :                 vty_out(vty, "%sip nht %s route-map %s\n", space, "any",
    1963             :                         NHT_RM_NAME(zvrf, AFI_IP, ZEBRA_ROUTE_MAX));
    1964             : 
    1965           0 :         if (NHT_RM_NAME(zvrf, AFI_IP6, ZEBRA_ROUTE_MAX))
    1966           0 :                 vty_out(vty, "%sipv6 nht %s route-map %s\n", space, "any",
    1967             :                         NHT_RM_NAME(zvrf, AFI_IP6, ZEBRA_ROUTE_MAX));
    1968             : 
    1969           0 :         if (zvrf_id(zvrf) == VRF_DEFAULT
    1970           0 :             && zebra_rmap_update_timer != ZEBRA_RMAP_DEFAULT_UPDATE_TIMER)
    1971           0 :                 vty_out(vty, "zebra route-map delay-timer %d\n",
    1972             :                         zebra_rmap_update_timer);
    1973           0 : }
    1974             : 
    1975           3 : void zebra_route_map_init(void)
    1976             : {
    1977           3 :         install_element(CONFIG_NODE, &ip_protocol_cmd);
    1978           3 :         install_element(CONFIG_NODE, &no_ip_protocol_cmd);
    1979           3 :         install_element(VRF_NODE, &ip_protocol_cmd);
    1980           3 :         install_element(VRF_NODE, &no_ip_protocol_cmd);
    1981           3 :         install_element(VIEW_NODE, &show_ip_protocol_cmd);
    1982           3 :         install_element(CONFIG_NODE, &ipv6_protocol_cmd);
    1983           3 :         install_element(CONFIG_NODE, &no_ipv6_protocol_cmd);
    1984           3 :         install_element(VRF_NODE, &ipv6_protocol_cmd);
    1985           3 :         install_element(VRF_NODE, &no_ipv6_protocol_cmd);
    1986           3 :         install_element(VIEW_NODE, &show_ipv6_protocol_cmd);
    1987           3 :         install_element(CONFIG_NODE, &ip_protocol_nht_rmap_cmd);
    1988           3 :         install_element(CONFIG_NODE, &no_ip_protocol_nht_rmap_cmd);
    1989           3 :         install_element(VRF_NODE, &ip_protocol_nht_rmap_cmd);
    1990           3 :         install_element(VRF_NODE, &no_ip_protocol_nht_rmap_cmd);
    1991           3 :         install_element(VIEW_NODE, &show_ip_protocol_nht_cmd);
    1992           3 :         install_element(CONFIG_NODE, &ipv6_protocol_nht_rmap_cmd);
    1993           3 :         install_element(CONFIG_NODE, &no_ipv6_protocol_nht_rmap_cmd);
    1994           3 :         install_element(VRF_NODE, &ipv6_protocol_nht_rmap_cmd);
    1995           3 :         install_element(VRF_NODE, &no_ipv6_protocol_nht_rmap_cmd);
    1996           3 :         install_element(VIEW_NODE, &show_ipv6_protocol_nht_cmd);
    1997           3 :         install_element(CONFIG_NODE, &zebra_route_map_timer_cmd);
    1998           3 :         install_element(CONFIG_NODE, &no_zebra_route_map_timer_cmd);
    1999             : 
    2000           3 :         route_map_init();
    2001             : 
    2002           3 :         route_map_add_hook(zebra_route_map_add);
    2003           3 :         route_map_delete_hook(zebra_route_map_delete);
    2004           3 :         route_map_event_hook(zebra_route_map_event);
    2005             : 
    2006           3 :         route_map_match_interface_hook(generic_match_add);
    2007           3 :         route_map_no_match_interface_hook(generic_match_delete);
    2008             : 
    2009           3 :         route_map_match_ip_address_hook(generic_match_add);
    2010           3 :         route_map_no_match_ip_address_hook(generic_match_delete);
    2011             : 
    2012           3 :         route_map_match_ip_address_prefix_list_hook(generic_match_add);
    2013           3 :         route_map_no_match_ip_address_prefix_list_hook(generic_match_delete);
    2014             : 
    2015           3 :         route_map_match_ip_next_hop_hook(generic_match_add);
    2016           3 :         route_map_no_match_ip_next_hop_hook(generic_match_delete);
    2017             : 
    2018           3 :         route_map_match_ip_next_hop_prefix_list_hook(generic_match_add);
    2019           3 :         route_map_no_match_ip_next_hop_prefix_list_hook(generic_match_delete);
    2020             : 
    2021           3 :         route_map_match_ip_next_hop_type_hook(generic_match_add);
    2022           3 :         route_map_no_match_ip_next_hop_type_hook(generic_match_delete);
    2023             : 
    2024           3 :         route_map_match_tag_hook(generic_match_add);
    2025           3 :         route_map_no_match_tag_hook(generic_match_delete);
    2026             : 
    2027           3 :         route_map_match_ipv6_address_hook(generic_match_add);
    2028           3 :         route_map_no_match_ipv6_address_hook(generic_match_delete);
    2029             : 
    2030           3 :         route_map_match_ipv6_address_prefix_list_hook(generic_match_add);
    2031           3 :         route_map_no_match_ipv6_address_prefix_list_hook(generic_match_delete);
    2032             : 
    2033           3 :         route_map_match_ipv6_next_hop_type_hook(generic_match_add);
    2034           3 :         route_map_no_match_ipv6_next_hop_type_hook(generic_match_delete);
    2035             : 
    2036           3 :         route_map_install_match(&route_match_tag_cmd);
    2037           3 :         route_map_install_match(&route_match_interface_cmd);
    2038           3 :         route_map_install_match(&route_match_ip_next_hop_cmd);
    2039           3 :         route_map_install_match(&route_match_ip_next_hop_prefix_list_cmd);
    2040           3 :         route_map_install_match(&route_match_ip_address_cmd);
    2041           3 :         route_map_install_match(&route_match_ipv6_address_cmd);
    2042           3 :         route_map_install_match(&route_match_ip_address_prefix_list_cmd);
    2043           3 :         route_map_install_match(&route_match_ipv6_address_prefix_list_cmd);
    2044           3 :         route_map_install_match(&route_match_ip_address_prefix_len_cmd);
    2045           3 :         route_map_install_match(&route_match_ipv6_address_prefix_len_cmd);
    2046           3 :         route_map_install_match(&route_match_ip_nexthop_prefix_len_cmd);
    2047           3 :         route_map_install_match(&route_match_ip_next_hop_type_cmd);
    2048           3 :         route_map_install_match(&route_match_ipv6_next_hop_type_cmd);
    2049           3 :         route_map_install_match(&route_match_source_protocol_cmd);
    2050           3 :         route_map_install_match(&route_match_source_instance_cmd);
    2051             : 
    2052             :         /* */
    2053           3 :         route_map_install_set(&route_set_src_cmd);
    2054             :         /* */
    2055           3 :         install_element(RMAP_NODE, &match_ip_nexthop_prefix_len_cmd);
    2056           3 :         install_element(RMAP_NODE, &no_match_ip_nexthop_prefix_len_cmd);
    2057           3 :         install_element(RMAP_NODE, &match_ip_address_prefix_len_cmd);
    2058           3 :         install_element(RMAP_NODE, &match_ipv6_address_prefix_len_cmd);
    2059           3 :         install_element(RMAP_NODE, &no_match_ipv6_address_prefix_len_cmd);
    2060           3 :         install_element(RMAP_NODE, &no_match_ip_address_prefix_len_cmd);
    2061           3 :         install_element(RMAP_NODE, &match_source_protocol_cmd);
    2062           3 :         install_element(RMAP_NODE, &no_match_source_protocol_cmd);
    2063           3 :         install_element(RMAP_NODE, &match_source_instance_cmd);
    2064           3 :         install_element(RMAP_NODE, &no_match_source_instance_cmd);
    2065             : 
    2066             :         /* */
    2067           3 :         install_element(RMAP_NODE, &set_src_cmd);
    2068           3 :         install_element(RMAP_NODE, &no_set_src_cmd);
    2069           3 : }

Generated by: LCOV version v1.16-topotato