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