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(struct nb_cb_destroy_args
*args
)
38 struct routemap_hook_context
*rhc
;
41 if (args
->event
!= NB_EV_APPLY
)
44 rhc
= nb_running_get_entry(args
->dnode
, NULL
, true);
45 if (rhc
->rhc_mhook
== NULL
)
48 rv
= rhc
->rhc_mhook(rhc
->rhc_rmi
, rhc
->rhc_rule
, NULL
,
50 args
->errmsg
, args
->errmsg_len
);
51 if (rv
!= CMD_SUCCESS
)
52 return NB_ERR_INCONSISTENCY
;
57 int lib_route_map_entry_set_destroy(struct nb_cb_destroy_args
*args
)
59 struct routemap_hook_context
*rhc
;
62 if (args
->event
!= NB_EV_APPLY
)
65 rhc
= nb_running_get_entry(args
->dnode
, NULL
, true);
66 if (rhc
->rhc_shook
== NULL
)
69 rv
= rhc
->rhc_shook(rhc
->rhc_rmi
, rhc
->rhc_rule
, NULL
,
70 args
->errmsg
, args
->errmsg_len
);
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
);
92 void routemap_hook_context_free(struct routemap_hook_context
*rhc
)
94 struct route_map_index
*rmi
= rhc
->rhc_rmi
;
96 TAILQ_REMOVE(&rmi
->rhclist
, rhc
, rhc_entry
);
97 XFREE(MTYPE_TMP
, rhc
);
101 * XPath: /frr-route-map:lib/route-map
103 static int lib_route_map_create(struct nb_cb_create_args
*args
)
105 struct route_map
*rm
;
108 switch (args
->event
) {
115 rm_name
= yang_dnode_get_string(args
->dnode
, "./name");
116 rm
= route_map_get(rm_name
);
117 nb_running_set_entry(args
->dnode
, rm
);
124 static int lib_route_map_destroy(struct nb_cb_destroy_args
*args
)
126 struct route_map
*rm
;
128 switch (args
->event
) {
135 rm
= nb_running_unset_entry(args
->dnode
);
136 route_map_delete(rm
);
144 * XPath: /frr-route-map:lib/route-map/optimization-disabled
147 lib_route_map_optimization_disabled_modify(struct nb_cb_modify_args
*args
)
149 struct route_map
*rm
;
150 bool disabled
= yang_dnode_get_bool(args
->dnode
, NULL
);
152 switch (args
->event
) {
159 rm
= nb_running_get_entry(args
->dnode
, NULL
, true);
160 rm
->optimization_disabled
= disabled
;
168 * XPath: /frr-route-map:lib/route-map/entry
170 static int lib_route_map_entry_create(struct nb_cb_create_args
*args
)
172 struct route_map_index
*rmi
;
173 struct route_map
*rm
;
177 switch (args
->event
) {
184 sequence
= yang_dnode_get_uint16(args
->dnode
, "./sequence");
185 action
= yang_dnode_get_enum(args
->dnode
, "./action") == 0
188 rm
= nb_running_get_entry(args
->dnode
, NULL
, true);
189 rmi
= route_map_index_get(rm
, action
, sequence
);
190 nb_running_set_entry(args
->dnode
, rmi
);
197 static int lib_route_map_entry_destroy(struct nb_cb_destroy_args
*args
)
199 struct route_map_index
*rmi
;
201 switch (args
->event
) {
208 rmi
= nb_running_unset_entry(args
->dnode
);
209 route_map_index_delete(rmi
, 1);
217 * XPath: /frr-route-map:lib/route-map/entry/description
220 lib_route_map_entry_description_modify(struct nb_cb_modify_args
*args
)
222 struct route_map_index
*rmi
;
223 const char *description
;
225 switch (args
->event
) {
230 description
= yang_dnode_get_string(args
->dnode
, NULL
);
231 args
->resource
->ptr
= XSTRDUP(MTYPE_TMP
, description
);
232 if (args
->resource
->ptr
== NULL
)
233 return NB_ERR_RESOURCE
;
236 XFREE(MTYPE_TMP
, args
->resource
->ptr
);
239 rmi
= nb_running_get_entry(args
->dnode
, NULL
, true);
240 XFREE(MTYPE_TMP
, rmi
->description
);
241 rmi
->description
= args
->resource
->ptr
;
249 lib_route_map_entry_description_destroy(struct nb_cb_destroy_args
*args
)
251 struct route_map_index
*rmi
;
253 switch (args
->event
) {
260 rmi
= nb_running_get_entry(args
->dnode
, NULL
, true);
261 XFREE(MTYPE_TMP
, rmi
->description
);
269 * XPath: /frr-route-map:lib/route-map/entry/action
271 static int lib_route_map_entry_action_modify(struct nb_cb_modify_args
*args
)
273 struct route_map_index
*rmi
;
275 switch (args
->event
) {
282 rmi
= nb_running_get_entry(args
->dnode
, NULL
, true);
283 rmi
->type
= yang_dnode_get_enum(args
->dnode
, NULL
);
292 * XPath: /frr-route-map:lib/route-map/entry/call
294 static int lib_route_map_entry_call_modify(struct nb_cb_modify_args
*args
)
296 struct route_map_index
*rmi
;
297 const char *rm_name
, *rmn_name
;
299 switch (args
->event
) {
301 rm_name
= yang_dnode_get_string(args
->dnode
, "../../name");
302 rmn_name
= yang_dnode_get_string(args
->dnode
, NULL
);
303 /* Don't allow to jump to the same route map instance. */
304 if (strcmp(rm_name
, rmn_name
) == 0)
305 return NB_ERR_VALIDATION
;
307 /* TODO: detect circular route map sequences. */
310 rmn_name
= yang_dnode_get_string(args
->dnode
, NULL
);
311 args
->resource
->ptr
= XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmn_name
);
314 XFREE(MTYPE_ROUTE_MAP_NAME
, args
->resource
->ptr
);
317 rmi
= nb_running_get_entry(args
->dnode
, NULL
, true);
319 route_map_upd8_dependency(RMAP_EVENT_CALL_DELETED
,
320 rmi
->nextrm
, rmi
->map
->name
);
321 XFREE(MTYPE_ROUTE_MAP_NAME
, rmi
->nextrm
);
323 rmi
->nextrm
= args
->resource
->ptr
;
324 route_map_upd8_dependency(RMAP_EVENT_CALL_ADDED
, rmi
->nextrm
,
332 static int lib_route_map_entry_call_destroy(struct nb_cb_destroy_args
*args
)
334 struct route_map_index
*rmi
;
336 switch (args
->event
) {
343 rmi
= nb_running_get_entry(args
->dnode
, NULL
, true);
344 route_map_upd8_dependency(RMAP_EVENT_CALL_DELETED
, rmi
->nextrm
,
346 XFREE(MTYPE_ROUTE_MAP_NAME
, rmi
->nextrm
);
355 * XPath: /frr-route-map:lib/route-map/entry/exit-policy
358 lib_route_map_entry_exit_policy_modify(struct nb_cb_modify_args
*args
)
360 struct route_map_index
*rmi
;
364 switch (args
->event
) {
366 policy
= yang_dnode_get_enum(args
->dnode
, NULL
);
368 case 0: /* permit-or-deny */
374 yang_dnode_get_enum(args
->dnode
, "../action");
375 if (rm_action
== 1 /* deny */) {
377 * On deny it is not possible to 'goto'
380 return NB_ERR_VALIDATION
;
389 rmi
= nb_running_get_entry(args
->dnode
, NULL
, true);
390 policy
= yang_dnode_get_enum(args
->dnode
, NULL
);
393 case 0: /* permit-or-deny */
394 rmi
->exitpolicy
= RMAP_EXIT
;
397 rmi
->exitpolicy
= RMAP_NEXT
;
400 rmi
->exitpolicy
= RMAP_GOTO
;
410 * XPath: /frr-route-map:lib/route-map/entry/goto-value
412 static int lib_route_map_entry_goto_value_modify(struct nb_cb_modify_args
*args
)
414 struct route_map_index
*rmi
;
418 switch (args
->event
) {
420 rmi_index
= yang_dnode_get_uint16(args
->dnode
, "../sequence");
421 rmi_next
= yang_dnode_get_uint16(args
->dnode
, NULL
);
422 if (rmi_next
<= rmi_index
) {
423 /* Can't jump backwards on a route map. */
424 return NB_ERR_VALIDATION
;
432 rmi
= nb_running_get_entry(args
->dnode
, NULL
, true);
433 rmi
->nextpref
= yang_dnode_get_uint16(args
->dnode
, NULL
);
441 lib_route_map_entry_goto_value_destroy(struct nb_cb_destroy_args
*args
)
443 struct route_map_index
*rmi
;
445 switch (args
->event
) {
452 rmi
= nb_running_get_entry(args
->dnode
, NULL
, true);
461 * XPath: /frr-route-map:lib/route-map/entry/match-condition
464 lib_route_map_entry_match_condition_create(struct nb_cb_create_args
*args
)
466 struct routemap_hook_context
*rhc
;
467 struct route_map_index
*rmi
;
469 switch (args
->event
) {
476 rmi
= nb_running_get_entry(args
->dnode
, NULL
, true);
477 rhc
= routemap_hook_context_insert(rmi
);
478 nb_running_set_entry(args
->dnode
, rhc
);
486 lib_route_map_entry_match_condition_destroy(struct nb_cb_destroy_args
*args
)
488 struct routemap_hook_context
*rhc
;
491 if (args
->event
!= NB_EV_APPLY
)
494 rv
= lib_route_map_entry_match_destroy(args
);
495 rhc
= nb_running_unset_entry(args
->dnode
);
496 routemap_hook_context_free(rhc
);
502 * XPath: /frr-route-map:lib/route-map/entry/match-condition/interface
504 static int lib_route_map_entry_match_condition_interface_modify(
505 struct nb_cb_modify_args
*args
)
507 struct routemap_hook_context
*rhc
;
511 if (args
->event
!= NB_EV_APPLY
)
514 /* Check for hook function. */
515 if (rmap_match_set_hook
.match_interface
== NULL
)
518 /* Add configuration. */
519 rhc
= nb_running_get_entry(args
->dnode
, NULL
, true);
520 ifname
= yang_dnode_get_string(args
->dnode
, NULL
);
522 /* Set destroy information. */
523 rhc
->rhc_mhook
= rmap_match_set_hook
.no_match_interface
;
524 rhc
->rhc_rule
= "interface";
525 rhc
->rhc_event
= RMAP_EVENT_MATCH_DELETED
;
527 rv
= rmap_match_set_hook
.match_interface(rhc
->rhc_rmi
,
529 RMAP_EVENT_MATCH_ADDED
,
530 args
->errmsg
, args
->errmsg_len
);
531 if (rv
!= CMD_SUCCESS
) {
532 rhc
->rhc_mhook
= NULL
;
533 return NB_ERR_INCONSISTENCY
;
539 static int lib_route_map_entry_match_condition_interface_destroy(
540 struct nb_cb_destroy_args
*args
)
542 return lib_route_map_entry_match_destroy(args
);
546 * XPath: /frr-route-map:lib/route-map/entry/match-condition/list-name
548 static int lib_route_map_entry_match_condition_list_name_modify(
549 struct nb_cb_modify_args
*args
)
551 struct routemap_hook_context
*rhc
;
553 const char *condition
;
556 if (args
->event
!= NB_EV_APPLY
)
559 /* Check for hook installation, otherwise we can just stop. */
560 acl
= yang_dnode_get_string(args
->dnode
, NULL
);
561 rhc
= nb_running_get_entry(args
->dnode
, NULL
, true);
562 condition
= yang_dnode_get_string(args
->dnode
, "../../condition");
564 if (IS_MATCH_IPv4_ADDRESS_LIST(condition
)) {
565 if (rmap_match_set_hook
.match_ip_address
== NULL
)
567 rhc
->rhc_mhook
= rmap_match_set_hook
.no_match_ip_address
;
568 rhc
->rhc_rule
= "ip address";
569 rhc
->rhc_event
= RMAP_EVENT_FILTER_DELETED
;
570 rv
= rmap_match_set_hook
.match_ip_address(
571 rhc
->rhc_rmi
, "ip address", acl
,
572 RMAP_EVENT_FILTER_ADDED
,
573 args
->errmsg
, args
->errmsg_len
);
574 } else if (IS_MATCH_IPv4_PREFIX_LIST(condition
)) {
575 if (rmap_match_set_hook
.match_ip_address_prefix_list
== NULL
)
578 rmap_match_set_hook
.no_match_ip_address_prefix_list
;
579 rhc
->rhc_rule
= "ip address prefix-list";
580 rhc
->rhc_event
= RMAP_EVENT_PLIST_DELETED
;
581 rv
= rmap_match_set_hook
.match_ip_address_prefix_list(
582 rhc
->rhc_rmi
, "ip address prefix-list", acl
,
583 RMAP_EVENT_PLIST_ADDED
,
584 args
->errmsg
, args
->errmsg_len
);
585 } else if (IS_MATCH_IPv4_NEXTHOP_LIST(condition
)) {
586 if (rmap_match_set_hook
.match_ip_next_hop
== NULL
)
588 rhc
->rhc_mhook
= rmap_match_set_hook
.no_match_ip_next_hop
;
589 rhc
->rhc_rule
= "ip next-hop";
590 rhc
->rhc_event
= RMAP_EVENT_FILTER_DELETED
;
591 rv
= rmap_match_set_hook
.match_ip_next_hop(
592 rhc
->rhc_rmi
, "ip next-hop", acl
,
593 RMAP_EVENT_FILTER_ADDED
,
594 args
->errmsg
, args
->errmsg_len
);
595 } else if (IS_MATCH_IPv4_NEXTHOP_PREFIX_LIST(condition
)) {
596 if (rmap_match_set_hook
.match_ip_next_hop_prefix_list
== NULL
)
599 rmap_match_set_hook
.no_match_ip_next_hop_prefix_list
;
600 rhc
->rhc_rule
= "ip next-hop prefix-list";
601 rhc
->rhc_event
= RMAP_EVENT_PLIST_DELETED
;
602 rv
= rmap_match_set_hook
.match_ip_next_hop_prefix_list(
603 rhc
->rhc_rmi
, "ip next-hop prefix-list", acl
,
604 RMAP_EVENT_PLIST_ADDED
,
605 args
->errmsg
, args
->errmsg_len
);
606 } else if (IS_MATCH_IPv6_ADDRESS_LIST(condition
)) {
607 if (rmap_match_set_hook
.match_ipv6_address
== NULL
)
609 rhc
->rhc_mhook
= rmap_match_set_hook
.no_match_ipv6_address
;
610 rhc
->rhc_rule
= "ipv6 address";
611 rhc
->rhc_event
= RMAP_EVENT_FILTER_DELETED
;
612 rv
= rmap_match_set_hook
.match_ipv6_address(
613 rhc
->rhc_rmi
, "ipv6 address", acl
,
614 RMAP_EVENT_FILTER_ADDED
,
615 args
->errmsg
, args
->errmsg_len
);
616 } else if (IS_MATCH_IPv6_PREFIX_LIST(condition
)) {
617 if (rmap_match_set_hook
.match_ipv6_address_prefix_list
== NULL
)
620 rmap_match_set_hook
.no_match_ipv6_address_prefix_list
;
621 rhc
->rhc_rule
= "ipv6 address prefix-list";
622 rhc
->rhc_event
= RMAP_EVENT_PLIST_DELETED
;
623 rv
= rmap_match_set_hook
.match_ipv6_address_prefix_list(
624 rhc
->rhc_rmi
, "ipv6 address prefix-list", acl
,
625 RMAP_EVENT_PLIST_ADDED
,
626 args
->errmsg
, args
->errmsg_len
);
628 rv
= CMD_ERR_NO_MATCH
;
630 if (rv
!= CMD_SUCCESS
) {
631 rhc
->rhc_mhook
= NULL
;
632 return NB_ERR_INCONSISTENCY
;
638 static int lib_route_map_entry_match_condition_list_name_destroy(
639 struct nb_cb_destroy_args
*args
)
641 return lib_route_map_entry_match_destroy(args
);
645 * XPath: /frr-route-map:lib/route-map/entry/match-condition/ipv4-next-hop-type
647 static int lib_route_map_entry_match_condition_ipv4_next_hop_type_modify(
648 struct nb_cb_modify_args
*args
)
650 struct routemap_hook_context
*rhc
;
654 if (args
->event
!= NB_EV_APPLY
)
657 /* Check for hook function. */
658 if (rmap_match_set_hook
.match_ip_next_hop_type
== NULL
)
661 /* Add configuration. */
662 rhc
= nb_running_get_entry(args
->dnode
, NULL
, true);
663 type
= yang_dnode_get_string(args
->dnode
, NULL
);
665 /* Set destroy information. */
666 rhc
->rhc_mhook
= rmap_match_set_hook
.no_match_ip_next_hop_type
;
667 rhc
->rhc_rule
= "ip next-hop type";
668 rhc
->rhc_event
= RMAP_EVENT_MATCH_DELETED
;
670 rv
= rmap_match_set_hook
.match_ip_next_hop_type(
671 rhc
->rhc_rmi
, "ip next-hop type", type
,
672 RMAP_EVENT_MATCH_ADDED
,
673 args
->errmsg
, args
->errmsg_len
);
674 if (rv
!= CMD_SUCCESS
) {
675 rhc
->rhc_mhook
= NULL
;
676 return NB_ERR_INCONSISTENCY
;
682 static int lib_route_map_entry_match_condition_ipv4_next_hop_type_destroy(
683 struct nb_cb_destroy_args
*args
)
685 return lib_route_map_entry_match_destroy(args
);
689 * XPath: /frr-route-map:lib/route-map/entry/match-condition/ipv6-next-hop-type
691 static int lib_route_map_entry_match_condition_ipv6_next_hop_type_modify(
692 struct nb_cb_modify_args
*args
)
694 struct routemap_hook_context
*rhc
;
698 if (args
->event
!= NB_EV_APPLY
)
701 /* Check for hook function. */
702 if (rmap_match_set_hook
.match_ipv6_next_hop_type
== NULL
)
705 /* Add configuration. */
706 rhc
= nb_running_get_entry(args
->dnode
, NULL
, true);
707 type
= yang_dnode_get_string(args
->dnode
, NULL
);
709 /* Set destroy information. */
710 rhc
->rhc_mhook
= rmap_match_set_hook
.no_match_ipv6_next_hop_type
;
711 rhc
->rhc_rule
= "ipv6 next-hop type";
712 rhc
->rhc_event
= RMAP_EVENT_MATCH_DELETED
;
714 rv
= rmap_match_set_hook
.match_ipv6_next_hop_type(
715 rhc
->rhc_rmi
, "ipv6 next-hop type", type
,
716 RMAP_EVENT_MATCH_ADDED
,
717 args
->errmsg
, args
->errmsg_len
);
718 if (rv
!= CMD_SUCCESS
) {
719 rhc
->rhc_mhook
= NULL
;
720 return NB_ERR_INCONSISTENCY
;
726 static int lib_route_map_entry_match_condition_ipv6_next_hop_type_destroy(
727 struct nb_cb_destroy_args
*args
)
729 return lib_route_map_entry_match_destroy(args
);
733 * XPath: /frr-route-map:lib/route-map/entry/match-condition/metric
735 static int lib_route_map_entry_match_condition_metric_modify(
736 struct nb_cb_modify_args
*args
)
738 struct routemap_hook_context
*rhc
;
742 if (args
->event
!= NB_EV_APPLY
)
745 /* Check for hook function. */
746 if (rmap_match_set_hook
.match_metric
== NULL
)
749 /* Add configuration. */
750 rhc
= nb_running_get_entry(args
->dnode
, NULL
, true);
751 type
= yang_dnode_get_string(args
->dnode
, NULL
);
753 /* Set destroy information. */
754 rhc
->rhc_mhook
= rmap_match_set_hook
.no_match_metric
;
755 rhc
->rhc_rule
= "metric";
756 rhc
->rhc_event
= RMAP_EVENT_MATCH_DELETED
;
758 rv
= rmap_match_set_hook
.match_metric(rhc
->rhc_rmi
, "metric",
759 type
, RMAP_EVENT_MATCH_ADDED
,
760 args
->errmsg
, args
->errmsg_len
);
761 if (rv
!= CMD_SUCCESS
) {
762 rhc
->rhc_mhook
= NULL
;
763 return NB_ERR_INCONSISTENCY
;
769 static int lib_route_map_entry_match_condition_metric_destroy(
770 struct nb_cb_destroy_args
*args
)
772 return lib_route_map_entry_match_destroy(args
);
776 * XPath: /frr-route-map:lib/route-map/entry/match-condition/tag
779 lib_route_map_entry_match_condition_tag_modify(struct nb_cb_modify_args
*args
)
781 struct routemap_hook_context
*rhc
;
785 if (args
->event
!= NB_EV_APPLY
)
788 /* Check for hook function. */
789 if (rmap_match_set_hook
.match_tag
== NULL
)
792 /* Add configuration. */
793 rhc
= nb_running_get_entry(args
->dnode
, NULL
, true);
794 tag
= yang_dnode_get_string(args
->dnode
, NULL
);
796 /* Set destroy information. */
797 rhc
->rhc_mhook
= rmap_match_set_hook
.no_match_tag
;
798 rhc
->rhc_rule
= "tag";
799 rhc
->rhc_event
= RMAP_EVENT_MATCH_DELETED
;
801 rv
= rmap_match_set_hook
.match_tag(rhc
->rhc_rmi
, "tag", tag
,
802 RMAP_EVENT_MATCH_ADDED
,
803 args
->errmsg
, args
->errmsg_len
);
804 if (rv
!= CMD_SUCCESS
) {
805 rhc
->rhc_mhook
= NULL
;
806 return NB_ERR_INCONSISTENCY
;
813 lib_route_map_entry_match_condition_tag_destroy(struct nb_cb_destroy_args
*args
)
815 return lib_route_map_entry_match_destroy(args
);
819 * XPath: /frr-route-map:lib/route-map/entry/set-action
821 static int lib_route_map_entry_set_action_create(struct nb_cb_create_args
*args
)
823 return lib_route_map_entry_match_condition_create(args
);
827 lib_route_map_entry_set_action_destroy(struct nb_cb_destroy_args
*args
)
829 struct routemap_hook_context
*rhc
;
832 if (args
->event
!= NB_EV_APPLY
)
835 rv
= lib_route_map_entry_set_destroy(args
);
836 rhc
= nb_running_unset_entry(args
->dnode
);
837 routemap_hook_context_free(rhc
);
843 * XPath: /frr-route-map:lib/route-map/entry/set-action/ipv4-address
845 static int lib_route_map_entry_set_action_ipv4_address_modify(
846 struct nb_cb_modify_args
*args
)
848 struct routemap_hook_context
*rhc
;
853 switch (args
->event
) {
856 * NOTE: validate if 'action' is 'ipv4-next-hop',
857 * currently it is not necessary because this is the
858 * only implemented action.
860 yang_dnode_get_ipv4(&ia
, args
->dnode
, NULL
);
861 if (ia
.s_addr
== INADDR_ANY
|| IPV4_CLASS_DE(ntohl(ia
.s_addr
)))
862 return NB_ERR_VALIDATION
;
871 /* Check for hook function. */
872 if (rmap_match_set_hook
.set_ip_nexthop
== NULL
)
875 /* Add configuration. */
876 rhc
= nb_running_get_entry(args
->dnode
, NULL
, true);
877 address
= yang_dnode_get_string(args
->dnode
, NULL
);
879 /* Set destroy information. */
880 rhc
->rhc_shook
= rmap_match_set_hook
.no_set_ip_nexthop
;
881 rhc
->rhc_rule
= "ip next-hop";
883 rv
= rmap_match_set_hook
.set_ip_nexthop(rhc
->rhc_rmi
, "ip next-hop",
885 args
->errmsg
, args
->errmsg_len
);
886 if (rv
!= CMD_SUCCESS
) {
887 rhc
->rhc_shook
= NULL
;
888 return NB_ERR_INCONSISTENCY
;
894 static int lib_route_map_entry_set_action_ipv4_address_destroy(
895 struct nb_cb_destroy_args
*args
)
897 return lib_route_map_entry_set_destroy(args
);
901 * XPath: /frr-route-map:lib/route-map/entry/set-action/ipv6-address
903 static int lib_route_map_entry_set_action_ipv6_address_modify(
904 struct nb_cb_modify_args
*args
)
906 struct routemap_hook_context
*rhc
;
911 switch (args
->event
) {
914 * NOTE: validate if 'action' is 'ipv6-next-hop',
915 * currently it is not necessary because this is the
916 * only implemented action. Other actions might have
917 * different validations.
919 yang_dnode_get_ipv6(&i6a
, args
->dnode
, NULL
);
920 if (!IN6_IS_ADDR_LINKLOCAL(&i6a
))
921 return NB_ERR_VALIDATION
;
930 /* Check for hook function. */
931 if (rmap_match_set_hook
.set_ipv6_nexthop_local
== NULL
)
934 /* Add configuration. */
935 rhc
= nb_running_get_entry(args
->dnode
, NULL
, true);
936 address
= yang_dnode_get_string(args
->dnode
, NULL
);
938 /* Set destroy information. */
939 rhc
->rhc_shook
= rmap_match_set_hook
.no_set_ipv6_nexthop_local
;
940 rhc
->rhc_rule
= "ipv6 next-hop local";
942 rv
= rmap_match_set_hook
.set_ipv6_nexthop_local(
943 rhc
->rhc_rmi
, "ipv6 next-hop local", address
,
944 args
->errmsg
, args
->errmsg_len
);
945 if (rv
!= CMD_SUCCESS
) {
946 rhc
->rhc_shook
= NULL
;
947 return NB_ERR_INCONSISTENCY
;
953 static int lib_route_map_entry_set_action_ipv6_address_destroy(
954 struct nb_cb_destroy_args
*args
)
956 return lib_route_map_entry_set_destroy(args
);
960 * XPath: /frr-route-map:lib/route-map/entry/set-action/value
962 static int set_action_modify(enum nb_event event
, const struct lyd_node
*dnode
,
963 union nb_resource
*resource
, const char *value
,
964 char *errmsg
, size_t errmsg_len
)
966 struct routemap_hook_context
*rhc
;
970 * NOTE: validate if 'action' is 'metric', currently it is not
971 * necessary because this is the only implemented action. Other
972 * actions might have different validations.
974 if (event
!= NB_EV_APPLY
)
977 /* Check for hook function. */
978 if (rmap_match_set_hook
.set_metric
== NULL
)
981 /* Add configuration. */
982 rhc
= nb_running_get_entry(dnode
, NULL
, true);
984 /* Set destroy information. */
985 rhc
->rhc_shook
= rmap_match_set_hook
.no_set_metric
;
986 rhc
->rhc_rule
= "metric";
988 rv
= rmap_match_set_hook
.set_metric(rhc
->rhc_rmi
, "metric",
992 if (rv
!= CMD_SUCCESS
) {
993 rhc
->rhc_shook
= NULL
;
994 return NB_ERR_INCONSISTENCY
;
1001 lib_route_map_entry_set_action_value_modify(struct nb_cb_modify_args
*args
)
1003 const char *metric
= yang_dnode_get_string(args
->dnode
, NULL
);
1005 return set_action_modify(args
->event
, args
->dnode
, args
->resource
,
1006 metric
, args
->errmsg
, args
->errmsg_len
);
1010 lib_route_map_entry_set_action_value_destroy(struct nb_cb_destroy_args
*args
)
1012 return lib_route_map_entry_set_destroy(args
);
1016 * XPath: /frr-route-map:lib/route-map/entry/set-action/add-metric
1019 lib_route_map_entry_set_action_add_metric_modify(struct nb_cb_modify_args
*args
)
1021 char metric_str
[16];
1023 if (args
->event
== NB_EV_VALIDATE
1024 && yang_dnode_get_uint32(args
->dnode
, NULL
) == 0) {
1025 snprintf(args
->errmsg
, args
->errmsg_len
,
1026 "Can't add zero to metric");
1027 return NB_ERR_VALIDATION
;
1030 snprintf(metric_str
, sizeof(metric_str
), "+%s",
1031 yang_dnode_get_string(args
->dnode
, NULL
));
1032 return set_action_modify(args
->event
, args
->dnode
, args
->resource
,
1034 args
->errmsg
, args
->errmsg_len
);
1037 static int lib_route_map_entry_set_action_add_metric_destroy(
1038 struct nb_cb_destroy_args
*args
)
1040 return lib_route_map_entry_set_action_value_destroy(args
);
1044 * XPath: /frr-route-map:lib/route-map/entry/set-action/subtract-metric
1046 static int lib_route_map_entry_set_action_subtract_metric_modify(
1047 struct nb_cb_modify_args
*args
)
1049 char metric_str
[16];
1051 if (args
->event
== NB_EV_VALIDATE
1052 && yang_dnode_get_uint32(args
->dnode
, NULL
) == 0) {
1053 snprintf(args
->errmsg
, args
->errmsg_len
,
1054 "Can't subtract zero from metric");
1055 return NB_ERR_VALIDATION
;
1058 snprintf(metric_str
, sizeof(metric_str
), "-%s",
1059 yang_dnode_get_string(args
->dnode
, NULL
));
1060 return set_action_modify(args
->event
, args
->dnode
, args
->resource
,
1062 args
->errmsg
, args
->errmsg_len
);
1065 static int lib_route_map_entry_set_action_subtract_metric_destroy(
1066 struct nb_cb_destroy_args
*args
)
1068 return lib_route_map_entry_set_action_value_destroy(args
);
1072 * XPath: /frr-route-map:lib/route-map/entry/set-action/use-round-trip-time
1074 static int lib_route_map_entry_set_action_use_round_trip_time_modify(
1075 struct nb_cb_modify_args
*args
)
1077 return set_action_modify(args
->event
, args
->dnode
, args
->resource
,
1079 args
->errmsg
, args
->errmsg_len
);
1082 static int lib_route_map_entry_set_action_use_round_trip_time_destroy(
1083 struct nb_cb_destroy_args
*args
)
1085 return lib_route_map_entry_set_action_value_destroy(args
);
1089 * XPath: /frr-route-map:lib/route-map/entry/set-action/add-round-trip-time
1091 static int lib_route_map_entry_set_action_add_round_trip_time_modify(
1092 struct nb_cb_modify_args
*args
)
1094 return set_action_modify(args
->event
, args
->dnode
, args
->resource
,
1096 args
->errmsg
, args
->errmsg_len
);
1099 static int lib_route_map_entry_set_action_add_round_trip_time_destroy(
1100 struct nb_cb_destroy_args
*args
)
1102 return lib_route_map_entry_set_action_value_destroy(args
);
1106 * XPath: /frr-route-map:lib/route-map/entry/set-action/subtract-round-trip-time
1108 static int lib_route_map_entry_set_action_subtract_round_trip_time_modify(
1109 struct nb_cb_modify_args
*args
)
1111 return set_action_modify(args
->event
, args
->dnode
, args
->resource
,
1112 "-rtt", args
->errmsg
, args
->errmsg_len
);
1115 static int lib_route_map_entry_set_action_subtract_round_trip_time_destroy(
1116 struct nb_cb_destroy_args
*args
)
1118 return lib_route_map_entry_set_action_value_destroy(args
);
1122 * XPath: /frr-route-map:lib/route-map/entry/set-action/tag
1125 lib_route_map_entry_set_action_tag_modify(struct nb_cb_modify_args
*args
)
1127 struct routemap_hook_context
*rhc
;
1132 * NOTE: validate if 'action' is 'tag', currently it is not
1133 * necessary because this is the only implemented action. Other
1134 * actions might have different validations.
1136 if (args
->event
!= NB_EV_APPLY
)
1139 /* Check for hook function. */
1140 if (rmap_match_set_hook
.set_tag
== NULL
)
1143 /* Add configuration. */
1144 rhc
= nb_running_get_entry(args
->dnode
, NULL
, true);
1145 tag
= yang_dnode_get_string(args
->dnode
, NULL
);
1147 /* Set destroy information. */
1148 rhc
->rhc_shook
= rmap_match_set_hook
.no_set_tag
;
1149 rhc
->rhc_rule
= "tag";
1151 rv
= rmap_match_set_hook
.set_tag(rhc
->rhc_rmi
, "tag", tag
,
1152 args
->errmsg
, args
->errmsg_len
);
1153 if (rv
!= CMD_SUCCESS
) {
1154 rhc
->rhc_shook
= NULL
;
1155 return NB_ERR_INCONSISTENCY
;
1162 lib_route_map_entry_set_action_tag_destroy(struct nb_cb_destroy_args
*args
)
1164 return lib_route_map_entry_set_destroy(args
);
1168 * XPath: /frr-route-map:lib/route-map/entry/set-action/policy
1171 lib_route_map_entry_set_action_policy_modify(struct nb_cb_modify_args
*args
)
1173 struct routemap_hook_context
*rhc
;
1178 * NOTE: validate if 'action' is 'tag', currently it is not
1179 * necessary because this is the only implemented action. Other
1180 * actions might have different validations.
1182 if (args
->event
!= NB_EV_APPLY
)
1185 /* Check for hook function. */
1186 if (rmap_match_set_hook
.set_srte_color
== NULL
)
1189 /* Add configuration. */
1190 rhc
= nb_running_get_entry(args
->dnode
, NULL
, true);
1191 policy
= yang_dnode_get_string(args
->dnode
, NULL
);
1193 /* Set destroy information. */
1194 rhc
->rhc_shook
= rmap_match_set_hook
.no_set_tag
;
1195 rhc
->rhc_rule
= "sr-te color";
1197 rv
= rmap_match_set_hook
.set_tag(rhc
->rhc_rmi
, "sr-te color", policy
,
1198 args
->errmsg
, args
->errmsg_len
);
1199 if (rv
!= CMD_SUCCESS
) {
1200 rhc
->rhc_shook
= NULL
;
1201 return NB_ERR_INCONSISTENCY
;
1208 lib_route_map_entry_set_action_policy_destroy(struct nb_cb_destroy_args
*args
)
1210 return lib_route_map_entry_set_destroy(args
);
1213 /* clang-format off */
1214 const struct frr_yang_module_info frr_route_map_info
= {
1215 .name
= "frr-route-map",
1218 .xpath
= "/frr-route-map:lib/route-map",
1220 .create
= lib_route_map_create
,
1221 .destroy
= lib_route_map_destroy
,
1225 .xpath
= "/frr-route-map:lib/route-map/optimization-disabled",
1227 .modify
= lib_route_map_optimization_disabled_modify
,
1228 .cli_show
= route_map_optimization_disabled_show
,
1232 .xpath
= "/frr-route-map:lib/route-map/entry",
1234 .create
= lib_route_map_entry_create
,
1235 .destroy
= lib_route_map_entry_destroy
,
1236 .cli_cmp
= route_map_instance_cmp
,
1237 .cli_show
= route_map_instance_show
,
1238 .cli_show_end
= route_map_instance_show_end
,
1242 .xpath
= "/frr-route-map:lib/route-map/entry/description",
1244 .modify
= lib_route_map_entry_description_modify
,
1245 .destroy
= lib_route_map_entry_description_destroy
,
1246 .cli_show
= route_map_description_show
,
1250 .xpath
= "/frr-route-map:lib/route-map/entry/action",
1252 .modify
= lib_route_map_entry_action_modify
,
1256 .xpath
= "/frr-route-map:lib/route-map/entry/call",
1258 .modify
= lib_route_map_entry_call_modify
,
1259 .destroy
= lib_route_map_entry_call_destroy
,
1260 .cli_show
= route_map_call_show
,
1264 .xpath
= "/frr-route-map:lib/route-map/entry/exit-policy",
1266 .modify
= lib_route_map_entry_exit_policy_modify
,
1267 .cli_show
= route_map_exit_policy_show
,
1271 .xpath
= "/frr-route-map:lib/route-map/entry/goto-value",
1273 .modify
= lib_route_map_entry_goto_value_modify
,
1274 .destroy
= lib_route_map_entry_goto_value_destroy
,
1278 .xpath
= "/frr-route-map:lib/route-map/entry/match-condition",
1280 .create
= lib_route_map_entry_match_condition_create
,
1281 .destroy
= lib_route_map_entry_match_condition_destroy
,
1282 .cli_show
= route_map_condition_show
,
1286 .xpath
= "/frr-route-map:lib/route-map/entry/match-condition/rmap-match-condition/interface",
1288 .modify
= lib_route_map_entry_match_condition_interface_modify
,
1289 .destroy
= lib_route_map_entry_match_condition_interface_destroy
,
1293 .xpath
= "/frr-route-map:lib/route-map/entry/match-condition/rmap-match-condition/list-name",
1295 .modify
= lib_route_map_entry_match_condition_list_name_modify
,
1296 .destroy
= lib_route_map_entry_match_condition_list_name_destroy
,
1300 .xpath
= "/frr-route-map:lib/route-map/entry/match-condition/rmap-match-condition/ipv4-next-hop-type",
1302 .modify
= lib_route_map_entry_match_condition_ipv4_next_hop_type_modify
,
1303 .destroy
= lib_route_map_entry_match_condition_ipv4_next_hop_type_destroy
,
1307 .xpath
= "/frr-route-map:lib/route-map/entry/match-condition/rmap-match-condition/ipv6-next-hop-type",
1309 .modify
= lib_route_map_entry_match_condition_ipv6_next_hop_type_modify
,
1310 .destroy
= lib_route_map_entry_match_condition_ipv6_next_hop_type_destroy
,
1314 .xpath
= "/frr-route-map:lib/route-map/entry/match-condition/rmap-match-condition/metric",
1316 .modify
= lib_route_map_entry_match_condition_metric_modify
,
1317 .destroy
= lib_route_map_entry_match_condition_metric_destroy
,
1321 .xpath
= "/frr-route-map:lib/route-map/entry/match-condition/rmap-match-condition/tag",
1323 .modify
= lib_route_map_entry_match_condition_tag_modify
,
1324 .destroy
= lib_route_map_entry_match_condition_tag_destroy
,
1328 .xpath
= "/frr-route-map:lib/route-map/entry/set-action",
1330 .create
= lib_route_map_entry_set_action_create
,
1331 .destroy
= lib_route_map_entry_set_action_destroy
,
1332 .cli_show
= route_map_action_show
,
1336 .xpath
= "/frr-route-map:lib/route-map/entry/set-action/rmap-set-action/ipv4-address",
1338 .modify
= lib_route_map_entry_set_action_ipv4_address_modify
,
1339 .destroy
= lib_route_map_entry_set_action_ipv4_address_destroy
,
1343 .xpath
= "/frr-route-map:lib/route-map/entry/set-action/rmap-set-action/ipv6-address",
1345 .modify
= lib_route_map_entry_set_action_ipv6_address_modify
,
1346 .destroy
= lib_route_map_entry_set_action_ipv6_address_destroy
,
1350 .xpath
= "/frr-route-map:lib/route-map/entry/set-action/rmap-set-action/value",
1352 .modify
= lib_route_map_entry_set_action_value_modify
,
1353 .destroy
= lib_route_map_entry_set_action_value_destroy
,
1357 .xpath
= "/frr-route-map:lib/route-map/entry/set-action/rmap-set-action/add-metric",
1359 .modify
= lib_route_map_entry_set_action_add_metric_modify
,
1360 .destroy
= lib_route_map_entry_set_action_add_metric_destroy
,
1364 .xpath
= "/frr-route-map:lib/route-map/entry/set-action/rmap-set-action/subtract-metric",
1366 .modify
= lib_route_map_entry_set_action_subtract_metric_modify
,
1367 .destroy
= lib_route_map_entry_set_action_subtract_metric_destroy
,
1371 .xpath
= "/frr-route-map:lib/route-map/entry/set-action/rmap-set-action/use-round-trip-time",
1373 .modify
= lib_route_map_entry_set_action_use_round_trip_time_modify
,
1374 .destroy
= lib_route_map_entry_set_action_use_round_trip_time_destroy
,
1378 .xpath
= "/frr-route-map:lib/route-map/entry/set-action/rmap-set-action/add-round-trip-time",
1380 .modify
= lib_route_map_entry_set_action_add_round_trip_time_modify
,
1381 .destroy
= lib_route_map_entry_set_action_add_round_trip_time_destroy
,
1385 .xpath
= "/frr-route-map:lib/route-map/entry/set-action/rmap-set-action/subtract-round-trip-time",
1387 .modify
= lib_route_map_entry_set_action_subtract_round_trip_time_modify
,
1388 .destroy
= lib_route_map_entry_set_action_subtract_round_trip_time_destroy
,
1392 .xpath
= "/frr-route-map:lib/route-map/entry/set-action/rmap-set-action/tag",
1394 .modify
= lib_route_map_entry_set_action_tag_modify
,
1395 .destroy
= lib_route_map_entry_set_action_tag_destroy
,
1399 .xpath
= "/frr-route-map:lib/route-map/entry/set-action/rmap-set-action/policy",
1401 .modify
= lib_route_map_entry_set_action_policy_modify
,
1402 .destroy
= lib_route_map_entry_set_action_policy_destroy
,