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(NULL
, rhc
->rhc_rmi
, rhc
->rhc_rule
, NULL
,
50 if (rv
!= CMD_SUCCESS
)
51 return NB_ERR_INCONSISTENCY
;
56 int lib_route_map_entry_set_destroy(struct nb_cb_destroy_args
*args
)
58 struct routemap_hook_context
*rhc
;
61 if (args
->event
!= NB_EV_APPLY
)
64 rhc
= nb_running_get_entry(args
->dnode
, NULL
, true);
65 if (rhc
->rhc_shook
== NULL
)
68 rv
= rhc
->rhc_shook(NULL
, rhc
->rhc_rmi
, rhc
->rhc_rule
, NULL
);
69 if (rv
!= CMD_SUCCESS
)
70 return NB_ERR_INCONSISTENCY
;
76 * Auxiliary hook context list manipulation functions.
78 struct routemap_hook_context
*
79 routemap_hook_context_insert(struct route_map_index
*rmi
)
81 struct routemap_hook_context
*rhc
;
83 rhc
= XCALLOC(MTYPE_TMP
, sizeof(*rhc
));
85 TAILQ_INSERT_TAIL(&rmi
->rhclist
, rhc
, rhc_entry
);
90 void routemap_hook_context_free(struct routemap_hook_context
*rhc
)
92 struct route_map_index
*rmi
= rhc
->rhc_rmi
;
94 TAILQ_REMOVE(&rmi
->rhclist
, rhc
, rhc_entry
);
95 XFREE(MTYPE_TMP
, rhc
);
99 * XPath: /frr-route-map:lib/route-map
101 static int lib_route_map_create(struct nb_cb_create_args
*args
)
103 struct route_map
*rm
;
106 switch (args
->event
) {
113 rm_name
= yang_dnode_get_string(args
->dnode
, "./name");
114 rm
= route_map_get(rm_name
);
115 nb_running_set_entry(args
->dnode
, rm
);
122 static int lib_route_map_destroy(struct nb_cb_destroy_args
*args
)
124 struct route_map
*rm
;
126 switch (args
->event
) {
133 rm
= nb_running_unset_entry(args
->dnode
);
134 route_map_delete(rm
);
142 * XPath: /frr-route-map:lib/route-map/entry
144 static int lib_route_map_entry_create(struct nb_cb_create_args
*args
)
146 struct route_map_index
*rmi
;
147 struct route_map
*rm
;
151 switch (args
->event
) {
158 sequence
= yang_dnode_get_uint16(args
->dnode
, "./sequence");
159 action
= yang_dnode_get_enum(args
->dnode
, "./action") == 0
162 rm
= nb_running_get_entry(args
->dnode
, NULL
, true);
163 rmi
= route_map_index_get(rm
, action
, sequence
);
164 nb_running_set_entry(args
->dnode
, rmi
);
171 static int lib_route_map_entry_destroy(struct nb_cb_destroy_args
*args
)
173 struct route_map_index
*rmi
;
175 switch (args
->event
) {
182 rmi
= nb_running_unset_entry(args
->dnode
);
183 route_map_index_delete(rmi
, 1);
191 * XPath: /frr-route-map:lib/route-map/entry/description
194 lib_route_map_entry_description_modify(struct nb_cb_modify_args
*args
)
196 struct route_map_index
*rmi
;
197 const char *description
;
199 switch (args
->event
) {
204 description
= yang_dnode_get_string(args
->dnode
, NULL
);
205 args
->resource
->ptr
= XSTRDUP(MTYPE_TMP
, description
);
206 if (args
->resource
->ptr
== NULL
)
207 return NB_ERR_RESOURCE
;
210 XFREE(MTYPE_TMP
, args
->resource
->ptr
);
213 rmi
= nb_running_get_entry(args
->dnode
, NULL
, true);
214 XFREE(MTYPE_TMP
, rmi
->description
);
215 rmi
->description
= args
->resource
->ptr
;
223 lib_route_map_entry_description_destroy(struct nb_cb_destroy_args
*args
)
225 struct route_map_index
*rmi
;
227 switch (args
->event
) {
234 rmi
= nb_running_get_entry(args
->dnode
, NULL
, true);
235 XFREE(MTYPE_TMP
, rmi
->description
);
243 * XPath: /frr-route-map:lib/route-map/entry/action
245 static int lib_route_map_entry_action_modify(struct nb_cb_modify_args
*args
)
247 struct route_map_index
*rmi
;
249 switch (args
->event
) {
256 rmi
= nb_running_get_entry(args
->dnode
, NULL
, true);
257 rmi
->type
= yang_dnode_get_enum(args
->dnode
, NULL
);
266 * XPath: /frr-route-map:lib/route-map/entry/call
268 static int lib_route_map_entry_call_modify(struct nb_cb_modify_args
*args
)
270 struct route_map_index
*rmi
;
271 const char *rm_name
, *rmn_name
;
273 switch (args
->event
) {
275 rm_name
= yang_dnode_get_string(args
->dnode
, "../../name");
276 rmn_name
= yang_dnode_get_string(args
->dnode
, NULL
);
277 /* Don't allow to jump to the same route map instance. */
278 if (strcmp(rm_name
, rmn_name
) == 0)
279 return NB_ERR_VALIDATION
;
281 /* TODO: detect circular route map sequences. */
284 rmn_name
= yang_dnode_get_string(args
->dnode
, NULL
);
285 args
->resource
->ptr
= XSTRDUP(MTYPE_ROUTE_MAP_NAME
, rmn_name
);
288 XFREE(MTYPE_ROUTE_MAP_NAME
, args
->resource
->ptr
);
291 rmi
= nb_running_get_entry(args
->dnode
, NULL
, true);
293 route_map_upd8_dependency(RMAP_EVENT_CALL_DELETED
,
294 rmi
->nextrm
, rmi
->map
->name
);
295 XFREE(MTYPE_ROUTE_MAP_NAME
, rmi
->nextrm
);
297 rmi
->nextrm
= args
->resource
->ptr
;
298 route_map_upd8_dependency(RMAP_EVENT_CALL_ADDED
, rmi
->nextrm
,
306 static int lib_route_map_entry_call_destroy(struct nb_cb_destroy_args
*args
)
308 struct route_map_index
*rmi
;
310 switch (args
->event
) {
317 rmi
= nb_running_get_entry(args
->dnode
, NULL
, true);
318 route_map_upd8_dependency(RMAP_EVENT_CALL_DELETED
, rmi
->nextrm
,
320 XFREE(MTYPE_ROUTE_MAP_NAME
, rmi
->nextrm
);
329 * XPath: /frr-route-map:lib/route-map/entry/exit-policy
332 lib_route_map_entry_exit_policy_modify(struct nb_cb_modify_args
*args
)
334 struct route_map_index
*rmi
;
338 switch (args
->event
) {
340 policy
= yang_dnode_get_enum(args
->dnode
, NULL
);
342 case 0: /* permit-or-deny */
348 yang_dnode_get_enum(args
->dnode
, "../action");
349 if (rm_action
== 1 /* deny */) {
351 * On deny it is not possible to 'goto'
354 return NB_ERR_VALIDATION
;
363 rmi
= nb_running_get_entry(args
->dnode
, NULL
, true);
364 policy
= yang_dnode_get_enum(args
->dnode
, NULL
);
367 case 0: /* permit-or-deny */
368 rmi
->exitpolicy
= RMAP_EXIT
;
371 rmi
->exitpolicy
= RMAP_NEXT
;
374 rmi
->exitpolicy
= RMAP_GOTO
;
384 * XPath: /frr-route-map:lib/route-map/entry/goto-value
386 static int lib_route_map_entry_goto_value_modify(struct nb_cb_modify_args
*args
)
388 struct route_map_index
*rmi
;
392 switch (args
->event
) {
394 rmi_index
= yang_dnode_get_uint16(args
->dnode
, "../sequence");
395 rmi_next
= yang_dnode_get_uint16(args
->dnode
, NULL
);
396 if (rmi_next
<= rmi_index
) {
397 /* Can't jump backwards on a route map. */
398 return NB_ERR_VALIDATION
;
406 rmi
= nb_running_get_entry(args
->dnode
, NULL
, true);
407 rmi
->nextpref
= yang_dnode_get_uint16(args
->dnode
, NULL
);
415 lib_route_map_entry_goto_value_destroy(struct nb_cb_destroy_args
*args
)
417 struct route_map_index
*rmi
;
419 switch (args
->event
) {
426 rmi
= nb_running_get_entry(args
->dnode
, NULL
, true);
435 * XPath: /frr-route-map:lib/route-map/entry/match-condition
438 lib_route_map_entry_match_condition_create(struct nb_cb_create_args
*args
)
440 struct routemap_hook_context
*rhc
;
441 struct route_map_index
*rmi
;
443 switch (args
->event
) {
450 rmi
= nb_running_get_entry(args
->dnode
, NULL
, true);
451 rhc
= routemap_hook_context_insert(rmi
);
452 nb_running_set_entry(args
->dnode
, rhc
);
460 lib_route_map_entry_match_condition_destroy(struct nb_cb_destroy_args
*args
)
462 struct routemap_hook_context
*rhc
;
465 if (args
->event
!= NB_EV_APPLY
)
468 rv
= lib_route_map_entry_match_destroy(args
);
469 rhc
= nb_running_unset_entry(args
->dnode
);
470 routemap_hook_context_free(rhc
);
476 * XPath: /frr-route-map:lib/route-map/entry/match-condition/interface
478 static int lib_route_map_entry_match_condition_interface_modify(
479 struct nb_cb_modify_args
*args
)
481 struct routemap_hook_context
*rhc
;
485 if (args
->event
!= NB_EV_APPLY
)
488 /* Check for hook function. */
489 if (rmap_match_set_hook
.match_interface
== NULL
)
492 /* Add configuration. */
493 rhc
= nb_running_get_entry(args
->dnode
, NULL
, true);
494 ifname
= yang_dnode_get_string(args
->dnode
, NULL
);
496 /* Set destroy information. */
497 rhc
->rhc_mhook
= rmap_match_set_hook
.no_match_interface
;
498 rhc
->rhc_rule
= "interface";
499 rhc
->rhc_event
= RMAP_EVENT_MATCH_DELETED
;
501 rv
= rmap_match_set_hook
.match_interface(NULL
, rhc
->rhc_rmi
,
503 RMAP_EVENT_MATCH_ADDED
);
504 if (rv
!= CMD_SUCCESS
) {
505 rhc
->rhc_mhook
= NULL
;
506 return NB_ERR_INCONSISTENCY
;
512 static int lib_route_map_entry_match_condition_interface_destroy(
513 struct nb_cb_destroy_args
*args
)
515 return lib_route_map_entry_match_destroy(args
);
519 * XPath: /frr-route-map:lib/route-map/entry/match-condition/list-name
521 static int lib_route_map_entry_match_condition_list_name_modify(
522 struct nb_cb_modify_args
*args
)
524 struct routemap_hook_context
*rhc
;
529 if (args
->event
!= NB_EV_APPLY
)
532 /* Check for hook installation, otherwise we can just stop. */
533 acl
= yang_dnode_get_string(args
->dnode
, NULL
);
534 rhc
= nb_running_get_entry(args
->dnode
, NULL
, true);
535 condition
= yang_dnode_get_enum(args
->dnode
, "../condition");
537 case 1: /* ipv4-address-list */
538 if (rmap_match_set_hook
.match_ip_address
== NULL
)
540 rhc
->rhc_mhook
= rmap_match_set_hook
.no_match_ip_address
;
541 rhc
->rhc_rule
= "ip address";
542 rhc
->rhc_event
= RMAP_EVENT_FILTER_DELETED
;
543 rv
= rmap_match_set_hook
.match_ip_address(
544 NULL
, rhc
->rhc_rmi
, "ip address", acl
,
545 RMAP_EVENT_FILTER_ADDED
);
547 case 2: /* ipv4-prefix-list */
548 if (rmap_match_set_hook
.match_ip_address_prefix_list
== NULL
)
551 rmap_match_set_hook
.no_match_ip_address_prefix_list
;
552 rhc
->rhc_rule
= "ip address prefix-list";
553 rhc
->rhc_event
= RMAP_EVENT_PLIST_DELETED
;
554 rv
= rmap_match_set_hook
.match_ip_address_prefix_list(
555 NULL
, rhc
->rhc_rmi
, "ip address prefix-list", acl
,
556 RMAP_EVENT_PLIST_ADDED
);
558 case 3: /* ipv4-next-hop-list */
559 if (rmap_match_set_hook
.match_ip_next_hop
== NULL
)
561 rhc
->rhc_mhook
= rmap_match_set_hook
.no_match_ip_next_hop
;
562 rhc
->rhc_rule
= "ip next-hop";
563 rhc
->rhc_event
= RMAP_EVENT_FILTER_DELETED
;
564 rv
= rmap_match_set_hook
.match_ip_next_hop(
565 NULL
, rhc
->rhc_rmi
, "ip next-hop", acl
,
566 RMAP_EVENT_FILTER_ADDED
);
568 case 4: /* ipv4-next-hop-prefix-list */
569 if (rmap_match_set_hook
.match_ip_next_hop_prefix_list
== NULL
)
572 rmap_match_set_hook
.no_match_ip_next_hop_prefix_list
;
573 rhc
->rhc_rule
= "ip next-hop prefix-list";
574 rhc
->rhc_event
= RMAP_EVENT_PLIST_DELETED
;
575 rv
= rmap_match_set_hook
.match_ip_next_hop_prefix_list(
576 NULL
, rhc
->rhc_rmi
, "ip next-hop prefix-list", acl
,
577 RMAP_EVENT_PLIST_ADDED
);
579 case 6: /* ipv6-address-list */
580 if (rmap_match_set_hook
.match_ipv6_address
== NULL
)
582 rhc
->rhc_mhook
= rmap_match_set_hook
.no_match_ipv6_address
;
583 rhc
->rhc_rule
= "ipv6 address";
584 rhc
->rhc_event
= RMAP_EVENT_FILTER_DELETED
;
585 rv
= rmap_match_set_hook
.match_ipv6_address(
586 NULL
, rhc
->rhc_rmi
, "ipv6 address", acl
,
587 RMAP_EVENT_FILTER_ADDED
);
589 case 7: /* ipv6-prefix-list */
590 if (rmap_match_set_hook
.match_ipv6_address_prefix_list
== NULL
)
593 rmap_match_set_hook
.no_match_ipv6_address_prefix_list
;
594 rhc
->rhc_rule
= "ipv6 address prefix-list";
595 rhc
->rhc_event
= RMAP_EVENT_PLIST_DELETED
;
596 rv
= rmap_match_set_hook
.match_ipv6_address_prefix_list(
597 NULL
, rhc
->rhc_rmi
, "ipv6 address prefix-list", acl
,
598 RMAP_EVENT_PLIST_ADDED
);
601 rv
= CMD_ERR_NO_MATCH
;
604 if (rv
!= CMD_SUCCESS
) {
605 rhc
->rhc_mhook
= NULL
;
606 return NB_ERR_INCONSISTENCY
;
612 static int lib_route_map_entry_match_condition_list_name_destroy(
613 struct nb_cb_destroy_args
*args
)
615 return lib_route_map_entry_match_destroy(args
);
619 * XPath: /frr-route-map:lib/route-map/entry/match-condition/ipv4-next-hop-type
621 static int lib_route_map_entry_match_condition_ipv4_next_hop_type_modify(
622 struct nb_cb_modify_args
*args
)
624 struct routemap_hook_context
*rhc
;
628 if (args
->event
!= NB_EV_APPLY
)
631 /* Check for hook function. */
632 if (rmap_match_set_hook
.match_ip_next_hop_type
== NULL
)
635 /* Add configuration. */
636 rhc
= nb_running_get_entry(args
->dnode
, NULL
, true);
637 type
= yang_dnode_get_string(args
->dnode
, NULL
);
639 /* Set destroy information. */
640 rhc
->rhc_mhook
= rmap_match_set_hook
.no_match_ip_next_hop_type
;
641 rhc
->rhc_rule
= "ip next-hop type";
642 rhc
->rhc_event
= RMAP_EVENT_MATCH_DELETED
;
644 rv
= rmap_match_set_hook
.match_ip_next_hop_type(
645 NULL
, rhc
->rhc_rmi
, "ip next-hop type", type
,
646 RMAP_EVENT_MATCH_ADDED
);
647 if (rv
!= CMD_SUCCESS
) {
648 rhc
->rhc_mhook
= NULL
;
649 return NB_ERR_INCONSISTENCY
;
655 static int lib_route_map_entry_match_condition_ipv4_next_hop_type_destroy(
656 struct nb_cb_destroy_args
*args
)
658 return lib_route_map_entry_match_destroy(args
);
662 * XPath: /frr-route-map:lib/route-map/entry/match-condition/ipv6-next-hop-type
664 static int lib_route_map_entry_match_condition_ipv6_next_hop_type_modify(
665 struct nb_cb_modify_args
*args
)
667 struct routemap_hook_context
*rhc
;
671 if (args
->event
!= NB_EV_APPLY
)
674 /* Check for hook function. */
675 if (rmap_match_set_hook
.match_ipv6_next_hop_type
== NULL
)
678 /* Add configuration. */
679 rhc
= nb_running_get_entry(args
->dnode
, NULL
, true);
680 type
= yang_dnode_get_string(args
->dnode
, NULL
);
682 /* Set destroy information. */
683 rhc
->rhc_mhook
= rmap_match_set_hook
.no_match_ipv6_next_hop_type
;
684 rhc
->rhc_rule
= "ipv6 next-hop type";
685 rhc
->rhc_event
= RMAP_EVENT_MATCH_DELETED
;
687 rv
= rmap_match_set_hook
.match_ipv6_next_hop_type(
688 NULL
, rhc
->rhc_rmi
, "ipv6 next-hop type", type
,
689 RMAP_EVENT_MATCH_ADDED
);
690 if (rv
!= CMD_SUCCESS
) {
691 rhc
->rhc_mhook
= NULL
;
692 return NB_ERR_INCONSISTENCY
;
698 static int lib_route_map_entry_match_condition_ipv6_next_hop_type_destroy(
699 struct nb_cb_destroy_args
*args
)
701 return lib_route_map_entry_match_destroy(args
);
705 * XPath: /frr-route-map:lib/route-map/entry/match-condition/metric
707 static int lib_route_map_entry_match_condition_metric_modify(
708 struct nb_cb_modify_args
*args
)
710 struct routemap_hook_context
*rhc
;
714 if (args
->event
!= NB_EV_APPLY
)
717 /* Check for hook function. */
718 if (rmap_match_set_hook
.match_metric
== NULL
)
721 /* Add configuration. */
722 rhc
= nb_running_get_entry(args
->dnode
, NULL
, true);
723 type
= yang_dnode_get_string(args
->dnode
, NULL
);
725 /* Set destroy information. */
726 rhc
->rhc_mhook
= rmap_match_set_hook
.no_match_metric
;
727 rhc
->rhc_rule
= "metric";
728 rhc
->rhc_event
= RMAP_EVENT_MATCH_DELETED
;
730 rv
= rmap_match_set_hook
.match_metric(NULL
, rhc
->rhc_rmi
, "metric",
731 type
, RMAP_EVENT_MATCH_ADDED
);
732 if (rv
!= CMD_SUCCESS
) {
733 rhc
->rhc_mhook
= NULL
;
734 return NB_ERR_INCONSISTENCY
;
740 static int lib_route_map_entry_match_condition_metric_destroy(
741 struct nb_cb_destroy_args
*args
)
743 return lib_route_map_entry_match_destroy(args
);
747 * XPath: /frr-route-map:lib/route-map/entry/match-condition/tag
750 lib_route_map_entry_match_condition_tag_modify(struct nb_cb_modify_args
*args
)
752 struct routemap_hook_context
*rhc
;
756 if (args
->event
!= NB_EV_APPLY
)
759 /* Check for hook function. */
760 if (rmap_match_set_hook
.match_tag
== NULL
)
763 /* Add configuration. */
764 rhc
= nb_running_get_entry(args
->dnode
, NULL
, true);
765 tag
= yang_dnode_get_string(args
->dnode
, NULL
);
767 /* Set destroy information. */
768 rhc
->rhc_mhook
= rmap_match_set_hook
.no_match_tag
;
769 rhc
->rhc_rule
= "tag";
770 rhc
->rhc_event
= RMAP_EVENT_MATCH_DELETED
;
772 rv
= rmap_match_set_hook
.match_tag(NULL
, rhc
->rhc_rmi
, "tag", tag
,
773 RMAP_EVENT_MATCH_ADDED
);
774 if (rv
!= CMD_SUCCESS
) {
775 rhc
->rhc_mhook
= NULL
;
776 return NB_ERR_INCONSISTENCY
;
783 lib_route_map_entry_match_condition_tag_destroy(struct nb_cb_destroy_args
*args
)
785 return lib_route_map_entry_match_destroy(args
);
789 * XPath: /frr-route-map:lib/route-map/entry/set-action
791 static int lib_route_map_entry_set_action_create(struct nb_cb_create_args
*args
)
793 return lib_route_map_entry_match_condition_create(args
);
797 lib_route_map_entry_set_action_destroy(struct nb_cb_destroy_args
*args
)
799 struct routemap_hook_context
*rhc
;
802 if (args
->event
!= NB_EV_APPLY
)
805 rv
= lib_route_map_entry_set_destroy(args
);
806 rhc
= nb_running_unset_entry(args
->dnode
);
807 routemap_hook_context_free(rhc
);
813 * XPath: /frr-route-map:lib/route-map/entry/set-action/ipv4-address
815 static int lib_route_map_entry_set_action_ipv4_address_modify(
816 struct nb_cb_modify_args
*args
)
818 struct routemap_hook_context
*rhc
;
823 switch (args
->event
) {
826 * NOTE: validate if 'action' is 'ipv4-next-hop',
827 * currently it is not necessary because this is the
828 * only implemented action.
830 yang_dnode_get_ipv4(&ia
, args
->dnode
, NULL
);
831 if (ia
.s_addr
== INADDR_ANY
|| IPV4_CLASS_DE(ntohl(ia
.s_addr
)))
832 return NB_ERR_VALIDATION
;
841 /* Check for hook function. */
842 if (rmap_match_set_hook
.set_ip_nexthop
== NULL
)
845 /* Add configuration. */
846 rhc
= nb_running_get_entry(args
->dnode
, NULL
, true);
847 address
= yang_dnode_get_string(args
->dnode
, NULL
);
849 /* Set destroy information. */
850 rhc
->rhc_shook
= rmap_match_set_hook
.no_set_ip_nexthop
;
851 rhc
->rhc_rule
= "ip next-hop";
853 rv
= rmap_match_set_hook
.set_ip_nexthop(NULL
, rhc
->rhc_rmi
,
854 "ip next-hop", address
);
855 if (rv
!= CMD_SUCCESS
) {
856 rhc
->rhc_shook
= NULL
;
857 return NB_ERR_INCONSISTENCY
;
863 static int lib_route_map_entry_set_action_ipv4_address_destroy(
864 struct nb_cb_destroy_args
*args
)
866 return lib_route_map_entry_set_destroy(args
);
870 * XPath: /frr-route-map:lib/route-map/entry/set-action/ipv6-address
872 static int lib_route_map_entry_set_action_ipv6_address_modify(
873 struct nb_cb_modify_args
*args
)
875 struct routemap_hook_context
*rhc
;
880 switch (args
->event
) {
883 * NOTE: validate if 'action' is 'ipv6-next-hop',
884 * currently it is not necessary because this is the
885 * only implemented action. Other actions might have
886 * different validations.
888 yang_dnode_get_ipv6(&i6a
, args
->dnode
, NULL
);
889 if (!IN6_IS_ADDR_LINKLOCAL(&i6a
))
890 return NB_ERR_VALIDATION
;
899 /* Check for hook function. */
900 if (rmap_match_set_hook
.set_ipv6_nexthop_local
== NULL
)
903 /* Add configuration. */
904 rhc
= nb_running_get_entry(args
->dnode
, NULL
, true);
905 address
= yang_dnode_get_string(args
->dnode
, NULL
);
907 /* Set destroy information. */
908 rhc
->rhc_shook
= rmap_match_set_hook
.no_set_ipv6_nexthop_local
;
909 rhc
->rhc_rule
= "ipv6 next-hop local";
911 rv
= rmap_match_set_hook
.set_ipv6_nexthop_local(
912 NULL
, rhc
->rhc_rmi
, "ipv6 next-hop local", address
);
913 if (rv
!= CMD_SUCCESS
) {
914 rhc
->rhc_shook
= NULL
;
915 return NB_ERR_INCONSISTENCY
;
921 static int lib_route_map_entry_set_action_ipv6_address_destroy(
922 struct nb_cb_destroy_args
*args
)
924 return lib_route_map_entry_set_destroy(args
);
928 * XPath: /frr-route-map:lib/route-map/entry/set-action/value
930 static int set_action_modify(enum nb_event event
, const struct lyd_node
*dnode
,
931 union nb_resource
*resource
, const char *value
)
933 struct routemap_hook_context
*rhc
;
937 * NOTE: validate if 'action' is 'metric', currently it is not
938 * necessary because this is the only implemented action. Other
939 * actions might have different validations.
941 if (event
!= NB_EV_APPLY
)
944 /* Check for hook function. */
945 if (rmap_match_set_hook
.set_metric
== NULL
)
948 /* Add configuration. */
949 rhc
= nb_running_get_entry(dnode
, NULL
, true);
951 /* Set destroy information. */
952 rhc
->rhc_shook
= rmap_match_set_hook
.no_set_metric
;
953 rhc
->rhc_rule
= "metric";
955 rv
= rmap_match_set_hook
.set_metric(NULL
, rhc
->rhc_rmi
, "metric",
957 if (rv
!= CMD_SUCCESS
) {
958 rhc
->rhc_shook
= NULL
;
959 return NB_ERR_INCONSISTENCY
;
966 lib_route_map_entry_set_action_value_modify(struct nb_cb_modify_args
*args
)
968 const char *metric
= yang_dnode_get_string(args
->dnode
, NULL
);
970 return set_action_modify(args
->event
, args
->dnode
, args
->resource
,
975 lib_route_map_entry_set_action_value_destroy(struct nb_cb_destroy_args
*args
)
977 return lib_route_map_entry_set_destroy(args
);
981 * XPath: /frr-route-map:lib/route-map/entry/set-action/add-metric
984 lib_route_map_entry_set_action_add_metric_modify(struct nb_cb_modify_args
*args
)
986 return set_action_modify(args
->event
, args
->dnode
, args
->resource
,
990 static int lib_route_map_entry_set_action_add_metric_destroy(
991 struct nb_cb_destroy_args
*args
)
993 return lib_route_map_entry_set_action_value_destroy(args
);
997 * XPath: /frr-route-map:lib/route-map/entry/set-action/subtract-metric
999 static int lib_route_map_entry_set_action_subtract_metric_modify(
1000 struct nb_cb_modify_args
*args
)
1002 return set_action_modify(args
->event
, args
->dnode
, args
->resource
,
1006 static int lib_route_map_entry_set_action_subtract_metric_destroy(
1007 struct nb_cb_destroy_args
*args
)
1009 return lib_route_map_entry_set_action_value_destroy(args
);
1013 * XPath: /frr-route-map:lib/route-map/entry/set-action/use-round-trip-time
1015 static int lib_route_map_entry_set_action_use_round_trip_time_modify(
1016 struct nb_cb_modify_args
*args
)
1018 return set_action_modify(args
->event
, args
->dnode
, args
->resource
,
1022 static int lib_route_map_entry_set_action_use_round_trip_time_destroy(
1023 struct nb_cb_destroy_args
*args
)
1025 return lib_route_map_entry_set_action_value_destroy(args
);
1029 * XPath: /frr-route-map:lib/route-map/entry/set-action/add-round-trip-time
1031 static int lib_route_map_entry_set_action_add_round_trip_time_modify(
1032 struct nb_cb_modify_args
*args
)
1034 return set_action_modify(args
->event
, args
->dnode
, args
->resource
,
1038 static int lib_route_map_entry_set_action_add_round_trip_time_destroy(
1039 struct nb_cb_destroy_args
*args
)
1041 return lib_route_map_entry_set_action_value_destroy(args
);
1045 * XPath: /frr-route-map:lib/route-map/entry/set-action/subtract-round-trip-time
1047 static int lib_route_map_entry_set_action_subtract_round_trip_time_modify(
1048 struct nb_cb_modify_args
*args
)
1050 return set_action_modify(args
->event
, args
->dnode
, args
->resource
,
1054 static int lib_route_map_entry_set_action_subtract_round_trip_time_destroy(
1055 struct nb_cb_destroy_args
*args
)
1057 return lib_route_map_entry_set_action_value_destroy(args
);
1061 * XPath: /frr-route-map:lib/route-map/entry/set-action/tag
1064 lib_route_map_entry_set_action_tag_modify(struct nb_cb_modify_args
*args
)
1066 struct routemap_hook_context
*rhc
;
1071 * NOTE: validate if 'action' is 'tag', currently it is not
1072 * necessary because this is the only implemented action. Other
1073 * actions might have different validations.
1075 if (args
->event
!= NB_EV_APPLY
)
1078 /* Check for hook function. */
1079 if (rmap_match_set_hook
.set_tag
== NULL
)
1082 /* Add configuration. */
1083 rhc
= nb_running_get_entry(args
->dnode
, NULL
, true);
1084 tag
= yang_dnode_get_string(args
->dnode
, NULL
);
1086 /* Set destroy information. */
1087 rhc
->rhc_shook
= rmap_match_set_hook
.no_set_tag
;
1088 rhc
->rhc_rule
= "tag";
1090 rv
= rmap_match_set_hook
.set_tag(NULL
, rhc
->rhc_rmi
, "tag", tag
);
1091 if (rv
!= CMD_SUCCESS
) {
1092 rhc
->rhc_shook
= NULL
;
1093 return NB_ERR_INCONSISTENCY
;
1100 lib_route_map_entry_set_action_tag_destroy(struct nb_cb_destroy_args
*args
)
1102 return lib_route_map_entry_set_destroy(args
);
1105 /* clang-format off */
1106 const struct frr_yang_module_info frr_route_map_info
= {
1107 .name
= "frr-route-map",
1110 .xpath
= "/frr-route-map:lib/route-map",
1112 .create
= lib_route_map_create
,
1113 .destroy
= lib_route_map_destroy
,
1117 .xpath
= "/frr-route-map:lib/route-map/entry",
1119 .create
= lib_route_map_entry_create
,
1120 .destroy
= lib_route_map_entry_destroy
,
1121 .cli_show
= route_map_instance_show
,
1122 .cli_show_end
= route_map_instance_show_end
,
1126 .xpath
= "/frr-route-map:lib/route-map/entry/description",
1128 .modify
= lib_route_map_entry_description_modify
,
1129 .destroy
= lib_route_map_entry_description_destroy
,
1130 .cli_show
= route_map_description_show
,
1134 .xpath
= "/frr-route-map:lib/route-map/entry/action",
1136 .modify
= lib_route_map_entry_action_modify
,
1140 .xpath
= "/frr-route-map:lib/route-map/entry/call",
1142 .modify
= lib_route_map_entry_call_modify
,
1143 .destroy
= lib_route_map_entry_call_destroy
,
1144 .cli_show
= route_map_call_show
,
1148 .xpath
= "/frr-route-map:lib/route-map/entry/exit-policy",
1150 .modify
= lib_route_map_entry_exit_policy_modify
,
1151 .cli_show
= route_map_exit_policy_show
,
1155 .xpath
= "/frr-route-map:lib/route-map/entry/goto-value",
1157 .modify
= lib_route_map_entry_goto_value_modify
,
1158 .destroy
= lib_route_map_entry_goto_value_destroy
,
1162 .xpath
= "/frr-route-map:lib/route-map/entry/match-condition",
1164 .create
= lib_route_map_entry_match_condition_create
,
1165 .destroy
= lib_route_map_entry_match_condition_destroy
,
1166 .cli_show
= route_map_condition_show
,
1170 .xpath
= "/frr-route-map:lib/route-map/entry/match-condition/interface",
1172 .modify
= lib_route_map_entry_match_condition_interface_modify
,
1173 .destroy
= lib_route_map_entry_match_condition_interface_destroy
,
1177 .xpath
= "/frr-route-map:lib/route-map/entry/match-condition/list-name",
1179 .modify
= lib_route_map_entry_match_condition_list_name_modify
,
1180 .destroy
= lib_route_map_entry_match_condition_list_name_destroy
,
1184 .xpath
= "/frr-route-map:lib/route-map/entry/match-condition/ipv4-next-hop-type",
1186 .modify
= lib_route_map_entry_match_condition_ipv4_next_hop_type_modify
,
1187 .destroy
= lib_route_map_entry_match_condition_ipv4_next_hop_type_destroy
,
1191 .xpath
= "/frr-route-map:lib/route-map/entry/match-condition/ipv6-next-hop-type",
1193 .modify
= lib_route_map_entry_match_condition_ipv6_next_hop_type_modify
,
1194 .destroy
= lib_route_map_entry_match_condition_ipv6_next_hop_type_destroy
,
1198 .xpath
= "/frr-route-map:lib/route-map/entry/match-condition/metric",
1200 .modify
= lib_route_map_entry_match_condition_metric_modify
,
1201 .destroy
= lib_route_map_entry_match_condition_metric_destroy
,
1205 .xpath
= "/frr-route-map:lib/route-map/entry/match-condition/tag",
1207 .modify
= lib_route_map_entry_match_condition_tag_modify
,
1208 .destroy
= lib_route_map_entry_match_condition_tag_destroy
,
1212 .xpath
= "/frr-route-map:lib/route-map/entry/set-action",
1214 .create
= lib_route_map_entry_set_action_create
,
1215 .destroy
= lib_route_map_entry_set_action_destroy
,
1216 .cli_show
= route_map_action_show
,
1220 .xpath
= "/frr-route-map:lib/route-map/entry/set-action/ipv4-address",
1222 .modify
= lib_route_map_entry_set_action_ipv4_address_modify
,
1223 .destroy
= lib_route_map_entry_set_action_ipv4_address_destroy
,
1227 .xpath
= "/frr-route-map:lib/route-map/entry/set-action/ipv6-address",
1229 .modify
= lib_route_map_entry_set_action_ipv6_address_modify
,
1230 .destroy
= lib_route_map_entry_set_action_ipv6_address_destroy
,
1234 .xpath
= "/frr-route-map:lib/route-map/entry/set-action/value",
1236 .modify
= lib_route_map_entry_set_action_value_modify
,
1237 .destroy
= lib_route_map_entry_set_action_value_destroy
,
1241 .xpath
= "/frr-route-map:lib/route-map/entry/set-action/add-metric",
1243 .modify
= lib_route_map_entry_set_action_add_metric_modify
,
1244 .destroy
= lib_route_map_entry_set_action_add_metric_destroy
,
1248 .xpath
= "/frr-route-map:lib/route-map/entry/set-action/subtract-metric",
1250 .modify
= lib_route_map_entry_set_action_subtract_metric_modify
,
1251 .destroy
= lib_route_map_entry_set_action_subtract_metric_destroy
,
1255 .xpath
= "/frr-route-map:lib/route-map/entry/set-action/use-round-trip-time",
1257 .modify
= lib_route_map_entry_set_action_use_round_trip_time_modify
,
1258 .destroy
= lib_route_map_entry_set_action_use_round_trip_time_destroy
,
1262 .xpath
= "/frr-route-map:lib/route-map/entry/set-action/add-round-trip-time",
1264 .modify
= lib_route_map_entry_set_action_add_round_trip_time_modify
,
1265 .destroy
= lib_route_map_entry_set_action_add_round_trip_time_destroy
,
1269 .xpath
= "/frr-route-map:lib/route-map/entry/set-action/subtract-round-trip-time",
1271 .modify
= lib_route_map_entry_set_action_subtract_round_trip_time_modify
,
1272 .destroy
= lib_route_map_entry_set_action_subtract_round_trip_time_destroy
,
1276 .xpath
= "/frr-route-map:lib/route-map/entry/set-action/tag",
1278 .modify
= lib_route_map_entry_set_action_tag_modify
,
1279 .destroy
= lib_route_map_entry_set_action_tag_destroy
,