1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Route map northbound implementation.
5 * Copyright (C) 2019 Network Device Education Foundation, Inc. ("NetDEF")
11 #include "lib/command.h"
13 #include "lib/northbound.h"
14 #include "lib/routemap.h"
17 * Auxiliary functions to avoid code duplication:
19 * lib_route_map_entry_set_destroy: unset `set` commands.
20 * lib_route_map_entry_match_destroy: unset `match` commands.
22 int lib_route_map_entry_match_destroy(struct nb_cb_destroy_args
*args
)
24 struct routemap_hook_context
*rhc
;
27 if (args
->event
!= NB_EV_APPLY
)
30 rhc
= nb_running_get_entry(args
->dnode
, NULL
, true);
31 if (rhc
->rhc_mhook
== NULL
)
34 rv
= rhc
->rhc_mhook(rhc
->rhc_rmi
, rhc
->rhc_rule
, NULL
,
36 args
->errmsg
, args
->errmsg_len
);
37 if (rv
!= CMD_SUCCESS
)
38 return NB_ERR_INCONSISTENCY
;
43 int lib_route_map_entry_set_destroy(struct nb_cb_destroy_args
*args
)
45 struct routemap_hook_context
*rhc
;
48 if (args
->event
!= NB_EV_APPLY
)
51 rhc
= nb_running_get_entry(args
->dnode
, NULL
, true);
52 if (rhc
->rhc_shook
== NULL
)
55 rv
= rhc
->rhc_shook(rhc
->rhc_rmi
, rhc
->rhc_rule
, NULL
,
56 args
->errmsg
, args
->errmsg_len
);
57 if (rv
!= CMD_SUCCESS
)
58 return NB_ERR_INCONSISTENCY
;
64 * Auxiliary hook context list manipulation functions.
66 struct routemap_hook_context
*
67 routemap_hook_context_insert(struct route_map_index
*rmi
)
69 struct routemap_hook_context
*rhc
;
71 rhc
= XCALLOC(MTYPE_TMP
, sizeof(*rhc
));
73 TAILQ_INSERT_TAIL(&rmi
->rhclist
, rhc
, rhc_entry
);
78 void routemap_hook_context_free(struct routemap_hook_context
*rhc
)
80 struct route_map_index
*rmi
= rhc
->rhc_rmi
;
82 TAILQ_REMOVE(&rmi
->rhclist
, rhc
, rhc_entry
);
83 XFREE(MTYPE_TMP
, rhc
);
87 * XPath: /frr-route-map:lib/route-map
89 static int lib_route_map_create(struct nb_cb_create_args
*args
)
94 switch (args
->event
) {
101 rm_name
= yang_dnode_get_string(args
->dnode
, "./name");
102 rm
= route_map_get(rm_name
);
103 nb_running_set_entry(args
->dnode
, rm
);
110 static int lib_route_map_destroy(struct nb_cb_destroy_args
*args
)
112 struct route_map
*rm
;
114 switch (args
->event
) {
121 rm
= nb_running_unset_entry(args
->dnode
);
122 route_map_delete(rm
);
130 * XPath: /frr-route-map:lib/route-map/optimization-disabled
133 lib_route_map_optimization_disabled_modify(struct nb_cb_modify_args
*args
)
135 struct route_map
*rm
;
136 bool disabled
= yang_dnode_get_bool(args
->dnode
, NULL
);
138 switch (args
->event
) {
145 rm
= nb_running_get_entry(args
->dnode
, NULL
, true);
146 rm
->optimization_disabled
= disabled
;
154 * XPath: /frr-route-map:lib/route-map/entry
156 static int lib_route_map_entry_create(struct nb_cb_create_args
*args
)
158 struct route_map_index
*rmi
;
159 struct route_map
*rm
;
163 switch (args
->event
) {
170 sequence
= yang_dnode_get_uint16(args
->dnode
, "./sequence");
171 action
= yang_dnode_get_enum(args
->dnode
, "./action") == 0
174 rm
= nb_running_get_entry(args
->dnode
, NULL
, true);
175 rmi
= route_map_index_get(rm
, action
, sequence
);
176 nb_running_set_entry(args
->dnode
, rmi
);
183 static int lib_route_map_entry_destroy(struct nb_cb_destroy_args
*args
)
185 struct route_map_index
*rmi
;
187 switch (args
->event
) {
194 rmi
= nb_running_unset_entry(args
->dnode
);
195 route_map_index_delete(rmi
, 1);
203 * XPath: /frr-route-map:lib/route-map/entry/description
206 lib_route_map_entry_description_modify(struct nb_cb_modify_args
*args
)
208 struct route_map_index
*rmi
;
209 const char *description
;
211 switch (args
->event
) {
216 description
= yang_dnode_get_string(args
->dnode
, NULL
);
217 args
->resource
->ptr
= XSTRDUP(MTYPE_TMP
, description
);
218 if (args
->resource
->ptr
== NULL
)
219 return NB_ERR_RESOURCE
;
222 XFREE(MTYPE_TMP
, args
->resource
->ptr
);
225 rmi
= nb_running_get_entry(args
->dnode
, NULL
, true);
226 XFREE(MTYPE_TMP
, rmi
->description
);
227 rmi
->description
= args
->resource
->ptr
;
235 lib_route_map_entry_description_destroy(struct nb_cb_destroy_args
*args
)
237 struct route_map_index
*rmi
;
239 switch (args
->event
) {
246 rmi
= nb_running_get_entry(args
->dnode
, NULL
, true);
247 XFREE(MTYPE_TMP
, rmi
->description
);
255 * XPath: /frr-route-map:lib/route-map/entry/action
257 static int lib_route_map_entry_action_modify(struct nb_cb_modify_args
*args
)
259 struct route_map_index
*rmi
;
260 struct route_map
*map
;
262 switch (args
->event
) {
269 rmi
= nb_running_get_entry(args
->dnode
, NULL
, true);
270 rmi
->type
= yang_dnode_get_enum(args
->dnode
, NULL
);
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
);
287 * XPath: /frr-route-map:lib/route-map/entry/call
289 static int lib_route_map_entry_call_modify(struct nb_cb_modify_args
*args
)
291 struct route_map_index
*rmi
;
292 const char *rm_name
, *rmn_name
;
294 switch (args
->event
) {
296 rm_name
= yang_dnode_get_string(args
->dnode
, "../../name");
297 rmn_name
= yang_dnode_get_string(args
->dnode
, NULL
);
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
;
302 /* TODO: detect circular route map sequences. */
305 rmn_name
= yang_dnode_get_string(args
->dnode
, NULL
);
306 args
->resource
->ptr
= XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmn_name
);
309 XFREE(MTYPE_ROUTE_MAP_NAME
, args
->resource
->ptr
);
312 rmi
= nb_running_get_entry(args
->dnode
, NULL
, true);
314 route_map_upd8_dependency(RMAP_EVENT_CALL_DELETED
,
315 rmi
->nextrm
, rmi
->map
->name
);
316 XFREE(MTYPE_ROUTE_MAP_NAME
, rmi
->nextrm
);
318 rmi
->nextrm
= args
->resource
->ptr
;
319 route_map_upd8_dependency(RMAP_EVENT_CALL_ADDED
, rmi
->nextrm
,
327 static int lib_route_map_entry_call_destroy(struct nb_cb_destroy_args
*args
)
329 struct route_map_index
*rmi
;
331 switch (args
->event
) {
338 rmi
= nb_running_get_entry(args
->dnode
, NULL
, true);
339 route_map_upd8_dependency(RMAP_EVENT_CALL_DELETED
, rmi
->nextrm
,
341 XFREE(MTYPE_ROUTE_MAP_NAME
, rmi
->nextrm
);
350 * XPath: /frr-route-map:lib/route-map/entry/exit-policy
353 lib_route_map_entry_exit_policy_modify(struct nb_cb_modify_args
*args
)
355 struct route_map_index
*rmi
;
359 switch (args
->event
) {
361 policy
= yang_dnode_get_enum(args
->dnode
, NULL
);
363 case 0: /* permit-or-deny */
369 yang_dnode_get_enum(args
->dnode
, "../action");
370 if (rm_action
== 1 /* deny */) {
372 * On deny it is not possible to 'goto'
375 return NB_ERR_VALIDATION
;
384 rmi
= nb_running_get_entry(args
->dnode
, NULL
, true);
385 policy
= yang_dnode_get_enum(args
->dnode
, NULL
);
388 case 0: /* permit-or-deny */
389 rmi
->exitpolicy
= RMAP_EXIT
;
392 rmi
->exitpolicy
= RMAP_NEXT
;
395 rmi
->exitpolicy
= RMAP_GOTO
;
405 * XPath: /frr-route-map:lib/route-map/entry/goto-value
407 static int lib_route_map_entry_goto_value_modify(struct nb_cb_modify_args
*args
)
409 struct route_map_index
*rmi
;
413 switch (args
->event
) {
415 rmi_index
= yang_dnode_get_uint16(args
->dnode
, "../sequence");
416 rmi_next
= yang_dnode_get_uint16(args
->dnode
, NULL
);
417 if (rmi_next
<= rmi_index
) {
418 /* Can't jump backwards on a route map. */
419 return NB_ERR_VALIDATION
;
427 rmi
= nb_running_get_entry(args
->dnode
, NULL
, true);
428 rmi
->nextpref
= yang_dnode_get_uint16(args
->dnode
, NULL
);
436 lib_route_map_entry_goto_value_destroy(struct nb_cb_destroy_args
*args
)
438 struct route_map_index
*rmi
;
440 switch (args
->event
) {
447 rmi
= nb_running_get_entry(args
->dnode
, NULL
, true);
456 * XPath: /frr-route-map:lib/route-map/entry/match-condition
459 lib_route_map_entry_match_condition_create(struct nb_cb_create_args
*args
)
461 struct routemap_hook_context
*rhc
;
462 struct route_map_index
*rmi
;
464 switch (args
->event
) {
471 rmi
= nb_running_get_entry(args
->dnode
, NULL
, true);
472 rhc
= routemap_hook_context_insert(rmi
);
473 nb_running_set_entry(args
->dnode
, rhc
);
481 lib_route_map_entry_match_condition_destroy(struct nb_cb_destroy_args
*args
)
483 struct routemap_hook_context
*rhc
;
486 if (args
->event
!= NB_EV_APPLY
)
489 rv
= lib_route_map_entry_match_destroy(args
);
490 rhc
= nb_running_unset_entry(args
->dnode
);
491 routemap_hook_context_free(rhc
);
497 * XPath: /frr-route-map:lib/route-map/entry/match-condition/interface
499 static int lib_route_map_entry_match_condition_interface_modify(
500 struct nb_cb_modify_args
*args
)
502 struct routemap_hook_context
*rhc
;
506 if (args
->event
!= NB_EV_APPLY
)
509 /* Check for hook function. */
510 if (rmap_match_set_hook
.match_interface
== NULL
)
513 /* Add configuration. */
514 rhc
= nb_running_get_entry(args
->dnode
, NULL
, true);
515 ifname
= yang_dnode_get_string(args
->dnode
, NULL
);
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
;
522 rv
= rmap_match_set_hook
.match_interface(rhc
->rhc_rmi
,
524 RMAP_EVENT_MATCH_ADDED
,
525 args
->errmsg
, args
->errmsg_len
);
526 if (rv
!= CMD_SUCCESS
) {
527 rhc
->rhc_mhook
= NULL
;
528 return NB_ERR_INCONSISTENCY
;
534 static int lib_route_map_entry_match_condition_interface_destroy(
535 struct nb_cb_destroy_args
*args
)
537 return lib_route_map_entry_match_destroy(args
);
541 * XPath: /frr-route-map:lib/route-map/entry/match-condition/list-name
543 static int lib_route_map_entry_match_condition_list_name_modify(
544 struct nb_cb_modify_args
*args
)
546 struct routemap_hook_context
*rhc
;
548 const char *condition
;
551 if (args
->event
!= NB_EV_APPLY
)
554 /* Check for hook installation, otherwise we can just stop. */
555 acl
= yang_dnode_get_string(args
->dnode
, NULL
);
556 rhc
= nb_running_get_entry(args
->dnode
, NULL
, true);
557 condition
= yang_dnode_get_string(args
->dnode
, "../../condition");
559 if (IS_MATCH_IPv4_ADDRESS_LIST(condition
)) {
560 if (rmap_match_set_hook
.match_ip_address
== NULL
)
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(
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
)) {
570 if (rmap_match_set_hook
.match_ip_address_prefix_list
== NULL
)
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(
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
)) {
581 if (rmap_match_set_hook
.match_ip_next_hop
== NULL
)
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(
587 rhc
->rhc_rmi
, "ip next-hop", acl
,
588 RMAP_EVENT_FILTER_ADDED
,
589 args
->errmsg
, args
->errmsg_len
);
590 } else if (IS_MATCH_IPv6_NEXTHOP_LIST(condition
)) {
591 if (rmap_match_set_hook
.match_ipv6_next_hop
== NULL
)
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
,
600 } else if (IS_MATCH_IPv4_NEXTHOP_PREFIX_LIST(condition
)) {
601 if (rmap_match_set_hook
.match_ip_next_hop_prefix_list
== NULL
)
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(
608 rhc
->rhc_rmi
, "ip next-hop prefix-list", acl
,
609 RMAP_EVENT_PLIST_ADDED
,
610 args
->errmsg
, args
->errmsg_len
);
611 } else if (IS_MATCH_IPv6_NEXTHOP_PREFIX_LIST(condition
)) {
612 if (rmap_match_set_hook
.match_ipv6_next_hop_prefix_list
== NULL
)
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
);
621 } else if (IS_MATCH_IPv6_ADDRESS_LIST(condition
)) {
622 if (rmap_match_set_hook
.match_ipv6_address
== NULL
)
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(
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
)) {
632 if (rmap_match_set_hook
.match_ipv6_address_prefix_list
== NULL
)
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(
639 rhc
->rhc_rmi
, "ipv6 address prefix-list", acl
,
640 RMAP_EVENT_PLIST_ADDED
,
641 args
->errmsg
, args
->errmsg_len
);
643 rv
= CMD_ERR_NO_MATCH
;
645 if (rv
!= CMD_SUCCESS
) {
646 rhc
->rhc_mhook
= NULL
;
647 return NB_ERR_INCONSISTENCY
;
653 static int lib_route_map_entry_match_condition_list_name_destroy(
654 struct nb_cb_destroy_args
*args
)
656 return lib_route_map_entry_match_destroy(args
);
660 * XPath: /frr-route-map:lib/route-map/entry/match-condition/ipv4-next-hop-type
662 static int lib_route_map_entry_match_condition_ipv4_next_hop_type_modify(
663 struct nb_cb_modify_args
*args
)
665 struct routemap_hook_context
*rhc
;
669 if (args
->event
!= NB_EV_APPLY
)
672 /* Check for hook function. */
673 if (rmap_match_set_hook
.match_ip_next_hop_type
== NULL
)
676 /* Add configuration. */
677 rhc
= nb_running_get_entry(args
->dnode
, NULL
, true);
678 type
= yang_dnode_get_string(args
->dnode
, NULL
);
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
;
685 rv
= rmap_match_set_hook
.match_ip_next_hop_type(
686 rhc
->rhc_rmi
, "ip next-hop type", type
,
687 RMAP_EVENT_MATCH_ADDED
,
688 args
->errmsg
, args
->errmsg_len
);
689 if (rv
!= CMD_SUCCESS
) {
690 rhc
->rhc_mhook
= NULL
;
691 return NB_ERR_INCONSISTENCY
;
697 static int lib_route_map_entry_match_condition_ipv4_next_hop_type_destroy(
698 struct nb_cb_destroy_args
*args
)
700 return lib_route_map_entry_match_destroy(args
);
704 * XPath: /frr-route-map:lib/route-map/entry/match-condition/ipv6-next-hop-type
706 static int lib_route_map_entry_match_condition_ipv6_next_hop_type_modify(
707 struct nb_cb_modify_args
*args
)
709 struct routemap_hook_context
*rhc
;
713 if (args
->event
!= NB_EV_APPLY
)
716 /* Check for hook function. */
717 if (rmap_match_set_hook
.match_ipv6_next_hop_type
== NULL
)
720 /* Add configuration. */
721 rhc
= nb_running_get_entry(args
->dnode
, NULL
, true);
722 type
= yang_dnode_get_string(args
->dnode
, NULL
);
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
;
729 rv
= rmap_match_set_hook
.match_ipv6_next_hop_type(
730 rhc
->rhc_rmi
, "ipv6 next-hop type", type
,
731 RMAP_EVENT_MATCH_ADDED
,
732 args
->errmsg
, args
->errmsg_len
);
733 if (rv
!= CMD_SUCCESS
) {
734 rhc
->rhc_mhook
= NULL
;
735 return NB_ERR_INCONSISTENCY
;
741 static int lib_route_map_entry_match_condition_ipv6_next_hop_type_destroy(
742 struct nb_cb_destroy_args
*args
)
744 return lib_route_map_entry_match_destroy(args
);
748 * XPath: /frr-route-map:lib/route-map/entry/match-condition/metric
750 static int lib_route_map_entry_match_condition_metric_modify(
751 struct nb_cb_modify_args
*args
)
753 struct routemap_hook_context
*rhc
;
757 if (args
->event
!= NB_EV_APPLY
)
760 /* Check for hook function. */
761 if (rmap_match_set_hook
.match_metric
== NULL
)
764 /* Add configuration. */
765 rhc
= nb_running_get_entry(args
->dnode
, NULL
, true);
766 type
= yang_dnode_get_string(args
->dnode
, NULL
);
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
;
773 rv
= rmap_match_set_hook
.match_metric(rhc
->rhc_rmi
, "metric",
774 type
, RMAP_EVENT_MATCH_ADDED
,
775 args
->errmsg
, args
->errmsg_len
);
776 if (rv
!= CMD_SUCCESS
) {
777 rhc
->rhc_mhook
= NULL
;
778 return NB_ERR_INCONSISTENCY
;
784 static int lib_route_map_entry_match_condition_metric_destroy(
785 struct nb_cb_destroy_args
*args
)
787 return lib_route_map_entry_match_destroy(args
);
791 * XPath: /frr-route-map:lib/route-map/entry/match-condition/tag
794 lib_route_map_entry_match_condition_tag_modify(struct nb_cb_modify_args
*args
)
796 struct routemap_hook_context
*rhc
;
800 if (args
->event
!= NB_EV_APPLY
)
803 /* Check for hook function. */
804 if (rmap_match_set_hook
.match_tag
== NULL
)
807 /* Add configuration. */
808 rhc
= nb_running_get_entry(args
->dnode
, NULL
, true);
809 tag
= yang_dnode_get_string(args
->dnode
, NULL
);
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
;
816 rv
= rmap_match_set_hook
.match_tag(rhc
->rhc_rmi
, "tag", tag
,
817 RMAP_EVENT_MATCH_ADDED
,
818 args
->errmsg
, args
->errmsg_len
);
819 if (rv
!= CMD_SUCCESS
) {
820 rhc
->rhc_mhook
= NULL
;
821 return NB_ERR_INCONSISTENCY
;
828 lib_route_map_entry_match_condition_tag_destroy(struct nb_cb_destroy_args
*args
)
830 return lib_route_map_entry_match_destroy(args
);
834 * XPath: /frr-route-map:lib/route-map/entry/set-action
836 static int lib_route_map_entry_set_action_create(struct nb_cb_create_args
*args
)
838 return lib_route_map_entry_match_condition_create(args
);
842 lib_route_map_entry_set_action_destroy(struct nb_cb_destroy_args
*args
)
844 struct routemap_hook_context
*rhc
;
847 if (args
->event
!= NB_EV_APPLY
)
850 rv
= lib_route_map_entry_set_destroy(args
);
851 rhc
= nb_running_unset_entry(args
->dnode
);
852 routemap_hook_context_free(rhc
);
858 * XPath: /frr-route-map:lib/route-map/entry/set-action/ipv4-address
860 static int lib_route_map_entry_set_action_ipv4_address_modify(
861 struct nb_cb_modify_args
*args
)
863 struct routemap_hook_context
*rhc
;
868 switch (args
->event
) {
871 * NOTE: validate if 'action' is 'ipv4-next-hop',
872 * currently it is not necessary because this is the
873 * only implemented action.
875 yang_dnode_get_ipv4(&ia
, args
->dnode
, NULL
);
876 if (ia
.s_addr
== INADDR_ANY
|| !ipv4_unicast_valid(&ia
))
877 return NB_ERR_VALIDATION
;
886 /* Check for hook function. */
887 if (rmap_match_set_hook
.set_ip_nexthop
== NULL
)
890 /* Add configuration. */
891 rhc
= nb_running_get_entry(args
->dnode
, NULL
, true);
892 address
= yang_dnode_get_string(args
->dnode
, NULL
);
894 /* Set destroy information. */
895 rhc
->rhc_shook
= rmap_match_set_hook
.no_set_ip_nexthop
;
896 rhc
->rhc_rule
= "ip next-hop";
898 rv
= rmap_match_set_hook
.set_ip_nexthop(rhc
->rhc_rmi
, "ip next-hop",
900 args
->errmsg
, args
->errmsg_len
);
901 if (rv
!= CMD_SUCCESS
) {
902 rhc
->rhc_shook
= NULL
;
903 return NB_ERR_INCONSISTENCY
;
909 static int lib_route_map_entry_set_action_ipv4_address_destroy(
910 struct nb_cb_destroy_args
*args
)
912 return lib_route_map_entry_set_destroy(args
);
916 * XPath: /frr-route-map:lib/route-map/entry/set-action/ipv6-address
918 static int lib_route_map_entry_set_action_ipv6_address_modify(
919 struct nb_cb_modify_args
*args
)
921 struct routemap_hook_context
*rhc
;
926 switch (args
->event
) {
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.
934 yang_dnode_get_ipv6(&i6a
, args
->dnode
, NULL
);
935 if (!IN6_IS_ADDR_LINKLOCAL(&i6a
))
936 return NB_ERR_VALIDATION
;
945 /* Check for hook function. */
946 if (rmap_match_set_hook
.set_ipv6_nexthop_local
== NULL
)
949 /* Add configuration. */
950 rhc
= nb_running_get_entry(args
->dnode
, NULL
, true);
951 address
= yang_dnode_get_string(args
->dnode
, NULL
);
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";
957 rv
= rmap_match_set_hook
.set_ipv6_nexthop_local(
958 rhc
->rhc_rmi
, "ipv6 next-hop local", address
,
959 args
->errmsg
, args
->errmsg_len
);
960 if (rv
!= CMD_SUCCESS
) {
961 rhc
->rhc_shook
= NULL
;
962 return NB_ERR_INCONSISTENCY
;
968 static int lib_route_map_entry_set_action_ipv6_address_destroy(
969 struct nb_cb_destroy_args
*args
)
971 return lib_route_map_entry_set_destroy(args
);
975 * XPath: /frr-route-map:lib/route-map/entry/set-action/value
977 static int set_action_modify(enum nb_event event
, const struct lyd_node
*dnode
,
978 union nb_resource
*resource
, const char *value
,
979 char *errmsg
, size_t errmsg_len
)
981 struct routemap_hook_context
*rhc
;
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.
989 if (event
!= NB_EV_APPLY
)
992 /* Check for hook function. */
993 if (rmap_match_set_hook
.set_metric
== NULL
)
996 /* Add configuration. */
997 rhc
= nb_running_get_entry(dnode
, NULL
, true);
999 /* Set destroy information. */
1000 rhc
->rhc_shook
= rmap_match_set_hook
.no_set_metric
;
1001 rhc
->rhc_rule
= "metric";
1003 rv
= rmap_match_set_hook
.set_metric(rhc
->rhc_rmi
, "metric",
1007 if (rv
!= CMD_SUCCESS
) {
1008 rhc
->rhc_shook
= NULL
;
1009 return NB_ERR_INCONSISTENCY
;
1016 lib_route_map_entry_set_action_value_modify(struct nb_cb_modify_args
*args
)
1018 const char *metric
= yang_dnode_get_string(args
->dnode
, NULL
);
1020 return set_action_modify(args
->event
, args
->dnode
, args
->resource
,
1021 metric
, args
->errmsg
, args
->errmsg_len
);
1025 lib_route_map_entry_set_action_value_destroy(struct nb_cb_destroy_args
*args
)
1027 return lib_route_map_entry_set_destroy(args
);
1031 * XPath: /frr-route-map:lib/route-map/entry/set-action/min-metric
1033 static int set_action_min_metric_modify(enum nb_event event
,
1034 const struct lyd_node
*dnode
,
1035 union nb_resource
*resource
,
1036 const char *value
, char *errmsg
,
1039 struct routemap_hook_context
*rhc
;
1042 if (event
!= NB_EV_APPLY
)
1045 /* Check for hook function. */
1046 if (rmap_match_set_hook
.set_min_metric
== NULL
)
1049 /* Add configuration. */
1050 rhc
= nb_running_get_entry(dnode
, NULL
, true);
1052 /* Set destroy information. */
1053 rhc
->rhc_shook
= rmap_match_set_hook
.no_set_min_metric
;
1054 rhc
->rhc_rule
= "min-metric";
1056 rv
= rmap_match_set_hook
.set_min_metric(rhc
->rhc_rmi
, "min-metric",
1057 value
, errmsg
, errmsg_len
);
1058 if (rv
!= CMD_SUCCESS
) {
1059 rhc
->rhc_shook
= NULL
;
1060 return NB_ERR_INCONSISTENCY
;
1067 lib_route_map_entry_set_action_min_metric_modify(struct nb_cb_modify_args
*args
)
1069 const char *min_metric
= yang_dnode_get_string(args
->dnode
, NULL
);
1071 return set_action_min_metric_modify(args
->event
, args
->dnode
,
1072 args
->resource
, min_metric
,
1073 args
->errmsg
, args
->errmsg_len
);
1076 static int lib_route_map_entry_set_action_min_metric_destroy(
1077 struct nb_cb_destroy_args
*args
)
1079 return lib_route_map_entry_set_destroy(args
);
1083 * XPath: /frr-route-map:lib/route-map/entry/set-action/max-metric
1085 static int set_action_max_metric_modify(enum nb_event event
,
1086 const struct lyd_node
*dnode
,
1087 union nb_resource
*resource
,
1088 const char *value
, char *errmsg
,
1091 struct routemap_hook_context
*rhc
;
1094 if (event
!= NB_EV_APPLY
)
1097 /* Check for hook function. */
1098 if (rmap_match_set_hook
.set_max_metric
== NULL
)
1101 /* Add configuration. */
1102 rhc
= nb_running_get_entry(dnode
, NULL
, true);
1104 /* Set destroy information. */
1105 rhc
->rhc_shook
= rmap_match_set_hook
.no_set_max_metric
;
1106 rhc
->rhc_rule
= "max-metric";
1108 rv
= rmap_match_set_hook
.set_max_metric(rhc
->rhc_rmi
, "max-metric",
1109 value
, errmsg
, errmsg_len
);
1110 if (rv
!= CMD_SUCCESS
) {
1111 rhc
->rhc_shook
= NULL
;
1112 return NB_ERR_INCONSISTENCY
;
1119 lib_route_map_entry_set_action_max_metric_modify(struct nb_cb_modify_args
*args
)
1121 const char *max_metric
= yang_dnode_get_string(args
->dnode
, NULL
);
1123 return set_action_max_metric_modify(args
->event
, args
->dnode
,
1124 args
->resource
, max_metric
,
1125 args
->errmsg
, args
->errmsg_len
);
1128 static int lib_route_map_entry_set_action_max_metric_destroy(
1129 struct nb_cb_destroy_args
*args
)
1131 return lib_route_map_entry_set_destroy(args
);
1135 * XPath: /frr-route-map:lib/route-map/entry/set-action/add-metric
1138 lib_route_map_entry_set_action_add_metric_modify(struct nb_cb_modify_args
*args
)
1140 char metric_str
[16];
1142 if (args
->event
== NB_EV_VALIDATE
1143 && yang_dnode_get_uint32(args
->dnode
, NULL
) == 0) {
1144 snprintf(args
->errmsg
, args
->errmsg_len
,
1145 "Can't add zero to metric");
1146 return NB_ERR_VALIDATION
;
1149 snprintf(metric_str
, sizeof(metric_str
), "+%s",
1150 yang_dnode_get_string(args
->dnode
, NULL
));
1151 return set_action_modify(args
->event
, args
->dnode
, args
->resource
,
1153 args
->errmsg
, args
->errmsg_len
);
1156 static int lib_route_map_entry_set_action_add_metric_destroy(
1157 struct nb_cb_destroy_args
*args
)
1159 return lib_route_map_entry_set_action_value_destroy(args
);
1163 * XPath: /frr-route-map:lib/route-map/entry/set-action/subtract-metric
1165 static int lib_route_map_entry_set_action_subtract_metric_modify(
1166 struct nb_cb_modify_args
*args
)
1168 char metric_str
[16];
1170 if (args
->event
== NB_EV_VALIDATE
1171 && yang_dnode_get_uint32(args
->dnode
, NULL
) == 0) {
1172 snprintf(args
->errmsg
, args
->errmsg_len
,
1173 "Can't subtract zero from metric");
1174 return NB_ERR_VALIDATION
;
1177 snprintf(metric_str
, sizeof(metric_str
), "-%s",
1178 yang_dnode_get_string(args
->dnode
, NULL
));
1179 return set_action_modify(args
->event
, args
->dnode
, args
->resource
,
1181 args
->errmsg
, args
->errmsg_len
);
1184 static int lib_route_map_entry_set_action_subtract_metric_destroy(
1185 struct nb_cb_destroy_args
*args
)
1187 return lib_route_map_entry_set_action_value_destroy(args
);
1191 * XPath: /frr-route-map:lib/route-map/entry/set-action/use-round-trip-time
1193 static int lib_route_map_entry_set_action_use_round_trip_time_modify(
1194 struct nb_cb_modify_args
*args
)
1196 return set_action_modify(args
->event
, args
->dnode
, args
->resource
,
1198 args
->errmsg
, args
->errmsg_len
);
1201 static int lib_route_map_entry_set_action_use_round_trip_time_destroy(
1202 struct nb_cb_destroy_args
*args
)
1204 return lib_route_map_entry_set_action_value_destroy(args
);
1208 * XPath: /frr-route-map:lib/route-map/entry/set-action/add-round-trip-time
1210 static int lib_route_map_entry_set_action_add_round_trip_time_modify(
1211 struct nb_cb_modify_args
*args
)
1213 return set_action_modify(args
->event
, args
->dnode
, args
->resource
,
1215 args
->errmsg
, args
->errmsg_len
);
1218 static int lib_route_map_entry_set_action_add_round_trip_time_destroy(
1219 struct nb_cb_destroy_args
*args
)
1221 return lib_route_map_entry_set_action_value_destroy(args
);
1225 * XPath: /frr-route-map:lib/route-map/entry/set-action/subtract-round-trip-time
1227 static int lib_route_map_entry_set_action_subtract_round_trip_time_modify(
1228 struct nb_cb_modify_args
*args
)
1230 return set_action_modify(args
->event
, args
->dnode
, args
->resource
,
1231 "-rtt", args
->errmsg
, args
->errmsg_len
);
1234 static int lib_route_map_entry_set_action_subtract_round_trip_time_destroy(
1235 struct nb_cb_destroy_args
*args
)
1237 return lib_route_map_entry_set_action_value_destroy(args
);
1241 * XPath: /frr-route-map:lib/route-map/entry/set-action/tag
1244 lib_route_map_entry_set_action_tag_modify(struct nb_cb_modify_args
*args
)
1246 struct routemap_hook_context
*rhc
;
1251 * NOTE: validate if 'action' is 'tag', currently it is not
1252 * necessary because this is the only implemented action. Other
1253 * actions might have different validations.
1255 if (args
->event
!= NB_EV_APPLY
)
1258 /* Check for hook function. */
1259 if (rmap_match_set_hook
.set_tag
== NULL
)
1262 /* Add configuration. */
1263 rhc
= nb_running_get_entry(args
->dnode
, NULL
, true);
1264 tag
= yang_dnode_get_string(args
->dnode
, NULL
);
1266 /* Set destroy information. */
1267 rhc
->rhc_shook
= rmap_match_set_hook
.no_set_tag
;
1268 rhc
->rhc_rule
= "tag";
1270 rv
= rmap_match_set_hook
.set_tag(rhc
->rhc_rmi
, "tag", tag
,
1271 args
->errmsg
, args
->errmsg_len
);
1272 if (rv
!= CMD_SUCCESS
) {
1273 rhc
->rhc_shook
= NULL
;
1274 return NB_ERR_INCONSISTENCY
;
1281 lib_route_map_entry_set_action_tag_destroy(struct nb_cb_destroy_args
*args
)
1283 return lib_route_map_entry_set_destroy(args
);
1287 * XPath: /frr-route-map:lib/route-map/entry/set-action/policy
1290 lib_route_map_entry_set_action_policy_modify(struct nb_cb_modify_args
*args
)
1292 struct routemap_hook_context
*rhc
;
1297 * NOTE: validate if 'action' is 'tag', currently it is not
1298 * necessary because this is the only implemented action. Other
1299 * actions might have different validations.
1301 if (args
->event
!= NB_EV_APPLY
)
1304 /* Check for hook function. */
1305 if (rmap_match_set_hook
.set_srte_color
== NULL
)
1308 /* Add configuration. */
1309 rhc
= nb_running_get_entry(args
->dnode
, NULL
, true);
1310 policy
= yang_dnode_get_string(args
->dnode
, NULL
);
1312 /* Set destroy information. */
1313 rhc
->rhc_shook
= rmap_match_set_hook
.no_set_tag
;
1314 rhc
->rhc_rule
= "sr-te color";
1316 rv
= rmap_match_set_hook
.set_tag(rhc
->rhc_rmi
, "sr-te color", policy
,
1317 args
->errmsg
, args
->errmsg_len
);
1318 if (rv
!= CMD_SUCCESS
) {
1319 rhc
->rhc_shook
= NULL
;
1320 return NB_ERR_INCONSISTENCY
;
1327 lib_route_map_entry_set_action_policy_destroy(struct nb_cb_destroy_args
*args
)
1329 return lib_route_map_entry_set_destroy(args
);
1332 /* clang-format off */
1333 const struct frr_yang_module_info frr_route_map_info
= {
1334 .name
= "frr-route-map",
1337 .xpath
= "/frr-route-map:lib/route-map",
1339 .create
= lib_route_map_create
,
1340 .destroy
= lib_route_map_destroy
,
1344 .xpath
= "/frr-route-map:lib/route-map/optimization-disabled",
1346 .modify
= lib_route_map_optimization_disabled_modify
,
1347 .cli_show
= route_map_optimization_disabled_show
,
1351 .xpath
= "/frr-route-map:lib/route-map/entry",
1353 .create
= lib_route_map_entry_create
,
1354 .destroy
= lib_route_map_entry_destroy
,
1355 .cli_cmp
= route_map_instance_cmp
,
1356 .cli_show
= route_map_instance_show
,
1357 .cli_show_end
= route_map_instance_show_end
,
1361 .xpath
= "/frr-route-map:lib/route-map/entry/description",
1363 .modify
= lib_route_map_entry_description_modify
,
1364 .destroy
= lib_route_map_entry_description_destroy
,
1365 .cli_show
= route_map_description_show
,
1369 .xpath
= "/frr-route-map:lib/route-map/entry/action",
1371 .modify
= lib_route_map_entry_action_modify
,
1375 .xpath
= "/frr-route-map:lib/route-map/entry/call",
1377 .modify
= lib_route_map_entry_call_modify
,
1378 .destroy
= lib_route_map_entry_call_destroy
,
1379 .cli_show
= route_map_call_show
,
1383 .xpath
= "/frr-route-map:lib/route-map/entry/exit-policy",
1385 .modify
= lib_route_map_entry_exit_policy_modify
,
1386 .cli_show
= route_map_exit_policy_show
,
1390 .xpath
= "/frr-route-map:lib/route-map/entry/goto-value",
1392 .modify
= lib_route_map_entry_goto_value_modify
,
1393 .destroy
= lib_route_map_entry_goto_value_destroy
,
1397 .xpath
= "/frr-route-map:lib/route-map/entry/match-condition",
1399 .create
= lib_route_map_entry_match_condition_create
,
1400 .destroy
= lib_route_map_entry_match_condition_destroy
,
1401 .cli_show
= route_map_condition_show
,
1405 .xpath
= "/frr-route-map:lib/route-map/entry/match-condition/rmap-match-condition/interface",
1407 .modify
= lib_route_map_entry_match_condition_interface_modify
,
1408 .destroy
= lib_route_map_entry_match_condition_interface_destroy
,
1412 .xpath
= "/frr-route-map:lib/route-map/entry/match-condition/rmap-match-condition/list-name",
1414 .modify
= lib_route_map_entry_match_condition_list_name_modify
,
1415 .destroy
= lib_route_map_entry_match_condition_list_name_destroy
,
1419 .xpath
= "/frr-route-map:lib/route-map/entry/match-condition/rmap-match-condition/ipv4-next-hop-type",
1421 .modify
= lib_route_map_entry_match_condition_ipv4_next_hop_type_modify
,
1422 .destroy
= lib_route_map_entry_match_condition_ipv4_next_hop_type_destroy
,
1426 .xpath
= "/frr-route-map:lib/route-map/entry/match-condition/rmap-match-condition/ipv6-next-hop-type",
1428 .modify
= lib_route_map_entry_match_condition_ipv6_next_hop_type_modify
,
1429 .destroy
= lib_route_map_entry_match_condition_ipv6_next_hop_type_destroy
,
1433 .xpath
= "/frr-route-map:lib/route-map/entry/match-condition/rmap-match-condition/metric",
1435 .modify
= lib_route_map_entry_match_condition_metric_modify
,
1436 .destroy
= lib_route_map_entry_match_condition_metric_destroy
,
1440 .xpath
= "/frr-route-map:lib/route-map/entry/match-condition/rmap-match-condition/tag",
1442 .modify
= lib_route_map_entry_match_condition_tag_modify
,
1443 .destroy
= lib_route_map_entry_match_condition_tag_destroy
,
1447 .xpath
= "/frr-route-map:lib/route-map/entry/set-action",
1449 .create
= lib_route_map_entry_set_action_create
,
1450 .destroy
= lib_route_map_entry_set_action_destroy
,
1451 .cli_show
= route_map_action_show
,
1455 .xpath
= "/frr-route-map:lib/route-map/entry/set-action/rmap-set-action/ipv4-address",
1457 .modify
= lib_route_map_entry_set_action_ipv4_address_modify
,
1458 .destroy
= lib_route_map_entry_set_action_ipv4_address_destroy
,
1462 .xpath
= "/frr-route-map:lib/route-map/entry/set-action/rmap-set-action/ipv6-address",
1464 .modify
= lib_route_map_entry_set_action_ipv6_address_modify
,
1465 .destroy
= lib_route_map_entry_set_action_ipv6_address_destroy
,
1469 .xpath
= "/frr-route-map:lib/route-map/entry/set-action/rmap-set-action/value",
1471 .modify
= lib_route_map_entry_set_action_value_modify
,
1472 .destroy
= lib_route_map_entry_set_action_value_destroy
,
1476 .xpath
= "/frr-route-map:lib/route-map/entry/set-action/rmap-set-action/min-metric",
1478 .modify
= lib_route_map_entry_set_action_min_metric_modify
,
1479 .destroy
= lib_route_map_entry_set_action_min_metric_destroy
,
1483 .xpath
= "/frr-route-map:lib/route-map/entry/set-action/rmap-set-action/max-metric",
1485 .modify
= lib_route_map_entry_set_action_max_metric_modify
,
1486 .destroy
= lib_route_map_entry_set_action_max_metric_destroy
,
1490 .xpath
= "/frr-route-map:lib/route-map/entry/set-action/rmap-set-action/add-metric",
1492 .modify
= lib_route_map_entry_set_action_add_metric_modify
,
1493 .destroy
= lib_route_map_entry_set_action_add_metric_destroy
,
1497 .xpath
= "/frr-route-map:lib/route-map/entry/set-action/rmap-set-action/subtract-metric",
1499 .modify
= lib_route_map_entry_set_action_subtract_metric_modify
,
1500 .destroy
= lib_route_map_entry_set_action_subtract_metric_destroy
,
1504 .xpath
= "/frr-route-map:lib/route-map/entry/set-action/rmap-set-action/use-round-trip-time",
1506 .modify
= lib_route_map_entry_set_action_use_round_trip_time_modify
,
1507 .destroy
= lib_route_map_entry_set_action_use_round_trip_time_destroy
,
1511 .xpath
= "/frr-route-map:lib/route-map/entry/set-action/rmap-set-action/add-round-trip-time",
1513 .modify
= lib_route_map_entry_set_action_add_round_trip_time_modify
,
1514 .destroy
= lib_route_map_entry_set_action_add_round_trip_time_destroy
,
1518 .xpath
= "/frr-route-map:lib/route-map/entry/set-action/rmap-set-action/subtract-round-trip-time",
1520 .modify
= lib_route_map_entry_set_action_subtract_round_trip_time_modify
,
1521 .destroy
= lib_route_map_entry_set_action_subtract_round_trip_time_destroy
,
1525 .xpath
= "/frr-route-map:lib/route-map/entry/set-action/rmap-set-action/tag",
1527 .modify
= lib_route_map_entry_set_action_tag_modify
,
1528 .destroy
= lib_route_map_entry_set_action_tag_destroy
,
1532 .xpath
= "/frr-route-map:lib/route-map/entry/set-action/rmap-set-action/policy",
1534 .modify
= lib_route_map_entry_set_action_policy_modify
,
1535 .destroy
= lib_route_map_entry_set_action_policy_destroy
,