back to topotato report
topotato coverage report
Current view: top level - lib - routemap_northbound.c (source / functions) Hit Total Coverage
Test: test_pim6_bootstrap.py::PIM6Bootstrap Lines: 0 496 0.0 %
Date: 2023-02-16 02:07:22 Functions: 0 54 0.0 %

          Line data    Source code
       1             : /*
       2             :  * Route map northbound implementation.
       3             :  *
       4             :  * Copyright (C) 2019 Network Device Education Foundation, Inc. ("NetDEF")
       5             :  *                    Rafael Zalamena
       6             :  *
       7             :  * This program is free software; you can redistribute it and/or modify
       8             :  * it under the terms of the GNU General Public License as published by
       9             :  * the Free Software Foundation; either version 2 of the License, or
      10             :  * (at your option) any later version.
      11             :  *
      12             :  * This program is distributed in the hope that it will be useful,
      13             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      14             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      15             :  * GNU General Public License for more details.
      16             :  *
      17             :  * You should have received a copy of the GNU General Public License
      18             :  * along with this program; if not, write to the Free Software
      19             :  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
      20             :  * 02110-1301 USA.
      21             :  */
      22             : 
      23             : #include <zebra.h>
      24             : 
      25             : #include "lib/command.h"
      26             : #include "lib/log.h"
      27             : #include "lib/northbound.h"
      28             : #include "lib/routemap.h"
      29             : 
      30             : /*
      31             :  * Auxiliary functions to avoid code duplication:
      32             :  *
      33             :  * lib_route_map_entry_set_destroy: unset `set` commands.
      34             :  * lib_route_map_entry_match_destroy: unset `match` commands.
      35             :  */
      36           0 : int lib_route_map_entry_match_destroy(struct nb_cb_destroy_args *args)
      37             : {
      38           0 :         struct routemap_hook_context *rhc;
      39           0 :         int rv;
      40             : 
      41           0 :         if (args->event != NB_EV_APPLY)
      42             :                 return NB_OK;
      43             : 
      44           0 :         rhc = nb_running_get_entry(args->dnode, NULL, true);
      45           0 :         if (rhc->rhc_mhook == NULL)
      46             :                 return NB_OK;
      47             : 
      48           0 :         rv = rhc->rhc_mhook(rhc->rhc_rmi, rhc->rhc_rule, NULL,
      49             :                             rhc->rhc_event,
      50             :                             args->errmsg, args->errmsg_len);
      51           0 :         if (rv != CMD_SUCCESS)
      52             :                 return NB_ERR_INCONSISTENCY;
      53             : 
      54             :         return NB_OK;
      55             : }
      56             : 
      57           0 : int lib_route_map_entry_set_destroy(struct nb_cb_destroy_args *args)
      58             : {
      59           0 :         struct routemap_hook_context *rhc;
      60           0 :         int rv;
      61             : 
      62           0 :         if (args->event != NB_EV_APPLY)
      63             :                 return NB_OK;
      64             : 
      65           0 :         rhc = nb_running_get_entry(args->dnode, NULL, true);
      66           0 :         if (rhc->rhc_shook == NULL)
      67             :                 return NB_OK;
      68             : 
      69           0 :         rv = rhc->rhc_shook(rhc->rhc_rmi, rhc->rhc_rule, NULL,
      70             :                             args->errmsg, args->errmsg_len);
      71           0 :         if (rv != CMD_SUCCESS)
      72             :                 return NB_ERR_INCONSISTENCY;
      73             : 
      74             :         return NB_OK;
      75             : }
      76             : 
      77             : /*
      78             :  * Auxiliary hook context list manipulation functions.
      79             :  */
      80             : struct routemap_hook_context *
      81           0 : routemap_hook_context_insert(struct route_map_index *rmi)
      82             : {
      83           0 :         struct routemap_hook_context *rhc;
      84             : 
      85           0 :         rhc = XCALLOC(MTYPE_TMP, sizeof(*rhc));
      86           0 :         rhc->rhc_rmi = rmi;
      87           0 :         TAILQ_INSERT_TAIL(&rmi->rhclist, rhc, rhc_entry);
      88             : 
      89           0 :         return rhc;
      90             : }
      91             : 
      92           0 : void routemap_hook_context_free(struct routemap_hook_context *rhc)
      93             : {
      94           0 :         struct route_map_index *rmi = rhc->rhc_rmi;
      95             : 
      96           0 :         TAILQ_REMOVE(&rmi->rhclist, rhc, rhc_entry);
      97           0 :         XFREE(MTYPE_TMP, rhc);
      98           0 : }
      99             : 
     100             : /*
     101             :  * XPath: /frr-route-map:lib/route-map
     102             :  */
     103           0 : static int lib_route_map_create(struct nb_cb_create_args *args)
     104             : {
     105           0 :         struct route_map *rm;
     106           0 :         const char *rm_name;
     107             : 
     108           0 :         switch (args->event) {
     109             :         case NB_EV_VALIDATE:
     110             :         case NB_EV_PREPARE:
     111             :         case NB_EV_ABORT:
     112             :                 /* NOTHING */
     113             :                 break;
     114           0 :         case NB_EV_APPLY:
     115           0 :                 rm_name = yang_dnode_get_string(args->dnode, "./name");
     116           0 :                 rm = route_map_get(rm_name);
     117           0 :                 nb_running_set_entry(args->dnode, rm);
     118           0 :                 break;
     119             :         }
     120             : 
     121           0 :         return NB_OK;
     122             : }
     123             : 
     124           0 : static int lib_route_map_destroy(struct nb_cb_destroy_args *args)
     125             : {
     126           0 :         struct route_map *rm;
     127             : 
     128           0 :         switch (args->event) {
     129             :         case NB_EV_VALIDATE:
     130             :         case NB_EV_PREPARE:
     131             :         case NB_EV_ABORT:
     132             :                 /* NOTHING */
     133             :                 break;
     134           0 :         case NB_EV_APPLY:
     135           0 :                 rm = nb_running_unset_entry(args->dnode);
     136           0 :                 route_map_delete(rm);
     137           0 :                 break;
     138             :         }
     139             : 
     140           0 :         return NB_OK;
     141             : }
     142             : 
     143             : /*
     144             :  * XPath: /frr-route-map:lib/route-map/optimization-disabled
     145             :  */
     146             : static int
     147           0 : lib_route_map_optimization_disabled_modify(struct nb_cb_modify_args *args)
     148             : {
     149           0 :         struct route_map *rm;
     150           0 :         bool disabled = yang_dnode_get_bool(args->dnode, NULL);
     151             : 
     152           0 :         switch (args->event) {
     153             :         case NB_EV_VALIDATE:
     154             :         case NB_EV_PREPARE:
     155             :         case NB_EV_ABORT:
     156             :                 /* NOTHING */
     157             :                 break;
     158           0 :         case NB_EV_APPLY:
     159           0 :                 rm = nb_running_get_entry(args->dnode, NULL, true);
     160           0 :                 rm->optimization_disabled = disabled;
     161           0 :                 break;
     162             :         }
     163             : 
     164           0 :         return NB_OK;
     165             : }
     166             : 
     167             : /*
     168             :  * XPath: /frr-route-map:lib/route-map/entry
     169             :  */
     170           0 : static int lib_route_map_entry_create(struct nb_cb_create_args *args)
     171             : {
     172           0 :         struct route_map_index *rmi;
     173           0 :         struct route_map *rm;
     174           0 :         uint16_t sequence;
     175           0 :         int action;
     176             : 
     177           0 :         switch (args->event) {
     178             :         case NB_EV_VALIDATE:
     179             :         case NB_EV_PREPARE:
     180             :         case NB_EV_ABORT:
     181             :                 /* NOTHING */
     182             :                 break;
     183           0 :         case NB_EV_APPLY:
     184           0 :                 sequence = yang_dnode_get_uint16(args->dnode, "./sequence");
     185           0 :                 action = yang_dnode_get_enum(args->dnode, "./action") == 0
     186             :                                  ? RMAP_PERMIT
     187           0 :                                  : RMAP_DENY;
     188           0 :                 rm = nb_running_get_entry(args->dnode, NULL, true);
     189           0 :                 rmi = route_map_index_get(rm, action, sequence);
     190           0 :                 nb_running_set_entry(args->dnode, rmi);
     191           0 :                 break;
     192             :         }
     193             : 
     194           0 :         return NB_OK;
     195             : }
     196             : 
     197           0 : static int lib_route_map_entry_destroy(struct nb_cb_destroy_args *args)
     198             : {
     199           0 :         struct route_map_index *rmi;
     200             : 
     201           0 :         switch (args->event) {
     202             :         case NB_EV_VALIDATE:
     203             :         case NB_EV_PREPARE:
     204             :         case NB_EV_ABORT:
     205             :                 /* NOTHING */
     206             :                 break;
     207           0 :         case NB_EV_APPLY:
     208           0 :                 rmi = nb_running_unset_entry(args->dnode);
     209           0 :                 route_map_index_delete(rmi, 1);
     210           0 :                 break;
     211             :         }
     212             : 
     213           0 :         return NB_OK;
     214             : }
     215             : 
     216             : /*
     217             :  * XPath: /frr-route-map:lib/route-map/entry/description
     218             :  */
     219             : static int
     220           0 : lib_route_map_entry_description_modify(struct nb_cb_modify_args *args)
     221             : {
     222           0 :         struct route_map_index *rmi;
     223           0 :         const char *description;
     224             : 
     225           0 :         switch (args->event) {
     226             :         case NB_EV_VALIDATE:
     227             :                 /* NOTHING */
     228             :                 break;
     229           0 :         case NB_EV_PREPARE:
     230           0 :                 description = yang_dnode_get_string(args->dnode, NULL);
     231           0 :                 args->resource->ptr = XSTRDUP(MTYPE_TMP, description);
     232           0 :                 if (args->resource->ptr == NULL)
     233             :                         return NB_ERR_RESOURCE;
     234             :                 break;
     235           0 :         case NB_EV_ABORT:
     236           0 :                 XFREE(MTYPE_TMP, args->resource->ptr);
     237           0 :                 break;
     238           0 :         case NB_EV_APPLY:
     239           0 :                 rmi = nb_running_get_entry(args->dnode, NULL, true);
     240           0 :                 XFREE(MTYPE_TMP, rmi->description);
     241           0 :                 rmi->description = args->resource->ptr;
     242           0 :                 break;
     243             :         }
     244             : 
     245             :         return NB_OK;
     246             : }
     247             : 
     248             : static int
     249           0 : lib_route_map_entry_description_destroy(struct nb_cb_destroy_args *args)
     250             : {
     251           0 :         struct route_map_index *rmi;
     252             : 
     253           0 :         switch (args->event) {
     254             :         case NB_EV_VALIDATE:
     255             :         case NB_EV_PREPARE:
     256             :         case NB_EV_ABORT:
     257             :                 /* NOTHING */
     258             :                 break;
     259           0 :         case NB_EV_APPLY:
     260           0 :                 rmi = nb_running_get_entry(args->dnode, NULL, true);
     261           0 :                 XFREE(MTYPE_TMP, rmi->description);
     262           0 :                 break;
     263             :         }
     264             : 
     265           0 :         return NB_OK;
     266             : }
     267             : 
     268             : /*
     269             :  * XPath: /frr-route-map:lib/route-map/entry/action
     270             :  */
     271           0 : static int lib_route_map_entry_action_modify(struct nb_cb_modify_args *args)
     272             : {
     273           0 :         struct route_map_index *rmi;
     274           0 :         struct route_map *map;
     275             : 
     276           0 :         switch (args->event) {
     277             :         case NB_EV_VALIDATE:
     278             :         case NB_EV_PREPARE:
     279             :         case NB_EV_ABORT:
     280             :                 /* NOTHING */
     281             :                 break;
     282           0 :         case NB_EV_APPLY:
     283           0 :                 rmi = nb_running_get_entry(args->dnode, NULL, true);
     284           0 :                 rmi->type = yang_dnode_get_enum(args->dnode, NULL);
     285           0 :                 map = rmi->map;
     286             : 
     287             :                 /* Execute event hook. */
     288           0 :                 if (route_map_master.event_hook) {
     289           0 :                         (*route_map_master.event_hook)(map->name);
     290           0 :                         route_map_notify_dependencies(map->name,
     291             :                                                       RMAP_EVENT_CALL_ADDED);
     292             :                 }
     293             : 
     294             :                 break;
     295             :         }
     296             : 
     297           0 :         return NB_OK;
     298             : }
     299             : 
     300             : /*
     301             :  * XPath: /frr-route-map:lib/route-map/entry/call
     302             :  */
     303           0 : static int lib_route_map_entry_call_modify(struct nb_cb_modify_args *args)
     304             : {
     305           0 :         struct route_map_index *rmi;
     306           0 :         const char *rm_name, *rmn_name;
     307             : 
     308           0 :         switch (args->event) {
     309           0 :         case NB_EV_VALIDATE:
     310           0 :                 rm_name = yang_dnode_get_string(args->dnode, "../../name");
     311           0 :                 rmn_name = yang_dnode_get_string(args->dnode, NULL);
     312             :                 /* Don't allow to jump to the same route map instance. */
     313           0 :                 if (strcmp(rm_name, rmn_name) == 0)
     314             :                         return NB_ERR_VALIDATION;
     315             : 
     316             :                 /* TODO: detect circular route map sequences. */
     317             :                 break;
     318           0 :         case NB_EV_PREPARE:
     319           0 :                 rmn_name = yang_dnode_get_string(args->dnode, NULL);
     320           0 :                 args->resource->ptr = XSTRDUP(MTYPE_ROUTE_MAP_NAME, rmn_name);
     321           0 :                 break;
     322           0 :         case NB_EV_ABORT:
     323           0 :                 XFREE(MTYPE_ROUTE_MAP_NAME, args->resource->ptr);
     324           0 :                 break;
     325           0 :         case NB_EV_APPLY:
     326           0 :                 rmi = nb_running_get_entry(args->dnode, NULL, true);
     327           0 :                 if (rmi->nextrm) {
     328           0 :                         route_map_upd8_dependency(RMAP_EVENT_CALL_DELETED,
     329           0 :                                                   rmi->nextrm, rmi->map->name);
     330           0 :                         XFREE(MTYPE_ROUTE_MAP_NAME, rmi->nextrm);
     331             :                 }
     332           0 :                 rmi->nextrm = args->resource->ptr;
     333           0 :                 route_map_upd8_dependency(RMAP_EVENT_CALL_ADDED, rmi->nextrm,
     334           0 :                                           rmi->map->name);
     335           0 :                 break;
     336             :         }
     337             : 
     338             :         return NB_OK;
     339             : }
     340             : 
     341           0 : static int lib_route_map_entry_call_destroy(struct nb_cb_destroy_args *args)
     342             : {
     343           0 :         struct route_map_index *rmi;
     344             : 
     345           0 :         switch (args->event) {
     346             :         case NB_EV_VALIDATE:
     347             :         case NB_EV_PREPARE:
     348             :         case NB_EV_ABORT:
     349             :                 /* NOTHING */
     350             :                 break;
     351           0 :         case NB_EV_APPLY:
     352           0 :                 rmi = nb_running_get_entry(args->dnode, NULL, true);
     353           0 :                 route_map_upd8_dependency(RMAP_EVENT_CALL_DELETED, rmi->nextrm,
     354           0 :                                           rmi->map->name);
     355           0 :                 XFREE(MTYPE_ROUTE_MAP_NAME, rmi->nextrm);
     356           0 :                 rmi->nextrm = NULL;
     357           0 :                 break;
     358             :         }
     359             : 
     360           0 :         return NB_OK;
     361             : }
     362             : 
     363             : /*
     364             :  * XPath: /frr-route-map:lib/route-map/entry/exit-policy
     365             :  */
     366             : static int
     367           0 : lib_route_map_entry_exit_policy_modify(struct nb_cb_modify_args *args)
     368             : {
     369           0 :         struct route_map_index *rmi;
     370           0 :         int rm_action;
     371           0 :         int policy;
     372             : 
     373           0 :         switch (args->event) {
     374           0 :         case NB_EV_VALIDATE:
     375           0 :                 policy = yang_dnode_get_enum(args->dnode, NULL);
     376           0 :                 switch (policy) {
     377             :                 case 0: /* permit-or-deny */
     378             :                         break;
     379           0 :                 case 1: /* next */
     380             :                         /* FALLTHROUGH */
     381             :                 case 2: /* goto */
     382           0 :                         rm_action =
     383           0 :                                 yang_dnode_get_enum(args->dnode, "../action");
     384           0 :                         if (rm_action == 1 /* deny */) {
     385             :                                 /*
     386             :                                  * On deny it is not possible to 'goto'
     387             :                                  * anywhere.
     388             :                                  */
     389             :                                 return NB_ERR_VALIDATION;
     390             :                         }
     391             :                         break;
     392             :                 }
     393             :                 break;
     394             :         case NB_EV_PREPARE:
     395             :         case NB_EV_ABORT:
     396             :                 break;
     397           0 :         case NB_EV_APPLY:
     398           0 :                 rmi = nb_running_get_entry(args->dnode, NULL, true);
     399           0 :                 policy = yang_dnode_get_enum(args->dnode, NULL);
     400             : 
     401           0 :                 switch (policy) {
     402           0 :                 case 0: /* permit-or-deny */
     403           0 :                         rmi->exitpolicy = RMAP_EXIT;
     404           0 :                         break;
     405           0 :                 case 1: /* next */
     406           0 :                         rmi->exitpolicy = RMAP_NEXT;
     407           0 :                         break;
     408           0 :                 case 2: /* goto */
     409           0 :                         rmi->exitpolicy = RMAP_GOTO;
     410           0 :                         break;
     411             :                 }
     412             :                 break;
     413             :         }
     414             : 
     415             :         return NB_OK;
     416             : }
     417             : 
     418             : /*
     419             :  * XPath: /frr-route-map:lib/route-map/entry/goto-value
     420             :  */
     421           0 : static int lib_route_map_entry_goto_value_modify(struct nb_cb_modify_args *args)
     422             : {
     423           0 :         struct route_map_index *rmi;
     424           0 :         uint16_t rmi_index;
     425           0 :         uint16_t rmi_next;
     426             : 
     427           0 :         switch (args->event) {
     428           0 :         case NB_EV_VALIDATE:
     429           0 :                 rmi_index = yang_dnode_get_uint16(args->dnode, "../sequence");
     430           0 :                 rmi_next = yang_dnode_get_uint16(args->dnode, NULL);
     431           0 :                 if (rmi_next <= rmi_index) {
     432             :                         /* Can't jump backwards on a route map. */
     433             :                         return NB_ERR_VALIDATION;
     434             :                 }
     435             :                 break;
     436             :         case NB_EV_PREPARE:
     437             :         case NB_EV_ABORT:
     438             :                 /* NOTHING */
     439             :                 break;
     440           0 :         case NB_EV_APPLY:
     441           0 :                 rmi = nb_running_get_entry(args->dnode, NULL, true);
     442           0 :                 rmi->nextpref = yang_dnode_get_uint16(args->dnode, NULL);
     443           0 :                 break;
     444             :         }
     445             : 
     446             :         return NB_OK;
     447             : }
     448             : 
     449             : static int
     450           0 : lib_route_map_entry_goto_value_destroy(struct nb_cb_destroy_args *args)
     451             : {
     452           0 :         struct route_map_index *rmi;
     453             : 
     454           0 :         switch (args->event) {
     455             :         case NB_EV_VALIDATE:
     456             :         case NB_EV_PREPARE:
     457             :         case NB_EV_ABORT:
     458             :                 /* NOTHING */
     459             :                 break;
     460           0 :         case NB_EV_APPLY:
     461           0 :                 rmi = nb_running_get_entry(args->dnode, NULL, true);
     462           0 :                 rmi->nextpref = 0;
     463           0 :                 break;
     464             :         }
     465             : 
     466           0 :         return NB_OK;
     467             : }
     468             : 
     469             : /*
     470             :  * XPath: /frr-route-map:lib/route-map/entry/match-condition
     471             :  */
     472             : static int
     473           0 : lib_route_map_entry_match_condition_create(struct nb_cb_create_args *args)
     474             : {
     475           0 :         struct routemap_hook_context *rhc;
     476           0 :         struct route_map_index *rmi;
     477             : 
     478           0 :         switch (args->event) {
     479             :         case NB_EV_VALIDATE:
     480             :         case NB_EV_PREPARE:
     481             :         case NB_EV_ABORT:
     482             :                 /* NOTHING */
     483             :                 break;
     484           0 :         case NB_EV_APPLY:
     485           0 :                 rmi = nb_running_get_entry(args->dnode, NULL, true);
     486           0 :                 rhc = routemap_hook_context_insert(rmi);
     487           0 :                 nb_running_set_entry(args->dnode, rhc);
     488           0 :                 break;
     489             :         }
     490             : 
     491           0 :         return NB_OK;
     492             : }
     493             : 
     494             : static int
     495           0 : lib_route_map_entry_match_condition_destroy(struct nb_cb_destroy_args *args)
     496             : {
     497           0 :         struct routemap_hook_context *rhc;
     498           0 :         int rv;
     499             : 
     500           0 :         if (args->event != NB_EV_APPLY)
     501             :                 return NB_OK;
     502             : 
     503           0 :         rv = lib_route_map_entry_match_destroy(args);
     504           0 :         rhc = nb_running_unset_entry(args->dnode);
     505           0 :         routemap_hook_context_free(rhc);
     506             : 
     507           0 :         return rv;
     508             : }
     509             : 
     510             : /*
     511             :  * XPath: /frr-route-map:lib/route-map/entry/match-condition/interface
     512             :  */
     513           0 : static int lib_route_map_entry_match_condition_interface_modify(
     514             :         struct nb_cb_modify_args *args)
     515             : {
     516           0 :         struct routemap_hook_context *rhc;
     517           0 :         const char *ifname;
     518           0 :         int rv;
     519             : 
     520           0 :         if (args->event != NB_EV_APPLY)
     521             :                 return NB_OK;
     522             : 
     523             :         /* Check for hook function. */
     524           0 :         if (rmap_match_set_hook.match_interface == NULL)
     525             :                 return NB_OK;
     526             : 
     527             :         /* Add configuration. */
     528           0 :         rhc = nb_running_get_entry(args->dnode, NULL, true);
     529           0 :         ifname = yang_dnode_get_string(args->dnode, NULL);
     530             : 
     531             :         /* Set destroy information. */
     532           0 :         rhc->rhc_mhook = rmap_match_set_hook.no_match_interface;
     533           0 :         rhc->rhc_rule = "interface";
     534           0 :         rhc->rhc_event = RMAP_EVENT_MATCH_DELETED;
     535             : 
     536           0 :         rv = rmap_match_set_hook.match_interface(rhc->rhc_rmi,
     537             :                                                  "interface", ifname,
     538             :                                                  RMAP_EVENT_MATCH_ADDED,
     539             :                                                  args->errmsg, args->errmsg_len);
     540           0 :         if (rv != CMD_SUCCESS) {
     541           0 :                 rhc->rhc_mhook = NULL;
     542           0 :                 return NB_ERR_INCONSISTENCY;
     543             :         }
     544             : 
     545             :         return NB_OK;
     546             : }
     547             : 
     548           0 : static int lib_route_map_entry_match_condition_interface_destroy(
     549             :         struct nb_cb_destroy_args *args)
     550             : {
     551           0 :         return lib_route_map_entry_match_destroy(args);
     552             : }
     553             : 
     554             : /*
     555             :  * XPath: /frr-route-map:lib/route-map/entry/match-condition/list-name
     556             :  */
     557           0 : static int lib_route_map_entry_match_condition_list_name_modify(
     558             :         struct nb_cb_modify_args *args)
     559             : {
     560           0 :         struct routemap_hook_context *rhc;
     561           0 :         const char *acl;
     562           0 :         const char *condition;
     563           0 :         int rv;
     564             : 
     565           0 :         if (args->event != NB_EV_APPLY)
     566             :                 return NB_OK;
     567             : 
     568             :         /* Check for hook installation, otherwise we can just stop. */
     569           0 :         acl = yang_dnode_get_string(args->dnode, NULL);
     570           0 :         rhc = nb_running_get_entry(args->dnode, NULL, true);
     571           0 :         condition = yang_dnode_get_string(args->dnode, "../../condition");
     572             : 
     573           0 :         if (IS_MATCH_IPv4_ADDRESS_LIST(condition)) {
     574           0 :                 if (rmap_match_set_hook.match_ip_address == NULL)
     575             :                         return NB_OK;
     576           0 :                 rhc->rhc_mhook = rmap_match_set_hook.no_match_ip_address;
     577           0 :                 rhc->rhc_rule = "ip address";
     578           0 :                 rhc->rhc_event = RMAP_EVENT_FILTER_DELETED;
     579           0 :                 rv = rmap_match_set_hook.match_ip_address(
     580             :                         rhc->rhc_rmi, "ip address", acl,
     581             :                         RMAP_EVENT_FILTER_ADDED,
     582             :                         args->errmsg, args->errmsg_len);
     583           0 :         } else if (IS_MATCH_IPv4_PREFIX_LIST(condition)) {
     584           0 :                 if (rmap_match_set_hook.match_ip_address_prefix_list == NULL)
     585             :                         return NB_OK;
     586           0 :                 rhc->rhc_mhook =
     587           0 :                         rmap_match_set_hook.no_match_ip_address_prefix_list;
     588           0 :                 rhc->rhc_rule = "ip address prefix-list";
     589           0 :                 rhc->rhc_event = RMAP_EVENT_PLIST_DELETED;
     590           0 :                 rv = rmap_match_set_hook.match_ip_address_prefix_list(
     591             :                         rhc->rhc_rmi, "ip address prefix-list", acl,
     592             :                         RMAP_EVENT_PLIST_ADDED,
     593             :                         args->errmsg, args->errmsg_len);
     594           0 :         } else if (IS_MATCH_IPv4_NEXTHOP_LIST(condition)) {
     595           0 :                 if (rmap_match_set_hook.match_ip_next_hop == NULL)
     596             :                         return NB_OK;
     597           0 :                 rhc->rhc_mhook = rmap_match_set_hook.no_match_ip_next_hop;
     598           0 :                 rhc->rhc_rule = "ip next-hop";
     599           0 :                 rhc->rhc_event = RMAP_EVENT_FILTER_DELETED;
     600           0 :                 rv = rmap_match_set_hook.match_ip_next_hop(
     601             :                         rhc->rhc_rmi, "ip next-hop", acl,
     602             :                         RMAP_EVENT_FILTER_ADDED,
     603             :                         args->errmsg, args->errmsg_len);
     604           0 :         } else if (IS_MATCH_IPv6_NEXTHOP_LIST(condition)) {
     605           0 :                 if (rmap_match_set_hook.match_ipv6_next_hop == NULL)
     606             :                         return NB_OK;
     607           0 :                 rhc->rhc_mhook = rmap_match_set_hook.no_match_ipv6_next_hop;
     608           0 :                 rhc->rhc_rule = "ipv6 next-hop";
     609           0 :                 rhc->rhc_event = RMAP_EVENT_FILTER_DELETED;
     610           0 :                 rv = rmap_match_set_hook.match_ipv6_next_hop(
     611             :                         rhc->rhc_rmi, "ipv6 next-hop", acl,
     612             :                         RMAP_EVENT_FILTER_ADDED, args->errmsg,
     613             :                         args->errmsg_len);
     614           0 :         } else if (IS_MATCH_IPv4_NEXTHOP_PREFIX_LIST(condition)) {
     615           0 :                 if (rmap_match_set_hook.match_ip_next_hop_prefix_list == NULL)
     616             :                         return NB_OK;
     617           0 :                 rhc->rhc_mhook =
     618           0 :                         rmap_match_set_hook.no_match_ip_next_hop_prefix_list;
     619           0 :                 rhc->rhc_rule = "ip next-hop prefix-list";
     620           0 :                 rhc->rhc_event = RMAP_EVENT_PLIST_DELETED;
     621           0 :                 rv = rmap_match_set_hook.match_ip_next_hop_prefix_list(
     622             :                         rhc->rhc_rmi, "ip next-hop prefix-list", acl,
     623             :                         RMAP_EVENT_PLIST_ADDED,
     624             :                         args->errmsg, args->errmsg_len);
     625           0 :         } else if (IS_MATCH_IPv6_NEXTHOP_PREFIX_LIST(condition)) {
     626           0 :                 if (rmap_match_set_hook.match_ipv6_next_hop_prefix_list == NULL)
     627             :                         return NB_OK;
     628           0 :                 rhc->rhc_mhook =
     629           0 :                         rmap_match_set_hook.no_match_ipv6_next_hop_prefix_list;
     630           0 :                 rhc->rhc_rule = "ipv6 next-hop prefix-list";
     631           0 :                 rhc->rhc_event = RMAP_EVENT_PLIST_DELETED;
     632           0 :                 rv = rmap_match_set_hook.match_ipv6_next_hop_prefix_list(
     633             :                         rhc->rhc_rmi, "ipv6 next-hop prefix-list", acl,
     634             :                         RMAP_EVENT_PLIST_ADDED, args->errmsg, args->errmsg_len);
     635           0 :         } else if (IS_MATCH_IPv6_ADDRESS_LIST(condition)) {
     636           0 :                 if (rmap_match_set_hook.match_ipv6_address == NULL)
     637             :                         return NB_OK;
     638           0 :                 rhc->rhc_mhook = rmap_match_set_hook.no_match_ipv6_address;
     639           0 :                 rhc->rhc_rule = "ipv6 address";
     640           0 :                 rhc->rhc_event = RMAP_EVENT_FILTER_DELETED;
     641           0 :                 rv = rmap_match_set_hook.match_ipv6_address(
     642             :                         rhc->rhc_rmi, "ipv6 address", acl,
     643             :                         RMAP_EVENT_FILTER_ADDED,
     644             :                         args->errmsg, args->errmsg_len);
     645           0 :         } else if (IS_MATCH_IPv6_PREFIX_LIST(condition)) {
     646           0 :                 if (rmap_match_set_hook.match_ipv6_address_prefix_list == NULL)
     647             :                         return NB_OK;
     648           0 :                 rhc->rhc_mhook =
     649           0 :                         rmap_match_set_hook.no_match_ipv6_address_prefix_list;
     650           0 :                 rhc->rhc_rule = "ipv6 address prefix-list";
     651           0 :                 rhc->rhc_event = RMAP_EVENT_PLIST_DELETED;
     652           0 :                 rv = rmap_match_set_hook.match_ipv6_address_prefix_list(
     653             :                         rhc->rhc_rmi, "ipv6 address prefix-list", acl,
     654             :                         RMAP_EVENT_PLIST_ADDED,
     655             :                         args->errmsg, args->errmsg_len);
     656             :         } else
     657             :                 rv = CMD_ERR_NO_MATCH;
     658             : 
     659           0 :         if (rv != CMD_SUCCESS) {
     660           0 :                 rhc->rhc_mhook = NULL;
     661           0 :                 return NB_ERR_INCONSISTENCY;
     662             :         }
     663             : 
     664             :         return NB_OK;
     665             : }
     666             : 
     667           0 : static int lib_route_map_entry_match_condition_list_name_destroy(
     668             :         struct nb_cb_destroy_args *args)
     669             : {
     670           0 :         return lib_route_map_entry_match_destroy(args);
     671             : }
     672             : 
     673             : /*
     674             :  * XPath: /frr-route-map:lib/route-map/entry/match-condition/ipv4-next-hop-type
     675             :  */
     676           0 : static int lib_route_map_entry_match_condition_ipv4_next_hop_type_modify(
     677             :         struct nb_cb_modify_args *args)
     678             : {
     679           0 :         struct routemap_hook_context *rhc;
     680           0 :         const char *type;
     681           0 :         int rv;
     682             : 
     683           0 :         if (args->event != NB_EV_APPLY)
     684             :                 return NB_OK;
     685             : 
     686             :         /* Check for hook function. */
     687           0 :         if (rmap_match_set_hook.match_ip_next_hop_type == NULL)
     688             :                 return NB_OK;
     689             : 
     690             :         /* Add configuration. */
     691           0 :         rhc = nb_running_get_entry(args->dnode, NULL, true);
     692           0 :         type = yang_dnode_get_string(args->dnode, NULL);
     693             : 
     694             :         /* Set destroy information. */
     695           0 :         rhc->rhc_mhook = rmap_match_set_hook.no_match_ip_next_hop_type;
     696           0 :         rhc->rhc_rule = "ip next-hop type";
     697           0 :         rhc->rhc_event = RMAP_EVENT_MATCH_DELETED;
     698             : 
     699           0 :         rv = rmap_match_set_hook.match_ip_next_hop_type(
     700             :                 rhc->rhc_rmi, "ip next-hop type", type,
     701             :                 RMAP_EVENT_MATCH_ADDED,
     702             :                 args->errmsg, args->errmsg_len);
     703           0 :         if (rv != CMD_SUCCESS) {
     704           0 :                 rhc->rhc_mhook = NULL;
     705           0 :                 return NB_ERR_INCONSISTENCY;
     706             :         }
     707             : 
     708             :         return NB_OK;
     709             : }
     710             : 
     711           0 : static int lib_route_map_entry_match_condition_ipv4_next_hop_type_destroy(
     712             :         struct nb_cb_destroy_args *args)
     713             : {
     714           0 :         return lib_route_map_entry_match_destroy(args);
     715             : }
     716             : 
     717             : /*
     718             :  * XPath: /frr-route-map:lib/route-map/entry/match-condition/ipv6-next-hop-type
     719             :  */
     720           0 : static int lib_route_map_entry_match_condition_ipv6_next_hop_type_modify(
     721             :         struct nb_cb_modify_args *args)
     722             : {
     723           0 :         struct routemap_hook_context *rhc;
     724           0 :         const char *type;
     725           0 :         int rv;
     726             : 
     727           0 :         if (args->event != NB_EV_APPLY)
     728             :                 return NB_OK;
     729             : 
     730             :         /* Check for hook function. */
     731           0 :         if (rmap_match_set_hook.match_ipv6_next_hop_type == NULL)
     732             :                 return NB_OK;
     733             : 
     734             :         /* Add configuration. */
     735           0 :         rhc = nb_running_get_entry(args->dnode, NULL, true);
     736           0 :         type = yang_dnode_get_string(args->dnode, NULL);
     737             : 
     738             :         /* Set destroy information. */
     739           0 :         rhc->rhc_mhook = rmap_match_set_hook.no_match_ipv6_next_hop_type;
     740           0 :         rhc->rhc_rule = "ipv6 next-hop type";
     741           0 :         rhc->rhc_event = RMAP_EVENT_MATCH_DELETED;
     742             : 
     743           0 :         rv = rmap_match_set_hook.match_ipv6_next_hop_type(
     744             :                 rhc->rhc_rmi, "ipv6 next-hop type", type,
     745             :                 RMAP_EVENT_MATCH_ADDED,
     746             :                 args->errmsg, args->errmsg_len);
     747           0 :         if (rv != CMD_SUCCESS) {
     748           0 :                 rhc->rhc_mhook = NULL;
     749           0 :                 return NB_ERR_INCONSISTENCY;
     750             :         }
     751             : 
     752             :         return NB_OK;
     753             : }
     754             : 
     755           0 : static int lib_route_map_entry_match_condition_ipv6_next_hop_type_destroy(
     756             :         struct nb_cb_destroy_args *args)
     757             : {
     758           0 :         return lib_route_map_entry_match_destroy(args);
     759             : }
     760             : 
     761             : /*
     762             :  * XPath: /frr-route-map:lib/route-map/entry/match-condition/metric
     763             :  */
     764           0 : static int lib_route_map_entry_match_condition_metric_modify(
     765             :         struct nb_cb_modify_args *args)
     766             : {
     767           0 :         struct routemap_hook_context *rhc;
     768           0 :         const char *type;
     769           0 :         int rv;
     770             : 
     771           0 :         if (args->event != NB_EV_APPLY)
     772             :                 return NB_OK;
     773             : 
     774             :         /* Check for hook function. */
     775           0 :         if (rmap_match_set_hook.match_metric == NULL)
     776             :                 return NB_OK;
     777             : 
     778             :         /* Add configuration. */
     779           0 :         rhc = nb_running_get_entry(args->dnode, NULL, true);
     780           0 :         type = yang_dnode_get_string(args->dnode, NULL);
     781             : 
     782             :         /* Set destroy information. */
     783           0 :         rhc->rhc_mhook = rmap_match_set_hook.no_match_metric;
     784           0 :         rhc->rhc_rule = "metric";
     785           0 :         rhc->rhc_event = RMAP_EVENT_MATCH_DELETED;
     786             : 
     787           0 :         rv = rmap_match_set_hook.match_metric(rhc->rhc_rmi, "metric",
     788             :                                               type, RMAP_EVENT_MATCH_ADDED,
     789             :                                               args->errmsg, args->errmsg_len);
     790           0 :         if (rv != CMD_SUCCESS) {
     791           0 :                 rhc->rhc_mhook = NULL;
     792           0 :                 return NB_ERR_INCONSISTENCY;
     793             :         }
     794             : 
     795             :         return NB_OK;
     796             : }
     797             : 
     798           0 : static int lib_route_map_entry_match_condition_metric_destroy(
     799             :         struct nb_cb_destroy_args *args)
     800             : {
     801           0 :         return lib_route_map_entry_match_destroy(args);
     802             : }
     803             : 
     804             : /*
     805             :  * XPath: /frr-route-map:lib/route-map/entry/match-condition/tag
     806             :  */
     807             : static int
     808           0 : lib_route_map_entry_match_condition_tag_modify(struct nb_cb_modify_args *args)
     809             : {
     810           0 :         struct routemap_hook_context *rhc;
     811           0 :         const char *tag;
     812           0 :         int rv;
     813             : 
     814           0 :         if (args->event != NB_EV_APPLY)
     815             :                 return NB_OK;
     816             : 
     817             :         /* Check for hook function. */
     818           0 :         if (rmap_match_set_hook.match_tag == NULL)
     819             :                 return NB_OK;
     820             : 
     821             :         /* Add configuration. */
     822           0 :         rhc = nb_running_get_entry(args->dnode, NULL, true);
     823           0 :         tag = yang_dnode_get_string(args->dnode, NULL);
     824             : 
     825             :         /* Set destroy information. */
     826           0 :         rhc->rhc_mhook = rmap_match_set_hook.no_match_tag;
     827           0 :         rhc->rhc_rule = "tag";
     828           0 :         rhc->rhc_event = RMAP_EVENT_MATCH_DELETED;
     829             : 
     830           0 :         rv = rmap_match_set_hook.match_tag(rhc->rhc_rmi, "tag", tag,
     831             :                                            RMAP_EVENT_MATCH_ADDED,
     832             :                                            args->errmsg, args->errmsg_len);
     833           0 :         if (rv != CMD_SUCCESS) {
     834           0 :                 rhc->rhc_mhook = NULL;
     835           0 :                 return NB_ERR_INCONSISTENCY;
     836             :         }
     837             : 
     838             :         return NB_OK;
     839             : }
     840             : 
     841             : static int
     842           0 : lib_route_map_entry_match_condition_tag_destroy(struct nb_cb_destroy_args *args)
     843             : {
     844           0 :         return lib_route_map_entry_match_destroy(args);
     845             : }
     846             : 
     847             : /*
     848             :  * XPath: /frr-route-map:lib/route-map/entry/set-action
     849             :  */
     850           0 : static int lib_route_map_entry_set_action_create(struct nb_cb_create_args *args)
     851             : {
     852           0 :         return lib_route_map_entry_match_condition_create(args);
     853             : }
     854             : 
     855             : static int
     856           0 : lib_route_map_entry_set_action_destroy(struct nb_cb_destroy_args *args)
     857             : {
     858           0 :         struct routemap_hook_context *rhc;
     859           0 :         int rv;
     860             : 
     861           0 :         if (args->event != NB_EV_APPLY)
     862             :                 return NB_OK;
     863             : 
     864           0 :         rv = lib_route_map_entry_set_destroy(args);
     865           0 :         rhc = nb_running_unset_entry(args->dnode);
     866           0 :         routemap_hook_context_free(rhc);
     867             : 
     868           0 :         return rv;
     869             : }
     870             : 
     871             : /*
     872             :  * XPath: /frr-route-map:lib/route-map/entry/set-action/ipv4-address
     873             :  */
     874           0 : static int lib_route_map_entry_set_action_ipv4_address_modify(
     875             :         struct nb_cb_modify_args *args)
     876             : {
     877           0 :         struct routemap_hook_context *rhc;
     878           0 :         const char *address;
     879           0 :         struct in_addr ia;
     880           0 :         int rv;
     881             : 
     882           0 :         switch (args->event) {
     883           0 :         case NB_EV_VALIDATE:
     884             :                 /*
     885             :                  * NOTE: validate if 'action' is 'ipv4-next-hop',
     886             :                  * currently it is not necessary because this is the
     887             :                  * only implemented action.
     888             :                  */
     889           0 :                 yang_dnode_get_ipv4(&ia, args->dnode, NULL);
     890           0 :                 if (ia.s_addr == INADDR_ANY || !ipv4_unicast_valid(&ia))
     891           0 :                         return NB_ERR_VALIDATION;
     892             :                 /* FALLTHROUGH */
     893             :         case NB_EV_PREPARE:
     894             :         case NB_EV_ABORT:
     895             :                 return NB_OK;
     896             :         case NB_EV_APPLY:
     897             :                 break;
     898             :         }
     899             : 
     900             :         /* Check for hook function. */
     901           0 :         if (rmap_match_set_hook.set_ip_nexthop == NULL)
     902             :                 return NB_OK;
     903             : 
     904             :         /* Add configuration. */
     905           0 :         rhc = nb_running_get_entry(args->dnode, NULL, true);
     906           0 :         address = yang_dnode_get_string(args->dnode, NULL);
     907             : 
     908             :         /* Set destroy information. */
     909           0 :         rhc->rhc_shook = rmap_match_set_hook.no_set_ip_nexthop;
     910           0 :         rhc->rhc_rule = "ip next-hop";
     911             : 
     912           0 :         rv = rmap_match_set_hook.set_ip_nexthop(rhc->rhc_rmi, "ip next-hop",
     913             :                                                 address,
     914             :                                                 args->errmsg, args->errmsg_len);
     915           0 :         if (rv != CMD_SUCCESS) {
     916           0 :                 rhc->rhc_shook = NULL;
     917           0 :                 return NB_ERR_INCONSISTENCY;
     918             :         }
     919             : 
     920             :         return NB_OK;
     921             : }
     922             : 
     923           0 : static int lib_route_map_entry_set_action_ipv4_address_destroy(
     924             :         struct nb_cb_destroy_args *args)
     925             : {
     926           0 :         return lib_route_map_entry_set_destroy(args);
     927             : }
     928             : 
     929             : /*
     930             :  * XPath: /frr-route-map:lib/route-map/entry/set-action/ipv6-address
     931             :  */
     932           0 : static int lib_route_map_entry_set_action_ipv6_address_modify(
     933             :         struct nb_cb_modify_args *args)
     934             : {
     935           0 :         struct routemap_hook_context *rhc;
     936           0 :         const char *address;
     937           0 :         struct in6_addr i6a;
     938           0 :         int rv;
     939             : 
     940           0 :         switch (args->event) {
     941           0 :         case NB_EV_VALIDATE:
     942             :                 /*
     943             :                  * NOTE: validate if 'action' is 'ipv6-next-hop',
     944             :                  * currently it is not necessary because this is the
     945             :                  * only implemented action. Other actions might have
     946             :                  * different validations.
     947             :                  */
     948           0 :                 yang_dnode_get_ipv6(&i6a, args->dnode, NULL);
     949           0 :                 if (!IN6_IS_ADDR_LINKLOCAL(&i6a))
     950             :                         return NB_ERR_VALIDATION;
     951             :                 /* FALLTHROUGH */
     952             :         case NB_EV_PREPARE:
     953             :         case NB_EV_ABORT:
     954             :                 return NB_OK;
     955             :         case NB_EV_APPLY:
     956             :                 break;
     957             :         }
     958             : 
     959             :         /* Check for hook function. */
     960           0 :         if (rmap_match_set_hook.set_ipv6_nexthop_local == NULL)
     961             :                 return NB_OK;
     962             : 
     963             :         /* Add configuration. */
     964           0 :         rhc = nb_running_get_entry(args->dnode, NULL, true);
     965           0 :         address = yang_dnode_get_string(args->dnode, NULL);
     966             : 
     967             :         /* Set destroy information. */
     968           0 :         rhc->rhc_shook = rmap_match_set_hook.no_set_ipv6_nexthop_local;
     969           0 :         rhc->rhc_rule = "ipv6 next-hop local";
     970             : 
     971           0 :         rv = rmap_match_set_hook.set_ipv6_nexthop_local(
     972             :                 rhc->rhc_rmi, "ipv6 next-hop local", address,
     973             :                 args->errmsg, args->errmsg_len);
     974           0 :         if (rv != CMD_SUCCESS) {
     975           0 :                 rhc->rhc_shook = NULL;
     976           0 :                 return NB_ERR_INCONSISTENCY;
     977             :         }
     978             : 
     979             :         return NB_OK;
     980             : }
     981             : 
     982           0 : static int lib_route_map_entry_set_action_ipv6_address_destroy(
     983             :         struct nb_cb_destroy_args *args)
     984             : {
     985           0 :         return lib_route_map_entry_set_destroy(args);
     986             : }
     987             : 
     988             : /*
     989             :  * XPath: /frr-route-map:lib/route-map/entry/set-action/value
     990             :  */
     991           0 : static int set_action_modify(enum nb_event event, const struct lyd_node *dnode,
     992             :                              union nb_resource *resource, const char *value,
     993             :                              char *errmsg, size_t errmsg_len)
     994             : {
     995           0 :         struct routemap_hook_context *rhc;
     996           0 :         int rv;
     997             : 
     998             :         /*
     999             :          * NOTE: validate if 'action' is 'metric', currently it is not
    1000             :          * necessary because this is the only implemented action. Other
    1001             :          * actions might have different validations.
    1002             :          */
    1003           0 :         if (event != NB_EV_APPLY)
    1004             :                 return NB_OK;
    1005             : 
    1006             :         /* Check for hook function. */
    1007           0 :         if (rmap_match_set_hook.set_metric == NULL)
    1008             :                 return NB_OK;
    1009             : 
    1010             :         /* Add configuration. */
    1011           0 :         rhc = nb_running_get_entry(dnode, NULL, true);
    1012             : 
    1013             :         /* Set destroy information. */
    1014           0 :         rhc->rhc_shook = rmap_match_set_hook.no_set_metric;
    1015           0 :         rhc->rhc_rule = "metric";
    1016             : 
    1017           0 :         rv = rmap_match_set_hook.set_metric(rhc->rhc_rmi, "metric",
    1018             :                                             value,
    1019             :                                             errmsg, errmsg_len
    1020             :                                             );
    1021           0 :         if (rv != CMD_SUCCESS) {
    1022           0 :                 rhc->rhc_shook = NULL;
    1023           0 :                 return NB_ERR_INCONSISTENCY;
    1024             :         }
    1025             : 
    1026             :         return NB_OK;
    1027             : }
    1028             : 
    1029             : static int
    1030           0 : lib_route_map_entry_set_action_value_modify(struct nb_cb_modify_args *args)
    1031             : {
    1032           0 :         const char *metric = yang_dnode_get_string(args->dnode, NULL);
    1033             : 
    1034           0 :         return set_action_modify(args->event, args->dnode, args->resource,
    1035             :                                  metric, args->errmsg, args->errmsg_len);
    1036             : }
    1037             : 
    1038             : static int
    1039           0 : lib_route_map_entry_set_action_value_destroy(struct nb_cb_destroy_args *args)
    1040             : {
    1041           0 :         return lib_route_map_entry_set_destroy(args);
    1042             : }
    1043             : 
    1044             : /*
    1045             :  * XPath: /frr-route-map:lib/route-map/entry/set-action/add-metric
    1046             :  */
    1047             : static int
    1048           0 : lib_route_map_entry_set_action_add_metric_modify(struct nb_cb_modify_args *args)
    1049             : {
    1050           0 :         char metric_str[16];
    1051             : 
    1052           0 :         if (args->event == NB_EV_VALIDATE
    1053           0 :             && yang_dnode_get_uint32(args->dnode, NULL) == 0) {
    1054           0 :                 snprintf(args->errmsg, args->errmsg_len,
    1055             :                          "Can't add zero to metric");
    1056           0 :                 return NB_ERR_VALIDATION;
    1057             :         }
    1058             : 
    1059           0 :         snprintf(metric_str, sizeof(metric_str), "+%s",
    1060             :                  yang_dnode_get_string(args->dnode, NULL));
    1061           0 :         return set_action_modify(args->event, args->dnode, args->resource,
    1062             :                                  metric_str,
    1063             :                                  args->errmsg, args->errmsg_len);
    1064             : }
    1065             : 
    1066           0 : static int lib_route_map_entry_set_action_add_metric_destroy(
    1067             :         struct nb_cb_destroy_args *args)
    1068             : {
    1069           0 :         return lib_route_map_entry_set_action_value_destroy(args);
    1070             : }
    1071             : 
    1072             : /*
    1073             :  * XPath: /frr-route-map:lib/route-map/entry/set-action/subtract-metric
    1074             :  */
    1075           0 : static int lib_route_map_entry_set_action_subtract_metric_modify(
    1076             :         struct nb_cb_modify_args *args)
    1077             : {
    1078           0 :         char metric_str[16];
    1079             : 
    1080           0 :         if (args->event == NB_EV_VALIDATE
    1081           0 :             && yang_dnode_get_uint32(args->dnode, NULL) == 0) {
    1082           0 :                 snprintf(args->errmsg, args->errmsg_len,
    1083             :                          "Can't subtract zero from metric");
    1084           0 :                 return NB_ERR_VALIDATION;
    1085             :         }
    1086             : 
    1087           0 :         snprintf(metric_str, sizeof(metric_str), "-%s",
    1088             :                  yang_dnode_get_string(args->dnode, NULL));
    1089           0 :         return set_action_modify(args->event, args->dnode, args->resource,
    1090             :                                  metric_str,
    1091             :                                  args->errmsg, args->errmsg_len);
    1092             : }
    1093             : 
    1094           0 : static int lib_route_map_entry_set_action_subtract_metric_destroy(
    1095             :         struct nb_cb_destroy_args *args)
    1096             : {
    1097           0 :         return lib_route_map_entry_set_action_value_destroy(args);
    1098             : }
    1099             : 
    1100             : /*
    1101             :  * XPath: /frr-route-map:lib/route-map/entry/set-action/use-round-trip-time
    1102             :  */
    1103           0 : static int lib_route_map_entry_set_action_use_round_trip_time_modify(
    1104             :         struct nb_cb_modify_args *args)
    1105             : {
    1106           0 :         return set_action_modify(args->event, args->dnode, args->resource,
    1107             :                                  "rtt",
    1108             :                                  args->errmsg, args->errmsg_len);
    1109             : }
    1110             : 
    1111           0 : static int lib_route_map_entry_set_action_use_round_trip_time_destroy(
    1112             :         struct nb_cb_destroy_args *args)
    1113             : {
    1114           0 :         return lib_route_map_entry_set_action_value_destroy(args);
    1115             : }
    1116             : 
    1117             : /*
    1118             :  * XPath: /frr-route-map:lib/route-map/entry/set-action/add-round-trip-time
    1119             :  */
    1120           0 : static int lib_route_map_entry_set_action_add_round_trip_time_modify(
    1121             :         struct nb_cb_modify_args *args)
    1122             : {
    1123           0 :         return set_action_modify(args->event, args->dnode, args->resource,
    1124             :                                  "+rtt",
    1125             :                                  args->errmsg, args->errmsg_len);
    1126             : }
    1127             : 
    1128           0 : static int lib_route_map_entry_set_action_add_round_trip_time_destroy(
    1129             :         struct nb_cb_destroy_args *args)
    1130             : {
    1131           0 :         return lib_route_map_entry_set_action_value_destroy(args);
    1132             : }
    1133             : 
    1134             : /*
    1135             :  * XPath: /frr-route-map:lib/route-map/entry/set-action/subtract-round-trip-time
    1136             :  */
    1137           0 : static int lib_route_map_entry_set_action_subtract_round_trip_time_modify(
    1138             :         struct nb_cb_modify_args *args)
    1139             : {
    1140           0 :         return set_action_modify(args->event, args->dnode, args->resource,
    1141             :                                  "-rtt", args->errmsg, args->errmsg_len);
    1142             : }
    1143             : 
    1144           0 : static int lib_route_map_entry_set_action_subtract_round_trip_time_destroy(
    1145             :         struct nb_cb_destroy_args *args)
    1146             : {
    1147           0 :         return lib_route_map_entry_set_action_value_destroy(args);
    1148             : }
    1149             : 
    1150             : /*
    1151             :  * XPath: /frr-route-map:lib/route-map/entry/set-action/tag
    1152             :  */
    1153             : static int
    1154           0 : lib_route_map_entry_set_action_tag_modify(struct nb_cb_modify_args *args)
    1155             : {
    1156           0 :         struct routemap_hook_context *rhc;
    1157           0 :         const char *tag;
    1158           0 :         int rv;
    1159             : 
    1160             :         /*
    1161             :          * NOTE: validate if 'action' is 'tag', currently it is not
    1162             :          * necessary because this is the only implemented action. Other
    1163             :          * actions might have different validations.
    1164             :          */
    1165           0 :         if (args->event != NB_EV_APPLY)
    1166             :                 return NB_OK;
    1167             : 
    1168             :         /* Check for hook function. */
    1169           0 :         if (rmap_match_set_hook.set_tag == NULL)
    1170             :                 return NB_OK;
    1171             : 
    1172             :         /* Add configuration. */
    1173           0 :         rhc = nb_running_get_entry(args->dnode, NULL, true);
    1174           0 :         tag = yang_dnode_get_string(args->dnode, NULL);
    1175             : 
    1176             :         /* Set destroy information. */
    1177           0 :         rhc->rhc_shook = rmap_match_set_hook.no_set_tag;
    1178           0 :         rhc->rhc_rule = "tag";
    1179             : 
    1180           0 :         rv = rmap_match_set_hook.set_tag(rhc->rhc_rmi, "tag", tag,
    1181             :                                          args->errmsg, args->errmsg_len);
    1182           0 :         if (rv != CMD_SUCCESS) {
    1183           0 :                 rhc->rhc_shook = NULL;
    1184           0 :                 return NB_ERR_INCONSISTENCY;
    1185             :         }
    1186             : 
    1187             :         return NB_OK;
    1188             : }
    1189             : 
    1190             : static int
    1191           0 : lib_route_map_entry_set_action_tag_destroy(struct nb_cb_destroy_args *args)
    1192             : {
    1193           0 :         return lib_route_map_entry_set_destroy(args);
    1194             : }
    1195             : 
    1196             : /*
    1197             :  * XPath: /frr-route-map:lib/route-map/entry/set-action/policy
    1198             :  */
    1199             : static int
    1200           0 : lib_route_map_entry_set_action_policy_modify(struct nb_cb_modify_args *args)
    1201             : {
    1202           0 :         struct routemap_hook_context *rhc;
    1203           0 :         const char *policy;
    1204           0 :         int rv;
    1205             : 
    1206             :         /*
    1207             :          * NOTE: validate if 'action' is 'tag', currently it is not
    1208             :          * necessary because this is the only implemented action. Other
    1209             :          * actions might have different validations.
    1210             :          */
    1211           0 :         if (args->event != NB_EV_APPLY)
    1212             :                 return NB_OK;
    1213             : 
    1214             :         /* Check for hook function. */
    1215           0 :         if (rmap_match_set_hook.set_srte_color == NULL)
    1216             :                 return NB_OK;
    1217             : 
    1218             :         /* Add configuration. */
    1219           0 :         rhc = nb_running_get_entry(args->dnode, NULL, true);
    1220           0 :         policy = yang_dnode_get_string(args->dnode, NULL);
    1221             : 
    1222             :         /* Set destroy information. */
    1223           0 :         rhc->rhc_shook = rmap_match_set_hook.no_set_tag;
    1224           0 :         rhc->rhc_rule = "sr-te color";
    1225             : 
    1226           0 :         rv = rmap_match_set_hook.set_tag(rhc->rhc_rmi, "sr-te color", policy,
    1227             :                         args->errmsg, args->errmsg_len);
    1228           0 :         if (rv != CMD_SUCCESS) {
    1229           0 :                 rhc->rhc_shook = NULL;
    1230           0 :                 return NB_ERR_INCONSISTENCY;
    1231             :         }
    1232             : 
    1233             :         return NB_OK;
    1234             : }
    1235             : 
    1236             : static int
    1237           0 : lib_route_map_entry_set_action_policy_destroy(struct nb_cb_destroy_args *args)
    1238             : {
    1239           0 :         return lib_route_map_entry_set_destroy(args);
    1240             : }
    1241             : 
    1242             : /* clang-format off */
    1243             : const struct frr_yang_module_info frr_route_map_info = {
    1244             :         .name = "frr-route-map",
    1245             :         .nodes = {
    1246             :                 {
    1247             :                         .xpath = "/frr-route-map:lib/route-map",
    1248             :                         .cbs = {
    1249             :                                 .create = lib_route_map_create,
    1250             :                                 .destroy = lib_route_map_destroy,
    1251             :                         }
    1252             :                 },
    1253             :                 {
    1254             :                         .xpath = "/frr-route-map:lib/route-map/optimization-disabled",
    1255             :                         .cbs = {
    1256             :                                 .modify = lib_route_map_optimization_disabled_modify,
    1257             :                                 .cli_show = route_map_optimization_disabled_show,
    1258             :                         }
    1259             :                 },
    1260             :                 {
    1261             :                         .xpath = "/frr-route-map:lib/route-map/entry",
    1262             :                         .cbs = {
    1263             :                                 .create = lib_route_map_entry_create,
    1264             :                                 .destroy = lib_route_map_entry_destroy,
    1265             :                                 .cli_cmp = route_map_instance_cmp,
    1266             :                                 .cli_show = route_map_instance_show,
    1267             :                                 .cli_show_end = route_map_instance_show_end,
    1268             :                         }
    1269             :                 },
    1270             :                 {
    1271             :                         .xpath = "/frr-route-map:lib/route-map/entry/description",
    1272             :                         .cbs = {
    1273             :                                 .modify = lib_route_map_entry_description_modify,
    1274             :                                 .destroy = lib_route_map_entry_description_destroy,
    1275             :                                 .cli_show = route_map_description_show,
    1276             :                         }
    1277             :                 },
    1278             :                 {
    1279             :                         .xpath = "/frr-route-map:lib/route-map/entry/action",
    1280             :                         .cbs = {
    1281             :                                 .modify = lib_route_map_entry_action_modify,
    1282             :                         }
    1283             :                 },
    1284             :                 {
    1285             :                         .xpath = "/frr-route-map:lib/route-map/entry/call",
    1286             :                         .cbs = {
    1287             :                                 .modify = lib_route_map_entry_call_modify,
    1288             :                                 .destroy = lib_route_map_entry_call_destroy,
    1289             :                                 .cli_show = route_map_call_show,
    1290             :                         }
    1291             :                 },
    1292             :                 {
    1293             :                         .xpath = "/frr-route-map:lib/route-map/entry/exit-policy",
    1294             :                         .cbs = {
    1295             :                                 .modify = lib_route_map_entry_exit_policy_modify,
    1296             :                                 .cli_show = route_map_exit_policy_show,
    1297             :                         }
    1298             :                 },
    1299             :                 {
    1300             :                         .xpath = "/frr-route-map:lib/route-map/entry/goto-value",
    1301             :                         .cbs = {
    1302             :                                 .modify = lib_route_map_entry_goto_value_modify,
    1303             :                                 .destroy = lib_route_map_entry_goto_value_destroy,
    1304             :                         }
    1305             :                 },
    1306             :                 {
    1307             :                         .xpath = "/frr-route-map:lib/route-map/entry/match-condition",
    1308             :                         .cbs = {
    1309             :                                 .create = lib_route_map_entry_match_condition_create,
    1310             :                                 .destroy = lib_route_map_entry_match_condition_destroy,
    1311             :                                 .cli_show = route_map_condition_show,
    1312             :                         }
    1313             :                 },
    1314             :                 {
    1315             :                         .xpath = "/frr-route-map:lib/route-map/entry/match-condition/rmap-match-condition/interface",
    1316             :                         .cbs = {
    1317             :                                 .modify = lib_route_map_entry_match_condition_interface_modify,
    1318             :                                 .destroy = lib_route_map_entry_match_condition_interface_destroy,
    1319             :                         }
    1320             :                 },
    1321             :                 {
    1322             :                         .xpath = "/frr-route-map:lib/route-map/entry/match-condition/rmap-match-condition/list-name",
    1323             :                         .cbs = {
    1324             :                                 .modify = lib_route_map_entry_match_condition_list_name_modify,
    1325             :                                 .destroy = lib_route_map_entry_match_condition_list_name_destroy,
    1326             :                         }
    1327             :                 },
    1328             :                 {
    1329             :                         .xpath = "/frr-route-map:lib/route-map/entry/match-condition/rmap-match-condition/ipv4-next-hop-type",
    1330             :                         .cbs = {
    1331             :                                 .modify = lib_route_map_entry_match_condition_ipv4_next_hop_type_modify,
    1332             :                                 .destroy = lib_route_map_entry_match_condition_ipv4_next_hop_type_destroy,
    1333             :                         }
    1334             :                 },
    1335             :                 {
    1336             :                         .xpath = "/frr-route-map:lib/route-map/entry/match-condition/rmap-match-condition/ipv6-next-hop-type",
    1337             :                         .cbs = {
    1338             :                                 .modify = lib_route_map_entry_match_condition_ipv6_next_hop_type_modify,
    1339             :                                 .destroy = lib_route_map_entry_match_condition_ipv6_next_hop_type_destroy,
    1340             :                         }
    1341             :                 },
    1342             :                 {
    1343             :                         .xpath = "/frr-route-map:lib/route-map/entry/match-condition/rmap-match-condition/metric",
    1344             :                         .cbs = {
    1345             :                                 .modify = lib_route_map_entry_match_condition_metric_modify,
    1346             :                                 .destroy = lib_route_map_entry_match_condition_metric_destroy,
    1347             :                         }
    1348             :                 },
    1349             :                 {
    1350             :                         .xpath = "/frr-route-map:lib/route-map/entry/match-condition/rmap-match-condition/tag",
    1351             :                         .cbs = {
    1352             :                                 .modify = lib_route_map_entry_match_condition_tag_modify,
    1353             :                                 .destroy = lib_route_map_entry_match_condition_tag_destroy,
    1354             :                         }
    1355             :                 },
    1356             :                 {
    1357             :                         .xpath = "/frr-route-map:lib/route-map/entry/set-action",
    1358             :                         .cbs = {
    1359             :                                 .create = lib_route_map_entry_set_action_create,
    1360             :                                 .destroy = lib_route_map_entry_set_action_destroy,
    1361             :                                 .cli_show = route_map_action_show,
    1362             :                         }
    1363             :                 },
    1364             :                 {
    1365             :                         .xpath = "/frr-route-map:lib/route-map/entry/set-action/rmap-set-action/ipv4-address",
    1366             :                         .cbs = {
    1367             :                                 .modify = lib_route_map_entry_set_action_ipv4_address_modify,
    1368             :                                 .destroy = lib_route_map_entry_set_action_ipv4_address_destroy,
    1369             :                         }
    1370             :                 },
    1371             :                 {
    1372             :                         .xpath = "/frr-route-map:lib/route-map/entry/set-action/rmap-set-action/ipv6-address",
    1373             :                         .cbs = {
    1374             :                                 .modify = lib_route_map_entry_set_action_ipv6_address_modify,
    1375             :                                 .destroy = lib_route_map_entry_set_action_ipv6_address_destroy,
    1376             :                         }
    1377             :                 },
    1378             :                 {
    1379             :                         .xpath = "/frr-route-map:lib/route-map/entry/set-action/rmap-set-action/value",
    1380             :                         .cbs = {
    1381             :                                 .modify = lib_route_map_entry_set_action_value_modify,
    1382             :                                 .destroy = lib_route_map_entry_set_action_value_destroy,
    1383             :                         }
    1384             :                 },
    1385             :                 {
    1386             :                         .xpath = "/frr-route-map:lib/route-map/entry/set-action/rmap-set-action/add-metric",
    1387             :                         .cbs = {
    1388             :                                 .modify = lib_route_map_entry_set_action_add_metric_modify,
    1389             :                                 .destroy = lib_route_map_entry_set_action_add_metric_destroy,
    1390             :                         }
    1391             :                 },
    1392             :                 {
    1393             :                         .xpath = "/frr-route-map:lib/route-map/entry/set-action/rmap-set-action/subtract-metric",
    1394             :                         .cbs = {
    1395             :                                 .modify = lib_route_map_entry_set_action_subtract_metric_modify,
    1396             :                                 .destroy = lib_route_map_entry_set_action_subtract_metric_destroy,
    1397             :                         }
    1398             :                 },
    1399             :                 {
    1400             :                         .xpath = "/frr-route-map:lib/route-map/entry/set-action/rmap-set-action/use-round-trip-time",
    1401             :                         .cbs = {
    1402             :                                 .modify = lib_route_map_entry_set_action_use_round_trip_time_modify,
    1403             :                                 .destroy = lib_route_map_entry_set_action_use_round_trip_time_destroy,
    1404             :                         }
    1405             :                 },
    1406             :                 {
    1407             :                         .xpath = "/frr-route-map:lib/route-map/entry/set-action/rmap-set-action/add-round-trip-time",
    1408             :                         .cbs = {
    1409             :                                 .modify = lib_route_map_entry_set_action_add_round_trip_time_modify,
    1410             :                                 .destroy = lib_route_map_entry_set_action_add_round_trip_time_destroy,
    1411             :                         }
    1412             :                 },
    1413             :                 {
    1414             :                         .xpath = "/frr-route-map:lib/route-map/entry/set-action/rmap-set-action/subtract-round-trip-time",
    1415             :                         .cbs = {
    1416             :                                 .modify = lib_route_map_entry_set_action_subtract_round_trip_time_modify,
    1417             :                                 .destroy = lib_route_map_entry_set_action_subtract_round_trip_time_destroy,
    1418             :                         }
    1419             :                 },
    1420             :                 {
    1421             :                         .xpath = "/frr-route-map:lib/route-map/entry/set-action/rmap-set-action/tag",
    1422             :                         .cbs = {
    1423             :                                 .modify = lib_route_map_entry_set_action_tag_modify,
    1424             :                                 .destroy = lib_route_map_entry_set_action_tag_destroy,
    1425             :                         }
    1426             :                 },
    1427             :                 {
    1428             :                         .xpath = "/frr-route-map:lib/route-map/entry/set-action/rmap-set-action/policy",
    1429             :                         .cbs = {
    1430             :                                 .modify = lib_route_map_entry_set_action_policy_modify,
    1431             :                                 .destroy = lib_route_map_entry_set_action_policy_destroy,
    1432             :                         }
    1433             :                 },
    1434             : 
    1435             :                 {
    1436             :                         .xpath = NULL,
    1437             :                 },
    1438             :         }
    1439             : };

Generated by: LCOV version v1.16-topotato