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