2 * Route map northbound implementation.
4 * Copyright (C) 2019 Network Device Education Foundation, Inc. ("NetDEF")
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.
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.
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
25 #include "lib/command.h"
27 #include "lib/northbound.h"
28 #include "lib/routemap.h"
31 * Auxiliary functions to avoid code duplication:
33 * lib_route_map_entry_set_destroy: unset `set` commands.
34 * lib_route_map_entry_match_destroy: unset `match` commands.
36 int lib_route_map_entry_match_destroy(enum nb_event event
,
37 const struct lyd_node
*dnode
)
39 struct routemap_hook_context
*rhc
;
42 if (event
!= NB_EV_APPLY
)
45 rhc
= nb_running_get_entry(dnode
, NULL
, true);
46 if (rhc
->rhc_mhook
== NULL
)
49 rv
= rhc
->rhc_mhook(NULL
, rhc
->rhc_rmi
, rhc
->rhc_rule
, NULL
,
51 if (rv
!= CMD_SUCCESS
)
52 return NB_ERR_INCONSISTENCY
;
57 int lib_route_map_entry_set_destroy(enum nb_event event
,
58 const struct lyd_node
*dnode
)
60 struct routemap_hook_context
*rhc
;
63 if (event
!= NB_EV_APPLY
)
66 rhc
= nb_running_get_entry(dnode
, NULL
, true);
67 if (rhc
->rhc_shook
== NULL
)
70 rv
= rhc
->rhc_shook(NULL
, rhc
->rhc_rmi
, rhc
->rhc_rule
, NULL
);
71 if (rv
!= CMD_SUCCESS
)
72 return NB_ERR_INCONSISTENCY
;
78 * Auxiliary hook context list manipulation functions.
80 struct routemap_hook_context
*
81 routemap_hook_context_insert(struct route_map_index
*rmi
)
83 struct routemap_hook_context
*rhc
;
85 rhc
= XCALLOC(MTYPE_TMP
, sizeof(*rhc
));
87 TAILQ_INSERT_TAIL(&rmi
->rhclist
, rhc
, rhc_entry
);
93 routemap_hook_context_free(struct routemap_hook_context
*rhc
)
95 struct route_map_index
*rmi
= rhc
->rhc_rmi
;
97 TAILQ_REMOVE(&rmi
->rhclist
, rhc
, rhc_entry
);
98 XFREE(MTYPE_TMP
, rhc
);
102 * XPath: /frr-route-map:lib/route-map
104 static int lib_route_map_create(enum nb_event event
,
105 const struct lyd_node
*dnode
,
106 union nb_resource
*resource
)
108 struct route_map
*rm
;
118 rm_name
= yang_dnode_get_string(dnode
, "./name");
119 rm
= route_map_get(rm_name
);
120 nb_running_set_entry(dnode
, rm
);
127 static int lib_route_map_destroy(enum nb_event event
,
128 const struct lyd_node
*dnode
)
130 struct route_map
*rm
;
139 rm
= nb_running_unset_entry(dnode
);
140 route_map_delete(rm
);
148 * XPath: /frr-route-map:lib/route-map/entry
150 static int lib_route_map_entry_create(enum nb_event event
,
151 const struct lyd_node
*dnode
,
152 union nb_resource
*resource
)
154 struct route_map_index
*rmi
;
155 struct route_map
*rm
;
166 sequence
= yang_dnode_get_uint16(dnode
, "./sequence");
167 action
= yang_dnode_get_enum(dnode
, "./action") == 0
170 rm
= nb_running_get_entry(dnode
, NULL
, true);
171 rmi
= route_map_index_get(rm
, action
, sequence
);
172 nb_running_set_entry(dnode
, rmi
);
179 static int lib_route_map_entry_destroy(enum nb_event event
,
180 const struct lyd_node
*dnode
)
182 struct route_map_index
*rmi
;
191 rmi
= nb_running_unset_entry(dnode
);
192 route_map_index_delete(rmi
, 1);
200 * XPath: /frr-route-map:lib/route-map/entry/description
202 static int lib_route_map_entry_description_modify(enum nb_event event
,
203 const struct lyd_node
*dnode
,
204 union nb_resource
*resource
)
206 struct route_map_index
*rmi
;
207 const char *description
;
214 description
= yang_dnode_get_string(dnode
, NULL
);
215 resource
->ptr
= XSTRDUP(MTYPE_TMP
, description
);
216 if (resource
->ptr
== NULL
)
217 return NB_ERR_RESOURCE
;
220 XFREE(MTYPE_TMP
, resource
->ptr
);
223 rmi
= nb_running_get_entry(dnode
, NULL
, true);
224 XFREE(MTYPE_TMP
, rmi
->description
);
225 rmi
->description
= resource
->ptr
;
232 static int lib_route_map_entry_description_destroy(enum nb_event event
,
233 const struct lyd_node
*dnode
)
235 struct route_map_index
*rmi
;
244 rmi
= nb_running_get_entry(dnode
, NULL
, true);
245 XFREE(MTYPE_TMP
, rmi
->description
);
253 * XPath: /frr-route-map:lib/route-map/entry/action
255 static int lib_route_map_entry_action_modify(enum nb_event event
,
256 const struct lyd_node
*dnode
,
257 union nb_resource
*resource
)
259 struct route_map_index
*rmi
;
268 rmi
= nb_running_get_entry(dnode
, NULL
, true);
269 rmi
->type
= yang_dnode_get_enum(dnode
, NULL
);
278 * XPath: /frr-route-map:lib/route-map/entry/call
280 static int lib_route_map_entry_call_modify(enum nb_event event
,
281 const struct lyd_node
*dnode
,
282 union nb_resource
*resource
)
284 struct route_map_index
*rmi
;
285 const char *rm_name
, *rmn_name
;
289 rm_name
= yang_dnode_get_string(dnode
, "../../name");
290 rmn_name
= yang_dnode_get_string(dnode
, NULL
);
291 /* Don't allow to jump to the same route map instance. */
292 if (strcmp(rm_name
, rmn_name
) == 0)
293 return NB_ERR_VALIDATION
;
295 /* TODO: detect circular route map sequences. */
298 rmn_name
= yang_dnode_get_string(dnode
, NULL
);
299 resource
->ptr
= XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmn_name
);
302 XFREE(MTYPE_ROUTE_MAP_NAME
, resource
->ptr
);
305 rmi
= nb_running_get_entry(dnode
, NULL
, true);
307 route_map_upd8_dependency(RMAP_EVENT_CALL_DELETED
,
308 rmi
->nextrm
, rmi
->map
->name
);
309 XFREE(MTYPE_ROUTE_MAP_NAME
, rmi
->nextrm
);
311 rmi
->nextrm
= resource
->ptr
;
312 route_map_upd8_dependency(RMAP_EVENT_CALL_ADDED
, rmi
->nextrm
,
320 static int lib_route_map_entry_call_destroy(enum nb_event event
,
321 const struct lyd_node
*dnode
)
323 struct route_map_index
*rmi
;
332 rmi
= nb_running_get_entry(dnode
, NULL
, true);
333 route_map_upd8_dependency(RMAP_EVENT_CALL_DELETED
, rmi
->nextrm
,
335 XFREE(MTYPE_ROUTE_MAP_NAME
, rmi
->nextrm
);
344 * XPath: /frr-route-map:lib/route-map/entry/exit-policy
346 static int lib_route_map_entry_exit_policy_modify(enum nb_event event
,
347 const struct lyd_node
*dnode
,
348 union nb_resource
*resource
)
350 struct route_map_index
*rmi
;
356 policy
= yang_dnode_get_enum(dnode
, NULL
);
358 case 0: /* permit-or-deny */
363 rm_action
= yang_dnode_get_enum(dnode
, "../action");
364 if (rm_action
== 1 /* deny */) {
366 * On deny it is not possible to 'goto'
369 return NB_ERR_VALIDATION
;
378 rmi
= nb_running_get_entry(dnode
, NULL
, true);
379 policy
= yang_dnode_get_enum(dnode
, NULL
);
382 case 0: /* permit-or-deny */
383 rmi
->exitpolicy
= RMAP_EXIT
;
386 rmi
->exitpolicy
= RMAP_NEXT
;
389 rmi
->exitpolicy
= RMAP_GOTO
;
399 * XPath: /frr-route-map:lib/route-map/entry/goto-value
401 static int lib_route_map_entry_goto_value_modify(enum nb_event event
,
402 const struct lyd_node
*dnode
,
403 union nb_resource
*resource
)
405 struct route_map_index
*rmi
;
411 rmi_index
= yang_dnode_get_uint16(dnode
, "../sequence");
412 rmi_next
= yang_dnode_get_uint16(dnode
, NULL
);
413 if (rmi_next
<= rmi_index
) {
414 /* Can't jump backwards on a route map. */
415 return NB_ERR_VALIDATION
;
423 rmi
= nb_running_get_entry(dnode
, NULL
, true);
424 rmi
->nextpref
= yang_dnode_get_uint16(dnode
, NULL
);
431 static int lib_route_map_entry_goto_value_destroy(enum nb_event event
,
432 const struct lyd_node
*dnode
)
434 struct route_map_index
*rmi
;
443 rmi
= nb_running_get_entry(dnode
, NULL
, true);
452 * XPath: /frr-route-map:lib/route-map/entry/match-condition
455 lib_route_map_entry_match_condition_create(enum nb_event event
,
456 const struct lyd_node
*dnode
,
457 union nb_resource
*resource
)
459 struct routemap_hook_context
*rhc
;
460 struct route_map_index
*rmi
;
469 rmi
= nb_running_get_entry(dnode
, NULL
, true);
470 rhc
= routemap_hook_context_insert(rmi
);
471 nb_running_set_entry(dnode
, rhc
);
479 lib_route_map_entry_match_condition_destroy(enum nb_event event
,
480 const struct lyd_node
*dnode
)
482 struct routemap_hook_context
*rhc
;
485 if (event
!= NB_EV_APPLY
)
488 rv
= lib_route_map_entry_match_destroy(event
, dnode
);
489 rhc
= nb_running_unset_entry(dnode
);
490 routemap_hook_context_free(rhc
);
496 * XPath: /frr-route-map:lib/route-map/entry/match-condition/interface
498 static int lib_route_map_entry_match_condition_interface_modify(
499 enum nb_event event
, const struct lyd_node
*dnode
,
500 union nb_resource
*resource
)
502 struct routemap_hook_context
*rhc
;
506 if (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(dnode
, NULL
, true);
515 ifname
= yang_dnode_get_string(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(NULL
, rhc
->rhc_rmi
,
524 RMAP_EVENT_MATCH_ADDED
);
525 if (rv
!= CMD_SUCCESS
) {
526 rhc
->rhc_mhook
= NULL
;
527 return NB_ERR_INCONSISTENCY
;
533 static int lib_route_map_entry_match_condition_interface_destroy(
534 enum nb_event event
, const struct lyd_node
*dnode
)
536 return lib_route_map_entry_match_destroy(event
, dnode
);
540 * XPath: /frr-route-map:lib/route-map/entry/match-condition/access-list-num
542 static int lib_route_map_entry_match_condition_access_list_num_modify(
543 enum nb_event event
, const struct lyd_node
*dnode
,
544 union nb_resource
*resource
)
546 struct routemap_hook_context
*rhc
;
550 if (event
!= NB_EV_APPLY
)
553 /* Check for hook function. */
555 acl
= yang_dnode_get_string(dnode
, NULL
);
556 rhc
= nb_running_get_entry(dnode
, NULL
, true);
557 condition
= yang_dnode_get_enum(dnode
, "../condition");
559 case 1: /* ipv4-address-list */
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 NULL
, rhc
->rhc_rmi
, "ip address", acl
,
567 RMAP_EVENT_FILTER_ADDED
);
569 case 3: /* ipv4-next-hop-list */
570 if (rmap_match_set_hook
.match_ip_next_hop
== NULL
)
572 rhc
->rhc_mhook
= rmap_match_set_hook
.no_match_ip_next_hop
;
573 rhc
->rhc_rule
= "ip next-hop";
574 rhc
->rhc_event
= RMAP_EVENT_FILTER_DELETED
;
575 rv
= rmap_match_set_hook
.match_ip_next_hop(
576 NULL
, rhc
->rhc_rmi
, "ip next-hop", acl
,
577 RMAP_EVENT_FILTER_ADDED
);
580 if (rv
!= CMD_SUCCESS
) {
581 rhc
->rhc_mhook
= NULL
;
582 return NB_ERR_INCONSISTENCY
;
588 static int lib_route_map_entry_match_condition_access_list_num_destroy(
589 enum nb_event event
, const struct lyd_node
*dnode
)
591 return lib_route_map_entry_match_destroy(event
, dnode
);
596 * /frr-route-map:lib/route-map/entry/match-condition/access-list-num-extended
598 static int lib_route_map_entry_match_condition_access_list_num_extended_modify(
599 enum nb_event event
, const struct lyd_node
*dnode
,
600 union nb_resource
*resource
)
602 return lib_route_map_entry_match_condition_access_list_num_modify(
603 event
, dnode
, resource
);
606 static int lib_route_map_entry_match_condition_access_list_num_extended_destroy(
607 enum nb_event event
, const struct lyd_node
*dnode
)
609 return lib_route_map_entry_match_condition_access_list_num_destroy(
614 * XPath: /frr-route-map:lib/route-map/entry/match-condition/list-name
616 static int lib_route_map_entry_match_condition_list_name_modify(
617 enum nb_event event
, const struct lyd_node
*dnode
,
618 union nb_resource
*resource
)
620 struct routemap_hook_context
*rhc
;
625 if (event
!= NB_EV_APPLY
)
628 /* Check for hook installation, otherwise we can just stop. */
629 acl
= yang_dnode_get_string(dnode
, NULL
);
630 rhc
= nb_running_get_entry(dnode
, NULL
, true);
631 condition
= yang_dnode_get_enum(dnode
, "../condition");
633 case 1: /* ipv4-address-list */
634 if (rmap_match_set_hook
.match_ip_address
== NULL
)
636 rhc
->rhc_mhook
= rmap_match_set_hook
.no_match_ip_address
;
637 rhc
->rhc_rule
= "ip address";
638 rhc
->rhc_event
= RMAP_EVENT_FILTER_DELETED
;
639 rv
= rmap_match_set_hook
.match_ip_address(
640 NULL
, rhc
->rhc_rmi
, "ip address", acl
,
641 RMAP_EVENT_FILTER_ADDED
);
643 case 2: /* ipv4-prefix-list */
644 if (rmap_match_set_hook
.match_ip_address_prefix_list
== NULL
)
647 rmap_match_set_hook
.no_match_ip_address_prefix_list
;
648 rhc
->rhc_rule
= "ip address prefix-list";
649 rhc
->rhc_event
= RMAP_EVENT_PLIST_DELETED
;
650 rv
= rmap_match_set_hook
.match_ip_address_prefix_list(
651 NULL
, rhc
->rhc_rmi
, "ip address prefix-list", acl
,
652 RMAP_EVENT_PLIST_ADDED
);
654 case 3: /* ipv4-next-hop-list */
655 if (rmap_match_set_hook
.match_ip_next_hop
== NULL
)
657 rhc
->rhc_mhook
= rmap_match_set_hook
.no_match_ip_next_hop
;
658 rhc
->rhc_rule
= "ip next-hop";
659 rhc
->rhc_event
= RMAP_EVENT_FILTER_DELETED
;
660 rv
= rmap_match_set_hook
.match_ip_next_hop(
661 NULL
, rhc
->rhc_rmi
, "ip next-hop", acl
,
662 RMAP_EVENT_FILTER_ADDED
);
664 case 4: /* ipv4-next-hop-prefix-list */
665 if (rmap_match_set_hook
.match_ip_next_hop_prefix_list
== NULL
)
668 rmap_match_set_hook
.no_match_ip_next_hop_prefix_list
;
669 rhc
->rhc_rule
= "ip next-hop prefix-list";
670 rhc
->rhc_event
= RMAP_EVENT_PLIST_DELETED
;
671 rv
= rmap_match_set_hook
.match_ip_next_hop_prefix_list(
672 NULL
, rhc
->rhc_rmi
, "ip next-hop prefix-list", acl
,
673 RMAP_EVENT_PLIST_ADDED
);
675 case 6: /* ipv6-address-list */
676 if (rmap_match_set_hook
.match_ipv6_address
== NULL
)
678 rhc
->rhc_mhook
= rmap_match_set_hook
.no_match_ipv6_address
;
679 rhc
->rhc_rule
= "ipv6 address";
680 rhc
->rhc_event
= RMAP_EVENT_FILTER_DELETED
;
681 rv
= rmap_match_set_hook
.match_ipv6_address(
682 NULL
, rhc
->rhc_rmi
, "ipv6 address", acl
,
683 RMAP_EVENT_FILTER_ADDED
);
685 case 7: /* ipv6-prefix-list */
686 if (rmap_match_set_hook
.match_ipv6_address_prefix_list
== NULL
)
689 rmap_match_set_hook
.no_match_ipv6_address_prefix_list
;
690 rhc
->rhc_rule
= "ipv6 address prefix-list";
691 rhc
->rhc_event
= RMAP_EVENT_PLIST_DELETED
;
692 rv
= rmap_match_set_hook
.match_ipv6_address_prefix_list(
693 NULL
, rhc
->rhc_rmi
, "ipv6 address prefix-list", acl
,
694 RMAP_EVENT_PLIST_ADDED
);
697 rv
= CMD_ERR_NO_MATCH
;
700 if (rv
!= CMD_SUCCESS
) {
701 rhc
->rhc_mhook
= NULL
;
702 return NB_ERR_INCONSISTENCY
;
708 static int lib_route_map_entry_match_condition_list_name_destroy(
709 enum nb_event event
, const struct lyd_node
*dnode
)
711 return lib_route_map_entry_match_destroy(event
, dnode
);
715 * XPath: /frr-route-map:lib/route-map/entry/match-condition/ipv4-next-hop-type
717 static int lib_route_map_entry_match_condition_ipv4_next_hop_type_modify(
718 enum nb_event event
, const struct lyd_node
*dnode
,
719 union nb_resource
*resource
)
721 struct routemap_hook_context
*rhc
;
725 if (event
!= NB_EV_APPLY
)
728 /* Check for hook function. */
729 if (rmap_match_set_hook
.match_ip_next_hop_type
== NULL
)
732 /* Add configuration. */
733 rhc
= nb_running_get_entry(dnode
, NULL
, true);
734 type
= yang_dnode_get_string(dnode
, NULL
);
736 /* Set destroy information. */
737 rhc
->rhc_mhook
= rmap_match_set_hook
.no_match_ip_next_hop_type
;
738 rhc
->rhc_rule
= "ip next-hop type";
739 rhc
->rhc_event
= RMAP_EVENT_MATCH_DELETED
;
741 rv
= rmap_match_set_hook
.match_ip_next_hop_type(
742 NULL
, rhc
->rhc_rmi
, "ip next-hop type", type
,
743 RMAP_EVENT_MATCH_ADDED
);
744 if (rv
!= CMD_SUCCESS
) {
745 rhc
->rhc_mhook
= NULL
;
746 return NB_ERR_INCONSISTENCY
;
752 static int lib_route_map_entry_match_condition_ipv4_next_hop_type_destroy(
753 enum nb_event event
, const struct lyd_node
*dnode
)
755 return lib_route_map_entry_match_destroy(event
, dnode
);
759 * XPath: /frr-route-map:lib/route-map/entry/match-condition/ipv6-next-hop-type
761 static int lib_route_map_entry_match_condition_ipv6_next_hop_type_modify(
762 enum nb_event event
, const struct lyd_node
*dnode
,
763 union nb_resource
*resource
)
765 struct routemap_hook_context
*rhc
;
769 if (event
!= NB_EV_APPLY
)
772 /* Check for hook function. */
773 if (rmap_match_set_hook
.match_ipv6_next_hop_type
== NULL
)
776 /* Add configuration. */
777 rhc
= nb_running_get_entry(dnode
, NULL
, true);
778 type
= yang_dnode_get_string(dnode
, NULL
);
780 /* Set destroy information. */
781 rhc
->rhc_mhook
= rmap_match_set_hook
.no_match_ipv6_next_hop_type
;
782 rhc
->rhc_rule
= "ipv6 next-hop type";
783 rhc
->rhc_event
= RMAP_EVENT_MATCH_DELETED
;
785 rv
= rmap_match_set_hook
.match_ipv6_next_hop_type(
786 NULL
, rhc
->rhc_rmi
, "ipv6 next-hop type", type
,
787 RMAP_EVENT_MATCH_ADDED
);
788 if (rv
!= CMD_SUCCESS
) {
789 rhc
->rhc_mhook
= NULL
;
790 return NB_ERR_INCONSISTENCY
;
796 static int lib_route_map_entry_match_condition_ipv6_next_hop_type_destroy(
797 enum nb_event event
, const struct lyd_node
*dnode
)
799 return lib_route_map_entry_match_destroy(event
, dnode
);
803 * XPath: /frr-route-map:lib/route-map/entry/match-condition/metric
806 lib_route_map_entry_match_condition_metric_modify(enum nb_event event
,
807 const struct lyd_node
*dnode
,
808 union nb_resource
*resource
)
810 struct routemap_hook_context
*rhc
;
814 if (event
!= NB_EV_APPLY
)
817 /* Check for hook function. */
818 if (rmap_match_set_hook
.match_metric
== NULL
)
821 /* Add configuration. */
822 rhc
= nb_running_get_entry(dnode
, NULL
, true);
823 type
= yang_dnode_get_string(dnode
, NULL
);
825 /* Set destroy information. */
826 rhc
->rhc_mhook
= rmap_match_set_hook
.no_match_metric
;
827 rhc
->rhc_rule
= "metric";
828 rhc
->rhc_event
= RMAP_EVENT_MATCH_DELETED
;
830 rv
= rmap_match_set_hook
.match_metric(NULL
, rhc
->rhc_rmi
, "metric",
831 type
, RMAP_EVENT_MATCH_ADDED
);
832 if (rv
!= CMD_SUCCESS
) {
833 rhc
->rhc_mhook
= NULL
;
834 return NB_ERR_INCONSISTENCY
;
841 lib_route_map_entry_match_condition_metric_destroy(enum nb_event event
,
842 const struct lyd_node
*dnode
)
844 return lib_route_map_entry_match_destroy(event
, dnode
);
848 * XPath: /frr-route-map:lib/route-map/entry/match-condition/tag
851 lib_route_map_entry_match_condition_tag_modify(enum nb_event event
,
852 const struct lyd_node
*dnode
,
853 union nb_resource
*resource
)
855 struct routemap_hook_context
*rhc
;
859 if (event
!= NB_EV_APPLY
)
862 /* Check for hook function. */
863 if (rmap_match_set_hook
.match_tag
== NULL
)
866 /* Add configuration. */
867 rhc
= nb_running_get_entry(dnode
, NULL
, true);
868 tag
= yang_dnode_get_string(dnode
, NULL
);
870 /* Set destroy information. */
871 rhc
->rhc_mhook
= rmap_match_set_hook
.no_match_tag
;
872 rhc
->rhc_rule
= "tag";
873 rhc
->rhc_event
= RMAP_EVENT_MATCH_DELETED
;
875 rv
= rmap_match_set_hook
.match_tag(NULL
, rhc
->rhc_rmi
, "tag", tag
,
876 RMAP_EVENT_MATCH_ADDED
);
877 if (rv
!= CMD_SUCCESS
) {
878 rhc
->rhc_mhook
= NULL
;
879 return NB_ERR_INCONSISTENCY
;
886 lib_route_map_entry_match_condition_tag_destroy(enum nb_event event
,
887 const struct lyd_node
*dnode
)
889 return lib_route_map_entry_match_destroy(event
, dnode
);
893 * XPath: /frr-route-map:lib/route-map/entry/set-action
895 static int lib_route_map_entry_set_action_create(enum nb_event event
,
896 const struct lyd_node
*dnode
,
897 union nb_resource
*resource
)
899 return lib_route_map_entry_match_condition_create(event
, dnode
,
903 static int lib_route_map_entry_set_action_destroy(enum nb_event event
,
904 const struct lyd_node
*dnode
)
906 struct routemap_hook_context
*rhc
;
909 if (event
!= NB_EV_APPLY
)
912 rv
= lib_route_map_entry_set_destroy(event
, dnode
);
913 rhc
= nb_running_unset_entry(dnode
);
914 routemap_hook_context_free(rhc
);
920 * XPath: /frr-route-map:lib/route-map/entry/set-action/ipv4-address
923 lib_route_map_entry_set_action_ipv4_address_modify(enum nb_event event
,
924 const struct lyd_node
*dnode
,
925 union nb_resource
*resource
)
927 struct routemap_hook_context
*rhc
;
935 * NOTE: validate if 'action' is 'ipv4-next-hop',
936 * currently it is not necessary because this is the
937 * only implemented action.
939 yang_dnode_get_ipv4(&ia
, dnode
, NULL
);
940 if (ia
.s_addr
== INADDR_ANY
|| IPV4_CLASS_DE(ntohl(ia
.s_addr
)))
941 return NB_ERR_VALIDATION
;
950 /* Check for hook function. */
951 if (rmap_match_set_hook
.set_ip_nexthop
== NULL
)
954 /* Add configuration. */
955 rhc
= nb_running_get_entry(dnode
, NULL
, true);
956 address
= yang_dnode_get_string(dnode
, NULL
);
958 /* Set destroy information. */
959 rhc
->rhc_shook
= rmap_match_set_hook
.no_set_ip_nexthop
;
960 rhc
->rhc_rule
= "ip next-hop";
962 rv
= rmap_match_set_hook
.set_ip_nexthop(NULL
, rhc
->rhc_rmi
,
963 "ip next-hop", address
);
964 if (rv
!= CMD_SUCCESS
) {
965 rhc
->rhc_shook
= NULL
;
966 return NB_ERR_INCONSISTENCY
;
972 static int lib_route_map_entry_set_action_ipv4_address_destroy(
973 enum nb_event event
, const struct lyd_node
*dnode
)
975 return lib_route_map_entry_set_destroy(event
, dnode
);
979 * XPath: /frr-route-map:lib/route-map/entry/set-action/ipv6-address
982 lib_route_map_entry_set_action_ipv6_address_modify(enum nb_event event
,
983 const struct lyd_node
*dnode
,
984 union nb_resource
*resource
)
986 struct routemap_hook_context
*rhc
;
994 * NOTE: validate if 'action' is 'ipv6-next-hop',
995 * currently it is not necessary because this is the
996 * only implemented action. Other actions might have
997 * different validations.
999 yang_dnode_get_ipv6(&i6a
, dnode
, NULL
);
1000 if (!IN6_IS_ADDR_LINKLOCAL(&i6a
))
1001 return NB_ERR_VALIDATION
;
1010 /* Check for hook function. */
1011 if (rmap_match_set_hook
.set_ipv6_nexthop_local
== NULL
)
1014 /* Add configuration. */
1015 rhc
= nb_running_get_entry(dnode
, NULL
, true);
1016 address
= yang_dnode_get_string(dnode
, NULL
);
1018 /* Set destroy information. */
1019 rhc
->rhc_shook
= rmap_match_set_hook
.no_set_ipv6_nexthop_local
;
1020 rhc
->rhc_rule
= "ipv6 next-hop local";
1022 rv
= rmap_match_set_hook
.set_ipv6_nexthop_local(
1023 NULL
, rhc
->rhc_rmi
, "ipv6 next-hop local", address
);
1024 if (rv
!= CMD_SUCCESS
) {
1025 rhc
->rhc_shook
= NULL
;
1026 return NB_ERR_INCONSISTENCY
;
1032 static int lib_route_map_entry_set_action_ipv6_address_destroy(
1033 enum nb_event event
, const struct lyd_node
*dnode
)
1035 return lib_route_map_entry_set_destroy(event
, dnode
);
1039 * XPath: /frr-route-map:lib/route-map/entry/set-action/value
1041 static int set_action_modify(enum nb_event event
, const struct lyd_node
*dnode
,
1042 union nb_resource
*resource
, const char *value
)
1044 struct routemap_hook_context
*rhc
;
1048 * NOTE: validate if 'action' is 'metric', currently it is not
1049 * necessary because this is the only implemented action. Other
1050 * actions might have different validations.
1052 if (event
!= NB_EV_APPLY
)
1055 /* Check for hook function. */
1056 if (rmap_match_set_hook
.set_metric
== NULL
)
1059 /* Add configuration. */
1060 rhc
= nb_running_get_entry(dnode
, NULL
, true);
1062 /* Set destroy information. */
1063 rhc
->rhc_shook
= rmap_match_set_hook
.no_set_metric
;
1064 rhc
->rhc_rule
= "metric";
1066 rv
= rmap_match_set_hook
.set_metric(NULL
, rhc
->rhc_rmi
, "metric",
1068 if (rv
!= CMD_SUCCESS
) {
1069 rhc
->rhc_shook
= NULL
;
1070 return NB_ERR_INCONSISTENCY
;
1077 lib_route_map_entry_set_action_value_modify(enum nb_event event
,
1078 const struct lyd_node
*dnode
,
1079 union nb_resource
*resource
)
1081 const char *metric
= yang_dnode_get_string(dnode
, NULL
);
1083 return set_action_modify(event
, dnode
, resource
, metric
);
1087 lib_route_map_entry_set_action_value_destroy(enum nb_event event
,
1088 const struct lyd_node
*dnode
)
1090 return lib_route_map_entry_set_destroy(event
, dnode
);
1094 * XPath: /frr-route-map:lib/route-map/entry/set-action/add-metric
1097 lib_route_map_entry_set_action_add_metric_modify(enum nb_event event
,
1098 const struct lyd_node
*dnode
,
1099 union nb_resource
*resource
)
1101 return set_action_modify(event
, dnode
, resource
, "+metric");
1105 lib_route_map_entry_set_action_add_metric_destroy(enum nb_event event
,
1106 const struct lyd_node
*dnode
)
1108 return lib_route_map_entry_set_action_value_destroy(event
, dnode
);
1112 * XPath: /frr-route-map:lib/route-map/entry/set-action/subtract-metric
1114 static int lib_route_map_entry_set_action_subtract_metric_modify(
1115 enum nb_event event
, const struct lyd_node
*dnode
,
1116 union nb_resource
*resource
)
1118 return set_action_modify(event
, dnode
, resource
, "-metric");
1121 static int lib_route_map_entry_set_action_subtract_metric_destroy(
1122 enum nb_event event
, const struct lyd_node
*dnode
)
1124 return lib_route_map_entry_set_action_value_destroy(event
, dnode
);
1128 * XPath: /frr-route-map:lib/route-map/entry/set-action/use-round-trip-time
1130 static int lib_route_map_entry_set_action_use_round_trip_time_modify(
1131 enum nb_event event
, const struct lyd_node
*dnode
,
1132 union nb_resource
*resource
)
1134 return set_action_modify(event
, dnode
, resource
, "rtt");
1137 static int lib_route_map_entry_set_action_use_round_trip_time_destroy(
1138 enum nb_event event
, const struct lyd_node
*dnode
)
1140 return lib_route_map_entry_set_action_value_destroy(event
, dnode
);
1144 * XPath: /frr-route-map:lib/route-map/entry/set-action/add-round-trip-time
1146 static int lib_route_map_entry_set_action_add_round_trip_time_modify(
1147 enum nb_event event
, const struct lyd_node
*dnode
,
1148 union nb_resource
*resource
)
1150 return set_action_modify(event
, dnode
, resource
, "+rtt");
1153 static int lib_route_map_entry_set_action_add_round_trip_time_destroy(
1154 enum nb_event event
, const struct lyd_node
*dnode
)
1156 return lib_route_map_entry_set_action_value_destroy(event
, dnode
);
1160 * XPath: /frr-route-map:lib/route-map/entry/set-action/subtract-round-trip-time
1162 static int lib_route_map_entry_set_action_subtract_round_trip_time_modify(
1163 enum nb_event event
, const struct lyd_node
*dnode
,
1164 union nb_resource
*resource
)
1166 return set_action_modify(event
, dnode
, resource
, "-rtt");
1169 static int lib_route_map_entry_set_action_subtract_round_trip_time_destroy(
1170 enum nb_event event
, const struct lyd_node
*dnode
)
1172 return lib_route_map_entry_set_action_value_destroy(event
, dnode
);
1176 * XPath: /frr-route-map:lib/route-map/entry/set-action/tag
1179 lib_route_map_entry_set_action_tag_modify(enum nb_event event
,
1180 const struct lyd_node
*dnode
,
1181 union nb_resource
*resource
)
1183 struct routemap_hook_context
*rhc
;
1188 * NOTE: validate if 'action' is 'tag', currently it is not
1189 * necessary because this is the only implemented action. Other
1190 * actions might have different validations.
1192 if (event
!= NB_EV_APPLY
)
1195 /* Check for hook function. */
1196 if (rmap_match_set_hook
.set_tag
== NULL
)
1199 /* Add configuration. */
1200 rhc
= nb_running_get_entry(dnode
, NULL
, true);
1201 tag
= yang_dnode_get_string(dnode
, NULL
);
1203 /* Set destroy information. */
1204 rhc
->rhc_shook
= rmap_match_set_hook
.no_set_tag
;
1205 rhc
->rhc_rule
= "tag";
1207 rv
= rmap_match_set_hook
.set_tag(NULL
, rhc
->rhc_rmi
, "tag", tag
);
1208 if (rv
!= CMD_SUCCESS
) {
1209 rhc
->rhc_shook
= NULL
;
1210 return NB_ERR_INCONSISTENCY
;
1217 lib_route_map_entry_set_action_tag_destroy(enum nb_event event
,
1218 const struct lyd_node
*dnode
)
1220 return lib_route_map_entry_set_destroy(event
, dnode
);
1223 /* clang-format off */
1224 const struct frr_yang_module_info frr_route_map_info
= {
1225 .name
= "frr-route-map",
1228 .xpath
= "/frr-route-map:lib/route-map",
1230 .create
= lib_route_map_create
,
1231 .destroy
= lib_route_map_destroy
,
1235 .xpath
= "/frr-route-map:lib/route-map/entry",
1237 .create
= lib_route_map_entry_create
,
1238 .destroy
= lib_route_map_entry_destroy
,
1239 .cli_show
= route_map_instance_show
,
1240 .cli_show_end
= route_map_instance_show_end
,
1244 .xpath
= "/frr-route-map:lib/route-map/entry/description",
1246 .modify
= lib_route_map_entry_description_modify
,
1247 .destroy
= lib_route_map_entry_description_destroy
,
1248 .cli_show
= route_map_description_show
,
1252 .xpath
= "/frr-route-map:lib/route-map/entry/action",
1254 .modify
= lib_route_map_entry_action_modify
,
1258 .xpath
= "/frr-route-map:lib/route-map/entry/call",
1260 .modify
= lib_route_map_entry_call_modify
,
1261 .destroy
= lib_route_map_entry_call_destroy
,
1262 .cli_show
= route_map_call_show
,
1266 .xpath
= "/frr-route-map:lib/route-map/entry/exit-policy",
1268 .modify
= lib_route_map_entry_exit_policy_modify
,
1269 .cli_show
= route_map_exit_policy_show
,
1273 .xpath
= "/frr-route-map:lib/route-map/entry/goto-value",
1275 .modify
= lib_route_map_entry_goto_value_modify
,
1276 .destroy
= lib_route_map_entry_goto_value_destroy
,
1280 .xpath
= "/frr-route-map:lib/route-map/entry/match-condition",
1282 .create
= lib_route_map_entry_match_condition_create
,
1283 .destroy
= lib_route_map_entry_match_condition_destroy
,
1284 .cli_show
= route_map_condition_show
,
1288 .xpath
= "/frr-route-map:lib/route-map/entry/match-condition/interface",
1290 .modify
= lib_route_map_entry_match_condition_interface_modify
,
1291 .destroy
= lib_route_map_entry_match_condition_interface_destroy
,
1295 .xpath
= "/frr-route-map:lib/route-map/entry/match-condition/access-list-num",
1297 .modify
= lib_route_map_entry_match_condition_access_list_num_modify
,
1298 .destroy
= lib_route_map_entry_match_condition_access_list_num_destroy
,
1302 .xpath
= "/frr-route-map:lib/route-map/entry/match-condition/access-list-num-extended",
1304 .modify
= lib_route_map_entry_match_condition_access_list_num_extended_modify
,
1305 .destroy
= lib_route_map_entry_match_condition_access_list_num_extended_destroy
,
1309 .xpath
= "/frr-route-map:lib/route-map/entry/match-condition/list-name",
1311 .modify
= lib_route_map_entry_match_condition_list_name_modify
,
1312 .destroy
= lib_route_map_entry_match_condition_list_name_destroy
,
1316 .xpath
= "/frr-route-map:lib/route-map/entry/match-condition/ipv4-next-hop-type",
1318 .modify
= lib_route_map_entry_match_condition_ipv4_next_hop_type_modify
,
1319 .destroy
= lib_route_map_entry_match_condition_ipv4_next_hop_type_destroy
,
1323 .xpath
= "/frr-route-map:lib/route-map/entry/match-condition/ipv6-next-hop-type",
1325 .modify
= lib_route_map_entry_match_condition_ipv6_next_hop_type_modify
,
1326 .destroy
= lib_route_map_entry_match_condition_ipv6_next_hop_type_destroy
,
1330 .xpath
= "/frr-route-map:lib/route-map/entry/match-condition/metric",
1332 .modify
= lib_route_map_entry_match_condition_metric_modify
,
1333 .destroy
= lib_route_map_entry_match_condition_metric_destroy
,
1337 .xpath
= "/frr-route-map:lib/route-map/entry/match-condition/tag",
1339 .modify
= lib_route_map_entry_match_condition_tag_modify
,
1340 .destroy
= lib_route_map_entry_match_condition_tag_destroy
,
1344 .xpath
= "/frr-route-map:lib/route-map/entry/set-action",
1346 .create
= lib_route_map_entry_set_action_create
,
1347 .destroy
= lib_route_map_entry_set_action_destroy
,
1348 .cli_show
= route_map_action_show
,
1352 .xpath
= "/frr-route-map:lib/route-map/entry/set-action/ipv4-address",
1354 .modify
= lib_route_map_entry_set_action_ipv4_address_modify
,
1355 .destroy
= lib_route_map_entry_set_action_ipv4_address_destroy
,
1359 .xpath
= "/frr-route-map:lib/route-map/entry/set-action/ipv6-address",
1361 .modify
= lib_route_map_entry_set_action_ipv6_address_modify
,
1362 .destroy
= lib_route_map_entry_set_action_ipv6_address_destroy
,
1366 .xpath
= "/frr-route-map:lib/route-map/entry/set-action/value",
1368 .modify
= lib_route_map_entry_set_action_value_modify
,
1369 .destroy
= lib_route_map_entry_set_action_value_destroy
,
1373 .xpath
= "/frr-route-map:lib/route-map/entry/set-action/add-metric",
1375 .modify
= lib_route_map_entry_set_action_add_metric_modify
,
1376 .destroy
= lib_route_map_entry_set_action_add_metric_destroy
,
1380 .xpath
= "/frr-route-map:lib/route-map/entry/set-action/subtract-metric",
1382 .modify
= lib_route_map_entry_set_action_subtract_metric_modify
,
1383 .destroy
= lib_route_map_entry_set_action_subtract_metric_destroy
,
1387 .xpath
= "/frr-route-map:lib/route-map/entry/set-action/use-round-trip-time",
1389 .modify
= lib_route_map_entry_set_action_use_round_trip_time_modify
,
1390 .destroy
= lib_route_map_entry_set_action_use_round_trip_time_destroy
,
1394 .xpath
= "/frr-route-map:lib/route-map/entry/set-action/add-round-trip-time",
1396 .modify
= lib_route_map_entry_set_action_add_round_trip_time_modify
,
1397 .destroy
= lib_route_map_entry_set_action_add_round_trip_time_destroy
,
1401 .xpath
= "/frr-route-map:lib/route-map/entry/set-action/subtract-round-trip-time",
1403 .modify
= lib_route_map_entry_set_action_subtract_round_trip_time_modify
,
1404 .destroy
= lib_route_map_entry_set_action_subtract_round_trip_time_destroy
,
1408 .xpath
= "/frr-route-map:lib/route-map/entry/set-action/tag",
1410 .modify
= lib_route_map_entry_set_action_tag_modify
,
1411 .destroy
= lib_route_map_entry_set_action_tag_destroy
,