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/entry
146 static int lib_route_map_entry_create(struct nb_cb_create_args
*args
)
148 struct route_map_index
*rmi
;
149 struct route_map
*rm
;
153 switch (args
->event
) {
160 sequence
= yang_dnode_get_uint16(args
->dnode
, "./sequence");
161 action
= yang_dnode_get_enum(args
->dnode
, "./action") == 0
164 rm
= nb_running_get_entry(args
->dnode
, NULL
, true);
165 rmi
= route_map_index_get(rm
, action
, sequence
);
166 nb_running_set_entry(args
->dnode
, rmi
);
173 static int lib_route_map_entry_destroy(struct nb_cb_destroy_args
*args
)
175 struct route_map_index
*rmi
;
177 switch (args
->event
) {
184 rmi
= nb_running_unset_entry(args
->dnode
);
185 route_map_index_delete(rmi
, 1);
193 * XPath: /frr-route-map:lib/route-map/entry/description
196 lib_route_map_entry_description_modify(struct nb_cb_modify_args
*args
)
198 struct route_map_index
*rmi
;
199 const char *description
;
201 switch (args
->event
) {
206 description
= yang_dnode_get_string(args
->dnode
, NULL
);
207 args
->resource
->ptr
= XSTRDUP(MTYPE_TMP
, description
);
208 if (args
->resource
->ptr
== NULL
)
209 return NB_ERR_RESOURCE
;
212 XFREE(MTYPE_TMP
, args
->resource
->ptr
);
215 rmi
= nb_running_get_entry(args
->dnode
, NULL
, true);
216 XFREE(MTYPE_TMP
, rmi
->description
);
217 rmi
->description
= args
->resource
->ptr
;
225 lib_route_map_entry_description_destroy(struct nb_cb_destroy_args
*args
)
227 struct route_map_index
*rmi
;
229 switch (args
->event
) {
236 rmi
= nb_running_get_entry(args
->dnode
, NULL
, true);
237 XFREE(MTYPE_TMP
, rmi
->description
);
245 * XPath: /frr-route-map:lib/route-map/entry/action
247 static int lib_route_map_entry_action_modify(struct nb_cb_modify_args
*args
)
249 struct route_map_index
*rmi
;
251 switch (args
->event
) {
258 rmi
= nb_running_get_entry(args
->dnode
, NULL
, true);
259 rmi
->type
= yang_dnode_get_enum(args
->dnode
, NULL
);
268 * XPath: /frr-route-map:lib/route-map/entry/call
270 static int lib_route_map_entry_call_modify(struct nb_cb_modify_args
*args
)
272 struct route_map_index
*rmi
;
273 const char *rm_name
, *rmn_name
;
275 switch (args
->event
) {
277 rm_name
= yang_dnode_get_string(args
->dnode
, "../../name");
278 rmn_name
= yang_dnode_get_string(args
->dnode
, NULL
);
279 /* Don't allow to jump to the same route map instance. */
280 if (strcmp(rm_name
, rmn_name
) == 0)
281 return NB_ERR_VALIDATION
;
283 /* TODO: detect circular route map sequences. */
286 rmn_name
= yang_dnode_get_string(args
->dnode
, NULL
);
287 args
->resource
->ptr
= XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmn_name
);
290 XFREE(MTYPE_ROUTE_MAP_NAME
, args
->resource
->ptr
);
293 rmi
= nb_running_get_entry(args
->dnode
, NULL
, true);
295 route_map_upd8_dependency(RMAP_EVENT_CALL_DELETED
,
296 rmi
->nextrm
, rmi
->map
->name
);
297 XFREE(MTYPE_ROUTE_MAP_NAME
, rmi
->nextrm
);
299 rmi
->nextrm
= args
->resource
->ptr
;
300 route_map_upd8_dependency(RMAP_EVENT_CALL_ADDED
, rmi
->nextrm
,
308 static int lib_route_map_entry_call_destroy(struct nb_cb_destroy_args
*args
)
310 struct route_map_index
*rmi
;
312 switch (args
->event
) {
319 rmi
= nb_running_get_entry(args
->dnode
, NULL
, true);
320 route_map_upd8_dependency(RMAP_EVENT_CALL_DELETED
, rmi
->nextrm
,
322 XFREE(MTYPE_ROUTE_MAP_NAME
, rmi
->nextrm
);
331 * XPath: /frr-route-map:lib/route-map/entry/exit-policy
334 lib_route_map_entry_exit_policy_modify(struct nb_cb_modify_args
*args
)
336 struct route_map_index
*rmi
;
340 switch (args
->event
) {
342 policy
= yang_dnode_get_enum(args
->dnode
, NULL
);
344 case 0: /* permit-or-deny */
350 yang_dnode_get_enum(args
->dnode
, "../action");
351 if (rm_action
== 1 /* deny */) {
353 * On deny it is not possible to 'goto'
356 return NB_ERR_VALIDATION
;
365 rmi
= nb_running_get_entry(args
->dnode
, NULL
, true);
366 policy
= yang_dnode_get_enum(args
->dnode
, NULL
);
369 case 0: /* permit-or-deny */
370 rmi
->exitpolicy
= RMAP_EXIT
;
373 rmi
->exitpolicy
= RMAP_NEXT
;
376 rmi
->exitpolicy
= RMAP_GOTO
;
386 * XPath: /frr-route-map:lib/route-map/entry/goto-value
388 static int lib_route_map_entry_goto_value_modify(struct nb_cb_modify_args
*args
)
390 struct route_map_index
*rmi
;
394 switch (args
->event
) {
396 rmi_index
= yang_dnode_get_uint16(args
->dnode
, "../sequence");
397 rmi_next
= yang_dnode_get_uint16(args
->dnode
, NULL
);
398 if (rmi_next
<= rmi_index
) {
399 /* Can't jump backwards on a route map. */
400 return NB_ERR_VALIDATION
;
408 rmi
= nb_running_get_entry(args
->dnode
, NULL
, true);
409 rmi
->nextpref
= yang_dnode_get_uint16(args
->dnode
, NULL
);
417 lib_route_map_entry_goto_value_destroy(struct nb_cb_destroy_args
*args
)
419 struct route_map_index
*rmi
;
421 switch (args
->event
) {
428 rmi
= nb_running_get_entry(args
->dnode
, NULL
, true);
437 * XPath: /frr-route-map:lib/route-map/entry/match-condition
440 lib_route_map_entry_match_condition_create(struct nb_cb_create_args
*args
)
442 struct routemap_hook_context
*rhc
;
443 struct route_map_index
*rmi
;
445 switch (args
->event
) {
452 rmi
= nb_running_get_entry(args
->dnode
, NULL
, true);
453 rhc
= routemap_hook_context_insert(rmi
);
454 nb_running_set_entry(args
->dnode
, rhc
);
462 lib_route_map_entry_match_condition_destroy(struct nb_cb_destroy_args
*args
)
464 struct routemap_hook_context
*rhc
;
467 if (args
->event
!= NB_EV_APPLY
)
470 rv
= lib_route_map_entry_match_destroy(args
);
471 rhc
= nb_running_unset_entry(args
->dnode
);
472 routemap_hook_context_free(rhc
);
478 * XPath: /frr-route-map:lib/route-map/entry/match-condition/interface
480 static int lib_route_map_entry_match_condition_interface_modify(
481 struct nb_cb_modify_args
*args
)
483 struct routemap_hook_context
*rhc
;
487 if (args
->event
!= NB_EV_APPLY
)
490 /* Check for hook function. */
491 if (rmap_match_set_hook
.match_interface
== NULL
)
494 /* Add configuration. */
495 rhc
= nb_running_get_entry(args
->dnode
, NULL
, true);
496 ifname
= yang_dnode_get_string(args
->dnode
, NULL
);
498 /* Set destroy information. */
499 rhc
->rhc_mhook
= rmap_match_set_hook
.no_match_interface
;
500 rhc
->rhc_rule
= "interface";
501 rhc
->rhc_event
= RMAP_EVENT_MATCH_DELETED
;
503 rv
= rmap_match_set_hook
.match_interface(rhc
->rhc_rmi
,
505 RMAP_EVENT_MATCH_ADDED
,
506 args
->errmsg
, args
->errmsg_len
);
507 if (rv
!= CMD_SUCCESS
) {
508 rhc
->rhc_mhook
= NULL
;
509 return NB_ERR_INCONSISTENCY
;
515 static int lib_route_map_entry_match_condition_interface_destroy(
516 struct nb_cb_destroy_args
*args
)
518 return lib_route_map_entry_match_destroy(args
);
522 * XPath: /frr-route-map:lib/route-map/entry/match-condition/list-name
524 static int lib_route_map_entry_match_condition_list_name_modify(
525 struct nb_cb_modify_args
*args
)
527 struct routemap_hook_context
*rhc
;
529 const char *condition
;
532 if (args
->event
!= NB_EV_APPLY
)
535 /* Check for hook installation, otherwise we can just stop. */
536 acl
= yang_dnode_get_string(args
->dnode
, NULL
);
537 rhc
= nb_running_get_entry(args
->dnode
, NULL
, true);
538 condition
= yang_dnode_get_string(args
->dnode
, "../../condition");
540 if (IS_MATCH_IPv4_ADDRESS_LIST(condition
)) {
541 if (rmap_match_set_hook
.match_ip_address
== NULL
)
543 rhc
->rhc_mhook
= rmap_match_set_hook
.no_match_ip_address
;
544 rhc
->rhc_rule
= "ip address";
545 rhc
->rhc_event
= RMAP_EVENT_FILTER_DELETED
;
546 rv
= rmap_match_set_hook
.match_ip_address(
547 rhc
->rhc_rmi
, "ip address", acl
,
548 RMAP_EVENT_FILTER_ADDED
,
549 args
->errmsg
, args
->errmsg_len
);
550 } else if (IS_MATCH_IPv4_PREFIX_LIST(condition
)) {
551 if (rmap_match_set_hook
.match_ip_address_prefix_list
== NULL
)
554 rmap_match_set_hook
.no_match_ip_address_prefix_list
;
555 rhc
->rhc_rule
= "ip address prefix-list";
556 rhc
->rhc_event
= RMAP_EVENT_PLIST_DELETED
;
557 rv
= rmap_match_set_hook
.match_ip_address_prefix_list(
558 rhc
->rhc_rmi
, "ip address prefix-list", acl
,
559 RMAP_EVENT_PLIST_ADDED
,
560 args
->errmsg
, args
->errmsg_len
);
561 } else if (IS_MATCH_IPv4_NEXTHOP_LIST(condition
)) {
562 if (rmap_match_set_hook
.match_ip_next_hop
== NULL
)
564 rhc
->rhc_mhook
= rmap_match_set_hook
.no_match_ip_next_hop
;
565 rhc
->rhc_rule
= "ip next-hop";
566 rhc
->rhc_event
= RMAP_EVENT_FILTER_DELETED
;
567 rv
= rmap_match_set_hook
.match_ip_next_hop(
568 rhc
->rhc_rmi
, "ip next-hop", acl
,
569 RMAP_EVENT_FILTER_ADDED
,
570 args
->errmsg
, args
->errmsg_len
);
571 } else if (IS_MATCH_IPv4_NEXTHOP_PREFIX_LIST(condition
)) {
572 if (rmap_match_set_hook
.match_ip_next_hop_prefix_list
== NULL
)
575 rmap_match_set_hook
.no_match_ip_next_hop_prefix_list
;
576 rhc
->rhc_rule
= "ip next-hop prefix-list";
577 rhc
->rhc_event
= RMAP_EVENT_PLIST_DELETED
;
578 rv
= rmap_match_set_hook
.match_ip_next_hop_prefix_list(
579 rhc
->rhc_rmi
, "ip next-hop prefix-list", acl
,
580 RMAP_EVENT_PLIST_ADDED
,
581 args
->errmsg
, args
->errmsg_len
);
582 } else if (IS_MATCH_IPv6_ADDRESS_LIST(condition
)) {
583 if (rmap_match_set_hook
.match_ipv6_address
== NULL
)
585 rhc
->rhc_mhook
= rmap_match_set_hook
.no_match_ipv6_address
;
586 rhc
->rhc_rule
= "ipv6 address";
587 rhc
->rhc_event
= RMAP_EVENT_FILTER_DELETED
;
588 rv
= rmap_match_set_hook
.match_ipv6_address(
589 rhc
->rhc_rmi
, "ipv6 address", acl
,
590 RMAP_EVENT_FILTER_ADDED
,
591 args
->errmsg
, args
->errmsg_len
);
592 } else if (IS_MATCH_IPv6_PREFIX_LIST(condition
)) {
593 if (rmap_match_set_hook
.match_ipv6_address_prefix_list
== NULL
)
596 rmap_match_set_hook
.no_match_ipv6_address_prefix_list
;
597 rhc
->rhc_rule
= "ipv6 address prefix-list";
598 rhc
->rhc_event
= RMAP_EVENT_PLIST_DELETED
;
599 rv
= rmap_match_set_hook
.match_ipv6_address_prefix_list(
600 rhc
->rhc_rmi
, "ipv6 address prefix-list", acl
,
601 RMAP_EVENT_PLIST_ADDED
,
602 args
->errmsg
, args
->errmsg_len
);
604 rv
= CMD_ERR_NO_MATCH
;
606 if (rv
!= CMD_SUCCESS
) {
607 rhc
->rhc_mhook
= NULL
;
608 return NB_ERR_INCONSISTENCY
;
614 static int lib_route_map_entry_match_condition_list_name_destroy(
615 struct nb_cb_destroy_args
*args
)
617 return lib_route_map_entry_match_destroy(args
);
621 * XPath: /frr-route-map:lib/route-map/entry/match-condition/ipv4-next-hop-type
623 static int lib_route_map_entry_match_condition_ipv4_next_hop_type_modify(
624 struct nb_cb_modify_args
*args
)
626 struct routemap_hook_context
*rhc
;
630 if (args
->event
!= NB_EV_APPLY
)
633 /* Check for hook function. */
634 if (rmap_match_set_hook
.match_ip_next_hop_type
== NULL
)
637 /* Add configuration. */
638 rhc
= nb_running_get_entry(args
->dnode
, NULL
, true);
639 type
= yang_dnode_get_string(args
->dnode
, NULL
);
641 /* Set destroy information. */
642 rhc
->rhc_mhook
= rmap_match_set_hook
.no_match_ip_next_hop_type
;
643 rhc
->rhc_rule
= "ip next-hop type";
644 rhc
->rhc_event
= RMAP_EVENT_MATCH_DELETED
;
646 rv
= rmap_match_set_hook
.match_ip_next_hop_type(
647 rhc
->rhc_rmi
, "ip next-hop type", type
,
648 RMAP_EVENT_MATCH_ADDED
,
649 args
->errmsg
, args
->errmsg_len
);
650 if (rv
!= CMD_SUCCESS
) {
651 rhc
->rhc_mhook
= NULL
;
652 return NB_ERR_INCONSISTENCY
;
658 static int lib_route_map_entry_match_condition_ipv4_next_hop_type_destroy(
659 struct nb_cb_destroy_args
*args
)
661 return lib_route_map_entry_match_destroy(args
);
665 * XPath: /frr-route-map:lib/route-map/entry/match-condition/ipv6-next-hop-type
667 static int lib_route_map_entry_match_condition_ipv6_next_hop_type_modify(
668 struct nb_cb_modify_args
*args
)
670 struct routemap_hook_context
*rhc
;
674 if (args
->event
!= NB_EV_APPLY
)
677 /* Check for hook function. */
678 if (rmap_match_set_hook
.match_ipv6_next_hop_type
== NULL
)
681 /* Add configuration. */
682 rhc
= nb_running_get_entry(args
->dnode
, NULL
, true);
683 type
= yang_dnode_get_string(args
->dnode
, NULL
);
685 /* Set destroy information. */
686 rhc
->rhc_mhook
= rmap_match_set_hook
.no_match_ipv6_next_hop_type
;
687 rhc
->rhc_rule
= "ipv6 next-hop type";
688 rhc
->rhc_event
= RMAP_EVENT_MATCH_DELETED
;
690 rv
= rmap_match_set_hook
.match_ipv6_next_hop_type(
691 rhc
->rhc_rmi
, "ipv6 next-hop type", type
,
692 RMAP_EVENT_MATCH_ADDED
,
693 args
->errmsg
, args
->errmsg_len
);
694 if (rv
!= CMD_SUCCESS
) {
695 rhc
->rhc_mhook
= NULL
;
696 return NB_ERR_INCONSISTENCY
;
702 static int lib_route_map_entry_match_condition_ipv6_next_hop_type_destroy(
703 struct nb_cb_destroy_args
*args
)
705 return lib_route_map_entry_match_destroy(args
);
709 * XPath: /frr-route-map:lib/route-map/entry/match-condition/metric
711 static int lib_route_map_entry_match_condition_metric_modify(
712 struct nb_cb_modify_args
*args
)
714 struct routemap_hook_context
*rhc
;
718 if (args
->event
!= NB_EV_APPLY
)
721 /* Check for hook function. */
722 if (rmap_match_set_hook
.match_metric
== NULL
)
725 /* Add configuration. */
726 rhc
= nb_running_get_entry(args
->dnode
, NULL
, true);
727 type
= yang_dnode_get_string(args
->dnode
, NULL
);
729 /* Set destroy information. */
730 rhc
->rhc_mhook
= rmap_match_set_hook
.no_match_metric
;
731 rhc
->rhc_rule
= "metric";
732 rhc
->rhc_event
= RMAP_EVENT_MATCH_DELETED
;
734 rv
= rmap_match_set_hook
.match_metric(rhc
->rhc_rmi
, "metric",
735 type
, RMAP_EVENT_MATCH_ADDED
,
736 args
->errmsg
, args
->errmsg_len
);
737 if (rv
!= CMD_SUCCESS
) {
738 rhc
->rhc_mhook
= NULL
;
739 return NB_ERR_INCONSISTENCY
;
745 static int lib_route_map_entry_match_condition_metric_destroy(
746 struct nb_cb_destroy_args
*args
)
748 return lib_route_map_entry_match_destroy(args
);
752 * XPath: /frr-route-map:lib/route-map/entry/match-condition/tag
755 lib_route_map_entry_match_condition_tag_modify(struct nb_cb_modify_args
*args
)
757 struct routemap_hook_context
*rhc
;
761 if (args
->event
!= NB_EV_APPLY
)
764 /* Check for hook function. */
765 if (rmap_match_set_hook
.match_tag
== NULL
)
768 /* Add configuration. */
769 rhc
= nb_running_get_entry(args
->dnode
, NULL
, true);
770 tag
= yang_dnode_get_string(args
->dnode
, NULL
);
772 /* Set destroy information. */
773 rhc
->rhc_mhook
= rmap_match_set_hook
.no_match_tag
;
774 rhc
->rhc_rule
= "tag";
775 rhc
->rhc_event
= RMAP_EVENT_MATCH_DELETED
;
777 rv
= rmap_match_set_hook
.match_tag(rhc
->rhc_rmi
, "tag", tag
,
778 RMAP_EVENT_MATCH_ADDED
,
779 args
->errmsg
, args
->errmsg_len
);
780 if (rv
!= CMD_SUCCESS
) {
781 rhc
->rhc_mhook
= NULL
;
782 return NB_ERR_INCONSISTENCY
;
789 lib_route_map_entry_match_condition_tag_destroy(struct nb_cb_destroy_args
*args
)
791 return lib_route_map_entry_match_destroy(args
);
795 * XPath: /frr-route-map:lib/route-map/entry/set-action
797 static int lib_route_map_entry_set_action_create(struct nb_cb_create_args
*args
)
799 return lib_route_map_entry_match_condition_create(args
);
803 lib_route_map_entry_set_action_destroy(struct nb_cb_destroy_args
*args
)
805 struct routemap_hook_context
*rhc
;
808 if (args
->event
!= NB_EV_APPLY
)
811 rv
= lib_route_map_entry_set_destroy(args
);
812 rhc
= nb_running_unset_entry(args
->dnode
);
813 routemap_hook_context_free(rhc
);
819 * XPath: /frr-route-map:lib/route-map/entry/set-action/ipv4-address
821 static int lib_route_map_entry_set_action_ipv4_address_modify(
822 struct nb_cb_modify_args
*args
)
824 struct routemap_hook_context
*rhc
;
829 switch (args
->event
) {
832 * NOTE: validate if 'action' is 'ipv4-next-hop',
833 * currently it is not necessary because this is the
834 * only implemented action.
836 yang_dnode_get_ipv4(&ia
, args
->dnode
, NULL
);
837 if (ia
.s_addr
== INADDR_ANY
|| IPV4_CLASS_DE(ntohl(ia
.s_addr
)))
838 return NB_ERR_VALIDATION
;
847 /* Check for hook function. */
848 if (rmap_match_set_hook
.set_ip_nexthop
== NULL
)
851 /* Add configuration. */
852 rhc
= nb_running_get_entry(args
->dnode
, NULL
, true);
853 address
= yang_dnode_get_string(args
->dnode
, NULL
);
855 /* Set destroy information. */
856 rhc
->rhc_shook
= rmap_match_set_hook
.no_set_ip_nexthop
;
857 rhc
->rhc_rule
= "ip next-hop";
859 rv
= rmap_match_set_hook
.set_ip_nexthop(rhc
->rhc_rmi
, "ip next-hop",
861 args
->errmsg
, args
->errmsg_len
);
862 if (rv
!= CMD_SUCCESS
) {
863 rhc
->rhc_shook
= NULL
;
864 return NB_ERR_INCONSISTENCY
;
870 static int lib_route_map_entry_set_action_ipv4_address_destroy(
871 struct nb_cb_destroy_args
*args
)
873 return lib_route_map_entry_set_destroy(args
);
877 * XPath: /frr-route-map:lib/route-map/entry/set-action/ipv6-address
879 static int lib_route_map_entry_set_action_ipv6_address_modify(
880 struct nb_cb_modify_args
*args
)
882 struct routemap_hook_context
*rhc
;
887 switch (args
->event
) {
890 * NOTE: validate if 'action' is 'ipv6-next-hop',
891 * currently it is not necessary because this is the
892 * only implemented action. Other actions might have
893 * different validations.
895 yang_dnode_get_ipv6(&i6a
, args
->dnode
, NULL
);
896 if (!IN6_IS_ADDR_LINKLOCAL(&i6a
))
897 return NB_ERR_VALIDATION
;
906 /* Check for hook function. */
907 if (rmap_match_set_hook
.set_ipv6_nexthop_local
== NULL
)
910 /* Add configuration. */
911 rhc
= nb_running_get_entry(args
->dnode
, NULL
, true);
912 address
= yang_dnode_get_string(args
->dnode
, NULL
);
914 /* Set destroy information. */
915 rhc
->rhc_shook
= rmap_match_set_hook
.no_set_ipv6_nexthop_local
;
916 rhc
->rhc_rule
= "ipv6 next-hop local";
918 rv
= rmap_match_set_hook
.set_ipv6_nexthop_local(
919 rhc
->rhc_rmi
, "ipv6 next-hop local", address
,
920 args
->errmsg
, args
->errmsg_len
);
921 if (rv
!= CMD_SUCCESS
) {
922 rhc
->rhc_shook
= NULL
;
923 return NB_ERR_INCONSISTENCY
;
929 static int lib_route_map_entry_set_action_ipv6_address_destroy(
930 struct nb_cb_destroy_args
*args
)
932 return lib_route_map_entry_set_destroy(args
);
936 * XPath: /frr-route-map:lib/route-map/entry/set-action/value
938 static int set_action_modify(enum nb_event event
, const struct lyd_node
*dnode
,
939 union nb_resource
*resource
, const char *value
,
940 char *errmsg
, size_t errmsg_len
)
942 struct routemap_hook_context
*rhc
;
946 * NOTE: validate if 'action' is 'metric', currently it is not
947 * necessary because this is the only implemented action. Other
948 * actions might have different validations.
950 if (event
!= NB_EV_APPLY
)
953 /* Check for hook function. */
954 if (rmap_match_set_hook
.set_metric
== NULL
)
957 /* Add configuration. */
958 rhc
= nb_running_get_entry(dnode
, NULL
, true);
960 /* Set destroy information. */
961 rhc
->rhc_shook
= rmap_match_set_hook
.no_set_metric
;
962 rhc
->rhc_rule
= "metric";
964 rv
= rmap_match_set_hook
.set_metric(rhc
->rhc_rmi
, "metric",
968 if (rv
!= CMD_SUCCESS
) {
969 rhc
->rhc_shook
= NULL
;
970 return NB_ERR_INCONSISTENCY
;
977 lib_route_map_entry_set_action_value_modify(struct nb_cb_modify_args
*args
)
979 const char *metric
= yang_dnode_get_string(args
->dnode
, NULL
);
981 return set_action_modify(args
->event
, args
->dnode
, args
->resource
,
982 metric
, args
->errmsg
, args
->errmsg_len
);
986 lib_route_map_entry_set_action_value_destroy(struct nb_cb_destroy_args
*args
)
988 return lib_route_map_entry_set_destroy(args
);
992 * XPath: /frr-route-map:lib/route-map/entry/set-action/add-metric
995 lib_route_map_entry_set_action_add_metric_modify(struct nb_cb_modify_args
*args
)
999 if (args
->event
== NB_EV_VALIDATE
1000 && yang_dnode_get_uint32(args
->dnode
, NULL
) == 0) {
1001 snprintf(args
->errmsg
, args
->errmsg_len
,
1002 "Can't add zero to metric");
1003 return NB_ERR_VALIDATION
;
1006 snprintf(metric_str
, sizeof(metric_str
), "+%s",
1007 yang_dnode_get_string(args
->dnode
, NULL
));
1008 return set_action_modify(args
->event
, args
->dnode
, args
->resource
,
1010 args
->errmsg
, args
->errmsg_len
);
1013 static int lib_route_map_entry_set_action_add_metric_destroy(
1014 struct nb_cb_destroy_args
*args
)
1016 return lib_route_map_entry_set_action_value_destroy(args
);
1020 * XPath: /frr-route-map:lib/route-map/entry/set-action/subtract-metric
1022 static int lib_route_map_entry_set_action_subtract_metric_modify(
1023 struct nb_cb_modify_args
*args
)
1025 char metric_str
[16];
1027 if (args
->event
== NB_EV_VALIDATE
1028 && yang_dnode_get_uint32(args
->dnode
, NULL
) == 0) {
1029 snprintf(args
->errmsg
, args
->errmsg_len
,
1030 "Can't subtract zero from metric");
1031 return NB_ERR_VALIDATION
;
1034 snprintf(metric_str
, sizeof(metric_str
), "-%s",
1035 yang_dnode_get_string(args
->dnode
, NULL
));
1036 return set_action_modify(args
->event
, args
->dnode
, args
->resource
,
1038 args
->errmsg
, args
->errmsg_len
);
1041 static int lib_route_map_entry_set_action_subtract_metric_destroy(
1042 struct nb_cb_destroy_args
*args
)
1044 return lib_route_map_entry_set_action_value_destroy(args
);
1048 * XPath: /frr-route-map:lib/route-map/entry/set-action/use-round-trip-time
1050 static int lib_route_map_entry_set_action_use_round_trip_time_modify(
1051 struct nb_cb_modify_args
*args
)
1053 return set_action_modify(args
->event
, args
->dnode
, args
->resource
,
1055 args
->errmsg
, args
->errmsg_len
);
1058 static int lib_route_map_entry_set_action_use_round_trip_time_destroy(
1059 struct nb_cb_destroy_args
*args
)
1061 return lib_route_map_entry_set_action_value_destroy(args
);
1065 * XPath: /frr-route-map:lib/route-map/entry/set-action/add-round-trip-time
1067 static int lib_route_map_entry_set_action_add_round_trip_time_modify(
1068 struct nb_cb_modify_args
*args
)
1070 return set_action_modify(args
->event
, args
->dnode
, args
->resource
,
1072 args
->errmsg
, args
->errmsg_len
);
1075 static int lib_route_map_entry_set_action_add_round_trip_time_destroy(
1076 struct nb_cb_destroy_args
*args
)
1078 return lib_route_map_entry_set_action_value_destroy(args
);
1082 * XPath: /frr-route-map:lib/route-map/entry/set-action/subtract-round-trip-time
1084 static int lib_route_map_entry_set_action_subtract_round_trip_time_modify(
1085 struct nb_cb_modify_args
*args
)
1087 return set_action_modify(args
->event
, args
->dnode
, args
->resource
,
1088 "-rtt", args
->errmsg
, args
->errmsg_len
);
1091 static int lib_route_map_entry_set_action_subtract_round_trip_time_destroy(
1092 struct nb_cb_destroy_args
*args
)
1094 return lib_route_map_entry_set_action_value_destroy(args
);
1098 * XPath: /frr-route-map:lib/route-map/entry/set-action/tag
1101 lib_route_map_entry_set_action_tag_modify(struct nb_cb_modify_args
*args
)
1103 struct routemap_hook_context
*rhc
;
1108 * NOTE: validate if 'action' is 'tag', currently it is not
1109 * necessary because this is the only implemented action. Other
1110 * actions might have different validations.
1112 if (args
->event
!= NB_EV_APPLY
)
1115 /* Check for hook function. */
1116 if (rmap_match_set_hook
.set_tag
== NULL
)
1119 /* Add configuration. */
1120 rhc
= nb_running_get_entry(args
->dnode
, NULL
, true);
1121 tag
= yang_dnode_get_string(args
->dnode
, NULL
);
1123 /* Set destroy information. */
1124 rhc
->rhc_shook
= rmap_match_set_hook
.no_set_tag
;
1125 rhc
->rhc_rule
= "tag";
1127 rv
= rmap_match_set_hook
.set_tag(rhc
->rhc_rmi
, "tag", tag
,
1128 args
->errmsg
, args
->errmsg_len
);
1129 if (rv
!= CMD_SUCCESS
) {
1130 rhc
->rhc_shook
= NULL
;
1131 return NB_ERR_INCONSISTENCY
;
1138 lib_route_map_entry_set_action_tag_destroy(struct nb_cb_destroy_args
*args
)
1140 return lib_route_map_entry_set_destroy(args
);
1144 * XPath: /frr-route-map:lib/route-map/entry/set-action/policy
1147 lib_route_map_entry_set_action_policy_modify(struct nb_cb_modify_args
*args
)
1149 struct routemap_hook_context
*rhc
;
1154 * NOTE: validate if 'action' is 'tag', currently it is not
1155 * necessary because this is the only implemented action. Other
1156 * actions might have different validations.
1158 if (args
->event
!= NB_EV_APPLY
)
1161 /* Check for hook function. */
1162 if (rmap_match_set_hook
.set_srte_color
== NULL
)
1165 /* Add configuration. */
1166 rhc
= nb_running_get_entry(args
->dnode
, NULL
, true);
1167 policy
= yang_dnode_get_string(args
->dnode
, NULL
);
1169 /* Set destroy information. */
1170 rhc
->rhc_shook
= rmap_match_set_hook
.no_set_tag
;
1171 rhc
->rhc_rule
= "sr-te color";
1173 rv
= rmap_match_set_hook
.set_tag(rhc
->rhc_rmi
, "sr-te color", policy
,
1174 args
->errmsg
, args
->errmsg_len
);
1175 if (rv
!= CMD_SUCCESS
) {
1176 rhc
->rhc_shook
= NULL
;
1177 return NB_ERR_INCONSISTENCY
;
1184 lib_route_map_entry_set_action_policy_destroy(struct nb_cb_destroy_args
*args
)
1186 return lib_route_map_entry_set_destroy(args
);
1189 /* clang-format off */
1190 const struct frr_yang_module_info frr_route_map_info
= {
1191 .name
= "frr-route-map",
1194 .xpath
= "/frr-route-map:lib/route-map",
1196 .create
= lib_route_map_create
,
1197 .destroy
= lib_route_map_destroy
,
1201 .xpath
= "/frr-route-map:lib/route-map/entry",
1203 .create
= lib_route_map_entry_create
,
1204 .destroy
= lib_route_map_entry_destroy
,
1205 .cli_cmp
= route_map_instance_cmp
,
1206 .cli_show
= route_map_instance_show
,
1207 .cli_show_end
= route_map_instance_show_end
,
1211 .xpath
= "/frr-route-map:lib/route-map/entry/description",
1213 .modify
= lib_route_map_entry_description_modify
,
1214 .destroy
= lib_route_map_entry_description_destroy
,
1215 .cli_show
= route_map_description_show
,
1219 .xpath
= "/frr-route-map:lib/route-map/entry/action",
1221 .modify
= lib_route_map_entry_action_modify
,
1225 .xpath
= "/frr-route-map:lib/route-map/entry/call",
1227 .modify
= lib_route_map_entry_call_modify
,
1228 .destroy
= lib_route_map_entry_call_destroy
,
1229 .cli_show
= route_map_call_show
,
1233 .xpath
= "/frr-route-map:lib/route-map/entry/exit-policy",
1235 .modify
= lib_route_map_entry_exit_policy_modify
,
1236 .cli_show
= route_map_exit_policy_show
,
1240 .xpath
= "/frr-route-map:lib/route-map/entry/goto-value",
1242 .modify
= lib_route_map_entry_goto_value_modify
,
1243 .destroy
= lib_route_map_entry_goto_value_destroy
,
1247 .xpath
= "/frr-route-map:lib/route-map/entry/match-condition",
1249 .create
= lib_route_map_entry_match_condition_create
,
1250 .destroy
= lib_route_map_entry_match_condition_destroy
,
1251 .cli_show
= route_map_condition_show
,
1255 .xpath
= "/frr-route-map:lib/route-map/entry/match-condition/rmap-match-condition/interface",
1257 .modify
= lib_route_map_entry_match_condition_interface_modify
,
1258 .destroy
= lib_route_map_entry_match_condition_interface_destroy
,
1262 .xpath
= "/frr-route-map:lib/route-map/entry/match-condition/rmap-match-condition/list-name",
1264 .modify
= lib_route_map_entry_match_condition_list_name_modify
,
1265 .destroy
= lib_route_map_entry_match_condition_list_name_destroy
,
1269 .xpath
= "/frr-route-map:lib/route-map/entry/match-condition/rmap-match-condition/ipv4-next-hop-type",
1271 .modify
= lib_route_map_entry_match_condition_ipv4_next_hop_type_modify
,
1272 .destroy
= lib_route_map_entry_match_condition_ipv4_next_hop_type_destroy
,
1276 .xpath
= "/frr-route-map:lib/route-map/entry/match-condition/rmap-match-condition/ipv6-next-hop-type",
1278 .modify
= lib_route_map_entry_match_condition_ipv6_next_hop_type_modify
,
1279 .destroy
= lib_route_map_entry_match_condition_ipv6_next_hop_type_destroy
,
1283 .xpath
= "/frr-route-map:lib/route-map/entry/match-condition/rmap-match-condition/metric",
1285 .modify
= lib_route_map_entry_match_condition_metric_modify
,
1286 .destroy
= lib_route_map_entry_match_condition_metric_destroy
,
1290 .xpath
= "/frr-route-map:lib/route-map/entry/match-condition/rmap-match-condition/tag",
1292 .modify
= lib_route_map_entry_match_condition_tag_modify
,
1293 .destroy
= lib_route_map_entry_match_condition_tag_destroy
,
1297 .xpath
= "/frr-route-map:lib/route-map/entry/set-action",
1299 .create
= lib_route_map_entry_set_action_create
,
1300 .destroy
= lib_route_map_entry_set_action_destroy
,
1301 .cli_show
= route_map_action_show
,
1305 .xpath
= "/frr-route-map:lib/route-map/entry/set-action/rmap-set-action/ipv4-address",
1307 .modify
= lib_route_map_entry_set_action_ipv4_address_modify
,
1308 .destroy
= lib_route_map_entry_set_action_ipv4_address_destroy
,
1312 .xpath
= "/frr-route-map:lib/route-map/entry/set-action/rmap-set-action/ipv6-address",
1314 .modify
= lib_route_map_entry_set_action_ipv6_address_modify
,
1315 .destroy
= lib_route_map_entry_set_action_ipv6_address_destroy
,
1319 .xpath
= "/frr-route-map:lib/route-map/entry/set-action/rmap-set-action/value",
1321 .modify
= lib_route_map_entry_set_action_value_modify
,
1322 .destroy
= lib_route_map_entry_set_action_value_destroy
,
1326 .xpath
= "/frr-route-map:lib/route-map/entry/set-action/rmap-set-action/add-metric",
1328 .modify
= lib_route_map_entry_set_action_add_metric_modify
,
1329 .destroy
= lib_route_map_entry_set_action_add_metric_destroy
,
1333 .xpath
= "/frr-route-map:lib/route-map/entry/set-action/rmap-set-action/subtract-metric",
1335 .modify
= lib_route_map_entry_set_action_subtract_metric_modify
,
1336 .destroy
= lib_route_map_entry_set_action_subtract_metric_destroy
,
1340 .xpath
= "/frr-route-map:lib/route-map/entry/set-action/rmap-set-action/use-round-trip-time",
1342 .modify
= lib_route_map_entry_set_action_use_round_trip_time_modify
,
1343 .destroy
= lib_route_map_entry_set_action_use_round_trip_time_destroy
,
1347 .xpath
= "/frr-route-map:lib/route-map/entry/set-action/rmap-set-action/add-round-trip-time",
1349 .modify
= lib_route_map_entry_set_action_add_round_trip_time_modify
,
1350 .destroy
= lib_route_map_entry_set_action_add_round_trip_time_destroy
,
1354 .xpath
= "/frr-route-map:lib/route-map/entry/set-action/rmap-set-action/subtract-round-trip-time",
1356 .modify
= lib_route_map_entry_set_action_subtract_round_trip_time_modify
,
1357 .destroy
= lib_route_map_entry_set_action_subtract_round_trip_time_destroy
,
1361 .xpath
= "/frr-route-map:lib/route-map/entry/set-action/rmap-set-action/tag",
1363 .modify
= lib_route_map_entry_set_action_tag_modify
,
1364 .destroy
= lib_route_map_entry_set_action_tag_destroy
,
1368 .xpath
= "/frr-route-map:lib/route-map/entry/set-action/rmap-set-action/policy",
1370 .modify
= lib_route_map_entry_set_action_policy_modify
,
1371 .destroy
= lib_route_map_entry_set_action_policy_destroy
,