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